├── .github └── workflows │ ├── TestUnit.yml │ ├── automerge.yml │ └── wip.yml ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── Makefile ├── README.md ├── api └── tibc │ ├── apps │ ├── mt_transfer │ │ ├── module │ │ │ └── v1 │ │ │ │ └── module.pulsar.go │ │ └── v1 │ │ │ ├── mt_transfer.pulsar.go │ │ │ ├── query.pulsar.go │ │ │ ├── query_grpc.pb.go │ │ │ ├── tx.pulsar.go │ │ │ └── tx_grpc.pb.go │ └── nft_transfer │ │ ├── module │ │ └── v1 │ │ │ └── module.pulsar.go │ │ └── v1 │ │ ├── nft_transfer.pulsar.go │ │ ├── query.pulsar.go │ │ ├── query_grpc.pb.go │ │ ├── tx.pulsar.go │ │ └── tx_grpc.pb.go │ └── core │ ├── client │ └── v1 │ │ ├── client.pulsar.go │ │ ├── genesis.pulsar.go │ │ ├── query.pulsar.go │ │ ├── query_grpc.pb.go │ │ ├── tx.pulsar.go │ │ └── tx_grpc.pb.go │ ├── module │ └── v1 │ │ └── module.pulsar.go │ ├── packet │ └── v1 │ │ ├── genesis.pulsar.go │ │ ├── packet.pulsar.go │ │ ├── query.pulsar.go │ │ ├── query_grpc.pb.go │ │ ├── tx.pulsar.go │ │ └── tx_grpc.pb.go │ ├── routing │ └── v1 │ │ ├── genesis.pulsar.go │ │ ├── query.pulsar.go │ │ ├── query_grpc.pb.go │ │ ├── routing.pulsar.go │ │ ├── tx.pulsar.go │ │ └── tx_grpc.pb.go │ └── types │ └── v1 │ └── genesis.pulsar.go ├── buf.work.yaml ├── go.mod ├── go.sum ├── modules └── tibc │ ├── apps │ ├── mt_transfer │ │ ├── client │ │ │ └── cli │ │ │ │ ├── cli.go │ │ │ │ ├── flags.go │ │ │ │ ├── query.go │ │ │ │ └── tx.go │ │ ├── depinject.go │ │ ├── keeper │ │ │ ├── encoding.go │ │ │ ├── grpc_query.go │ │ │ ├── grpc_query_test.go │ │ │ ├── keeper.go │ │ │ ├── keeper_test.go │ │ │ ├── msg_server.go │ │ │ ├── relay.go │ │ │ └── relay_test.go │ │ ├── moudle.go │ │ ├── transfer_test.go │ │ └── types │ │ │ ├── codec.go │ │ │ ├── errors.go │ │ │ ├── events.go │ │ │ ├── expected_keepers.go │ │ │ ├── keys.go │ │ │ ├── msgs.go │ │ │ ├── mt_transfer.pb.go │ │ │ ├── packet.go │ │ │ ├── query.pb.go │ │ │ ├── query.pb.gw.go │ │ │ ├── trace.go │ │ │ └── tx.pb.go │ └── nft_transfer │ │ ├── client │ │ └── cli │ │ │ ├── cli.go │ │ │ ├── flags.go │ │ │ ├── query.go │ │ │ └── tx.go │ │ ├── depinject.go │ │ ├── keeper │ │ ├── encoding.go │ │ ├── grpc_query.go │ │ ├── grpc_query_test.go │ │ ├── keeper.go │ │ ├── keeper_test.go │ │ ├── msg_server.go │ │ ├── relay.go │ │ └── relay_test.go │ │ ├── moudle.go │ │ ├── transfer_test.go │ │ └── types │ │ ├── codec.go │ │ ├── errors.go │ │ ├── events.go │ │ ├── expected_keepers.go │ │ ├── keys.go │ │ ├── msgs.go │ │ ├── nft.go │ │ ├── nft_transfer.pb.go │ │ ├── packet.go │ │ ├── query.pb.go │ │ ├── query.pb.gw.go │ │ ├── trace.go │ │ └── tx.pb.go │ ├── core │ ├── 02-client │ │ ├── client │ │ │ ├── cli │ │ │ │ ├── cli.go │ │ │ │ ├── query.go │ │ │ │ └── tx.go │ │ │ └── utils │ │ │ │ └── utils.go │ │ ├── doc.go │ │ ├── genesis.go │ │ ├── keeper │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── encoding.go │ │ │ ├── grpc_query.go │ │ │ ├── grpc_query_test.go │ │ │ ├── keeper.go │ │ │ ├── keeper_test.go │ │ │ ├── proposal.go │ │ │ ├── proposal_test.go │ │ │ └── relayer.go │ │ ├── module.go │ │ ├── simulation │ │ │ ├── decoder.go │ │ │ ├── decoder_test.go │ │ │ └── genesis.go │ │ └── types │ │ │ ├── client.go │ │ │ ├── client.pb.go │ │ │ ├── client_test.go │ │ │ ├── codec.go │ │ │ ├── codec_test.go │ │ │ ├── encoding.go │ │ │ ├── encoding_test.go │ │ │ ├── errors.go │ │ │ ├── events.go │ │ │ ├── expected_keepers.go │ │ │ ├── genesis.go │ │ │ ├── genesis.pb.go │ │ │ ├── genesis_test.go │ │ │ ├── height.go │ │ │ ├── height_test.go │ │ │ ├── keys.go │ │ │ ├── metrics.go │ │ │ ├── msgs.go │ │ │ ├── msgs_test.go │ │ │ ├── proposal.go │ │ │ ├── proposal_test.go │ │ │ ├── query.go │ │ │ ├── query.pb.go │ │ │ ├── query.pb.gw.go │ │ │ └── tx.pb.go │ ├── 04-packet │ │ ├── client │ │ │ ├── cli │ │ │ │ ├── cli.go │ │ │ │ ├── flags.go │ │ │ │ ├── query.go │ │ │ │ └── tx.go │ │ │ └── utils │ │ │ │ └── utils.go │ │ ├── genesis.go │ │ ├── keeper │ │ │ ├── grpc_query.go │ │ │ ├── grpc_query_test.go │ │ │ ├── keeper.go │ │ │ ├── keeper_test.go │ │ │ ├── packet.go │ │ │ └── packet_test.go │ │ ├── module.go │ │ ├── simulation │ │ │ ├── decoder.go │ │ │ ├── decoder_test.go │ │ │ └── genesis.go │ │ └── types │ │ │ ├── codec.go │ │ │ ├── errors.go │ │ │ ├── events.go │ │ │ ├── expected_keepers.go │ │ │ ├── genesis.go │ │ │ ├── genesis.pb.go │ │ │ ├── genesis_test.go │ │ │ ├── keys.go │ │ │ ├── msgs.go │ │ │ ├── msgs_test.go │ │ │ ├── packet.go │ │ │ ├── packet.pb.go │ │ │ ├── packet_test.go │ │ │ ├── query.go │ │ │ ├── query.pb.go │ │ │ ├── query.pb.gw.go │ │ │ └── tx.pb.go │ ├── 23-commitment │ │ └── types │ │ │ ├── bench_test.go │ │ │ ├── codec.go │ │ │ ├── commitment.pb.go │ │ │ ├── commitment_test.go │ │ │ ├── errors.go │ │ │ ├── merkle.go │ │ │ ├── merkle_test.go │ │ │ ├── utils.go │ │ │ └── utils_test.go │ ├── 24-host │ │ ├── errors.go │ │ ├── keys.go │ │ ├── parse.go │ │ ├── parse_test.go │ │ ├── validate.go │ │ └── validate_test.go │ ├── 26-routing │ │ ├── client │ │ │ └── cli │ │ │ │ ├── cli.go │ │ │ │ ├── query.go │ │ │ │ └── tx.go │ │ ├── genesis.go │ │ ├── keeper │ │ │ ├── grpc_query.go │ │ │ ├── grpc_query_test.go │ │ │ ├── keeper.go │ │ │ ├── keeper_test.go │ │ │ └── proposal.go │ │ ├── module.go │ │ └── types │ │ │ ├── codec.go │ │ │ ├── errors.go │ │ │ ├── genesis.go │ │ │ ├── genesis.pb.go │ │ │ ├── genesis_test.go │ │ │ ├── keys.go │ │ │ ├── module.go │ │ │ ├── msg.go │ │ │ ├── port.go │ │ │ ├── proposal.go │ │ │ ├── proposal_test.go │ │ │ ├── query.pb.go │ │ │ ├── query.pb.gw.go │ │ │ ├── router.go │ │ │ ├── routing.pb.go │ │ │ └── tx.pb.go │ ├── client │ │ ├── cli │ │ │ ├── cli.go │ │ │ ├── proposal_handler.go │ │ │ └── proposal_handler_test.go │ │ └── query.go │ ├── depinject.go │ ├── exported │ │ ├── client.go │ │ ├── commitment.go │ │ └── packet.go │ ├── genesis.go │ ├── genesis_test.go │ ├── keeper │ │ ├── grpc_query.go │ │ ├── keeper.go │ │ ├── msg_server.go │ │ └── msg_server_test.go │ ├── module.go │ ├── simulation │ │ ├── decoder.go │ │ ├── decoder_test.go │ │ ├── genesis.go │ │ └── genesis_test.go │ └── types │ │ ├── codec.go │ │ ├── genesis.go │ │ ├── genesis.pb.go │ │ ├── metrics.go │ │ ├── msg_server.go │ │ └── query.go │ ├── light-clients │ ├── 07-tendermint │ │ ├── doc.go │ │ ├── module.go │ │ └── types │ │ │ ├── client_state.go │ │ │ ├── client_state_test.go │ │ │ ├── codec.go │ │ │ ├── consensus_state.go │ │ │ ├── consensus_state_test.go │ │ │ ├── errors.go │ │ │ ├── fraction.go │ │ │ ├── genesis.go │ │ │ ├── genesis_test.go │ │ │ ├── header.go │ │ │ ├── header_test.go │ │ │ ├── store.go │ │ │ ├── store_test.go │ │ │ ├── tendermint.pb.go │ │ │ ├── tendermint_test.go │ │ │ ├── update.go │ │ │ └── update_test.go │ ├── 08-bsc │ │ ├── module.go │ │ └── types │ │ │ ├── bsc.go │ │ │ ├── bsc.pb.go │ │ │ ├── bsc_test.go │ │ │ ├── client_state.go │ │ │ ├── codec.go │ │ │ ├── consensus_state.go │ │ │ ├── errors.go │ │ │ ├── genesis_test.go │ │ │ ├── hashing.go │ │ │ ├── header.go │ │ │ ├── keys.go │ │ │ ├── snapshot.go │ │ │ ├── store.go │ │ │ ├── testdata │ │ │ ├── genesis_state.json │ │ │ └── update_headers.json │ │ │ ├── update.go │ │ │ └── update_test.go │ └── 09-eth │ │ ├── module.go │ │ └── types │ │ ├── algorithm.go │ │ ├── client_state.go │ │ ├── client_state_test.go │ │ ├── codec.go │ │ ├── consensus_state.go │ │ ├── errors.go │ │ ├── eth.go │ │ ├── eth.pb.go │ │ ├── eth_test.go │ │ ├── ethash.go │ │ ├── genesis_test.go │ │ ├── hashing.go │ │ ├── header.go │ │ ├── keys.go │ │ ├── sealer.go │ │ ├── store.go │ │ ├── testdata │ │ └── update_headers.json │ │ ├── update.go │ │ ├── update_test.go │ │ └── verify_header.go │ └── testing │ ├── app.go │ ├── chain.go │ ├── chain_test.go │ ├── config.go │ ├── coordinator.go │ ├── endpoint.go │ ├── mock │ ├── README.md │ ├── doc.go │ ├── mock.go │ ├── privval.go │ └── privval_test.go │ ├── path.go │ └── utils.go ├── proto ├── buf.gen.gogo.yaml ├── buf.gen.pulsar.yaml ├── buf.lock ├── buf.yaml └── tibc │ ├── apps │ ├── mt_transfer │ │ ├── module │ │ │ └── v1 │ │ │ │ └── module.proto │ │ └── v1 │ │ │ ├── mt_transfer.proto │ │ │ ├── query.proto │ │ │ └── tx.proto │ └── nft_transfer │ │ ├── module │ │ └── v1 │ │ │ └── module.proto │ │ └── v1 │ │ ├── nft_transfer.proto │ │ ├── query.proto │ │ └── tx.proto │ ├── core │ ├── client │ │ └── v1 │ │ │ ├── client.proto │ │ │ ├── genesis.proto │ │ │ ├── query.proto │ │ │ └── tx.proto │ ├── commitment │ │ └── v1 │ │ │ └── commitment.proto │ ├── module │ │ └── v1 │ │ │ └── module.proto │ ├── packet │ │ └── v1 │ │ │ ├── genesis.proto │ │ │ ├── packet.proto │ │ │ ├── query.proto │ │ │ └── tx.proto │ ├── routing │ │ └── v1 │ │ │ ├── genesis.proto │ │ │ ├── query.proto │ │ │ ├── routing.proto │ │ │ └── tx.proto │ └── types │ │ └── v1 │ │ └── genesis.proto │ └── lightclients │ ├── bsc │ └── v1 │ │ └── bsc.proto │ ├── eth │ └── v1 │ │ └── eth.proto │ └── tendermint │ └── v1 │ └── tendermint.proto ├── scripts ├── Makefile ├── protocgen-pulsar.sh └── protocgen.sh └── simapp ├── address.go ├── app.go ├── config.go ├── encoding.go ├── export.go ├── genesis.go ├── genesis_account.go ├── genesis_account_test.go ├── params ├── amino.go ├── doc.go ├── encoding.go ├── params.go ├── proto.go └── weights.go └── test_helpers.go /.github/workflows/TestUnit.yml: -------------------------------------------------------------------------------- 1 | name: TestUnit 2 | on: [pull_request] 3 | 4 | jobs: 5 | test-unit: 6 | name: Test Units 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: Checkout source code 10 | uses: actions/checkout@v3 11 | - name: Setup go 12 | uses: actions/setup-go@v3 13 | with: 14 | go-version: '^1.18' # The Go version to download (if necessary) and use. 15 | - run: make test-unit -------------------------------------------------------------------------------- /.github/workflows/automerge.yml: -------------------------------------------------------------------------------- 1 | name: automerge 2 | env: 3 | MERGE_METHOD: "squash" 4 | MERGE_DELETE_BRANCH: "true" 5 | MERGE_REMOVE_LABELS: "automerge" 6 | MERGE_RETRY_SLEEP: "20000" 7 | on: 8 | pull_request: 9 | types: 10 | - labeled 11 | - unlabeled 12 | - synchronize 13 | - opened 14 | - edited 15 | - ready_for_review 16 | - reopened 17 | - unlocked 18 | pull_request_review: 19 | types: 20 | - submitted 21 | check_suite: 22 | types: 23 | - completed 24 | status: {} 25 | jobs: 26 | automerge: 27 | runs-on: ubuntu-latest 28 | steps: 29 | - name: automerge 30 | uses: "pascalgn/automerge-action@v0.12.0" 31 | env: 32 | GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" -------------------------------------------------------------------------------- /.github/workflows/wip.yml: -------------------------------------------------------------------------------- 1 | name: WIP 2 | on: 3 | pull_request: 4 | types: [opened, synchronize, reopened, edited] 5 | 6 | jobs: 7 | wip: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: wip/action@v1 11 | env: 12 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS 2 | .DS_Store 3 | *.swp 4 | *.swo 5 | *.swl 6 | *.swm 7 | *.swn 8 | *.pyc 9 | 10 | # private files 11 | private[.-]* 12 | private 13 | 14 | # Build 15 | vendor 16 | build 17 | docs/_build 18 | docs/tutorial 19 | docs/node_modules 20 | docs/modules 21 | dist 22 | tools-stamp 23 | buf-stamp 24 | artifacts 25 | 26 | # Data - ideally these don't exist 27 | baseapp/data/* 28 | client/lcd/keys/* 29 | mytestnet 30 | 31 | # Testing 32 | coverage.txt 33 | profile.out 34 | sim_log_file 35 | 36 | # Vagrant 37 | .vagrant/ 38 | *.box 39 | *.log 40 | vagrant 41 | 42 | # IDE 43 | .idea 44 | *.iml 45 | .dir-locals.el 46 | .vscode 47 | 48 | # Graphviz 49 | dependency-graph.png 50 | 51 | # Latex 52 | *.aux 53 | *.out 54 | *.synctex.gz 55 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tibc-go 2 | Golang Implementation of Terse IBC 3 | 4 | ## build 5 | ```bash 6 | make build 7 | ``` 8 | 9 | ## local testnet 10 | ```bash 11 | ./build/simd testnet --v 1 --chain-id test --keyring-backend file 12 | 13 | ./build/simd start --home mytestnet/node0/simd 14 | ``` -------------------------------------------------------------------------------- /buf.work.yaml: -------------------------------------------------------------------------------- 1 | # Generated by "buf config migrate-v1beta1". Edit as necessary, and 2 | # remove this comment when you're finished. 3 | # 4 | # This workspace file points to the roots found in your 5 | # previous "buf.yaml" configuration. 6 | version: v1 7 | directories: 8 | - proto -------------------------------------------------------------------------------- /modules/tibc/apps/mt_transfer/client/cli/cli.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/cosmos/cosmos-sdk/client" 7 | ) 8 | 9 | // NewTxCmd returns the transaction commands for TIBC multi token transfer 10 | func NewTxCmd() *cobra.Command { 11 | txCmd := &cobra.Command{ 12 | Use: "tibc-mt-transfer", 13 | Short: "TIBC multi token transfer transaction subcommands", 14 | DisableFlagParsing: true, 15 | SuggestionsMinimumDistance: 2, 16 | RunE: client.ValidateCmd, 17 | } 18 | 19 | txCmd.AddCommand( 20 | NewTransferTxCmd(), 21 | ) 22 | 23 | return txCmd 24 | } 25 | 26 | // GetQueryCmd returns the query commands for TIBC multi token transfer 27 | func GetQueryCmd() *cobra.Command { 28 | queryCmd := &cobra.Command{ 29 | Use: "tibc-mt-transfer", 30 | Short: "TIBC multi token transfer query subcommands", 31 | DisableFlagParsing: true, 32 | SuggestionsMinimumDistance: 2, 33 | } 34 | 35 | queryCmd.AddCommand( 36 | GetCmdQueryClassTrace(), 37 | GetCmdQueryClassTraces(), 38 | ) 39 | 40 | return queryCmd 41 | } 42 | -------------------------------------------------------------------------------- /modules/tibc/apps/mt_transfer/client/cli/flags.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | flag "github.com/spf13/pflag" 5 | ) 6 | 7 | const ( 8 | FlagRelayChain = "relay-chain" 9 | FlagDestContract = "dest-contract" 10 | ) 11 | 12 | var ( 13 | FsMtTransfer = flag.NewFlagSet("", flag.ContinueOnError) 14 | ) 15 | 16 | func init() { 17 | FsMtTransfer.String(FlagRelayChain, "", "relay chain used by cross-chain mt") 18 | FsMtTransfer.String(FlagDestContract, "", "the destination contract address to receive the mt") 19 | } 20 | -------------------------------------------------------------------------------- /modules/tibc/apps/mt_transfer/client/cli/query.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/cosmos/cosmos-sdk/client" 7 | "github.com/cosmos/cosmos-sdk/client/flags" 8 | "github.com/cosmos/cosmos-sdk/version" 9 | "github.com/spf13/cobra" 10 | 11 | "github.com/bianjieai/tibc-go/modules/tibc/apps/nft_transfer/types" 12 | ) 13 | 14 | // GetCmdQueryClassTrace defines the command to query a class trace from a given hash. 15 | func GetCmdQueryClassTrace() *cobra.Command { 16 | cmd := &cobra.Command{ 17 | Use: "class-trace [hash]", 18 | Short: "Query the class trace info from a given trace hash", 19 | Long: "Query the class trace info from a given trace hash", 20 | Example: fmt.Sprintf("%s query tibc-mt-transfer class-trace [hash]", version.AppName), 21 | Args: cobra.ExactArgs(1), 22 | RunE: func(cmd *cobra.Command, args []string) error { 23 | clientCtx, err := client.GetClientQueryContext(cmd) 24 | if err != nil { 25 | return err 26 | } 27 | queryClient := types.NewQueryClient(clientCtx) 28 | 29 | req := &types.QueryClassTraceRequest{ 30 | Hash: args[0], 31 | } 32 | 33 | res, err := queryClient.ClassTrace(cmd.Context(), req) 34 | if err != nil { 35 | return err 36 | } 37 | 38 | return clientCtx.PrintProto(res) 39 | }, 40 | } 41 | 42 | flags.AddQueryFlagsToCmd(cmd) 43 | return cmd 44 | } 45 | 46 | // GetCmdQueryClassTraces defines the command to query all the class trace infos 47 | // that this chain mantains. 48 | func GetCmdQueryClassTraces() *cobra.Command { 49 | cmd := &cobra.Command{ 50 | Use: "class-traces", 51 | Short: "Query the trace info for all mt classes", 52 | Long: "Query the trace info for all mt classes", 53 | Example: fmt.Sprintf("%s query tibc-mt-transfer class-traces", version.AppName), 54 | Args: cobra.NoArgs, 55 | RunE: func(cmd *cobra.Command, _ []string) error { 56 | clientCtx, err := client.GetClientQueryContext(cmd) 57 | if err != nil { 58 | return err 59 | } 60 | queryClient := types.NewQueryClient(clientCtx) 61 | 62 | pageReq, err := client.ReadPageRequest(cmd.Flags()) 63 | if err != nil { 64 | return err 65 | } 66 | 67 | req := &types.QueryClassTracesRequest{ 68 | Pagination: pageReq, 69 | } 70 | 71 | res, err := queryClient.ClassTraces(cmd.Context(), req) 72 | if err != nil { 73 | return err 74 | } 75 | 76 | return clientCtx.PrintProto(res) 77 | }, 78 | } 79 | flags.AddQueryFlagsToCmd(cmd) 80 | flags.AddPaginationFlagsToCmd(cmd, "class trace") 81 | 82 | return cmd 83 | } 84 | -------------------------------------------------------------------------------- /modules/tibc/apps/mt_transfer/client/cli/tx.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | 7 | "github.com/spf13/cobra" 8 | 9 | "github.com/cosmos/cosmos-sdk/client" 10 | "github.com/cosmos/cosmos-sdk/client/flags" 11 | "github.com/cosmos/cosmos-sdk/client/tx" 12 | "github.com/cosmos/cosmos-sdk/version" 13 | 14 | "github.com/bianjieai/tibc-go/modules/tibc/apps/mt_transfer/types" 15 | ) 16 | 17 | // NewTransferTxCmd returns the command to create a NewMsgTransfer transaction 18 | func NewTransferTxCmd() *cobra.Command { 19 | cmd := &cobra.Command{ 20 | Use: "transfer [dest-chain] [receiver] [class] [id] [amount]", 21 | Short: "Transfer a mt through TIBC", 22 | Example: fmt.Sprintf( 23 | "%s tx tibc-mt-transfer transfer "+ 24 | "--relay-chain= "+ 25 | "--dest-contract=", 26 | version.AppName, 27 | ), 28 | Args: cobra.ExactArgs(5), 29 | RunE: func(cmd *cobra.Command, args []string) error { 30 | clientCtx, err := client.GetClientTxContext(cmd) 31 | if err != nil { 32 | return err 33 | } 34 | sender := clientCtx.GetFromAddress().String() 35 | destChain := args[0] 36 | receiver := args[1] 37 | class := args[2] 38 | id := args[3] 39 | amount := args[4] 40 | 41 | relayChain, err := cmd.Flags().GetString(FlagRelayChain) 42 | if err != nil { 43 | return err 44 | } 45 | 46 | destContract, err := cmd.Flags().GetString(FlagDestContract) 47 | if err != nil { 48 | return err 49 | } 50 | 51 | amt, err := strconv.ParseUint(amount, 10, 64) 52 | if err != nil { 53 | return err 54 | } 55 | 56 | msg := types.NewMsgMtTransfer( 57 | class, id, sender, receiver, 58 | destChain, relayChain, destContract, amt, 59 | ) 60 | if err := msg.ValidateBasic(); err != nil { 61 | return err 62 | } 63 | return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) 64 | }, 65 | } 66 | 67 | cmd.Flags().AddFlagSet(FsMtTransfer) 68 | flags.AddTxFlagsToCmd(cmd) 69 | 70 | return cmd 71 | } 72 | -------------------------------------------------------------------------------- /modules/tibc/apps/mt_transfer/depinject.go: -------------------------------------------------------------------------------- 1 | package mttransfer 2 | 3 | import ( 4 | "cosmossdk.io/core/appmodule" 5 | "cosmossdk.io/depinject" 6 | store "cosmossdk.io/store/types" 7 | "github.com/cosmos/cosmos-sdk/codec" 8 | 9 | modulev1 "github.com/bianjieai/tibc-go/api/tibc/apps/mt_transfer/module/v1" 10 | "github.com/bianjieai/tibc-go/modules/tibc/apps/mt_transfer/keeper" 11 | "github.com/bianjieai/tibc-go/modules/tibc/apps/mt_transfer/types" 12 | routingtypes "github.com/bianjieai/tibc-go/modules/tibc/core/26-routing/types" 13 | ) 14 | 15 | // App Wiring Setup 16 | 17 | func init() { 18 | appmodule.Register(&modulev1.Module{}, 19 | appmodule.Provide(ProvideModule), 20 | ) 21 | } 22 | 23 | var _ appmodule.AppModule = AppModule{} 24 | 25 | // IsOnePerModuleType implements the depinject.OnePerModuleType interface. 26 | func (am AppModule) IsOnePerModuleType() {} 27 | 28 | // IsAppModule implements the appmodule.AppModule interface. 29 | func (am AppModule) IsAppModule() {} 30 | 31 | // Inputs define the module inputs for the depinject. 32 | type Inputs struct { 33 | depinject.In 34 | 35 | Config *modulev1.Module 36 | Cdc codec.Codec 37 | Key *store.KVStoreKey 38 | 39 | AccountKeeper types.AccountKeeper 40 | MtKeeper types.MtKeeper 41 | PacketKeeper types.PacketKeeper 42 | ClientKeeper types.ClientKeeper 43 | } 44 | 45 | // Outputs define the module outputs for the depinject. 46 | type Outputs struct { 47 | depinject.Out 48 | 49 | MtTransferKeeper keeper.Keeper 50 | Route routingtypes.Route 51 | Module appmodule.AppModule 52 | } 53 | 54 | // ProvideModule creates and returns the farm module with the specified inputs. 55 | // 56 | // It takes Inputs as the parameter, which includes the configuration, codec, key, account keeper, bank keeper, governance keeper, coinswap keeper, and legacy subspace. 57 | // It returns Outputs containing the farm keeper and the app module. 58 | func ProvideModule(in Inputs) Outputs { 59 | keeper := keeper.NewKeeper( 60 | in.Cdc, 61 | in.Key, 62 | in.AccountKeeper, 63 | in.MtKeeper, 64 | in.PacketKeeper, 65 | in.ClientKeeper, 66 | ) 67 | m := NewAppModule(keeper) 68 | route := routingtypes.Route{ 69 | Port: string(routingtypes.MT), 70 | Module: m, 71 | } 72 | return Outputs{ 73 | MtTransferKeeper: keeper, 74 | Route: route, 75 | Module: m, 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /modules/tibc/apps/mt_transfer/keeper/encoding.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "github.com/bianjieai/tibc-go/modules/tibc/apps/mt_transfer/types" 5 | ) 6 | 7 | // MustMarshalClassTrace attempts to encode an ClassTrace object and returns the 8 | // raw encoded bytes. It panics on error. 9 | func (k Keeper) MustMarshalClassTrace(classTrace types.ClassTrace) []byte { 10 | return k.cdc.MustMarshal(&classTrace) 11 | } 12 | 13 | // UnmarshalClassTrace attempts to decode and return an ClassTrace object from 14 | // raw encoded bytes. 15 | func (k Keeper) UnmarshalClassTrace(bz []byte) (types.ClassTrace, error) { 16 | var classTrace types.ClassTrace 17 | if err := k.cdc.Unmarshal(bz, &classTrace); err != nil { 18 | return types.ClassTrace{}, err 19 | } 20 | 21 | return classTrace, nil 22 | } 23 | -------------------------------------------------------------------------------- /modules/tibc/apps/mt_transfer/keeper/grpc_query.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | errorsmod "cosmossdk.io/errors" 8 | "cosmossdk.io/store/prefix" 9 | sdk "github.com/cosmos/cosmos-sdk/types" 10 | "github.com/cosmos/cosmos-sdk/types/query" 11 | "google.golang.org/grpc/codes" 12 | "google.golang.org/grpc/status" 13 | 14 | "github.com/bianjieai/tibc-go/modules/tibc/apps/mt_transfer/types" 15 | ) 16 | 17 | var _ types.QueryServer = Keeper{} 18 | 19 | // ClassTrace implements the Query/ClassTrace gRPC method 20 | func (q Keeper) ClassTrace(c context.Context, req *types.QueryClassTraceRequest) (*types.QueryClassTraceResponse, error) { 21 | if req == nil { 22 | return nil, status.Error(codes.InvalidArgument, "empty request") 23 | } 24 | 25 | hash, err := types.ParseHexHash(req.Hash) 26 | if err != nil { 27 | return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("invalid class trace hash %s, %s", req.Hash, err)) 28 | } 29 | 30 | ctx := sdk.UnwrapSDKContext(c) 31 | classTrace, found := q.GetClassTrace(ctx, hash) 32 | if !found { 33 | return nil, status.Error( 34 | codes.NotFound, 35 | errorsmod.Wrap(types.ErrTraceNotFound, req.Hash).Error(), 36 | ) 37 | } 38 | 39 | return &types.QueryClassTraceResponse{ 40 | ClassTrace: &classTrace, 41 | }, nil 42 | } 43 | 44 | // ClassTraces implements the Query/ClassTraces gRPC method 45 | func (q Keeper) ClassTraces(c context.Context, req *types.QueryClassTracesRequest) (*types.QueryClassTracesResponse, error) { 46 | if req == nil { 47 | return nil, status.Error(codes.InvalidArgument, "empty request") 48 | } 49 | 50 | ctx := sdk.UnwrapSDKContext(c) 51 | 52 | traces := types.Traces{} 53 | store := prefix.NewStore(ctx.KVStore(q.storeKey), types.ClassTraceKey) 54 | 55 | pageRes, err := query.Paginate(store, req.Pagination, func(_, value []byte) error { 56 | result, err := q.UnmarshalClassTrace(value) 57 | if err != nil { 58 | return err 59 | } 60 | 61 | traces = append(traces, result) 62 | return nil 63 | }) 64 | 65 | if err != nil { 66 | return nil, err 67 | } 68 | 69 | return &types.QueryClassTracesResponse{ 70 | ClassTraces: traces.Sort(), 71 | Pagination: pageRes, 72 | }, nil 73 | } 74 | -------------------------------------------------------------------------------- /modules/tibc/apps/mt_transfer/keeper/keeper_test.go: -------------------------------------------------------------------------------- 1 | package keeper_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/cosmos/cosmos-sdk/baseapp" 7 | 8 | "github.com/stretchr/testify/suite" 9 | 10 | "github.com/cometbft/cometbft/crypto" 11 | 12 | sdk "github.com/cosmos/cosmos-sdk/types" 13 | 14 | "github.com/bianjieai/tibc-go/modules/tibc/apps/mt_transfer/types" 15 | tibctesting "github.com/bianjieai/tibc-go/modules/tibc/testing" 16 | ) 17 | 18 | type KeeperTestSuite struct { 19 | suite.Suite 20 | 21 | coordinator *tibctesting.Coordinator 22 | 23 | // testing chains used for convenience and readability 24 | chainA *tibctesting.TestChain 25 | chainB *tibctesting.TestChain 26 | chainC *tibctesting.TestChain 27 | queryClient types.QueryClient 28 | } 29 | 30 | func (suite *KeeperTestSuite) SetupTest() { 31 | suite.coordinator = tibctesting.NewCoordinator(suite.T(), 3) 32 | suite.chainA = suite.coordinator.GetChain(tibctesting.GetChainID(0)) 33 | suite.chainB = suite.coordinator.GetChain(tibctesting.GetChainID(1)) 34 | suite.chainC = suite.coordinator.GetChain(tibctesting.GetChainID(2)) 35 | 36 | queryHelper := baseapp.NewQueryServerTestHelper( 37 | suite.chainA.GetContext(), 38 | suite.chainA.App.InterfaceRegistry(), 39 | ) 40 | types.RegisterQueryServer(queryHelper, suite.chainA.App.MtTransferKeeper) 41 | suite.queryClient = types.NewQueryClient(queryHelper) 42 | } 43 | 44 | func (suite *KeeperTestSuite) TestGetTransferMoudleAddr() { 45 | expectedMaccAddr := sdk.AccAddress(crypto.AddressHash([]byte(types.ModuleName))) 46 | 47 | macc := suite.chainA.App.NftTransferKeeper.GetNftTransferModuleAddr(types.ModuleName) 48 | 49 | suite.Require().NotNil(macc) 50 | suite.Require().Equal(expectedMaccAddr, macc) 51 | } 52 | 53 | func NewTransferPath(scChain, destChain *tibctesting.TestChain) *tibctesting.Path { 54 | path := tibctesting.NewPath(scChain, destChain) 55 | return path 56 | } 57 | 58 | func TestKeeperTestSuite(t *testing.T) { 59 | suite.Run(t, new(KeeperTestSuite)) 60 | } 61 | -------------------------------------------------------------------------------- /modules/tibc/apps/mt_transfer/keeper/msg_server.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "context" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | 8 | "github.com/bianjieai/tibc-go/modules/tibc/apps/mt_transfer/types" 9 | ) 10 | 11 | var _ types.MsgServer = Keeper{} 12 | 13 | func (k Keeper) MtTransfer(goCtx context.Context, msg *types.MsgMtTransfer) (*types.MsgMtTransferResponse, error) { 14 | ctx := sdk.UnwrapSDKContext(goCtx) 15 | 16 | sender, err := sdk.AccAddressFromBech32(msg.Sender) 17 | if err != nil { 18 | return nil, err 19 | } 20 | 21 | if err := k.SendMtTransfer( 22 | ctx, msg.Class, msg.Id, 23 | sender, msg.Receiver, 24 | msg.DestChain, msg.RealayChain, msg.DestContract, 25 | msg.Amount, 26 | ); err != nil { 27 | return nil, err 28 | } 29 | 30 | k.Logger(ctx).Info("TIBC multi token transfer", "mt", msg.Id, "sender", msg.Sender, "receiver", msg.Receiver) 31 | 32 | ctx.EventManager().EmitEvents(sdk.Events{ 33 | sdk.NewEvent( 34 | types.EventTypeMtTransfer, 35 | sdk.NewAttribute(sdk.AttributeKeySender, msg.Sender), 36 | sdk.NewAttribute(types.AttributeKeyReceiver, msg.Receiver), 37 | ), 38 | sdk.NewEvent( 39 | sdk.EventTypeMessage, 40 | sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), 41 | ), 42 | }) 43 | 44 | return &types.MsgMtTransferResponse{}, nil 45 | } 46 | -------------------------------------------------------------------------------- /modules/tibc/apps/mt_transfer/types/codec.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/codec" 5 | codectypes "github.com/cosmos/cosmos-sdk/codec/types" 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | "github.com/cosmos/cosmos-sdk/types/msgservice" 8 | ) 9 | 10 | var ( 11 | amino = codec.NewLegacyAmino() 12 | ModuleCdc = codec.NewProtoCodec(codectypes.NewInterfaceRegistry()) 13 | // AminoCdc is a amino codec created to support amino json compatible msgs. 14 | AminoCdc = codec.NewAminoCodec(amino) 15 | ) 16 | 17 | func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { 18 | cdc.RegisterConcrete(&MsgMtTransfer{}, "cosmos-sdk/MsgMtTransfer", nil) 19 | } 20 | 21 | // RegisterInterfaces register the tibc-transfer module interfaces to protobuf 22 | // Any. 23 | func RegisterInterfaces(registry codectypes.InterfaceRegistry) { 24 | registry.RegisterImplementations((*sdk.Msg)(nil), &MsgMtTransfer{}) 25 | 26 | msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) 27 | } 28 | 29 | func init() { 30 | RegisterLegacyAminoCodec(amino) 31 | amino.Seal() 32 | } 33 | -------------------------------------------------------------------------------- /modules/tibc/apps/mt_transfer/types/errors.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | errorsmod "cosmossdk.io/errors" 5 | ) 6 | 7 | var ( 8 | ErrInvalidDenom = errorsmod.Register(ModuleName, 2, "invalid denom") 9 | ErrUnknownNFT = errorsmod.Register(ModuleName, 3, "unknown mt") 10 | ErrScChainEqualToDestChain = errorsmod.Register(ModuleName, 4, "source chain equals to destination chain") 11 | ErrTraceNotFound = errorsmod.Register(ModuleName, 5, "class trace not found") 12 | ErrInvalidAmount = errorsmod.Register(ModuleName, 6, "the amount must be greater than 0") 13 | ) 14 | -------------------------------------------------------------------------------- /modules/tibc/apps/mt_transfer/types/events.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // TIBC transfer events 4 | const ( 5 | EventTypePacket = "multi_token_packet" 6 | EventTypeMtTransfer = "tibc_mt_transfer" 7 | EventTypeClassTrace = "class_trace" 8 | 9 | AttributeKeyClass = "class" 10 | AttributeKeyId = "id" 11 | AttributeKeyData = "data" 12 | AttributeKeyAmount = "amount" 13 | AttributeKeyReceiver = "receiver" 14 | AttributeKeyAck = "ack" 15 | AttributeKeyAckSuccess = "success" 16 | AttributeKeyAckError = "error" 17 | AttributeKeyTraceHash = "trace_hash" 18 | ) 19 | -------------------------------------------------------------------------------- /modules/tibc/apps/mt_transfer/types/expected_keepers.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | 6 | mtexported "mods.irisnet.org/modules/mt/exported" 7 | "mods.irisnet.org/modules/mt/types" 8 | 9 | "github.com/bianjieai/tibc-go/modules/tibc/core/exported" 10 | ) 11 | 12 | // MtKeeper defines the expected mt keeper 13 | type MtKeeper interface { 14 | IssueDenom(ctx sdk.Context, 15 | id, name string, sender sdk.AccAddress, data []byte, 16 | ) types.Denom 17 | 18 | IssueMT(ctx sdk.Context, 19 | denomID string, mtID string, 20 | amount uint64, 21 | data []byte, 22 | recipient sdk.AccAddress, 23 | ) (types.MT, error) 24 | 25 | MintMT(ctx sdk.Context, 26 | denomID, mtID string, 27 | amount uint64, 28 | recipient sdk.AccAddress, 29 | ) error 30 | 31 | TransferOwner(ctx sdk.Context, 32 | denomID, mtID string, 33 | amount uint64, 34 | srcOwner, dstOwner sdk.AccAddress, 35 | ) error 36 | 37 | BurnMT(ctx sdk.Context, 38 | denomID, mtID string, 39 | amount uint64, 40 | owner sdk.AccAddress) error 41 | 42 | HasMT(ctx sdk.Context, denomID, mtID string) bool 43 | GetMT(ctx sdk.Context, denomID, mtID string) (mt mtexported.MT, err error) 44 | GetDenom(ctx sdk.Context, id string) (denom types.Denom, found bool) 45 | } 46 | 47 | // AccountKeeper defines the expected account keeper 48 | type AccountKeeper interface { 49 | GetModuleAddress(name string) sdk.AccAddress 50 | } 51 | 52 | // PacketKeeper defines the expected packet keeper 53 | type PacketKeeper interface { 54 | GetNextSequenceSend(ctx sdk.Context, sourceChain, destChain string) uint64 55 | SendPacket(ctx sdk.Context, packet exported.PacketI) error 56 | } 57 | 58 | // ClientKeeper defines the expected client keeper 59 | type ClientKeeper interface { 60 | GetChainName(ctx sdk.Context) string 61 | } 62 | -------------------------------------------------------------------------------- /modules/tibc/apps/mt_transfer/types/keys.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | const ( 4 | // ModuleName defines the TIBC mt_transfer name 5 | ModuleName = "MT" 6 | 7 | // RouterKey is the message route for the mt-transfer module 8 | RouterKey = ModuleName 9 | 10 | // PortID is the default port id that mt-transfer module binds to 11 | PortID = ModuleName 12 | 13 | // StoreKey is the store key string for TIBC mt-transfer 14 | StoreKey = ModuleName 15 | 16 | // QuerierRoute is the querier route for TIBC mt-transfer 17 | QuerierRoute = ModuleName 18 | 19 | // ClassPrefix is the prefix used for mt class. 20 | ClassPrefix = "tibc" 21 | ) 22 | 23 | var ( 24 | // ClassTraceKey defines the key to store the class trace info in store 25 | ClassTraceKey = []byte{0x01} 26 | ) 27 | -------------------------------------------------------------------------------- /modules/tibc/apps/mt_transfer/types/msgs.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | ) 6 | 7 | const ( 8 | TypeMsgMtTransfer = "tibc_mt_transfer" 9 | ) 10 | 11 | var _ sdk.Msg = &MsgMtTransfer{} 12 | 13 | // NewMsgMtTransfer creates a new NewMsgMtTransfer instance 14 | func NewMsgMtTransfer(class, id, sender, receiver, destChain, realayChain, destContract string, amount uint64) *MsgMtTransfer { 15 | return &MsgMtTransfer{ 16 | Class: class, 17 | Id: id, 18 | Sender: sender, 19 | Receiver: receiver, 20 | DestChain: destChain, 21 | RealayChain: realayChain, 22 | DestContract: destContract, 23 | Amount: amount, 24 | } 25 | } 26 | 27 | // GetSigners implements sdk.Msg 28 | func (msg MsgMtTransfer) GetSigners() []sdk.AccAddress { 29 | signer, err := sdk.AccAddressFromBech32(msg.Sender) 30 | if err != nil { 31 | panic(err) 32 | } 33 | return []sdk.AccAddress{signer} 34 | } 35 | 36 | // ValidateBasic Implements Msg. 37 | func (msg MsgMtTransfer) ValidateBasic() error { 38 | return nil 39 | } 40 | -------------------------------------------------------------------------------- /modules/tibc/apps/mt_transfer/types/packet.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "strings" 5 | 6 | errorsmod "cosmossdk.io/errors" 7 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 8 | ) 9 | 10 | // NewMultiTokenPacketData contructs a new MultiTokenPacketData instance 11 | func NewMultiTokenPacketData( 12 | class, id, sender, receiver string, 13 | awayFromOrigin bool, destContract string, 14 | amount uint64, data []byte, 15 | ) MultiTokenPacketData { 16 | return MultiTokenPacketData{ 17 | Class: class, 18 | Id: id, 19 | Data: data, 20 | Sender: sender, 21 | Receiver: receiver, 22 | AwayFromOrigin: awayFromOrigin, 23 | DestContract: destContract, 24 | Amount: amount, 25 | } 26 | } 27 | 28 | // ValidateBasic is used for validating the mt transfer. 29 | // NOTE: The addresses formats are not validated as the sender and recipient can have different 30 | // formats defined by their corresponding chains that are not known to TIBC. 31 | func (mtpd MultiTokenPacketData) ValidateBasic() error { 32 | if strings.TrimSpace(mtpd.Sender) == "" { 33 | return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "sender address cannot be blank") 34 | } 35 | if strings.TrimSpace(mtpd.Receiver) == "" { 36 | return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "receiver address cannot be blank") 37 | } 38 | if mtpd.Amount <= 0 { 39 | return ErrInvalidAmount 40 | } 41 | return nil 42 | } 43 | 44 | // GetBytes is a helper for serialising 45 | func (mtpd MultiTokenPacketData) GetBytes() []byte { 46 | return ModuleCdc.MustMarshal(&mtpd) 47 | } 48 | -------------------------------------------------------------------------------- /modules/tibc/apps/nft_transfer/client/cli/cli.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/cosmos/cosmos-sdk/client" 7 | ) 8 | 9 | // NewTxCmd returns the transaction commands for TIBC non-fungible token transfer 10 | func NewTxCmd() *cobra.Command { 11 | txCmd := &cobra.Command{ 12 | Use: "tibc-nft-transfer", 13 | Short: "TIBC non-fungible token transfer transaction subcommands", 14 | DisableFlagParsing: true, 15 | SuggestionsMinimumDistance: 2, 16 | RunE: client.ValidateCmd, 17 | } 18 | 19 | txCmd.AddCommand( 20 | NewTransferTxCmd(), 21 | ) 22 | 23 | return txCmd 24 | } 25 | 26 | // GetQueryCmd returns the query commands for TIBC connections 27 | func GetQueryCmd() *cobra.Command { 28 | queryCmd := &cobra.Command{ 29 | Use: "tibc-nft-transfer", 30 | Short: "TIBC non fungible token transfer query subcommands", 31 | DisableFlagParsing: true, 32 | SuggestionsMinimumDistance: 2, 33 | } 34 | 35 | queryCmd.AddCommand( 36 | GetCmdQueryClassTrace(), 37 | GetCmdQueryClassTraces(), 38 | ) 39 | 40 | return queryCmd 41 | } 42 | -------------------------------------------------------------------------------- /modules/tibc/apps/nft_transfer/client/cli/flags.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | flag "github.com/spf13/pflag" 5 | ) 6 | 7 | const ( 8 | FlagRelayChain = "relay-chain" 9 | FlagDestContract = "dest-contract" 10 | ) 11 | 12 | var ( 13 | FsNftTransfer = flag.NewFlagSet("", flag.ContinueOnError) 14 | ) 15 | 16 | func init() { 17 | FsNftTransfer.String(FlagRelayChain, "", "relay chain used by cross-chain NFT") 18 | FsNftTransfer.String(FlagDestContract, "", "the destination contract address to receive the nft") 19 | } 20 | -------------------------------------------------------------------------------- /modules/tibc/apps/nft_transfer/client/cli/tx.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/spf13/cobra" 7 | 8 | "github.com/cosmos/cosmos-sdk/client" 9 | "github.com/cosmos/cosmos-sdk/client/flags" 10 | "github.com/cosmos/cosmos-sdk/client/tx" 11 | "github.com/cosmos/cosmos-sdk/version" 12 | 13 | "github.com/bianjieai/tibc-go/modules/tibc/apps/nft_transfer/types" 14 | ) 15 | 16 | // NewTransferTxCmd returns the command to create a NewMsgTransfer transaction 17 | func NewTransferTxCmd() *cobra.Command { 18 | cmd := &cobra.Command{ 19 | Use: "transfer [dest-chain] [receiver] [class] [id]", 20 | Short: "Transfer a non fungible token through TIBC", 21 | Example: fmt.Sprintf( 22 | "%s tx tibc-nft-transfer transfer "+ 23 | "--relay-chain= "+ 24 | "--dest-contract=", 25 | version.AppName, 26 | ), 27 | Args: cobra.ExactArgs(4), 28 | RunE: func(cmd *cobra.Command, args []string) error { 29 | clientCtx, err := client.GetClientTxContext(cmd) 30 | if err != nil { 31 | return err 32 | } 33 | sender := clientCtx.GetFromAddress().String() 34 | destChain := args[0] 35 | receiver := args[1] 36 | class := args[2] 37 | id := args[3] 38 | 39 | relayChain, err := cmd.Flags().GetString(FlagRelayChain) 40 | if err != nil { 41 | return err 42 | } 43 | 44 | destContract, err := cmd.Flags().GetString(FlagDestContract) 45 | if err != nil { 46 | return err 47 | } 48 | 49 | msg := types.NewMsgNftTransfer( 50 | class, id, sender, receiver, 51 | destChain, relayChain, destContract, 52 | ) 53 | if err := msg.ValidateBasic(); err != nil { 54 | return err 55 | } 56 | return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) 57 | }, 58 | } 59 | 60 | cmd.Flags().AddFlagSet(FsNftTransfer) 61 | flags.AddTxFlagsToCmd(cmd) 62 | 63 | return cmd 64 | } 65 | -------------------------------------------------------------------------------- /modules/tibc/apps/nft_transfer/depinject.go: -------------------------------------------------------------------------------- 1 | package nfttransfer 2 | 3 | import ( 4 | "cosmossdk.io/core/appmodule" 5 | "cosmossdk.io/depinject" 6 | store "cosmossdk.io/store/types" 7 | "github.com/cosmos/cosmos-sdk/codec" 8 | 9 | modulev1 "github.com/bianjieai/tibc-go/api/tibc/apps/nft_transfer/module/v1" 10 | "github.com/bianjieai/tibc-go/modules/tibc/apps/nft_transfer/keeper" 11 | "github.com/bianjieai/tibc-go/modules/tibc/apps/nft_transfer/types" 12 | routingtypes "github.com/bianjieai/tibc-go/modules/tibc/core/26-routing/types" 13 | ) 14 | 15 | // App Wiring Setup 16 | 17 | func init() { 18 | appmodule.Register(&modulev1.Module{}, 19 | appmodule.Provide(ProvideModule), 20 | ) 21 | } 22 | 23 | var _ appmodule.AppModule = AppModule{} 24 | 25 | // IsOnePerModuleType implements the depinject.OnePerModuleType interface. 26 | func (am AppModule) IsOnePerModuleType() {} 27 | 28 | // IsAppModule implements the appmodule.AppModule interface. 29 | func (am AppModule) IsAppModule() {} 30 | 31 | // Inputs define the module inputs for the depinject. 32 | type Inputs struct { 33 | depinject.In 34 | 35 | Config *modulev1.Module 36 | Cdc codec.Codec 37 | Key *store.KVStoreKey 38 | 39 | AccountKeeper types.AccountKeeper 40 | NftKeeper types.NftKeeper 41 | PacketKeeper types.PacketKeeper 42 | ClientKeeper types.ClientKeeper 43 | } 44 | 45 | // Outputs define the module outputs for the depinject. 46 | type Outputs struct { 47 | depinject.Out 48 | 49 | NftTransferKeeper keeper.Keeper 50 | Route routingtypes.Route 51 | Module appmodule.AppModule 52 | } 53 | 54 | // ProvideModule creates and returns the module outputs for the depinject. 55 | // 56 | // It takes Inputs as the parameter, which includes the configuration, codec, key, account keeper, NFT keeper, packet keeper, and client keeper. 57 | // It returns Outputs containing the NFT transfer keeper and the app module. 58 | func ProvideModule(in Inputs) Outputs { 59 | keeper := keeper.NewKeeper( 60 | in.Cdc, 61 | in.Key, 62 | in.AccountKeeper, 63 | in.NftKeeper, 64 | in.PacketKeeper, 65 | in.ClientKeeper, 66 | ) 67 | m := NewAppModule(keeper) 68 | route := routingtypes.Route{ 69 | Port: string(routingtypes.NFT), 70 | Module: m, 71 | } 72 | return Outputs{ 73 | NftTransferKeeper: keeper, 74 | Route: route, 75 | Module: m, 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /modules/tibc/apps/nft_transfer/keeper/encoding.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import "github.com/bianjieai/tibc-go/modules/tibc/apps/nft_transfer/types" 4 | 5 | // MustMarshalClassTrace attempts to encode an ClassTrace object and returns the 6 | // raw encoded bytes. It panics on error. 7 | func (k Keeper) MustMarshalClassTrace(classTrace types.ClassTrace) []byte { 8 | return k.cdc.MustMarshal(&classTrace) 9 | } 10 | 11 | // UnmarshalClassTrace attempts to decode and return an ClassTrace object from 12 | // raw encoded bytes. 13 | func (k Keeper) UnmarshalClassTrace(bz []byte) (types.ClassTrace, error) { 14 | var classTrace types.ClassTrace 15 | if err := k.cdc.Unmarshal(bz, &classTrace); err != nil { 16 | return types.ClassTrace{}, err 17 | } 18 | 19 | return classTrace, nil 20 | } 21 | -------------------------------------------------------------------------------- /modules/tibc/apps/nft_transfer/keeper/grpc_query.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | errorsmod "cosmossdk.io/errors" 8 | "cosmossdk.io/store/prefix" 9 | sdk "github.com/cosmos/cosmos-sdk/types" 10 | "github.com/cosmos/cosmos-sdk/types/query" 11 | "google.golang.org/grpc/codes" 12 | "google.golang.org/grpc/status" 13 | 14 | "github.com/bianjieai/tibc-go/modules/tibc/apps/nft_transfer/types" 15 | ) 16 | 17 | var _ types.QueryServer = Keeper{} 18 | 19 | // ClassTrace implements the Query/ClassTrace gRPC method 20 | func (q Keeper) ClassTrace(c context.Context, req *types.QueryClassTraceRequest) (*types.QueryClassTraceResponse, error) { 21 | if req == nil { 22 | return nil, status.Error(codes.InvalidArgument, "empty request") 23 | } 24 | 25 | hash, err := types.ParseHexHash(req.Hash) 26 | if err != nil { 27 | return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("invalid class trace hash %s, %s", req.Hash, err)) 28 | } 29 | 30 | ctx := sdk.UnwrapSDKContext(c) 31 | classTrace, found := q.GetClassTrace(ctx, hash) 32 | if !found { 33 | return nil, status.Error( 34 | codes.NotFound, 35 | errorsmod.Wrap(types.ErrTraceNotFound, req.Hash).Error(), 36 | ) 37 | } 38 | 39 | return &types.QueryClassTraceResponse{ 40 | ClassTrace: &classTrace, 41 | }, nil 42 | } 43 | 44 | // ClassTraces implements the Query/ClassTraces gRPC method 45 | func (q Keeper) ClassTraces(c context.Context, req *types.QueryClassTracesRequest) (*types.QueryClassTracesResponse, error) { 46 | if req == nil { 47 | return nil, status.Error(codes.InvalidArgument, "empty request") 48 | } 49 | 50 | ctx := sdk.UnwrapSDKContext(c) 51 | 52 | traces := types.Traces{} 53 | store := prefix.NewStore(ctx.KVStore(q.storeKey), types.ClassTraceKey) 54 | 55 | pageRes, err := query.Paginate(store, req.Pagination, func(_, value []byte) error { 56 | result, err := q.UnmarshalClassTrace(value) 57 | if err != nil { 58 | return err 59 | } 60 | 61 | traces = append(traces, result) 62 | return nil 63 | }) 64 | 65 | if err != nil { 66 | return nil, err 67 | } 68 | 69 | return &types.QueryClassTracesResponse{ 70 | ClassTraces: traces.Sort(), 71 | Pagination: pageRes, 72 | }, nil 73 | } 74 | -------------------------------------------------------------------------------- /modules/tibc/apps/nft_transfer/keeper/keeper_test.go: -------------------------------------------------------------------------------- 1 | package keeper_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/cosmos/cosmos-sdk/baseapp" 7 | 8 | "github.com/stretchr/testify/suite" 9 | 10 | "github.com/cometbft/cometbft/crypto" 11 | 12 | sdk "github.com/cosmos/cosmos-sdk/types" 13 | 14 | "github.com/bianjieai/tibc-go/modules/tibc/apps/nft_transfer/types" 15 | tibctesting "github.com/bianjieai/tibc-go/modules/tibc/testing" 16 | ) 17 | 18 | type KeeperTestSuite struct { 19 | suite.Suite 20 | ctx sdk.Context 21 | 22 | coordinator *tibctesting.Coordinator 23 | 24 | // testing chains used for convenience and readability 25 | chainA *tibctesting.TestChain 26 | chainB *tibctesting.TestChain 27 | chainC *tibctesting.TestChain 28 | queryClient types.QueryClient 29 | } 30 | 31 | func (suite *KeeperTestSuite) SetupTest() { 32 | suite.coordinator = tibctesting.NewCoordinator(suite.T(), 3) 33 | suite.chainA = suite.coordinator.GetChain(tibctesting.GetChainID(0)) 34 | suite.chainB = suite.coordinator.GetChain(tibctesting.GetChainID(1)) 35 | suite.chainC = suite.coordinator.GetChain(tibctesting.GetChainID(2)) 36 | 37 | queryHelper := baseapp.NewQueryServerTestHelper( 38 | suite.chainA.GetContext(), 39 | suite.chainA.App.InterfaceRegistry(), 40 | ) 41 | types.RegisterQueryServer(queryHelper, suite.chainA.App.NftTransferKeeper) 42 | suite.queryClient = types.NewQueryClient(queryHelper) 43 | } 44 | 45 | func (suite *KeeperTestSuite) TestGetTransferMoudleAddr() { 46 | expectedMaccAddr := sdk.AccAddress(crypto.AddressHash([]byte(types.ModuleName))) 47 | 48 | macc := suite.chainA.App.NftTransferKeeper.GetNftTransferModuleAddr(types.ModuleName) 49 | 50 | suite.Require().NotNil(macc) 51 | suite.Require().Equal(expectedMaccAddr, macc) 52 | } 53 | 54 | func NewTransferPath(scChain, destChain *tibctesting.TestChain) *tibctesting.Path { 55 | path := tibctesting.NewPath(scChain, destChain) 56 | return path 57 | } 58 | 59 | func TestKeeperTestSuite(t *testing.T) { 60 | suite.Run(t, new(KeeperTestSuite)) 61 | } 62 | -------------------------------------------------------------------------------- /modules/tibc/apps/nft_transfer/keeper/msg_server.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "context" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | 8 | "github.com/bianjieai/tibc-go/modules/tibc/apps/nft_transfer/types" 9 | ) 10 | 11 | var _ types.MsgServer = Keeper{} 12 | 13 | func (k Keeper) NftTransfer(goCtx context.Context, msg *types.MsgNftTransfer) (*types.MsgNftTransferResponse, error) { 14 | ctx := sdk.UnwrapSDKContext(goCtx) 15 | 16 | sender, err := sdk.AccAddressFromBech32(msg.Sender) 17 | if err != nil { 18 | return nil, err 19 | } 20 | 21 | if err := k.SendNftTransfer( 22 | ctx, msg.Class, msg.Id, sender, msg.Receiver, msg.DestChain, msg.RealayChain, msg.DestContract); err != nil { 23 | return nil, err 24 | } 25 | 26 | k.Logger(ctx).Info("TIBC non fungible token transfer", "nft", msg.Id, "sender", msg.Sender, "receiver", msg.Receiver) 27 | 28 | ctx.EventManager().EmitEvents(sdk.Events{ 29 | sdk.NewEvent( 30 | types.EventTypeNftTransfer, 31 | sdk.NewAttribute(sdk.AttributeKeySender, msg.Sender), 32 | sdk.NewAttribute(types.AttributeKeyReceiver, msg.Receiver), 33 | ), 34 | sdk.NewEvent( 35 | sdk.EventTypeMessage, 36 | sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), 37 | ), 38 | }) 39 | 40 | return &types.MsgNftTransferResponse{}, nil 41 | } 42 | -------------------------------------------------------------------------------- /modules/tibc/apps/nft_transfer/types/codec.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/codec" 5 | codectypes "github.com/cosmos/cosmos-sdk/codec/types" 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | "github.com/cosmos/cosmos-sdk/types/msgservice" 8 | ) 9 | 10 | var ( 11 | amino = codec.NewLegacyAmino() 12 | ModuleCdc = codec.NewProtoCodec(codectypes.NewInterfaceRegistry()) 13 | // AminoCdc is a amino codec created to support amino json compatible msgs. 14 | AminoCdc = codec.NewAminoCodec(amino) 15 | ) 16 | 17 | func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { 18 | cdc.RegisterConcrete(&MsgNftTransfer{}, "cosmos-sdk/MsgNftTransfer", nil) 19 | } 20 | 21 | // RegisterInterfaces register the tibc-transfer module interfaces to protobuf 22 | // Any. 23 | func RegisterInterfaces(registry codectypes.InterfaceRegistry) { 24 | registry.RegisterImplementations((*sdk.Msg)(nil), &MsgNftTransfer{}) 25 | 26 | msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) 27 | } 28 | 29 | func init() { 30 | RegisterLegacyAminoCodec(amino) 31 | amino.Seal() 32 | } 33 | -------------------------------------------------------------------------------- /modules/tibc/apps/nft_transfer/types/errors.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | errorsmod "cosmossdk.io/errors" 5 | ) 6 | 7 | var ( 8 | ErrInvalidDenom = errorsmod.Register(ModuleName, 2, "invalid denom") 9 | ErrUnknownNFT = errorsmod.Register(ModuleName, 3, "unknown nft") 10 | ErrScChainEqualToDestChain = errorsmod.Register(ModuleName, 4, "source chain equals to destination chain") 11 | ErrTraceNotFound = errorsmod.Register(ModuleName, 5, "class trace not found") 12 | ) 13 | -------------------------------------------------------------------------------- /modules/tibc/apps/nft_transfer/types/events.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // TIBC transfer events 4 | const ( 5 | EventTypePacket = "non_fungible_token_packet" 6 | EventTypeNftTransfer = "tibc_nft_transfer" 7 | EventTypeClassTrace = "class_trace" 8 | 9 | AttributeKeyClass = "class" 10 | AttributeKeyId = "id" 11 | AttributeKeyUri = "uri" 12 | AttributeKeyReceiver = "receiver" 13 | AttributeKeyAck = "ack" 14 | AttributeKeyAckSuccess = "success" 15 | AttributeKeyAckError = "error" 16 | AttributeKeyTraceHash = "trace_hash" 17 | ) 18 | -------------------------------------------------------------------------------- /modules/tibc/apps/nft_transfer/types/expected_keepers.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | 6 | nftexported "mods.irisnet.org/modules/nft/exported" 7 | "mods.irisnet.org/modules/nft/types" 8 | 9 | "github.com/bianjieai/tibc-go/modules/tibc/core/exported" 10 | ) 11 | 12 | // NftKeeper defines the expected nft keeper 13 | type NftKeeper interface { 14 | MintNFT(ctx sdk.Context, denomID, tokenID, tokenNm, tokenURI, tokenData string, owner sdk.AccAddress) error 15 | BurnNFT(ctx sdk.Context, denomID, tokenID string, owner sdk.AccAddress) error 16 | GetNFT(ctx sdk.Context, denomID, tokenID string) (nft nftexported.NFT, err error) 17 | TransferOwner(ctx sdk.Context, denomID, tokenID, tokenNm, tokenURI, tokenData string, srcOwner, dstOwner sdk.AccAddress) error 18 | GetDenom(ctx sdk.Context, id string) (denom types.Denom, found bool) 19 | IssueDenom(ctx sdk.Context, id, name, schema, symbol string, creator sdk.AccAddress, mintRestricted, updateRestricted bool) error 20 | } 21 | 22 | // AccountKeeper defines the expected account keeper 23 | type AccountKeeper interface { 24 | GetModuleAddress(name string) sdk.AccAddress 25 | } 26 | 27 | // PacketKeeper defines the expected packet keeper 28 | type PacketKeeper interface { 29 | GetNextSequenceSend(ctx sdk.Context, sourceChain, destChain string) uint64 30 | SendPacket(ctx sdk.Context, packet exported.PacketI) error 31 | } 32 | 33 | // ClientKeeper defines the expected client keeper 34 | type ClientKeeper interface { 35 | GetChainName(ctx sdk.Context) string 36 | } 37 | -------------------------------------------------------------------------------- /modules/tibc/apps/nft_transfer/types/keys.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | const ( 4 | // ModuleName defines the TIBC nft_transfer name 5 | ModuleName = "NFT" 6 | 7 | // RouterKey is the message route for the nft-transfer module 8 | RouterKey = ModuleName 9 | 10 | // PortID is the default port id that nft-transfer module binds to 11 | PortID = ModuleName 12 | 13 | // StoreKey is the store key string for TIBC nft-transfer 14 | StoreKey = ModuleName 15 | 16 | // QuerierRoute is the querier route for TIBC nft-transfer 17 | QuerierRoute = ModuleName 18 | 19 | // ClassPrefix is the prefix used for nft class. 20 | ClassPrefix = "tibc" 21 | ) 22 | 23 | var ( 24 | // ClassTraceKey defines the key to store the class trace info in store 25 | ClassTraceKey = []byte{0x01} 26 | ) 27 | -------------------------------------------------------------------------------- /modules/tibc/apps/nft_transfer/types/msgs.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | ) 6 | 7 | const ( 8 | TypeMsgNftTransfer = "tibc_nft_transfer" 9 | ) 10 | 11 | var _ sdk.Msg = &MsgNftTransfer{} 12 | 13 | // NewMsgNftTransfer creates a new NewMsgNftTransfer instance 14 | func NewMsgNftTransfer(class, id, sender, receiver, destChain, realayChain, destContract string) *MsgNftTransfer { 15 | return &MsgNftTransfer{ 16 | Class: class, 17 | Id: id, 18 | Sender: sender, 19 | Receiver: receiver, 20 | DestChain: destChain, 21 | RealayChain: realayChain, 22 | DestContract: destContract, 23 | } 24 | } 25 | 26 | // GetSigners implements sdk.Msg 27 | func (msg MsgNftTransfer) GetSigners() []sdk.AccAddress { 28 | signer, err := sdk.AccAddressFromBech32(msg.Sender) 29 | if err != nil { 30 | panic(err) 31 | } 32 | return []sdk.AccAddress{signer} 33 | } 34 | 35 | // ValidateBasic Implements Msg. 36 | func (msg MsgNftTransfer) ValidateBasic() error { 37 | return nil 38 | } 39 | -------------------------------------------------------------------------------- /modules/tibc/apps/nft_transfer/types/nft.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import "fmt" 4 | 5 | // GetClassPrefix returns the receiving class prefix 6 | func GetClassPrefix(sourceChain, destChain string) string { 7 | return fmt.Sprintf("%s/%s/", sourceChain, destChain) 8 | } 9 | -------------------------------------------------------------------------------- /modules/tibc/apps/nft_transfer/types/packet.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "strings" 5 | 6 | errorsmod "cosmossdk.io/errors" 7 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 8 | ) 9 | 10 | // NewNonFungibleTokenPacketData contructs a new NonFungibleTokenPacketData instance 11 | func NewNonFungibleTokenPacketData( 12 | class, id, uri, sender, receiver string, awayFromOrigin bool, destContract string, 13 | ) NonFungibleTokenPacketData { 14 | return NonFungibleTokenPacketData{ 15 | Class: class, 16 | Id: id, 17 | Uri: uri, 18 | Sender: sender, 19 | Receiver: receiver, 20 | AwayFromOrigin: awayFromOrigin, 21 | DestContract: destContract, 22 | } 23 | } 24 | 25 | // ValidateBasic is used for validating the nft transfer. 26 | // NOTE: The addresses formats are not validated as the sender and recipient can have different 27 | // formats defined by their corresponding chains that are not known to TIBC. 28 | func (nftpd NonFungibleTokenPacketData) ValidateBasic() error { 29 | if strings.TrimSpace(nftpd.Sender) == "" { 30 | return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "sender address cannot be blank") 31 | } 32 | if strings.TrimSpace(nftpd.Receiver) == "" { 33 | return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "receiver address cannot be blank") 34 | } 35 | return nil 36 | } 37 | 38 | // GetBytes is a helper for serialising 39 | func (nftpd NonFungibleTokenPacketData) GetBytes() []byte { 40 | return ModuleCdc.MustMarshal(&nftpd) 41 | } 42 | -------------------------------------------------------------------------------- /modules/tibc/core/02-client/client/cli/cli.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/cosmos/cosmos-sdk/client" 7 | 8 | "github.com/bianjieai/tibc-go/modules/tibc/core/02-client/types" 9 | ) 10 | 11 | // GetQueryCmd returns a root CLI command handler for all tibc/client query commands. 12 | func GetQueryCmd() *cobra.Command { 13 | queryCmd := &cobra.Command{ 14 | Use: types.SubModuleName, 15 | Short: "TIBC client query subcommands", 16 | DisableFlagParsing: true, 17 | SuggestionsMinimumDistance: 2, 18 | RunE: client.ValidateCmd, 19 | } 20 | 21 | queryCmd.AddCommand( 22 | GetCmdQueryClientStates(), 23 | GetCmdQueryClientState(), 24 | GetCmdQueryConsensusStates(), 25 | GetCmdQueryConsensusState(), 26 | GetCmdQueryHeader(), 27 | GetCmdNodeConsensusState(), 28 | GetCmdQueryRelayers(), 29 | ) 30 | 31 | return queryCmd 32 | } 33 | 34 | // NewTxCmd returns a root CLI command handler for all tibc/client transaction commands. 35 | func NewTxCmd() *cobra.Command { 36 | txCmd := &cobra.Command{ 37 | Use: types.SubModuleName, 38 | Short: "TIBC client transaction subcommands", 39 | DisableFlagParsing: true, 40 | SuggestionsMinimumDistance: 2, 41 | RunE: client.ValidateCmd, 42 | } 43 | 44 | txCmd.AddCommand( 45 | NewUpdateClientCmd(), 46 | ) 47 | 48 | return txCmd 49 | } 50 | -------------------------------------------------------------------------------- /modules/tibc/core/02-client/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package client implements the TICS 02 - Client Semantics specification. This 3 | concrete implementations defines types and method to store and update light 4 | clients which tracks on other chain's state. 5 | 6 | The main type is `Client`, which provides `commitment.Root` to verify state proofs and `ConsensusState` to 7 | verify header proofs. 8 | */ 9 | package client 10 | -------------------------------------------------------------------------------- /modules/tibc/core/02-client/genesis.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | "fmt" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | 8 | "github.com/bianjieai/tibc-go/modules/tibc/core/02-client/keeper" 9 | "github.com/bianjieai/tibc-go/modules/tibc/core/02-client/types" 10 | "github.com/bianjieai/tibc-go/modules/tibc/core/exported" 11 | ) 12 | 13 | // InitGenesis initializes the tibc client submodule's state from a provided genesis 14 | // state. 15 | func InitGenesis(ctx sdk.Context, k keeper.Keeper, gs types.GenesisState) { 16 | // Set all client metadata first. This will allow client keeper to overwrite client and consensus state keys 17 | // if clients accidentally write to ClientKeeper reserved keys. 18 | if len(gs.ClientsMetadata) != 0 { 19 | k.SetAllClientMetadata(ctx, gs.ClientsMetadata) 20 | } 21 | 22 | for _, client := range gs.Clients { 23 | cs, ok := client.ClientState.GetCachedValue().(exported.ClientState) 24 | if !ok { 25 | panic("invalid client state") 26 | } 27 | 28 | k.SetClientState(ctx, client.ChainName, cs) 29 | } 30 | 31 | for _, cs := range gs.ClientsConsensus { 32 | for _, consState := range cs.ConsensusStates { 33 | consensusState, ok := consState.ConsensusState.GetCachedValue().(exported.ConsensusState) 34 | if !ok { 35 | panic(fmt.Sprintf("invalid consensus state with chain name %s at height %s", cs.ChainName, consState.Height)) 36 | } 37 | 38 | k.SetClientConsensusState(ctx, cs.ChainName, consState.Height, consensusState) 39 | } 40 | } 41 | 42 | for _, rs := range gs.Relayers { 43 | k.RegisterRelayers(ctx, rs.ChainName, rs.Relayers) 44 | } 45 | k.SetChainName(ctx, gs.NativeChainName) 46 | } 47 | 48 | // ExportGenesis returns the tibc client submodule's exported genesis. 49 | // NOTE: CreateLocalhost should always be false on export since a 50 | // created localhost will be included in the exported clients. 51 | func ExportGenesis(ctx sdk.Context, k keeper.Keeper) types.GenesisState { 52 | genClients := k.GetAllGenesisClients(ctx) 53 | clientsMetadata, err := k.GetAllClientMetadata(ctx, genClients) 54 | if err != nil { 55 | panic(err) 56 | } 57 | return types.GenesisState{ 58 | Clients: genClients, 59 | ClientsMetadata: clientsMetadata, 60 | ClientsConsensus: k.GetAllConsensusStates(ctx), 61 | NativeChainName: k.GetChainName(ctx), 62 | Relayers: k.GetAllRelayers(ctx), 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /modules/tibc/core/02-client/keeper/encoding.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "github.com/bianjieai/tibc-go/modules/tibc/core/02-client/types" 5 | "github.com/bianjieai/tibc-go/modules/tibc/core/exported" 6 | ) 7 | 8 | // UnmarshalClientState attempts to decode and return an ClientState object from 9 | // raw encoded bytes. 10 | func (k Keeper) UnmarshalClientState(bz []byte) (exported.ClientState, error) { 11 | return types.UnmarshalClientState(k.cdc, bz) 12 | } 13 | 14 | // MustUnmarshalClientState attempts to decode and return an ClientState object from 15 | // raw encoded bytes. It panics on error. 16 | func (k Keeper) MustUnmarshalClientState(bz []byte) exported.ClientState { 17 | return types.MustUnmarshalClientState(k.cdc, bz) 18 | } 19 | 20 | // UnmarshalConsensusState attempts to decode and return an ConsensusState object from 21 | // raw encoded bytes. 22 | func (k Keeper) UnmarshalConsensusState(bz []byte) (exported.ConsensusState, error) { 23 | return types.UnmarshalConsensusState(k.cdc, bz) 24 | } 25 | 26 | // MustUnmarshalConsensusState attempts to decode and return an ConsensusState object from 27 | // raw encoded bytes. It panics on error. 28 | func (k Keeper) MustUnmarshalConsensusState(bz []byte) exported.ConsensusState { 29 | return types.MustUnmarshalConsensusState(k.cdc, bz) 30 | } 31 | 32 | // MustMarshalClientState attempts to encode an ClientState object and returns the 33 | // raw encoded bytes. It panics on error. 34 | func (k Keeper) MustMarshalClientState(clientState exported.ClientState) []byte { 35 | return types.MustMarshalClientState(k.cdc, clientState) 36 | } 37 | 38 | // MustMarshalConsensusState attempts to encode an ConsensusState object and returns the 39 | // raw encoded bytes. It panics on error. 40 | func (k Keeper) MustMarshalConsensusState(consensusState exported.ConsensusState) []byte { 41 | return types.MustMarshalConsensusState(k.cdc, consensusState) 42 | } 43 | -------------------------------------------------------------------------------- /modules/tibc/core/02-client/keeper/relayer.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | storetypes "cosmossdk.io/store/types" 5 | sdk "github.com/cosmos/cosmos-sdk/types" 6 | 7 | "github.com/bianjieai/tibc-go/modules/tibc/core/02-client/types" 8 | ) 9 | 10 | // RegisterRelayers saves the relayers under the specified chainname 11 | func (k Keeper) RegisterRelayers(ctx sdk.Context, chainName string, relayers []string) { 12 | store := k.RelayerStore(ctx) 13 | ir := &types.IdentifiedRelayers{ 14 | ChainName: chainName, 15 | Relayers: relayers, 16 | } 17 | irBz := k.cdc.MustMarshal(ir) 18 | store.Set([]byte(chainName), irBz) 19 | } 20 | 21 | // AuthRelayer asserts whether a relayer is already registered 22 | func (k Keeper) AuthRelayer(ctx sdk.Context, chainName string, relayer string) bool { 23 | for _, r := range k.GetRelayers(ctx, chainName) { 24 | if r == relayer { 25 | return true 26 | } 27 | } 28 | return false 29 | } 30 | 31 | // GetRelayers returns all registered relayer addresses under the specified chain name 32 | func (k Keeper) GetRelayers(ctx sdk.Context, chainName string) (relayers []string) { 33 | store := k.RelayerStore(ctx) 34 | bz := store.Get([]byte(chainName)) 35 | 36 | var ir = &types.IdentifiedRelayers{} 37 | k.cdc.MustUnmarshal(bz, ir) 38 | return ir.Relayers 39 | } 40 | 41 | // GetAllRelayers returns all registered relayer addresses 42 | func (k Keeper) GetAllRelayers(ctx sdk.Context) (relayers []types.IdentifiedRelayers) { 43 | store := ctx.KVStore(k.storeKey) 44 | iterator := storetypes.KVStorePrefixIterator(store, []byte(types.KeyRelayers)) 45 | 46 | defer iterator.Close() 47 | for ; iterator.Valid(); iterator.Next() { 48 | var ir = &types.IdentifiedRelayers{} 49 | k.cdc.MustUnmarshal(iterator.Value(), ir) 50 | relayers = append(relayers, *ir) 51 | } 52 | return 53 | } 54 | -------------------------------------------------------------------------------- /modules/tibc/core/02-client/module.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | "github.com/cosmos/gogoproto/grpc" 5 | "github.com/spf13/cobra" 6 | 7 | "github.com/bianjieai/tibc-go/modules/tibc/core/02-client/client/cli" 8 | "github.com/bianjieai/tibc-go/modules/tibc/core/02-client/types" 9 | ) 10 | 11 | // Name returns the TIBC client name. 12 | func Name() string { 13 | return types.SubModuleName 14 | } 15 | 16 | // GetQueryCmd returns no root query command for the TIBC client. 17 | func GetQueryCmd() *cobra.Command { 18 | return cli.GetQueryCmd() 19 | } 20 | 21 | // GetTxCmd returns the root tx command for 02-client. 22 | func GetTxCmd() *cobra.Command { 23 | return cli.NewTxCmd() 24 | } 25 | 26 | // RegisterQueryService registers the gRPC query service for TIBC client. 27 | func RegisterQueryService(server grpc.Server, queryServer types.QueryServer) { 28 | types.RegisterQueryServer(server, queryServer) 29 | } 30 | -------------------------------------------------------------------------------- /modules/tibc/core/02-client/simulation/decoder.go: -------------------------------------------------------------------------------- 1 | package simulation 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | 7 | "github.com/cosmos/cosmos-sdk/types/kv" 8 | 9 | "github.com/bianjieai/tibc-go/modules/tibc/core/02-client/keeper" 10 | host "github.com/bianjieai/tibc-go/modules/tibc/core/24-host" 11 | "github.com/bianjieai/tibc-go/modules/tibc/core/exported" 12 | ) 13 | 14 | var _ ClientUnmarshaler = (*keeper.Keeper)(nil) 15 | 16 | // ClientUnmarshaler defines an interface for unmarshaling TICS02 interfaces. 17 | type ClientUnmarshaler interface { 18 | MustUnmarshalClientState([]byte) exported.ClientState 19 | MustUnmarshalConsensusState([]byte) exported.ConsensusState 20 | } 21 | 22 | // NewDecodeStore returns a decoder function closure that unmarshals the KVPair's 23 | // Value to the corresponding client type. 24 | func NewDecodeStore(cdc ClientUnmarshaler, kvA, kvB kv.Pair) (string, bool) { 25 | switch { 26 | case bytes.HasPrefix(kvA.Key, host.KeyClientStorePrefix) && bytes.HasSuffix(kvA.Key, []byte(host.KeyClientState)): 27 | clientStateA := cdc.MustUnmarshalClientState(kvA.Value) 28 | clientStateB := cdc.MustUnmarshalClientState(kvB.Value) 29 | return fmt.Sprintf("ClientState A: %v\nClientState B: %v", clientStateA, clientStateB), true 30 | 31 | case bytes.HasPrefix(kvA.Key, host.KeyClientStorePrefix) && bytes.Contains(kvA.Key, []byte(host.KeyConsensusStatePrefix)): 32 | consensusStateA := cdc.MustUnmarshalConsensusState(kvA.Value) 33 | consensusStateB := cdc.MustUnmarshalConsensusState(kvB.Value) 34 | return fmt.Sprintf("ConsensusState A: %v\nConsensusState B: %v", consensusStateA, consensusStateB), true 35 | 36 | default: 37 | return "", false 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /modules/tibc/core/02-client/simulation/decoder_test.go: -------------------------------------------------------------------------------- 1 | package simulation_test 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | "time" 7 | 8 | "github.com/stretchr/testify/require" 9 | 10 | "github.com/cosmos/cosmos-sdk/types/kv" 11 | 12 | "github.com/bianjieai/tibc-go/modules/tibc/core/02-client/simulation" 13 | "github.com/bianjieai/tibc-go/modules/tibc/core/02-client/types" 14 | host "github.com/bianjieai/tibc-go/modules/tibc/core/24-host" 15 | ibctmtypes "github.com/bianjieai/tibc-go/modules/tibc/light-clients/07-tendermint/types" 16 | "github.com/bianjieai/tibc-go/simapp" 17 | ) 18 | 19 | func TestDecodeStore(t *testing.T) { 20 | app := simapp.Setup(t) 21 | chainName := "clientidone" 22 | 23 | height := types.NewHeight(0, 10) 24 | 25 | clientState := &ibctmtypes.ClientState{} 26 | consState := &ibctmtypes.ConsensusState{ 27 | Timestamp: time.Now().UTC(), 28 | } 29 | 30 | kvPairs := kv.Pairs{ 31 | Pairs: []kv.Pair{{ 32 | Key: host.FullClientStateKey(chainName), 33 | Value: app.TIBCKeeper.ClientKeeper.MustMarshalClientState(clientState), 34 | }, { 35 | Key: host.FullConsensusStateKey(chainName, height), 36 | Value: app.TIBCKeeper.ClientKeeper.MustMarshalConsensusState(consState), 37 | }, { 38 | Key: []byte{0x99}, 39 | Value: []byte{0x99}, 40 | }}, 41 | } 42 | tests := []struct { 43 | name string 44 | expectedLog string 45 | }{ 46 | {"ClientState", fmt.Sprintf("ClientState A: %v\nClientState B: %v", clientState, clientState)}, 47 | {"ConsensusState", fmt.Sprintf("ConsensusState A: %v\nConsensusState B: %v", consState, consState)}, 48 | {"other", ""}, 49 | } 50 | 51 | for i, tt := range tests { 52 | i, tt := i, tt 53 | t.Run(tt.name, func(t *testing.T) { 54 | res, found := simulation.NewDecodeStore(app.TIBCKeeper.ClientKeeper, kvPairs.Pairs[i], kvPairs.Pairs[i]) 55 | if i == len(tests)-1 { 56 | require.False(t, found, string(kvPairs.Pairs[i].Key)) 57 | require.Empty(t, res, string(kvPairs.Pairs[i].Key)) 58 | } else { 59 | require.True(t, found, string(kvPairs.Pairs[i].Key)) 60 | require.Equal(t, tt.expectedLog, res, string(kvPairs.Pairs[i].Key)) 61 | } 62 | }) 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /modules/tibc/core/02-client/simulation/genesis.go: -------------------------------------------------------------------------------- 1 | package simulation 2 | 3 | import ( 4 | "math/rand" 5 | 6 | simtypes "github.com/cosmos/cosmos-sdk/types/simulation" 7 | 8 | "github.com/bianjieai/tibc-go/modules/tibc/core/02-client/types" 9 | ) 10 | 11 | // GenClientGenesis returns the default client genesis state. 12 | func GenClientGenesis(_ *rand.Rand, _ []simtypes.Account) types.GenesisState { 13 | return types.DefaultGenesisState() 14 | } 15 | -------------------------------------------------------------------------------- /modules/tibc/core/02-client/types/client_test.go: -------------------------------------------------------------------------------- 1 | package types_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | 8 | "github.com/bianjieai/tibc-go/modules/tibc/core/02-client/types" 9 | tibctesting "github.com/bianjieai/tibc-go/modules/tibc/testing" 10 | ) 11 | 12 | func (suite *TypesTestSuite) TestMarshalConsensusStateWithHeight() { 13 | var cswh types.ConsensusStateWithHeight 14 | 15 | testCases := []struct { 16 | name string 17 | malleate func() 18 | }{{ 19 | "tendermint client", 20 | func() { 21 | // setup testing conditions 22 | path := tibctesting.NewPath(suite.chainA, suite.chainB) 23 | suite.coordinator.SetupClients(path) 24 | clientState := path.EndpointA.GetClientState() 25 | consensusState := path.EndpointA.GetConsensusState(clientState.GetLatestHeight()) 26 | cswh = types.NewConsensusStateWithHeight(clientState.GetLatestHeight().(types.Height), consensusState) 27 | }, 28 | }} 29 | 30 | for _, tc := range testCases { 31 | tc := tc 32 | 33 | suite.Run(tc.name, func() { 34 | suite.SetupTest() 35 | 36 | tc.malleate() 37 | 38 | cdc := suite.chainA.App.AppCodec() 39 | 40 | // marshal message 41 | bz, err := cdc.MarshalJSON(&cswh) 42 | suite.Require().NoError(err) 43 | 44 | // unmarshal message 45 | newCswh := &types.ConsensusStateWithHeight{} 46 | err = cdc.UnmarshalJSON(bz, newCswh) 47 | suite.Require().NoError(err) 48 | }) 49 | } 50 | } 51 | 52 | func TestValidateClientType(t *testing.T) { 53 | testCases := []struct { 54 | name string 55 | clientType string 56 | expPass bool 57 | }{ 58 | {"valid", "tendermint", true}, 59 | {"valid solomachine", "solomachine-v1", true}, 60 | // {"too large", "tenderminttenderminttenderminttenderminttendermintt", false}, 61 | {"too short", "t", false}, 62 | {"blank id", " ", false}, 63 | {"empty id", "", false}, 64 | // {"ends with dash", "tendermint-", false}, 65 | } 66 | 67 | for _, tc := range testCases { 68 | err := types.ValidateClientType(tc.clientType) 69 | if tc.expPass { 70 | require.NoError(t, err, tc.name) 71 | } else { 72 | require.Error(t, err, tc.name) 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /modules/tibc/core/02-client/types/encoding_test.go: -------------------------------------------------------------------------------- 1 | package types_test 2 | 3 | import ( 4 | "github.com/bianjieai/tibc-go/modules/tibc/core/02-client/types" 5 | ibctmtypes "github.com/bianjieai/tibc-go/modules/tibc/light-clients/07-tendermint/types" 6 | ) 7 | 8 | func (suite *TypesTestSuite) TestMarshalHeader() { 9 | cdc := suite.chainA.App.AppCodec() 10 | h := &ibctmtypes.Header{ 11 | TrustedHeight: types.NewHeight(4, 100), 12 | } 13 | 14 | // marshal header 15 | bz, err := types.MarshalHeader(cdc, h) 16 | suite.Require().NoError(err) 17 | 18 | // unmarshal header 19 | newHeader, err := types.UnmarshalHeader(cdc, bz) 20 | suite.Require().NoError(err) 21 | 22 | suite.Require().Equal(h, newHeader) 23 | 24 | // use invalid bytes 25 | invalidHeader, err := types.UnmarshalHeader(cdc, []byte("invalid bytes")) 26 | suite.Require().Error(err) 27 | suite.Require().Nil(invalidHeader) 28 | 29 | } 30 | -------------------------------------------------------------------------------- /modules/tibc/core/02-client/types/events.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "fmt" 5 | 6 | host "github.com/bianjieai/tibc-go/modules/tibc/core/24-host" 7 | ) 8 | 9 | // TIBC client events 10 | const ( 11 | AttributeKeyChainName = "chain_name" 12 | AttributeKeyClientType = "client_type" 13 | AttributeKeyConsensusHeight = "consensus_height" 14 | AttributeKeyHeader = "header" 15 | ) 16 | 17 | // TIBC client events vars 18 | var ( 19 | EventTypeCreateClientProposal = "create_client_proposal" 20 | EventTypeUpdateClient = "update_client" 21 | EventTypeUpgradeClientProposal = "upgrade_client_proposal" 22 | EventTypeUpdateClientProposal = "update_client_proposal" 23 | 24 | AttributeValueCategory = fmt.Sprintf("%s_%s", host.ModuleName, SubModuleName) 25 | ) 26 | -------------------------------------------------------------------------------- /modules/tibc/core/02-client/types/expected_keepers.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | context "context" 5 | "time" 6 | 7 | stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" 8 | ) 9 | 10 | // StakingKeeper expected staking keeper 11 | type StakingKeeper interface { 12 | GetHistoricalInfo(ctx context.Context, height int64) (stakingtypes.HistoricalInfo, error) 13 | UnbondingTime(ctx context.Context) (time.Duration,error) 14 | } 15 | -------------------------------------------------------------------------------- /modules/tibc/core/02-client/types/keys.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | const ( 4 | // SubModuleName defines the TIBC client name 5 | SubModuleName string = "client" 6 | 7 | // RouterKey is the message route for TIBC client 8 | RouterKey string = SubModuleName 9 | 10 | // QuerierRoute is the querier route for TIBC client 11 | QuerierRoute string = SubModuleName 12 | 13 | // KeyClientName is the key used to store the chain name in the keeper. 14 | KeyClientName = "chainName" 15 | 16 | // KeyRelayers is the key used to store the relayers address in the keeper. 17 | KeyRelayers = "relayers" 18 | ) 19 | -------------------------------------------------------------------------------- /modules/tibc/core/02-client/types/metrics.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // Prometheus metric labels. 4 | const ( 5 | LabelClientType = "client_type" 6 | LabelChainName = "chain_name" 7 | LabelUpdateType = "update_type" 8 | LabelMsgType = "msg_type" 9 | ) 10 | -------------------------------------------------------------------------------- /modules/tibc/core/02-client/types/proposal_test.go: -------------------------------------------------------------------------------- 1 | package types_test 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/codec" 5 | codectypes "github.com/cosmos/cosmos-sdk/codec/types" 6 | govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" 7 | 8 | "github.com/bianjieai/tibc-go/modules/tibc/core/02-client/types" 9 | tibctmtypes "github.com/bianjieai/tibc-go/modules/tibc/light-clients/07-tendermint/types" 10 | tibctesting "github.com/bianjieai/tibc-go/modules/tibc/testing" 11 | ) 12 | 13 | func (suite *TypesTestSuite) TestNewCreateClientProposal() { 14 | p, err := types.NewCreateClientProposal(tibctesting.Title, tibctesting.Description, chainName, &tibctmtypes.ClientState{}, &tibctmtypes.ConsensusState{}) 15 | suite.Require().NoError(err) 16 | suite.Require().NotNil(p) 17 | 18 | p, err = types.NewCreateClientProposal(tibctesting.Title, tibctesting.Description, chainName, nil, nil) 19 | suite.Require().Error(err) 20 | suite.Require().Nil(p) 21 | } 22 | 23 | // tests a client update proposal can be marshaled and unmarshaled, and the 24 | // client state can be unpacked 25 | func (suite *TypesTestSuite) TestMarshalCreateClientProposalProposal() { 26 | path := tibctesting.NewPath(suite.chainA, suite.chainB) 27 | suite.coordinator.SetupClients(path) 28 | 29 | clientState := path.EndpointA.GetClientState() 30 | consensusState := path.EndpointA.GetConsensusState(clientState.GetLatestHeight()) 31 | // create proposal 32 | proposal, err := types.NewCreateClientProposal("update TIBC client", "description", "chain-name", clientState, consensusState) 33 | suite.Require().NoError(err) 34 | 35 | // create codec 36 | ir := codectypes.NewInterfaceRegistry() 37 | types.RegisterInterfaces(ir) 38 | govv1beta1.RegisterInterfaces(ir) 39 | tibctmtypes.RegisterInterfaces(ir) 40 | cdc := codec.NewProtoCodec(ir) 41 | 42 | // marshal message 43 | bz, err := cdc.MarshalJSON(proposal) 44 | suite.Require().NoError(err) 45 | 46 | // unmarshal proposal 47 | newProposal := &types.CreateClientProposal{} 48 | err = cdc.UnmarshalJSON(bz, newProposal) 49 | suite.Require().NoError(err) 50 | } 51 | -------------------------------------------------------------------------------- /modules/tibc/core/02-client/types/query.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | codectypes "github.com/cosmos/cosmos-sdk/codec/types" 5 | 6 | "github.com/bianjieai/tibc-go/modules/tibc/core/exported" 7 | ) 8 | 9 | var ( 10 | _ codectypes.UnpackInterfacesMessage = QueryClientStateResponse{} 11 | _ codectypes.UnpackInterfacesMessage = QueryClientStatesResponse{} 12 | _ codectypes.UnpackInterfacesMessage = QueryConsensusStateResponse{} 13 | _ codectypes.UnpackInterfacesMessage = QueryConsensusStatesResponse{} 14 | ) 15 | 16 | // UnpackInterfaces implements UnpackInterfacesMesssage.UnpackInterfaces 17 | func (qcsr QueryClientStatesResponse) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { 18 | for _, cs := range qcsr.ClientStates { 19 | if err := cs.UnpackInterfaces(unpacker); err != nil { 20 | return err 21 | } 22 | } 23 | return nil 24 | } 25 | 26 | // NewQueryClientStateResponse creates a new QueryClientStateResponse instance. 27 | func NewQueryClientStateResponse( 28 | clientStateAny *codectypes.Any, proof []byte, height Height, 29 | ) *QueryClientStateResponse { 30 | return &QueryClientStateResponse{ 31 | ClientState: clientStateAny, 32 | Proof: proof, 33 | ProofHeight: height, 34 | } 35 | } 36 | 37 | // UnpackInterfaces implements UnpackInterfacesMesssage.UnpackInterfaces 38 | func (qcsr QueryClientStateResponse) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { 39 | return unpacker.UnpackAny(qcsr.ClientState, new(exported.ClientState)) 40 | } 41 | 42 | // UnpackInterfaces implements UnpackInterfacesMesssage.UnpackInterfaces 43 | func (qcsr QueryConsensusStatesResponse) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { 44 | for _, cs := range qcsr.ConsensusStates { 45 | if err := cs.UnpackInterfaces(unpacker); err != nil { 46 | return err 47 | } 48 | } 49 | return nil 50 | } 51 | 52 | // NewQueryConsensusStateResponse creates a new QueryConsensusStateResponse instance. 53 | func NewQueryConsensusStateResponse( 54 | consensusStateAny *codectypes.Any, proof []byte, height Height, 55 | ) *QueryConsensusStateResponse { 56 | return &QueryConsensusStateResponse{ 57 | ConsensusState: consensusStateAny, 58 | Proof: proof, 59 | ProofHeight: height, 60 | } 61 | } 62 | 63 | // UnpackInterfaces implements UnpackInterfacesMesssage.UnpackInterfaces 64 | func (qcsr QueryConsensusStateResponse) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { 65 | return unpacker.UnpackAny(qcsr.ConsensusState, new(exported.ConsensusState)) 66 | } 67 | -------------------------------------------------------------------------------- /modules/tibc/core/04-packet/client/cli/cli.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/cosmos/cosmos-sdk/client" 7 | 8 | "github.com/bianjieai/tibc-go/modules/tibc/core/04-packet/types" 9 | ) 10 | 11 | // GetQueryCmd returns a root CLI command handler for all tibc/packet query commands. 12 | func GetQueryCmd() *cobra.Command { 13 | queryCmd := &cobra.Command{ 14 | Use: types.SubModuleName, 15 | Short: "tibc packet query subcommands", 16 | DisableFlagParsing: true, 17 | SuggestionsMinimumDistance: 2, 18 | RunE: client.ValidateCmd, 19 | } 20 | 21 | queryCmd.AddCommand( 22 | GetCmdQueryPacketCommitment(), 23 | GetCmdQueryPacketCommitments(), 24 | GetCmdQueryPacketReceipt(), 25 | GetCmdQueryPacketAcknowledgement(), 26 | GetCmdQueryUnreceivedPackets(), 27 | GetCmdQueryUnreceivedAcks(), 28 | GetCmdQueryCleanPacketCommitment(), 29 | ) 30 | 31 | return queryCmd 32 | } 33 | 34 | // NewTxCmd returns a root CLI command handler for all tibc/packet transaction commands. 35 | func NewTxCmd() *cobra.Command { 36 | txCmd := &cobra.Command{ 37 | Use: types.SubModuleName, 38 | Short: "TIBC client transaction subcommands", 39 | DisableFlagParsing: true, 40 | SuggestionsMinimumDistance: 2, 41 | RunE: client.ValidateCmd, 42 | } 43 | txCmd.AddCommand( 44 | NewSendCleanPacketCmd(), 45 | ) 46 | 47 | return txCmd 48 | } 49 | -------------------------------------------------------------------------------- /modules/tibc/core/04-packet/client/cli/flags.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | flag "github.com/spf13/pflag" 5 | ) 6 | 7 | const ( 8 | FlagRelayChain = "relay-chain-name" 9 | ) 10 | 11 | var ( 12 | FsSendCleanPacket = flag.NewFlagSet("", flag.ContinueOnError) 13 | ) 14 | 15 | func init() { 16 | FsSendCleanPacket.String(FlagRelayChain, "", "The name of relay chain") 17 | } 18 | -------------------------------------------------------------------------------- /modules/tibc/core/04-packet/client/cli/tx.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | 7 | "github.com/spf13/cobra" 8 | 9 | "github.com/cosmos/cosmos-sdk/client" 10 | "github.com/cosmos/cosmos-sdk/client/flags" 11 | "github.com/cosmos/cosmos-sdk/client/tx" 12 | "github.com/cosmos/cosmos-sdk/version" 13 | 14 | "github.com/bianjieai/tibc-go/modules/tibc/core/04-packet/types" 15 | ) 16 | 17 | // NewSendCleanPacketCmd defines the command to send clean packet. 18 | func NewSendCleanPacketCmd() *cobra.Command { 19 | cmd := &cobra.Command{ 20 | Use: "send-clean-packet [dest-chain-name] [sequence] [flags]", 21 | Short: "send a clean packet", 22 | Long: "send a clean packet", 23 | Example: fmt.Sprintf( 24 | "%s tx tibc %s send-clean-packet [dest-chain-name] [sequence] --relay-chain-name test2 --from node0", 25 | version.AppName, types.SubModuleName, 26 | ), 27 | Args: cobra.ExactArgs(2), 28 | RunE: func(cmd *cobra.Command, args []string) error { 29 | clientCtx, err := client.GetClientTxContext(cmd) 30 | if err != nil { 31 | return err 32 | } 33 | 34 | relayChain, err := cmd.Flags().GetString(FlagRelayChain) 35 | if err != nil { 36 | return err 37 | } 38 | destChain := args[0] 39 | sequence, err := strconv.ParseUint(args[1], 10, 64) 40 | if err != nil { 41 | return err 42 | } 43 | cleanPacket := types.CleanPacket{ 44 | Sequence: sequence, 45 | DestinationChain: destChain, 46 | RelayChain: relayChain, 47 | } 48 | 49 | msg := types.NewMsgCleanPacket(cleanPacket, clientCtx.GetFromAddress()) 50 | if err := msg.ValidateBasic(); err != nil { 51 | return err 52 | } 53 | return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) 54 | }, 55 | } 56 | cmd.Flags().AddFlagSet(FsSendCleanPacket) 57 | flags.AddTxFlagsToCmd(cmd) 58 | return cmd 59 | } 60 | -------------------------------------------------------------------------------- /modules/tibc/core/04-packet/genesis.go: -------------------------------------------------------------------------------- 1 | package packet 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | 6 | "github.com/bianjieai/tibc-go/modules/tibc/core/04-packet/keeper" 7 | "github.com/bianjieai/tibc-go/modules/tibc/core/04-packet/types" 8 | ) 9 | 10 | // InitGenesis initializes the tibc packet submodule's state from a provided genesis 11 | // state. 12 | func InitGenesis(ctx sdk.Context, k keeper.Keeper, gs types.GenesisState) { 13 | for _, ack := range gs.Acknowledgements { 14 | k.SetPacketAcknowledgement(ctx, ack.SourceChain, ack.DestinationChain, ack.Sequence, ack.Data) 15 | } 16 | for _, commitment := range gs.Commitments { 17 | k.SetPacketCommitment(ctx, commitment.SourceChain, commitment.DestinationChain, commitment.Sequence, commitment.Data) 18 | } 19 | for _, receipt := range gs.Receipts { 20 | k.SetPacketReceipt(ctx, receipt.SourceChain, receipt.DestinationChain, receipt.Sequence) 21 | } 22 | for _, ss := range gs.SendSequences { 23 | k.SetNextSequenceSend(ctx, ss.SourceChain, ss.DestinationChain, ss.Sequence) 24 | } 25 | } 26 | 27 | // ExportGenesis returns the tibc packet submodule's exported genesis. 28 | func ExportGenesis(ctx sdk.Context, k keeper.Keeper) types.GenesisState { 29 | return types.GenesisState{ 30 | Acknowledgements: k.GetAllPacketAcks(ctx), 31 | Commitments: k.GetAllPacketCommitments(ctx), 32 | Receipts: k.GetAllPacketReceipts(ctx), 33 | SendSequences: k.GetAllPacketSendSeqs(ctx), 34 | RecvSequences: k.GetAllPacketRecvSeqs(ctx), 35 | AckSequences: k.GetAllPacketAckSeqs(ctx), 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /modules/tibc/core/04-packet/module.go: -------------------------------------------------------------------------------- 1 | package packet 2 | 3 | import ( 4 | "github.com/cosmos/gogoproto/grpc" 5 | "github.com/spf13/cobra" 6 | 7 | "github.com/bianjieai/tibc-go/modules/tibc/core/04-packet/client/cli" 8 | "github.com/bianjieai/tibc-go/modules/tibc/core/04-packet/types" 9 | ) 10 | 11 | // Name returns the TIBC packet TICS name. 12 | func Name() string { 13 | return types.SubModuleName 14 | } 15 | 16 | // GetTxCmd returns the root tx command for TIBC packet. 17 | func GetTxCmd() *cobra.Command { 18 | return cli.NewTxCmd() 19 | } 20 | 21 | // GetQueryCmd returns the root query command for TIBC packet. 22 | func GetQueryCmd() *cobra.Command { 23 | return cli.GetQueryCmd() 24 | } 25 | 26 | // RegisterQueryService registers the gRPC query service for TIBC packet. 27 | func RegisterQueryService(server grpc.Server, queryServer types.QueryServer) { 28 | types.RegisterQueryServer(server, queryServer) 29 | } 30 | -------------------------------------------------------------------------------- /modules/tibc/core/04-packet/simulation/decoder.go: -------------------------------------------------------------------------------- 1 | package simulation 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | 7 | "github.com/cosmos/cosmos-sdk/codec" 8 | sdk "github.com/cosmos/cosmos-sdk/types" 9 | "github.com/cosmos/cosmos-sdk/types/kv" 10 | 11 | host "github.com/bianjieai/tibc-go/modules/tibc/core/24-host" 12 | ) 13 | 14 | // NewDecodeStore returns a decoder function closure that unmarshals the KVPair's 15 | // Value to the corresponding channel type. 16 | func NewDecodeStore(cdc codec.BinaryCodec, kvA, kvB kv.Pair) (string, bool) { 17 | switch { 18 | case bytes.HasPrefix(kvA.Key, []byte(host.KeyNextSeqSendPrefix)): 19 | seqA := sdk.BigEndianToUint64(kvA.Value) 20 | seqB := sdk.BigEndianToUint64(kvB.Value) 21 | return fmt.Sprintf("NextSeqSend A: %d\nNextSeqSend B: %d", seqA, seqB), true 22 | 23 | case bytes.HasPrefix(kvA.Key, []byte(host.KeyNextSeqRecvPrefix)): 24 | seqA := sdk.BigEndianToUint64(kvA.Value) 25 | seqB := sdk.BigEndianToUint64(kvB.Value) 26 | return fmt.Sprintf("NextSeqRecv A: %d\nNextSeqRecv B: %d", seqA, seqB), true 27 | 28 | case bytes.HasPrefix(kvA.Key, []byte(host.KeyNextSeqAckPrefix)): 29 | seqA := sdk.BigEndianToUint64(kvA.Value) 30 | seqB := sdk.BigEndianToUint64(kvB.Value) 31 | return fmt.Sprintf("NextSeqAck A: %d\nNextSeqAck B: %d", seqA, seqB), true 32 | 33 | case bytes.HasPrefix(kvA.Key, []byte(host.KeyPacketCommitmentPrefix)): 34 | return fmt.Sprintf("CommitmentHash A: %X\nCommitmentHash B: %X", kvA.Value, kvB.Value), true 35 | 36 | case bytes.HasPrefix(kvA.Key, []byte(host.KeyPacketAckPrefix)): 37 | return fmt.Sprintf("AckHash A: %X\nAckHash B: %X", kvA.Value, kvB.Value), true 38 | 39 | default: 40 | return "", false 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /modules/tibc/core/04-packet/simulation/decoder_test.go: -------------------------------------------------------------------------------- 1 | package simulation_test 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/require" 8 | 9 | sdk "github.com/cosmos/cosmos-sdk/types" 10 | "github.com/cosmos/cosmos-sdk/types/kv" 11 | 12 | "github.com/bianjieai/tibc-go/modules/tibc/core/04-packet/simulation" 13 | host "github.com/bianjieai/tibc-go/modules/tibc/core/24-host" 14 | "github.com/bianjieai/tibc-go/simapp" 15 | ) 16 | 17 | func TestDecodeStore(t *testing.T) { 18 | app := simapp.Setup(t) 19 | cdc := app.AppCodec() 20 | 21 | channelID := "channelidone" 22 | portID := "portidone" 23 | 24 | bz := []byte{0x1, 0x2, 0x3} 25 | 26 | kvPairs := kv.Pairs{ 27 | Pairs: []kv.Pair{{ 28 | Key: host.NextSequenceSendKey(portID, channelID), 29 | Value: sdk.Uint64ToBigEndian(1), 30 | }, { 31 | Key: host.PacketCommitmentKey(portID, channelID, 1), 32 | Value: bz, 33 | }, { 34 | Key: host.PacketAcknowledgementKey(portID, channelID, 1), 35 | Value: bz, 36 | }, { 37 | Key: []byte{0x99}, 38 | Value: []byte{0x99}, 39 | }}, 40 | } 41 | tests := []struct { 42 | name string 43 | expectedLog string 44 | }{ 45 | {"NextSeqSend", "NextSeqSend A: 1\nNextSeqSend B: 1"}, 46 | {"NextSeqRecv", "NextSeqRecv A: 1\nNextSeqRecv B: 1"}, 47 | {"NextSeqAck", "NextSeqAck A: 1\nNextSeqAck B: 1"}, 48 | {"CommitmentHash", fmt.Sprintf("CommitmentHash A: %X\nCommitmentHash B: %X", bz, bz)}, 49 | {"AckHash", fmt.Sprintf("AckHash A: %X\nAckHash B: %X", bz, bz)}, 50 | {"other", ""}, 51 | } 52 | 53 | for i, tt := range tests { 54 | i, tt := i, tt 55 | t.Run(tt.name, func(t *testing.T) { 56 | res, found := simulation.NewDecodeStore(cdc, kvPairs.Pairs[i], kvPairs.Pairs[i]) 57 | if i == len(tests)-1 { 58 | require.False(t, found, string(kvPairs.Pairs[i].Key)) 59 | require.Empty(t, res, string(kvPairs.Pairs[i].Key)) 60 | } else { 61 | require.True(t, found, string(kvPairs.Pairs[i].Key)) 62 | require.Equal(t, tt.expectedLog, res, string(kvPairs.Pairs[i].Key)) 63 | } 64 | }) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /modules/tibc/core/04-packet/simulation/genesis.go: -------------------------------------------------------------------------------- 1 | package simulation 2 | 3 | import ( 4 | "math/rand" 5 | 6 | simtypes "github.com/cosmos/cosmos-sdk/types/simulation" 7 | 8 | "github.com/bianjieai/tibc-go/modules/tibc/core/04-packet/types" 9 | ) 10 | 11 | // GenpacketGenesis returns the default packet genesis state. 12 | func GenpacketGenesis(_ *rand.Rand, _ []simtypes.Account) types.GenesisState { 13 | return types.DefaultGenesisState() 14 | } 15 | -------------------------------------------------------------------------------- /modules/tibc/core/04-packet/types/codec.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/codec" 5 | codectypes "github.com/cosmos/cosmos-sdk/codec/types" 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | "github.com/cosmos/cosmos-sdk/types/msgservice" 8 | 9 | "github.com/bianjieai/tibc-go/modules/tibc/core/exported" 10 | ) 11 | 12 | // RegisterInterfaces register the tibc packet submodule interfaces to protobuf 13 | // Any. 14 | func RegisterInterfaces(registry codectypes.InterfaceRegistry) { 15 | registry.RegisterInterface( 16 | "tibc.core.packet.v1.PacketI", 17 | (*exported.PacketI)(nil), 18 | ) 19 | registry.RegisterInterface( 20 | "tibc.core.packet.v1.CleanPacketI", 21 | (*exported.CleanPacketI)(nil), 22 | ) 23 | registry.RegisterImplementations( 24 | (*exported.PacketI)(nil), 25 | &Packet{}, 26 | ) 27 | registry.RegisterImplementations( 28 | (*exported.CleanPacketI)(nil), 29 | &CleanPacket{}, 30 | ) 31 | registry.RegisterImplementations( 32 | (*sdk.Msg)(nil), 33 | &MsgRecvPacket{}, 34 | &MsgAcknowledgement{}, 35 | &MsgCleanPacket{}, 36 | &MsgRecvCleanPacket{}, 37 | ) 38 | 39 | msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) 40 | } 41 | 42 | // SubModuleCdc references the global x/ibc/core/04-channel module codec. Note, the codec should 43 | // ONLY be used in certain instances of tests and for JSON encoding. 44 | // 45 | // The actual codec used for serialization should be provided to x/ibc/core/04-channel and 46 | // defined at the application level. 47 | var SubModuleCdc = codec.NewProtoCodec(codectypes.NewInterfaceRegistry()) 48 | -------------------------------------------------------------------------------- /modules/tibc/core/04-packet/types/errors.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | errorsmod "cosmossdk.io/errors" 5 | host "github.com/bianjieai/tibc-go/modules/tibc/core/24-host" 6 | ) 7 | 8 | const moduleName = host.ModuleName + "-" + SubModuleName 9 | 10 | // TIBC packet sentinel errors 11 | var ( 12 | ErrSequenceSendNotFound = errorsmod.Register(moduleName, 2, "sequence send not found") 13 | ErrSequenceReceiveNotFound = errorsmod.Register(moduleName, 3, "sequence receive not found") 14 | ErrSequenceAckNotFound = errorsmod.Register(moduleName, 4, "sequence acknowledgement not found") 15 | ErrInvalidPacket = errorsmod.Register(moduleName, 5, "invalid packet") 16 | ErrInvalidAcknowledgement = errorsmod.Register(moduleName, 6, "invalid acknowledgement") 17 | ErrPacketCommitmentNotFound = errorsmod.Register(moduleName, 7, "packet commitment not found") 18 | ErrPacketReceived = errorsmod.Register(moduleName, 8, "packet already received") 19 | ErrAcknowledgementExists = errorsmod.Register(moduleName, 9, "acknowledgement for packet already exists") 20 | ErrInvalidCleanPacket = errorsmod.Register(moduleName, 10, "invalid clean packet") 21 | ) 22 | -------------------------------------------------------------------------------- /modules/tibc/core/04-packet/types/events.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "fmt" 5 | 6 | host "github.com/bianjieai/tibc-go/modules/tibc/core/24-host" 7 | ) 8 | 9 | // TIBC packet events 10 | const ( 11 | EventTypeSendPacket = "send_packet" 12 | EventTypeRecvPacket = "recv_packet" 13 | EventTypeWriteAck = "write_acknowledgement" 14 | EventTypeAcknowledgePacket = "acknowledge_packet" 15 | EventTypeSendCleanPacket = "send_clean_packet" 16 | EventTypeRecvCleanPacket = "recv_clean_packet" 17 | 18 | AttributeKeyData = "packet_data" 19 | AttributeKeyAck = "packet_ack" 20 | AttributeKeySequence = "packet_sequence" 21 | AttributeKeyPort = "packet_port" 22 | AttributeKeySrcChain = "packet_src_chain" 23 | AttributeKeyDstChain = "packet_dst_port" 24 | AttributeKeyRelayChain = "packet_relay_channel" 25 | ) 26 | 27 | // tibc packet events vars 28 | var ( 29 | AttributeValueCategory = fmt.Sprintf("%s_%s", host.ModuleName, SubModuleName) 30 | ) 31 | -------------------------------------------------------------------------------- /modules/tibc/core/04-packet/types/expected_keepers.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | storetypes "cosmossdk.io/store/types" 5 | sdk "github.com/cosmos/cosmos-sdk/types" 6 | 7 | "github.com/bianjieai/tibc-go/modules/tibc/core/exported" 8 | ) 9 | 10 | // ClientKeeper expected account TIBC client keeper 11 | type ClientKeeper interface { 12 | GetClientState(ctx sdk.Context, chainName string) (exported.ClientState, bool) 13 | GetClientConsensusState(ctx sdk.Context, chainName string, height exported.Height) (exported.ConsensusState, bool) 14 | ClientStore(ctx sdk.Context, chainName string) storetypes.KVStore 15 | GetChainName(ctx sdk.Context) string 16 | } 17 | 18 | // PortKeeper expected account TIBC port keeper 19 | type RoutingKeeper interface { 20 | Authenticate(ctx sdk.Context, sourceChain, destinationChain, port string) bool 21 | } 22 | -------------------------------------------------------------------------------- /modules/tibc/core/04-packet/types/keys.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | const ( 4 | // SubModuleName defines the TIBC packets name 5 | SubModuleName = "packet" 6 | 7 | // StoreKey is the store key string for TIBC packets 8 | StoreKey = SubModuleName 9 | 10 | // RouterKey is the message route for TIBC packets 11 | RouterKey = SubModuleName 12 | 13 | // QuerierRoute is the querier route for TIBC packets 14 | QuerierRoute = SubModuleName 15 | ) 16 | -------------------------------------------------------------------------------- /modules/tibc/core/04-packet/types/packet_test.go: -------------------------------------------------------------------------------- 1 | package types_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | 8 | codectypes "github.com/cosmos/cosmos-sdk/codec/types" 9 | 10 | clienttypes "github.com/bianjieai/tibc-go/modules/tibc/core/02-client/types" 11 | "github.com/bianjieai/tibc-go/modules/tibc/core/04-packet/types" 12 | ) 13 | 14 | func TestCommitPacket(t *testing.T) { 15 | packet := types.NewPacket(validPacketData, 1, sourceChain, destChain, relayChain, port) 16 | 17 | registry := codectypes.NewInterfaceRegistry() 18 | clienttypes.RegisterInterfaces(registry) 19 | types.RegisterInterfaces(registry) 20 | 21 | commitment := types.CommitPacket(&packet) 22 | require.NotNil(t, commitment) 23 | } 24 | 25 | func TestPacketValidateBasic(t *testing.T) { 26 | testCases := []struct { 27 | packet types.Packet 28 | expPass bool 29 | errMsg string 30 | }{ 31 | {types.NewPacket(validPacketData, 1, sourceChain, destChain, relayChain, port), true, ""}, 32 | {types.NewPacket(validPacketData, 0, sourceChain, destChain, relayChain, port), false, "invalid sequence"}, 33 | // {types.NewPacket(validPacketData, 1, invalidPort, destChain, relayChain, port), false, "invalid source port"}, 34 | // {types.NewPacket(validPacketData, 1, sourceChain, destChain, relayChain, invalidPort), false, "invalid port"}, 35 | {types.NewPacket(unknownPacketData, 1, sourceChain, destChain, relayChain, port), true, ""}, 36 | } 37 | 38 | for i, tc := range testCases { 39 | err := tc.packet.ValidateBasic() 40 | if tc.expPass { 41 | require.NoError(t, err, "Case %d failed: %s", i, tc.errMsg) 42 | } else { 43 | require.Error(t, err, "Invalid Case %d passed: %s", i, tc.errMsg) 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /modules/tibc/core/04-packet/types/query.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | clienttypes "github.com/bianjieai/tibc-go/modules/tibc/core/02-client/types" 5 | ) 6 | 7 | // NewQueryPacketCommitmentResponse creates a new QueryPacketCommitmentResponse instance 8 | func NewQueryPacketCommitmentResponse( 9 | commitment []byte, proof []byte, height clienttypes.Height, 10 | ) *QueryPacketCommitmentResponse { 11 | return &QueryPacketCommitmentResponse{ 12 | Commitment: commitment, 13 | Proof: proof, 14 | ProofHeight: height, 15 | } 16 | } 17 | 18 | // NewQueryPacketReceiptResponse creates a new QueryPacketReceiptResponse instance 19 | func NewQueryPacketReceiptResponse( 20 | recvd bool, proof []byte, height clienttypes.Height, 21 | ) *QueryPacketReceiptResponse { 22 | return &QueryPacketReceiptResponse{ 23 | Received: recvd, 24 | Proof: proof, 25 | ProofHeight: height, 26 | } 27 | } 28 | 29 | // NewQueryPacketAcknowledgementResponse creates a new QueryPacketAcknowledgementResponse instance 30 | func NewQueryPacketAcknowledgementResponse( 31 | acknowledgement []byte, proof []byte, height clienttypes.Height, 32 | ) *QueryPacketAcknowledgementResponse { 33 | return &QueryPacketAcknowledgementResponse{ 34 | Acknowledgement: acknowledgement, 35 | Proof: proof, 36 | ProofHeight: height, 37 | } 38 | } 39 | 40 | // NewQueryCleanPacketCommitmentResponse creates a new NewQueryCleanPacketCommitmentResponse instance 41 | func NewQueryCleanPacketCommitmentResponse( 42 | commitment []byte, proof []byte, height clienttypes.Height, 43 | ) *QueryCleanPacketCommitmentResponse { 44 | return &QueryCleanPacketCommitmentResponse{ 45 | Commitment: commitment, 46 | Proof: proof, 47 | ProofHeight: height, 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /modules/tibc/core/23-commitment/types/bench_test.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func BenchmarkMerkleProofEmpty(b *testing.B) { 8 | b.ReportAllocs() 9 | var mk MerkleProof 10 | for i := 0; i < b.N; i++ { 11 | if !mk.Empty() { 12 | b.Fatal("supposed to be empty") 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /modules/tibc/core/23-commitment/types/codec.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | codectypes "github.com/cosmos/cosmos-sdk/codec/types" 5 | 6 | "github.com/bianjieai/tibc-go/modules/tibc/core/exported" 7 | ) 8 | 9 | // RegisterInterfaces registers the commitment interfaces to protobuf Any. 10 | func RegisterInterfaces(registry codectypes.InterfaceRegistry) { 11 | registry.RegisterInterface( 12 | "ibc.core.commitment.v1.Root", 13 | (*exported.Root)(nil), 14 | ) 15 | registry.RegisterInterface( 16 | "ibc.core.commitment.v1.Prefix", 17 | (*exported.Prefix)(nil), 18 | ) 19 | registry.RegisterInterface( 20 | "ibc.core.commitment.v1.Path", 21 | (*exported.Path)(nil), 22 | ) 23 | registry.RegisterInterface( 24 | "ibc.core.commitment.v1.Proof", 25 | (*exported.Proof)(nil), 26 | ) 27 | 28 | registry.RegisterImplementations( 29 | (*exported.Root)(nil), 30 | &MerkleRoot{}, 31 | ) 32 | registry.RegisterImplementations( 33 | (*exported.Prefix)(nil), 34 | &MerklePrefix{}, 35 | ) 36 | registry.RegisterImplementations( 37 | (*exported.Path)(nil), 38 | &MerklePath{}, 39 | ) 40 | registry.RegisterImplementations( 41 | (*exported.Proof)(nil), 42 | &MerkleProof{}, 43 | ) 44 | } 45 | -------------------------------------------------------------------------------- /modules/tibc/core/23-commitment/types/commitment_test.go: -------------------------------------------------------------------------------- 1 | package types_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/suite" 7 | 8 | "cosmossdk.io/log" 9 | "cosmossdk.io/store/iavl" 10 | "cosmossdk.io/store/metrics" 11 | "cosmossdk.io/store/rootmulti" 12 | storetypes "cosmossdk.io/store/types" 13 | dbm "github.com/cosmos/cosmos-db" 14 | ) 15 | 16 | type MerkleTestSuite struct { 17 | suite.Suite 18 | 19 | store *rootmulti.Store 20 | storeKey *storetypes.KVStoreKey 21 | iavlStore *iavl.Store 22 | } 23 | 24 | func (suite *MerkleTestSuite) SetupTest() { 25 | db := dbm.NewMemDB() 26 | suite.store = rootmulti.NewStore(db, log.NewNopLogger(), metrics.NewNoOpMetrics()) 27 | 28 | suite.storeKey = storetypes.NewKVStoreKey("iavlStoreKey") 29 | 30 | suite.store.MountStoreWithDB(suite.storeKey, storetypes.StoreTypeIAVL, nil) 31 | _ = suite.store.LoadVersion(0) 32 | 33 | suite.iavlStore = suite.store.GetCommitStore(suite.storeKey).(*iavl.Store) 34 | } 35 | 36 | func TestMerkleTestSuite(t *testing.T) { 37 | suite.Run(t, new(MerkleTestSuite)) 38 | } 39 | -------------------------------------------------------------------------------- /modules/tibc/core/23-commitment/types/errors.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | errorsmod "cosmossdk.io/errors" 5 | host "github.com/bianjieai/tibc-go/modules/tibc/core/24-host" 6 | ) 7 | 8 | // SubModuleName is the error codespace 9 | const SubModuleName string = "commitment" 10 | 11 | const moduleName = host.ModuleName + "-" + SubModuleName 12 | 13 | // TIBC connection sentinel errors 14 | var ( 15 | ErrInvalidProof = errorsmod.Register(moduleName, 2, "invalid proof") 16 | ErrInvalidPrefix = errorsmod.Register(moduleName, 3, "invalid prefix") 17 | ErrInvalidMerkleProof = errorsmod.Register(moduleName, 4, "invalid merkle proof") 18 | ) 19 | -------------------------------------------------------------------------------- /modules/tibc/core/23-commitment/types/utils.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | ics23 "github.com/cosmos/ics23/go" 5 | 6 | crypto "github.com/cometbft/cometbft/proto/tendermint/crypto" 7 | 8 | errorsmod "cosmossdk.io/errors" 9 | ) 10 | 11 | // ConvertProofs converts crypto.ProofOps into MerkleProof 12 | func ConvertProofs(tmProof *crypto.ProofOps) (MerkleProof, error) { 13 | if tmProof == nil { 14 | return MerkleProof{}, errorsmod.Wrapf(ErrInvalidMerkleProof, "tendermint proof is nil") 15 | } 16 | // Unmarshal all proof ops to CommitmentProof 17 | proofs := make([]*ics23.CommitmentProof, len(tmProof.Ops)) 18 | for i, op := range tmProof.Ops { 19 | var p ics23.CommitmentProof 20 | err := p.Unmarshal(op.Data) 21 | if err != nil || p.Proof == nil { 22 | return MerkleProof{}, errorsmod.Wrapf( 23 | ErrInvalidMerkleProof, 24 | "could not unmarshal proof op into CommitmentProof at index %d: %v", 25 | i, 26 | err, 27 | ) 28 | } 29 | proofs[i] = &p 30 | } 31 | return MerkleProof{Proofs: proofs}, nil 32 | } 33 | -------------------------------------------------------------------------------- /modules/tibc/core/24-host/errors.go: -------------------------------------------------------------------------------- 1 | package host 2 | 3 | import ( 4 | errorsmod "cosmossdk.io/errors" 5 | ) 6 | 7 | // SubModuleName defines the TICS 24 host 8 | const SubModuleName = "host" 9 | 10 | const moduleName = ModuleName + "-" + SubModuleName 11 | 12 | // TIBC client sentinel errors 13 | var ( 14 | ErrInvalidID = errorsmod.Register(moduleName, 2, "invalid identifier") 15 | ErrInvalidPath = errorsmod.Register(moduleName, 3, "invalid path") 16 | ErrInvalidPacket = errorsmod.Register(moduleName, 4, "invalid packet") 17 | ErrInvalidRule = errorsmod.Register(moduleName, 5, "invalid routing rule") 18 | ) 19 | -------------------------------------------------------------------------------- /modules/tibc/core/24-host/parse.go: -------------------------------------------------------------------------------- 1 | package host 2 | 3 | import ( 4 | "strconv" 5 | "strings" 6 | 7 | errorsmod "cosmossdk.io/errors" 8 | ) 9 | 10 | // ParseIdentifier parses the sequence from the identifier using the provided prefix. This function 11 | // does not need to be used by counterparty chains. SDK generated connection and channel identifiers 12 | // are required to use this format. 13 | func ParseIdentifier(identifier, prefix string) (uint64, error) { 14 | if !strings.HasPrefix(identifier, prefix) { 15 | return 0, errorsmod.Wrapf(ErrInvalidID, "identifier doesn't contain prefix `%s`", prefix) 16 | } 17 | 18 | splitStr := strings.Split(identifier, prefix) 19 | if len(splitStr) != 2 { 20 | return 0, errorsmod.Wrapf(ErrInvalidID, "identifier must be in format: `%s{N}`", prefix) 21 | } 22 | 23 | // sanity check 24 | if splitStr[0] != "" { 25 | return 0, errorsmod.Wrapf(ErrInvalidID, "identifier must begin with prefix %s", prefix) 26 | } 27 | 28 | sequence, err := strconv.ParseUint(splitStr[1], 10, 64) 29 | if err != nil { 30 | return 0, errorsmod.Wrap(err, "failed to parse identifier sequence") 31 | } 32 | return sequence, nil 33 | } 34 | 35 | // ParseChannelPath returns the port and channel ID from a full path. It returns 36 | // an error if the provided path is invalid. 37 | func ParseChannelPath(path string) (string, string, error) { 38 | split := strings.Split(path, "/") 39 | if len(split) < 3 { 40 | return "", "", errorsmod.Wrapf(ErrInvalidPath, "cannot parse channel path %s", path) 41 | } 42 | 43 | return split[1], split[2], nil 44 | } 45 | -------------------------------------------------------------------------------- /modules/tibc/core/24-host/parse_test.go: -------------------------------------------------------------------------------- 1 | package host_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | 8 | host "github.com/bianjieai/tibc-go/modules/tibc/core/24-host" 9 | ) 10 | 11 | func TestParseIdentifier(t *testing.T) { 12 | testCases := []struct { 13 | name string 14 | identifier string 15 | prefix string 16 | expSeq uint64 17 | expPass bool 18 | }{ 19 | {"valid 0", "connection-0", "connection-", 0, true}, 20 | {"valid 1", "connection-1", "connection-", 1, true}, 21 | // one above uint64 max 22 | {"invalid uint64", "connection-18446744073709551616", "connection-", 0, false}, 23 | // uint64 == 20 characters 24 | {"invalid large sequence", "connection-2345682193567182931243", "connection-", 0, false}, 25 | {"capital prefix", "Connection-0", "connection-", 0, false}, 26 | {"double prefix", "connection-connection-0", "connection-", 0, false}, 27 | {"doesn't have prefix", "connection-0", "prefix", 0, false}, 28 | {"missing dash", "connection0", "connection-", 0, false}, 29 | {"blank id", " ", "connection-", 0, false}, 30 | {"empty id", "", "connection-", 0, false}, 31 | {"negative sequence", "connection--1", "connection-", 0, false}, 32 | } 33 | 34 | for _, tc := range testCases { 35 | seq, err := host.ParseIdentifier(tc.identifier, tc.prefix) 36 | require.Equal(t, tc.expSeq, seq) 37 | 38 | if tc.expPass { 39 | require.NoError(t, err, tc.name) 40 | } else { 41 | require.Error(t, err, tc.name) 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /modules/tibc/core/26-routing/client/cli/cli.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/cosmos/cosmos-sdk/client" 7 | 8 | "github.com/bianjieai/tibc-go/modules/tibc/core/26-routing/types" 9 | ) 10 | 11 | // GetQueryCmd returns the query commands for TIBC routing 12 | func GetQueryCmd() *cobra.Command { 13 | queryCmd := &cobra.Command{ 14 | Use: types.SubModuleName, 15 | Short: "tibc routing query subcommands", 16 | DisableFlagParsing: true, 17 | SuggestionsMinimumDistance: 2, 18 | RunE: client.ValidateCmd, 19 | } 20 | 21 | queryCmd.AddCommand( 22 | GetCmdQueryRoutingRulesCommitment(), 23 | ) 24 | return queryCmd 25 | } 26 | -------------------------------------------------------------------------------- /modules/tibc/core/26-routing/client/cli/query.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/spf13/cobra" 8 | 9 | "github.com/cosmos/cosmos-sdk/client" 10 | "github.com/cosmos/cosmos-sdk/client/flags" 11 | "github.com/cosmos/cosmos-sdk/version" 12 | 13 | host "github.com/bianjieai/tibc-go/modules/tibc/core/24-host" 14 | "github.com/bianjieai/tibc-go/modules/tibc/core/26-routing/types" 15 | ) 16 | 17 | // GetCmdQueryRoutingRulesCommitment defines the command to query routing rules 18 | func GetCmdQueryRoutingRulesCommitment() *cobra.Command { 19 | cmd := &cobra.Command{ 20 | Use: "routing-rules", 21 | Short: "Query routing rules commitment", 22 | Long: "Query routing rules commitment", 23 | Example: fmt.Sprintf( 24 | "%s query %s %s routing-rules", version.AppName, host.ModuleName, types.SubModuleName, 25 | ), 26 | Args: cobra.NoArgs, 27 | RunE: func(cmd *cobra.Command, args []string) error { 28 | clientCtx, err := client.GetClientQueryContext(cmd) 29 | if err != nil { 30 | return err 31 | } 32 | queryClient := types.NewQueryClient(clientCtx) 33 | if err != nil { 34 | return err 35 | } 36 | req := &types.QueryRoutingRulesRequest{} 37 | 38 | res, err := queryClient.RoutingRules(context.Background(), req) 39 | if err != nil { 40 | return err 41 | } 42 | 43 | return clientCtx.PrintProto(res) 44 | }, 45 | } 46 | 47 | flags.AddQueryFlagsToCmd(cmd) 48 | return cmd 49 | } 50 | -------------------------------------------------------------------------------- /modules/tibc/core/26-routing/client/cli/tx.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "encoding/json" 5 | "io/ioutil" 6 | 7 | "github.com/pkg/errors" 8 | "github.com/spf13/cobra" 9 | 10 | "github.com/cosmos/cosmos-sdk/client" 11 | "github.com/cosmos/cosmos-sdk/client/tx" 12 | sdk "github.com/cosmos/cosmos-sdk/types" 13 | "github.com/cosmos/cosmos-sdk/x/gov/client/cli" 14 | govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" 15 | 16 | "github.com/bianjieai/tibc-go/modules/tibc/core/26-routing/types" 17 | ) 18 | 19 | // NewSetRoutingRulesProposalCmd implements a command handler for submitting a setting rules proposal transaction. 20 | func NewSetRoutingRulesProposalCmd() *cobra.Command { 21 | cmd := &cobra.Command{ 22 | Use: "set-rules [path/to/routing_rules.json] [flags]", 23 | Args: cobra.ExactArgs(1), 24 | Short: "Submit a rules set proposal", 25 | Long: "set routing rules", 26 | RunE: func(cmd *cobra.Command, args []string) error { 27 | clientCtx, err := client.GetClientTxContext(cmd) 28 | if err != nil { 29 | return err 30 | } 31 | routingRulesBz, err := ioutil.ReadFile(args[0]) 32 | if err != nil { 33 | return errors.Wrap(err, "neither JSON input nor path to .json file for routing rules were provided") 34 | } 35 | 36 | var rules []string 37 | if err := json.Unmarshal(routingRulesBz, &rules); err != nil { 38 | return errors.Wrap(err, "error unmarshalling rules file") 39 | } 40 | 41 | title, err := cmd.Flags().GetString(cli.FlagTitle) 42 | if err != nil { 43 | return err 44 | } 45 | 46 | description, err := cmd.Flags().GetString(cli.FlagDescription) 47 | if err != nil { 48 | return err 49 | } 50 | 51 | content, err := types.NewSetRoutingRulesProposal(title, description, rules) 52 | if err != nil { 53 | return err 54 | } 55 | 56 | depositStr, err := cmd.Flags().GetString(cli.FlagDeposit) 57 | if err != nil { 58 | return err 59 | } 60 | 61 | deposit, err := sdk.ParseCoinsNormalized(depositStr) 62 | if err != nil { 63 | return err 64 | } 65 | 66 | msg, err := govv1beta1.NewMsgSubmitProposal(content, deposit, clientCtx.GetFromAddress()) 67 | if err != nil { 68 | return err 69 | } 70 | 71 | return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) 72 | }, 73 | } 74 | 75 | cmd.Flags().String(cli.FlagTitle, "", "title of proposal") 76 | cmd.Flags().String(cli.FlagDescription, "", "description of proposal") 77 | cmd.Flags().String(cli.FlagDeposit, "", "deposit of proposal") 78 | return cmd 79 | } 80 | -------------------------------------------------------------------------------- /modules/tibc/core/26-routing/genesis.go: -------------------------------------------------------------------------------- 1 | package routing 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | 6 | "github.com/bianjieai/tibc-go/modules/tibc/core/26-routing/keeper" 7 | "github.com/bianjieai/tibc-go/modules/tibc/core/26-routing/types" 8 | ) 9 | 10 | // InitGenesis initializes the tibc routing submodule's state from a provided genesis 11 | // state. 12 | func InitGenesis(ctx sdk.Context, k keeper.Keeper, gs types.GenesisState) { 13 | err := k.SetRoutingRules(ctx, gs.Rules) 14 | if err != nil { 15 | panic(err) 16 | } 17 | } 18 | 19 | // ExportGenesis returns the tibc routing submodule's exported genesis. 20 | func ExportGenesis(ctx sdk.Context, k keeper.Keeper) types.GenesisState { 21 | rules, _ := k.GetRoutingRules(ctx) 22 | return types.GenesisState{ 23 | Rules: rules, 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /modules/tibc/core/26-routing/keeper/grpc_query.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "context" 5 | 6 | "google.golang.org/grpc/codes" 7 | "google.golang.org/grpc/status" 8 | 9 | errorsmod "cosmossdk.io/errors" 10 | sdk "github.com/cosmos/cosmos-sdk/types" 11 | 12 | "github.com/bianjieai/tibc-go/modules/tibc/core/26-routing/types" 13 | ) 14 | 15 | var _ types.QueryServer = (*Keeper)(nil) 16 | 17 | //RoutingRules implements the Query/RoutingRules gRPC method 18 | func (q Keeper) RoutingRules(c context.Context, req *types.QueryRoutingRulesRequest) (*types.QueryRoutingRulesResponse, error) { 19 | if req == nil { 20 | return nil, status.Error(codes.InvalidArgument, "empty request") 21 | } 22 | ctx := sdk.UnwrapSDKContext(c) 23 | routingRules, found := q.GetRoutingRules(ctx) 24 | if !found { 25 | return nil, status.Error( 26 | codes.NotFound, 27 | errorsmod.Wrap(types.ErrRoutingRulesNotFound, "routing rules not found").Error(), 28 | ) 29 | } 30 | 31 | return &types.QueryRoutingRulesResponse{Rules: routingRules}, nil 32 | } 33 | -------------------------------------------------------------------------------- /modules/tibc/core/26-routing/keeper/grpc_query_test.go: -------------------------------------------------------------------------------- 1 | package keeper_test 2 | 3 | import ( 4 | "fmt" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | 8 | "github.com/bianjieai/tibc-go/modules/tibc/core/26-routing/types" 9 | ) 10 | 11 | func (suite *KeeperTestSuite) TestQueryPacketCommitment() { 12 | var ( 13 | req *types.QueryRoutingRulesRequest 14 | rules []string 15 | ) 16 | 17 | testCases := []struct { 18 | msg string 19 | malleate func() 20 | expPass bool 21 | }{{ 22 | "empty request", 23 | func() { 24 | req = nil 25 | }, 26 | false, 27 | }, { 28 | "success", 29 | func() { 30 | rules = []string{"source,dest,dgsbl"} 31 | suite.chain.App.TIBCKeeper.RoutingKeeper.SetRoutingRules(suite.chain.GetContext(), rules) 32 | req = &types.QueryRoutingRulesRequest{} 33 | }, 34 | true, 35 | }} 36 | 37 | for _, tc := range testCases { 38 | suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { 39 | suite.SetupTest() // reset 40 | tc.malleate() 41 | ctx := sdk.WrapSDKContext(suite.chain.GetContext()) 42 | 43 | res, err := suite.chain.QueryServer.RoutingRules(ctx, req) 44 | 45 | if tc.expPass { 46 | suite.Require().NoError(err) 47 | suite.Require().NotNil(res) 48 | suite.Require().Equal(rules, res.Rules) 49 | } else { 50 | suite.Require().Error(err) 51 | } 52 | }) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /modules/tibc/core/26-routing/keeper/proposal.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | 6 | "github.com/bianjieai/tibc-go/modules/tibc/core/26-routing/types" 7 | ) 8 | 9 | // HandleSetRoutingRulesProposal will try to set routing rules if and only if the proposal passes. 10 | func (k Keeper) HandleSetRoutingRulesProposal(ctx sdk.Context, p *types.SetRoutingRulesProposal) error { 11 | return k.SetRoutingRules(ctx, p.Rules) 12 | } 13 | -------------------------------------------------------------------------------- /modules/tibc/core/26-routing/module.go: -------------------------------------------------------------------------------- 1 | package routing 2 | 3 | import ( 4 | "github.com/cosmos/gogoproto/grpc" 5 | "github.com/spf13/cobra" 6 | 7 | "github.com/bianjieai/tibc-go/modules/tibc/core/26-routing/client/cli" 8 | "github.com/bianjieai/tibc-go/modules/tibc/core/26-routing/types" 9 | ) 10 | 11 | // Name returns the TIBC routing TICS name. 12 | func Name() string { 13 | return types.SubModuleName 14 | } 15 | 16 | // GetTxCmd returns the root tx command for TIBC routing. 17 | func GetTxCmd() *cobra.Command { 18 | return nil 19 | } 20 | 21 | // GetQueryCmd returns the root query command for TIBC routing. 22 | func GetQueryCmd() *cobra.Command { 23 | return cli.GetQueryCmd() 24 | } 25 | 26 | // RegisterQueryService registers the gRPC query service for TIBC routing. 27 | func RegisterQueryService(server grpc.Server, queryServer types.QueryServer) { 28 | types.RegisterQueryServer(server, queryServer) 29 | } 30 | -------------------------------------------------------------------------------- /modules/tibc/core/26-routing/types/codec.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | codectypes "github.com/cosmos/cosmos-sdk/codec/types" 5 | sdk "github.com/cosmos/cosmos-sdk/types" 6 | govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" 7 | ) 8 | 9 | // RegisterInterfaces registers the routing interfaces to protobuf Any. 10 | func RegisterInterfaces(registry codectypes.InterfaceRegistry) { 11 | registry.RegisterImplementations( 12 | (*govv1beta1.Content)(nil), 13 | &SetRoutingRulesProposal{}, 14 | ) 15 | 16 | registry.RegisterImplementations( 17 | (*sdk.Msg)(nil), 18 | &MsgSetRoutingRules{}, 19 | ) 20 | } 21 | -------------------------------------------------------------------------------- /modules/tibc/core/26-routing/types/errors.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | errorsmod "cosmossdk.io/errors" 5 | host "github.com/bianjieai/tibc-go/modules/tibc/core/24-host" 6 | ) 7 | 8 | const moduleName = host.ModuleName + "-" + SubModuleName 9 | 10 | // TIBC routing sentinel errors 11 | var ( 12 | ErrInvalidRoute = errorsmod.Register(moduleName, 2, "route not found") 13 | ErrInvalidRule = errorsmod.Register(moduleName, 3, "invalid rule") 14 | ErrFailMarshalRules = errorsmod.Register(moduleName, 4, "failed to marshal rules") 15 | ErrFailUnmarshalRules = errorsmod.Register(moduleName, 5, "failed to unmarshal rules") 16 | ErrRoutingRulesNotFound = errorsmod.Register(moduleName, 6, "routing rules not found") 17 | ) 18 | -------------------------------------------------------------------------------- /modules/tibc/core/26-routing/types/genesis.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "regexp" 5 | 6 | errorsmod "cosmossdk.io/errors" 7 | ) 8 | 9 | func DefaultGenesisState() GenesisState { 10 | return GenesisState{ 11 | Rules: []string{}, 12 | } 13 | } 14 | func NewGenesisState(rules []string) GenesisState { 15 | return GenesisState{ 16 | Rules: rules, 17 | } 18 | } 19 | 20 | func (gs GenesisState) Validate() error { 21 | for _, rule := range gs.Rules { 22 | valid, _ := regexp.MatchString(RulePattern, rule) 23 | if !valid { 24 | return errorsmod.Wrap(ErrInvalidRule, "invalid rule") 25 | } 26 | } 27 | return nil 28 | } 29 | -------------------------------------------------------------------------------- /modules/tibc/core/26-routing/types/genesis_test.go: -------------------------------------------------------------------------------- 1 | package types_test 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/bianjieai/tibc-go/modules/tibc/core/26-routing/types" 7 | ) 8 | 9 | func (suite *TypesTestSuite) TestValidateGenesis() { 10 | 11 | testCases := []struct { 12 | name string 13 | genState types.GenesisState 14 | expPass bool 15 | }{ 16 | { 17 | name: "empty", 18 | genState: types.NewGenesisState(nil), 19 | expPass: true, 20 | }, 21 | { 22 | name: "invalid genesis1", 23 | genState: types.NewGenesisState([]string{"1a"}), 24 | expPass: false, 25 | }, 26 | { 27 | name: "invalid genesis2", 28 | genState: types.NewGenesisState([]string{"1a,2b"}), 29 | expPass: false, 30 | }, 31 | { 32 | name: "valid genesis", 33 | genState: types.NewGenesisState([]string{fmt.Sprintf("source,dest,port")}), 34 | expPass: true, 35 | }, 36 | } 37 | for _, tc := range testCases { 38 | tc := tc 39 | err := tc.genState.Validate() 40 | if tc.expPass { 41 | suite.Require().NoError(err, tc.name) 42 | } else { 43 | suite.Require().Error(err, tc.name) 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /modules/tibc/core/26-routing/types/keys.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | const ( 4 | // SubModuleName defines the TIBC port name 5 | SubModuleName = "routing" 6 | 7 | // StoreKey is the store key string for TIBC ports 8 | StoreKey = SubModuleName 9 | 10 | // RouterKey is the message route for TIBC ports 11 | RouterKey = SubModuleName 12 | 13 | // QuerierRoute is the querier route for TIBC ports 14 | QuerierRoute = SubModuleName 15 | ) 16 | 17 | const ( 18 | // RulePattern format "source,dest,port" 19 | RulePattern = "^(([a-zA-Z0-9\\.\\_\\+\\-\\#\\[\\]\\<\\>]{1,64}|[*]),){2}([a-zA-Z0-9\\.\\_\\+\\-\\#\\[\\]\\<\\>]{1,64}|[*])$" 20 | ) 21 | -------------------------------------------------------------------------------- /modules/tibc/core/26-routing/types/module.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | 6 | packettypes "github.com/bianjieai/tibc-go/modules/tibc/core/04-packet/types" 7 | ) 8 | 9 | // TIBCModule defines an interface that implements all the callbacks 10 | // that modules must define as specified in TICS-26 11 | type TIBCModule interface { 12 | // OnRecvPacket must return the acknowledgement bytes 13 | // In the case of an asynchronous acknowledgement, nil should be returned. 14 | OnRecvPacket( 15 | ctx sdk.Context, 16 | packet packettypes.Packet, 17 | ) (*sdk.Result, []byte, error) 18 | 19 | OnAcknowledgementPacket( 20 | ctx sdk.Context, 21 | packet packettypes.Packet, 22 | acknowledgement []byte, 23 | ) (*sdk.Result, error) 24 | } 25 | -------------------------------------------------------------------------------- /modules/tibc/core/26-routing/types/msg.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | errorsmod "cosmossdk.io/errors" 5 | sdk "github.com/cosmos/cosmos-sdk/types" 6 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 7 | ) 8 | 9 | var ( 10 | _ sdk.Msg = &MsgSetRoutingRules{} 11 | ) 12 | 13 | // ValidateBasic implements sdk.Msg 14 | func (msg MsgSetRoutingRules) ValidateBasic() error { 15 | _, err := sdk.AccAddressFromBech32(msg.Authority) 16 | if err != nil { 17 | return errorsmod.Wrapf( 18 | sdkerrors.ErrInvalidAddress, 19 | "string could not be parsed as address: %v", 20 | err, 21 | ) 22 | } 23 | context := SetRoutingRulesProposal{ 24 | Title: msg.Title, 25 | Description: msg.Description, 26 | Rules: msg.Rules, 27 | } 28 | return context.ValidateBasic() 29 | } 30 | 31 | // GetSigners implements sdk.Msg 32 | func (msg MsgSetRoutingRules) GetSigners() []sdk.AccAddress { 33 | accAddr, err := sdk.AccAddressFromBech32(msg.Authority) 34 | if err != nil { 35 | panic(err) 36 | } 37 | return []sdk.AccAddress{accAddr} 38 | } 39 | -------------------------------------------------------------------------------- /modules/tibc/core/26-routing/types/port.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | type Port string 4 | 5 | const ( 6 | FT Port = "FT" 7 | NFT Port = "NFT" 8 | MT Port = "MT" 9 | CONTRACT Port = "CONTRACT" 10 | SERVICE Port = "SERVICE" 11 | ) 12 | -------------------------------------------------------------------------------- /modules/tibc/core/26-routing/types/proposal.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" 5 | 6 | host "github.com/bianjieai/tibc-go/modules/tibc/core/24-host" 7 | ) 8 | 9 | const ( 10 | ProposalTypeSetRoutingRules = "SetRoutingRules" 11 | ) 12 | 13 | var ( 14 | _ govv1beta1.Content = &SetRoutingRulesProposal{} 15 | ) 16 | 17 | func init() { 18 | govv1beta1.RegisterProposalType(ProposalTypeSetRoutingRules) 19 | } 20 | 21 | // NewSetRoutingRulesProposal creates a new setting rules proposal. 22 | func NewSetRoutingRulesProposal(title, description string, rules []string) (*SetRoutingRulesProposal, error) { 23 | return &SetRoutingRulesProposal{ 24 | Title: title, 25 | Description: description, 26 | Rules: rules, 27 | }, nil 28 | } 29 | 30 | // GetTitle returns the title of a setting rules proposal. 31 | func (cup *SetRoutingRulesProposal) GetTitle() string { return cup.Title } 32 | 33 | // GetDescription returns the description of a setting rules proposal. 34 | func (cup *SetRoutingRulesProposal) GetDescription() string { return cup.Description } 35 | 36 | // ProposalRoute returns the routing key of a setting rules proposal. 37 | func (cup *SetRoutingRulesProposal) ProposalRoute() string { return host.RouterKey } 38 | 39 | // ProposalType returns the type of a setting rules proposal. 40 | func (cup *SetRoutingRulesProposal) ProposalType() string { return ProposalTypeSetRoutingRules } 41 | 42 | // ValidateBasic runs basic stateless validity checks 43 | func (cup *SetRoutingRulesProposal) ValidateBasic() error { 44 | err := govv1beta1.ValidateAbstract(cup) 45 | if err != nil { 46 | return err 47 | } 48 | 49 | if err := host.RoutingRulesValidator(cup.Rules); err != nil { 50 | return err 51 | } 52 | return nil 53 | } 54 | -------------------------------------------------------------------------------- /modules/tibc/core/26-routing/types/proposal_test.go: -------------------------------------------------------------------------------- 1 | package types_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/suite" 7 | 8 | "github.com/bianjieai/tibc-go/modules/tibc/core/26-routing/types" 9 | tibctesting "github.com/bianjieai/tibc-go/modules/tibc/testing" 10 | ) 11 | 12 | type TypesTestSuite struct { 13 | suite.Suite 14 | 15 | coordinator *tibctesting.Coordinator 16 | 17 | chain *tibctesting.TestChain 18 | } 19 | 20 | func (suite *TypesTestSuite) SetupTest() { 21 | suite.coordinator = tibctesting.NewCoordinator(suite.T(), 1) 22 | suite.chain = suite.coordinator.GetChain(tibctesting.GetChainID(0)) 23 | } 24 | 25 | func TestTypesTestSuite(t *testing.T) { 26 | suite.Run(t, new(TypesTestSuite)) 27 | } 28 | 29 | func (suite *TypesTestSuite) TestNewSetRoutingRulesProposal() { 30 | p, err := types.NewSetRoutingRulesProposal(tibctesting.Title, tibctesting.Description, []string{"source.dest.dgsbl"}) 31 | suite.Require().NoError(err) 32 | suite.Require().NotNil(p) 33 | } 34 | -------------------------------------------------------------------------------- /modules/tibc/core/client/cli/cli.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/cosmos/cosmos-sdk/client" 7 | 8 | ibcclient "github.com/bianjieai/tibc-go/modules/tibc/core/02-client" 9 | packet "github.com/bianjieai/tibc-go/modules/tibc/core/04-packet" 10 | host "github.com/bianjieai/tibc-go/modules/tibc/core/24-host" 11 | routing "github.com/bianjieai/tibc-go/modules/tibc/core/26-routing" 12 | ) 13 | 14 | // GetTxCmd returns the transaction commands for this module 15 | func GetTxCmd() *cobra.Command { 16 | ibcTxCmd := &cobra.Command{ 17 | Use: host.ModuleName, 18 | Short: "IBC transaction subcommands", 19 | DisableFlagParsing: true, 20 | SuggestionsMinimumDistance: 2, 21 | RunE: client.ValidateCmd, 22 | } 23 | 24 | ibcTxCmd.AddCommand( 25 | ibcclient.GetTxCmd(), 26 | packet.GetTxCmd(), 27 | ) 28 | 29 | return ibcTxCmd 30 | } 31 | 32 | // GetQueryCmd returns the cli query commands for this module 33 | func GetQueryCmd() *cobra.Command { 34 | // Group tibc queries under a subcommand 35 | ibcQueryCmd := &cobra.Command{ 36 | Use: host.ModuleName, 37 | Short: "Querying commands for the TIBC module", 38 | DisableFlagParsing: true, 39 | SuggestionsMinimumDistance: 2, 40 | RunE: client.ValidateCmd, 41 | } 42 | 43 | ibcQueryCmd.AddCommand( 44 | ibcclient.GetQueryCmd(), 45 | packet.GetQueryCmd(), 46 | routing.GetQueryCmd(), 47 | ) 48 | 49 | return ibcQueryCmd 50 | } 51 | -------------------------------------------------------------------------------- /modules/tibc/core/client/cli/proposal_handler.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | errorsmod "cosmossdk.io/errors" 5 | sdk "github.com/cosmos/cosmos-sdk/types" 6 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 7 | govclient "github.com/cosmos/cosmos-sdk/x/gov/client" 8 | govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" 9 | 10 | clientcli "github.com/bianjieai/tibc-go/modules/tibc/core/02-client/client/cli" 11 | clienttypes "github.com/bianjieai/tibc-go/modules/tibc/core/02-client/types" 12 | routingcli "github.com/bianjieai/tibc-go/modules/tibc/core/26-routing/client/cli" 13 | routingtypes "github.com/bianjieai/tibc-go/modules/tibc/core/26-routing/types" 14 | "github.com/bianjieai/tibc-go/modules/tibc/core/keeper" 15 | ) 16 | 17 | // GovHandlers defines the client manager proposal handlers 18 | var GovHandlers = []govclient.ProposalHandler{ 19 | govclient.NewProposalHandler(clientcli.NewCreateClientProposalCmd), 20 | govclient.NewProposalHandler(clientcli.NewUpgradeClientProposalCmd), 21 | govclient.NewProposalHandler(clientcli.NewRegisterRelayerProposalCmd), 22 | govclient.NewProposalHandler(routingcli.NewSetRoutingRulesProposalCmd), 23 | } 24 | 25 | // NewProposalHandler defines the client manager proposal handler 26 | func NewProposalHandler(k *keeper.Keeper) govv1beta1.Handler { 27 | return func(ctx sdk.Context, content govv1beta1.Content) error { 28 | switch c := content.(type) { 29 | case *clienttypes.CreateClientProposal: 30 | return k.ClientKeeper.HandleCreateClientProposal(ctx, c) 31 | case *clienttypes.UpgradeClientProposal: 32 | return k.ClientKeeper.HandleUpgradeClientProposal(ctx, c) 33 | case *clienttypes.RegisterRelayerProposal: 34 | return k.ClientKeeper.HandleRegisterRelayerProposal(ctx, c) 35 | case *routingtypes.SetRoutingRulesProposal: 36 | return k.RoutingKeeper.HandleSetRoutingRulesProposal(ctx, c) 37 | default: 38 | return errorsmod.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized tibc proposal content type: %T", c) 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /modules/tibc/core/exported/commitment.go: -------------------------------------------------------------------------------- 1 | package exported 2 | 3 | import ics23 "github.com/cosmos/ics23/go" 4 | 5 | // TICS 023 Types Implementation 6 | // 7 | // This file includes types defined under 8 | // https://github.com/bianjieai/tics/tree/master/spec/tics-023-vector-commitments 9 | 10 | // spec:Path and spec:Value are defined as bytestring 11 | 12 | // Root implements spec:CommitmentRoot. 13 | // A root is constructed from a set of key-value pairs, 14 | // and the inclusion or non-inclusion of an arbitrary key-value pair 15 | // can be proven with the proof. 16 | type Root interface { 17 | GetHash() []byte 18 | Empty() bool 19 | } 20 | 21 | // Prefix implements spec:CommitmentPrefix. 22 | // Prefix represents the common "prefix" that a set of keys shares. 23 | type Prefix interface { 24 | Bytes() []byte 25 | Empty() bool 26 | } 27 | 28 | // Path implements spec:CommitmentPath. 29 | // A path is the additional information provided to the verification function. 30 | type Path interface { 31 | String() string 32 | Empty() bool 33 | } 34 | 35 | // Proof implements spec:CommitmentProof. 36 | // Proof can prove whether the key-value pair is a part of the Root or not. 37 | // Each proof has designated key-value pair it is able to prove. 38 | // Proofs includes key but value is provided dynamically at the verification time. 39 | type Proof interface { 40 | VerifyMembership([]*ics23.ProofSpec, Root, Path, []byte) error 41 | VerifyNonMembership([]*ics23.ProofSpec, Root, Path) error 42 | Empty() bool 43 | 44 | ValidateBasic() error 45 | } 46 | -------------------------------------------------------------------------------- /modules/tibc/core/exported/packet.go: -------------------------------------------------------------------------------- 1 | package exported 2 | 3 | // PacketI defines the standard interface for TIBC clean packets 4 | type PacketI interface { 5 | GetSequence() uint64 6 | GetPort() string 7 | GetSourceChain() string 8 | GetDestChain() string 9 | GetRelayChain() string 10 | GetData() []byte 11 | ValidateBasic() error 12 | } 13 | 14 | // CleanPacketI defines the standard interface for TIBC clean packets 15 | type CleanPacketI interface { 16 | GetSequence() uint64 17 | GetSourceChain() string 18 | GetDestChain() string 19 | GetRelayChain() string 20 | ValidateBasic() error 21 | } 22 | -------------------------------------------------------------------------------- /modules/tibc/core/genesis.go: -------------------------------------------------------------------------------- 1 | package tibc 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | 6 | client "github.com/bianjieai/tibc-go/modules/tibc/core/02-client" 7 | packet "github.com/bianjieai/tibc-go/modules/tibc/core/04-packet" 8 | routing "github.com/bianjieai/tibc-go/modules/tibc/core/26-routing" 9 | "github.com/bianjieai/tibc-go/modules/tibc/core/keeper" 10 | "github.com/bianjieai/tibc-go/modules/tibc/core/types" 11 | ) 12 | 13 | // InitGenesis initializes the tibc state from a provided genesis 14 | // state. 15 | func InitGenesis(ctx sdk.Context, k keeper.Keeper, createLocalhost bool, gs *types.GenesisState) { 16 | client.InitGenesis(ctx, k.ClientKeeper, gs.ClientGenesis) 17 | packet.InitGenesis(ctx, k.PacketKeeper, gs.PacketGenesis) 18 | routing.InitGenesis(ctx, k.RoutingKeeper, gs.RoutingGenesis) 19 | } 20 | 21 | // ExportGenesis returns the tibc exported genesis. 22 | func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState { 23 | return &types.GenesisState{ 24 | ClientGenesis: client.ExportGenesis(ctx, k.ClientKeeper), 25 | PacketGenesis: packet.ExportGenesis(ctx, k.PacketKeeper), 26 | RoutingGenesis: routing.ExportGenesis(ctx, k.RoutingKeeper), 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /modules/tibc/core/keeper/keeper.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | storetypes "cosmossdk.io/store/types" 5 | "github.com/cosmos/cosmos-sdk/codec" 6 | 7 | clientkeeper "github.com/bianjieai/tibc-go/modules/tibc/core/02-client/keeper" 8 | clienttypes "github.com/bianjieai/tibc-go/modules/tibc/core/02-client/types" 9 | packetkeeper "github.com/bianjieai/tibc-go/modules/tibc/core/04-packet/keeper" 10 | routingkeeper "github.com/bianjieai/tibc-go/modules/tibc/core/26-routing/keeper" 11 | routingtypes "github.com/bianjieai/tibc-go/modules/tibc/core/26-routing/types" 12 | "github.com/bianjieai/tibc-go/modules/tibc/core/types" 13 | ) 14 | 15 | var _ types.QueryServer = (*Keeper)(nil) 16 | 17 | // Keeper defines each TICS keeper for TIBC 18 | type Keeper struct { 19 | // implements gRPC QueryServer interface 20 | types.QueryServer 21 | 22 | cdc codec.BinaryCodec 23 | 24 | ClientKeeper clientkeeper.Keeper 25 | PacketKeeper packetkeeper.Keeper 26 | RoutingKeeper routingkeeper.Keeper 27 | 28 | authority string 29 | } 30 | 31 | // NewKeeper creates a new tibc Keeper 32 | func NewKeeper( 33 | cdc codec.BinaryCodec, 34 | key storetypes.StoreKey, 35 | stakingKeeper clienttypes.StakingKeeper, 36 | authority string, 37 | ) *Keeper { 38 | clientKeeper := clientkeeper.NewKeeper(cdc, key, stakingKeeper) 39 | routingKeeper := routingkeeper.NewKeeper(key) 40 | packetkeeper := packetkeeper.NewKeeper(cdc, key, clientKeeper, routingKeeper) 41 | 42 | return &Keeper{ 43 | cdc: cdc, 44 | ClientKeeper: clientKeeper, 45 | PacketKeeper: packetkeeper, 46 | RoutingKeeper: routingKeeper, 47 | authority: authority, 48 | } 49 | } 50 | 51 | // Codec returns the TIBC module codec. 52 | func (k Keeper) Codec() codec.BinaryCodec { 53 | return k.cdc 54 | } 55 | 56 | // SetRouter sets the Router in TIBC Keeper and seals it. The method panics if 57 | // there is an existing router that's already sealed. 58 | func (k *Keeper) SetRouter(rtr *routingtypes.Router) { 59 | k.RoutingKeeper.SetRouter(rtr) 60 | } 61 | -------------------------------------------------------------------------------- /modules/tibc/core/simulation/decoder.go: -------------------------------------------------------------------------------- 1 | package simulation 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/cosmos/cosmos-sdk/types/kv" 7 | 8 | clientsim "github.com/bianjieai/tibc-go/modules/tibc/core/02-client/simulation" 9 | packetsim "github.com/bianjieai/tibc-go/modules/tibc/core/04-packet/simulation" 10 | host "github.com/bianjieai/tibc-go/modules/tibc/core/24-host" 11 | "github.com/bianjieai/tibc-go/modules/tibc/core/keeper" 12 | ) 13 | 14 | // NewDecodeStore returns a decoder function closure that unmarshals the KVPair's 15 | // Value to the corresponding tibc type. 16 | func NewDecodeStore(k keeper.Keeper) func(kvA, kvB kv.Pair) string { 17 | return func(kvA, kvB kv.Pair) string { 18 | if res, found := clientsim.NewDecodeStore(k.ClientKeeper, kvA, kvB); found { 19 | return res 20 | } 21 | 22 | if res, found := packetsim.NewDecodeStore(k.Codec(), kvA, kvB); found { 23 | return res 24 | } 25 | 26 | panic(fmt.Sprintf("invalid %s key prefix: %s", host.ModuleName, string(kvA.Key))) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /modules/tibc/core/simulation/decoder_test.go: -------------------------------------------------------------------------------- 1 | package simulation_test 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/require" 8 | 9 | "github.com/cosmos/cosmos-sdk/types/kv" 10 | 11 | host "github.com/bianjieai/tibc-go/modules/tibc/core/24-host" 12 | "github.com/bianjieai/tibc-go/modules/tibc/core/simulation" 13 | ibctmtypes "github.com/bianjieai/tibc-go/modules/tibc/light-clients/07-tendermint/types" 14 | "github.com/bianjieai/tibc-go/simapp" 15 | ) 16 | 17 | func TestDecodeStore(t *testing.T) { 18 | app := simapp.Setup(t) 19 | dec := simulation.NewDecodeStore(*app.TIBCKeeper) 20 | 21 | chainName := "clientidone" 22 | 23 | clientState := &ibctmtypes.ClientState{} 24 | 25 | kvPairs := kv.Pairs{ 26 | Pairs: []kv.Pair{{ 27 | Key: host.FullClientStateKey(chainName), 28 | Value: app.TIBCKeeper.ClientKeeper.MustMarshalClientState(clientState), 29 | }, { 30 | Key: []byte{0x99}, 31 | Value: []byte{0x99}, 32 | }}, 33 | } 34 | tests := []struct { 35 | name string 36 | expectedLog string 37 | }{ 38 | {"ClientState", fmt.Sprintf("ClientState A: %v\nClientState B: %v", clientState, clientState)}, 39 | {"other", ""}, 40 | } 41 | 42 | for i, tt := range tests { 43 | i, tt := i, tt 44 | t.Run(tt.name, func(t *testing.T) { 45 | if i == len(tests)-1 { 46 | require.Panics(t, func() { dec(kvPairs.Pairs[i], kvPairs.Pairs[i]) }, tt.name) 47 | } else { 48 | require.Equal(t, tt.expectedLog, dec(kvPairs.Pairs[i], kvPairs.Pairs[i]), tt.name) 49 | } 50 | }) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /modules/tibc/core/simulation/genesis.go: -------------------------------------------------------------------------------- 1 | package simulation 2 | 3 | // DONTCOVER 4 | 5 | import ( 6 | "encoding/json" 7 | "fmt" 8 | "math/rand" 9 | 10 | "github.com/cosmos/cosmos-sdk/types/module" 11 | 12 | clientsims "github.com/bianjieai/tibc-go/modules/tibc/core/02-client/simulation" 13 | clienttypes "github.com/bianjieai/tibc-go/modules/tibc/core/02-client/types" 14 | packetsims "github.com/bianjieai/tibc-go/modules/tibc/core/04-packet/simulation" 15 | packettypes "github.com/bianjieai/tibc-go/modules/tibc/core/04-packet/types" 16 | host "github.com/bianjieai/tibc-go/modules/tibc/core/24-host" 17 | "github.com/bianjieai/tibc-go/modules/tibc/core/types" 18 | ) 19 | 20 | // Simulation parameter constants 21 | const ( 22 | clientGenesis = "client_genesis" 23 | packetGenesis = "packet_genesis" 24 | ) 25 | 26 | // RandomizedGenState generates a random GenesisState for evidence 27 | func RandomizedGenState(simState *module.SimulationState) { 28 | var ( 29 | clientGenesisState clienttypes.GenesisState 30 | packetGenesisState packettypes.GenesisState 31 | ) 32 | 33 | simState.AppParams.GetOrGenerate( 34 | clientGenesis, &clientGenesisState, simState.Rand, 35 | func(r *rand.Rand) { clientGenesisState = clientsims.GenClientGenesis(r, simState.Accounts) }, 36 | ) 37 | 38 | simState.AppParams.GetOrGenerate( 39 | packetGenesis, &packetGenesisState, simState.Rand, 40 | func(r *rand.Rand) { packetGenesisState = packetsims.GenpacketGenesis(r, simState.Accounts) }, 41 | ) 42 | 43 | ibcGenesis := types.GenesisState{ 44 | ClientGenesis: clientGenesisState, 45 | PacketGenesis: packetGenesisState, 46 | } 47 | 48 | bz, err := json.MarshalIndent(&ibcGenesis, "", " ") 49 | if err != nil { 50 | panic(err) 51 | } 52 | fmt.Printf("Selected randomly generated %s parameters:\n%s\n", host.ModuleName, bz) 53 | simState.GenState[host.ModuleName] = simState.Cdc.MustMarshalJSON(&ibcGenesis) 54 | } 55 | -------------------------------------------------------------------------------- /modules/tibc/core/simulation/genesis_test.go: -------------------------------------------------------------------------------- 1 | package simulation_test 2 | 3 | import ( 4 | "encoding/json" 5 | "math/rand" 6 | "testing" 7 | 8 | "github.com/stretchr/testify/require" 9 | 10 | sdkmath "cosmossdk.io/math" 11 | "github.com/cosmos/cosmos-sdk/codec" 12 | codectypes "github.com/cosmos/cosmos-sdk/codec/types" 13 | "github.com/cosmos/cosmos-sdk/types/module" 14 | simtypes "github.com/cosmos/cosmos-sdk/types/simulation" 15 | 16 | host "github.com/bianjieai/tibc-go/modules/tibc/core/24-host" 17 | "github.com/bianjieai/tibc-go/modules/tibc/core/simulation" 18 | "github.com/bianjieai/tibc-go/modules/tibc/core/types" 19 | ) 20 | 21 | // TestRandomizedGenState tests the normal scenario of applying RandomizedGenState. 22 | // Abonormal scenarios are not tested here. 23 | func TestRandomizedGenState(t *testing.T) { 24 | interfaceRegistry := codectypes.NewInterfaceRegistry() 25 | cdc := codec.NewProtoCodec(interfaceRegistry) 26 | 27 | s := rand.NewSource(1) 28 | r := rand.New(s) 29 | 30 | simState := module.SimulationState{ 31 | AppParams: make(simtypes.AppParams), 32 | Cdc: cdc, 33 | Rand: r, 34 | NumBonded: 3, 35 | Accounts: simtypes.RandomAccounts(r, 3), 36 | InitialStake: sdkmath.NewInt(1000), 37 | GenState: make(map[string]json.RawMessage), 38 | } 39 | 40 | // Remark: the current RandomizedGenState function 41 | // is actually not random as it does not utilize concretely the random value r. 42 | // This tests will pass for any value of r. 43 | simulation.RandomizedGenState(&simState) 44 | 45 | var tibcGenesis types.GenesisState 46 | simState.Cdc.MustUnmarshalJSON(simState.GenState[host.ModuleName], &tibcGenesis) 47 | 48 | require.NotNil(t, tibcGenesis.ClientGenesis) 49 | } 50 | -------------------------------------------------------------------------------- /modules/tibc/core/types/codec.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | codectypes "github.com/cosmos/cosmos-sdk/codec/types" 5 | 6 | clienttypes "github.com/bianjieai/tibc-go/modules/tibc/core/02-client/types" 7 | packettypes "github.com/bianjieai/tibc-go/modules/tibc/core/04-packet/types" 8 | commitmenttypes "github.com/bianjieai/tibc-go/modules/tibc/core/23-commitment/types" 9 | routingtypes "github.com/bianjieai/tibc-go/modules/tibc/core/26-routing/types" 10 | ibctmtypes "github.com/bianjieai/tibc-go/modules/tibc/light-clients/07-tendermint/types" 11 | bsctypes "github.com/bianjieai/tibc-go/modules/tibc/light-clients/08-bsc/types" 12 | ethtypes "github.com/bianjieai/tibc-go/modules/tibc/light-clients/09-eth/types" 13 | ) 14 | 15 | // RegisterInterfaces registers x/ibc interfaces into protobuf Any. 16 | func RegisterInterfaces(registry codectypes.InterfaceRegistry) { 17 | clienttypes.RegisterInterfaces(registry) 18 | packettypes.RegisterInterfaces(registry) 19 | routingtypes.RegisterInterfaces(registry) 20 | ibctmtypes.RegisterInterfaces(registry) 21 | bsctypes.RegisterInterfaces(registry) 22 | ethtypes.RegisterInterfaces(registry) 23 | commitmenttypes.RegisterInterfaces(registry) 24 | } 25 | -------------------------------------------------------------------------------- /modules/tibc/core/types/genesis.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | codectypes "github.com/cosmos/cosmos-sdk/codec/types" 5 | 6 | clienttypes "github.com/bianjieai/tibc-go/modules/tibc/core/02-client/types" 7 | packettypes "github.com/bianjieai/tibc-go/modules/tibc/core/04-packet/types" 8 | routingtypes "github.com/bianjieai/tibc-go/modules/tibc/core/26-routing/types" 9 | ) 10 | 11 | var _ codectypes.UnpackInterfacesMessage = GenesisState{} 12 | 13 | // DefaultGenesisState returns the tibc module's default genesis state. 14 | func DefaultGenesisState() *GenesisState { 15 | return &GenesisState{ 16 | ClientGenesis: clienttypes.DefaultGenesisState(), 17 | PacketGenesis: packettypes.DefaultGenesisState(), 18 | RoutingGenesis: routingtypes.DefaultGenesisState(), 19 | } 20 | } 21 | 22 | // UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces 23 | func (gs GenesisState) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { 24 | return gs.ClientGenesis.UnpackInterfaces(unpacker) 25 | } 26 | 27 | // Validate performs basic genesis state validation returning an error upon any 28 | // failure. 29 | func (gs *GenesisState) Validate() error { 30 | if err := gs.ClientGenesis.Validate(); err != nil { 31 | return err 32 | } 33 | 34 | return gs.PacketGenesis.Validate() 35 | } 36 | -------------------------------------------------------------------------------- /modules/tibc/core/types/metrics.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // Prometheus metric labels. 4 | const ( 5 | LabelPort = "port" 6 | LabelSourceChain = "source_chain" 7 | LabelDestinationChain = "destination_chain" 8 | LabelRelayChain = "destination_chain" 9 | LabelDenom = "denom" 10 | LabelSource = "source" 11 | ) 12 | -------------------------------------------------------------------------------- /modules/tibc/core/types/msg_server.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | clienttypes "github.com/bianjieai/tibc-go/modules/tibc/core/02-client/types" 5 | packettypes "github.com/bianjieai/tibc-go/modules/tibc/core/04-packet/types" 6 | routingtypes "github.com/bianjieai/tibc-go/modules/tibc/core/26-routing/types" 7 | ) 8 | 9 | type MsgServer interface { 10 | clienttypes.MsgServer 11 | packettypes.MsgServer 12 | routingtypes.MsgServer 13 | } 14 | -------------------------------------------------------------------------------- /modules/tibc/core/types/query.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "github.com/cosmos/gogoproto/grpc" 5 | 6 | client "github.com/bianjieai/tibc-go/modules/tibc/core/02-client" 7 | clienttypes "github.com/bianjieai/tibc-go/modules/tibc/core/02-client/types" 8 | packet "github.com/bianjieai/tibc-go/modules/tibc/core/04-packet" 9 | packettypes "github.com/bianjieai/tibc-go/modules/tibc/core/04-packet/types" 10 | routing "github.com/bianjieai/tibc-go/modules/tibc/core/26-routing" 11 | routingtypes "github.com/bianjieai/tibc-go/modules/tibc/core/26-routing/types" 12 | ) 13 | 14 | // QueryServer defines the TIBC interfaces that the gRPC query server must implement 15 | type QueryServer interface { 16 | clienttypes.QueryServer 17 | packettypes.QueryServer 18 | routingtypes.QueryServer 19 | } 20 | 21 | // RegisterQueryService registers each individual TIBC submodule query service 22 | func RegisterQueryService(server grpc.Server, queryService QueryServer) { 23 | client.RegisterQueryService(server, queryService) 24 | packet.RegisterQueryService(server, queryService) 25 | routing.RegisterQueryService(server, queryService) 26 | } 27 | -------------------------------------------------------------------------------- /modules/tibc/light-clients/07-tendermint/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package tendermint implements a concrete `ConsensusState`, `Header`, 3 | `Misbehaviour` and `Equivocation` types for the Tendermint consensus light client. 4 | */ 5 | package tendermint 6 | -------------------------------------------------------------------------------- /modules/tibc/light-clients/07-tendermint/module.go: -------------------------------------------------------------------------------- 1 | package tendermint 2 | 3 | import ( 4 | "github.com/bianjieai/tibc-go/modules/tibc/light-clients/07-tendermint/types" 5 | ) 6 | 7 | // Name returns the TIBC tendermint client name 8 | func Name() string { 9 | return types.SubModuleName 10 | } 11 | -------------------------------------------------------------------------------- /modules/tibc/light-clients/07-tendermint/types/codec.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | codectypes "github.com/cosmos/cosmos-sdk/codec/types" 5 | 6 | "github.com/bianjieai/tibc-go/modules/tibc/core/exported" 7 | ) 8 | 9 | // RegisterInterfaces registers the tendermint concrete client-related 10 | // implementations and interfaces. 11 | func RegisterInterfaces(registry codectypes.InterfaceRegistry) { 12 | registry.RegisterImplementations( 13 | (*exported.ClientState)(nil), 14 | &ClientState{}, 15 | ) 16 | registry.RegisterImplementations( 17 | (*exported.ConsensusState)(nil), 18 | &ConsensusState{}, 19 | ) 20 | registry.RegisterImplementations( 21 | (*exported.Header)(nil), 22 | &Header{}, 23 | ) 24 | } 25 | -------------------------------------------------------------------------------- /modules/tibc/light-clients/07-tendermint/types/consensus_state.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "time" 5 | 6 | tmbytes "github.com/cometbft/cometbft/libs/bytes" 7 | tmtypes "github.com/cometbft/cometbft/types" 8 | 9 | errorsmod "cosmossdk.io/errors" 10 | 11 | clienttypes "github.com/bianjieai/tibc-go/modules/tibc/core/02-client/types" 12 | commitmenttypes "github.com/bianjieai/tibc-go/modules/tibc/core/23-commitment/types" 13 | "github.com/bianjieai/tibc-go/modules/tibc/core/exported" 14 | ) 15 | 16 | // NewConsensusState creates a new ConsensusState instance. 17 | func NewConsensusState( 18 | timestamp time.Time, root commitmenttypes.MerkleRoot, nextValsHash tmbytes.HexBytes, 19 | ) *ConsensusState { 20 | return &ConsensusState{ 21 | Timestamp: timestamp, 22 | Root: root, 23 | NextValidatorsHash: nextValsHash, 24 | } 25 | } 26 | 27 | // ClientType returns Tendermint 28 | func (ConsensusState) ClientType() string { 29 | return exported.Tendermint 30 | } 31 | 32 | // GetRoot returns the commitment Root for the specific 33 | func (cs ConsensusState) GetRoot() exported.Root { 34 | return cs.Root 35 | } 36 | 37 | // GetTimestamp returns block time in nanoseconds of the header that created consensus state 38 | func (cs ConsensusState) GetTimestamp() uint64 { 39 | return uint64(cs.Timestamp.UnixNano()) 40 | } 41 | 42 | // ValidateBasic defines a basic validation for the tendermint consensus state. 43 | // NOTE: ProcessedTimestamp may be zero if this is an initial consensus state passed in by relayer 44 | // as opposed to a consensus state constructed by the chain. 45 | func (cs ConsensusState) ValidateBasic() error { 46 | if cs.Root.Empty() { 47 | return errorsmod.Wrap(clienttypes.ErrInvalidConsensus, "root cannot be empty") 48 | } 49 | if err := tmtypes.ValidateHash(cs.NextValidatorsHash); err != nil { 50 | return errorsmod.Wrap(err, "next validators hash is invalid") 51 | } 52 | if cs.Timestamp.Unix() <= 0 { 53 | return errorsmod.Wrap( 54 | clienttypes.ErrInvalidConsensus, 55 | "timestamp must be a positive Unix time", 56 | ) 57 | } 58 | return nil 59 | } 60 | -------------------------------------------------------------------------------- /modules/tibc/light-clients/07-tendermint/types/consensus_state_test.go: -------------------------------------------------------------------------------- 1 | package types_test 2 | 3 | import ( 4 | "time" 5 | 6 | commitmenttypes "github.com/bianjieai/tibc-go/modules/tibc/core/23-commitment/types" 7 | "github.com/bianjieai/tibc-go/modules/tibc/core/exported" 8 | "github.com/bianjieai/tibc-go/modules/tibc/light-clients/07-tendermint/types" 9 | ) 10 | 11 | func (suite *TendermintTestSuite) TestConsensusStateValidateBasic() { 12 | testCases := []struct { 13 | msg string 14 | consensusState *types.ConsensusState 15 | expectPass bool 16 | }{{ 17 | "success", 18 | &types.ConsensusState{ 19 | Timestamp: suite.now, 20 | Root: commitmenttypes.NewMerkleRoot([]byte("app_hash")), 21 | NextValidatorsHash: suite.valsHash, 22 | }, 23 | true, 24 | }, { 25 | "root is nil", 26 | &types.ConsensusState{ 27 | Timestamp: suite.now, 28 | Root: commitmenttypes.MerkleRoot{}, 29 | NextValidatorsHash: suite.valsHash, 30 | }, 31 | false, 32 | }, { 33 | "root is empty", 34 | &types.ConsensusState{ 35 | Timestamp: suite.now, 36 | Root: commitmenttypes.MerkleRoot{}, 37 | NextValidatorsHash: suite.valsHash, 38 | }, 39 | false, 40 | }, { 41 | "nextvalshash is invalid", 42 | &types.ConsensusState{ 43 | Timestamp: suite.now, 44 | Root: commitmenttypes.NewMerkleRoot([]byte("app_hash")), 45 | NextValidatorsHash: []byte("hi"), 46 | }, 47 | false, 48 | }, { 49 | "timestamp is zero", 50 | &types.ConsensusState{ 51 | Timestamp: time.Time{}, 52 | Root: commitmenttypes.NewMerkleRoot([]byte("app_hash")), 53 | NextValidatorsHash: suite.valsHash, 54 | }, 55 | false, 56 | }} 57 | 58 | for i, tc := range testCases { 59 | tc := tc 60 | 61 | // check just to increase coverage 62 | suite.Require().Equal(exported.Tendermint, tc.consensusState.ClientType()) 63 | suite.Require().Equal(tc.consensusState.GetRoot(), tc.consensusState.Root) 64 | 65 | err := tc.consensusState.ValidateBasic() 66 | if tc.expectPass { 67 | suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.msg) 68 | } else { 69 | suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.msg) 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /modules/tibc/light-clients/07-tendermint/types/errors.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | errorsmod "cosmossdk.io/errors" 5 | host "github.com/bianjieai/tibc-go/modules/tibc/core/24-host" 6 | ) 7 | 8 | const ( 9 | SubModuleName = "tendermint-client" 10 | moduleName = host.ModuleName + "-" + SubModuleName 11 | ) 12 | 13 | // TIBC tendermint client sentinel errors 14 | var ( 15 | ErrInvalidChainID = errorsmod.Register(moduleName, 2, "invalid chain-id") 16 | ErrInvalidTrustingPeriod = errorsmod.Register(moduleName, 3, "invalid trusting period") 17 | ErrInvalidUnbondingPeriod = errorsmod.Register(moduleName, 4, "invalid unbonding period") 18 | ErrInvalidHeaderHeight = errorsmod.Register(moduleName, 5, "invalid header height") 19 | ErrInvalidHeader = errorsmod.Register(moduleName, 6, "invalid header") 20 | ErrInvalidMaxClockDrift = errorsmod.Register(moduleName, 7, "invalid max clock drift") 21 | ErrProcessedTimeNotFound = errorsmod.Register(moduleName, 8, "processed time not found") 22 | ErrDelayPeriodNotPassed = errorsmod.Register(moduleName, 9, "packet-specified delay period has not been reached") 23 | ErrTrustingPeriodExpired = errorsmod.Register(moduleName, 10, "time since latest trusted state has passed the trusting period") 24 | ErrUnbondingPeriodExpired = errorsmod.Register(moduleName, 11, "time since latest trusted state has passed the unbonding period") 25 | ErrInvalidProofSpecs = errorsmod.Register(moduleName, 12, "invalid proof specs") 26 | ErrInvalidValidatorSet = errorsmod.Register(moduleName, 13, "invalid validator set") 27 | ) 28 | -------------------------------------------------------------------------------- /modules/tibc/light-clients/07-tendermint/types/fraction.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | tmmath "github.com/cometbft/cometbft/libs/math" 5 | "github.com/cometbft/cometbft/light" 6 | ) 7 | 8 | // DefaultTrustLevel is the tendermint light client default trust level 9 | var DefaultTrustLevel = NewFractionFromTm(light.DefaultTrustLevel) 10 | 11 | // NewFractionFromTm returns a new Fraction instance from a tmmath.Fraction 12 | func NewFractionFromTm(f tmmath.Fraction) Fraction { 13 | return Fraction{ 14 | Numerator: f.Numerator, 15 | Denominator: f.Denominator, 16 | } 17 | } 18 | 19 | // ToTendermint converts Fraction to tmmath.Fraction 20 | func (f Fraction) ToTendermint() tmmath.Fraction { 21 | return tmmath.Fraction{ 22 | Numerator: f.Numerator, 23 | Denominator: f.Denominator, 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /modules/tibc/light-clients/07-tendermint/types/genesis.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | storetypes "cosmossdk.io/store/types" 5 | clienttypes "github.com/bianjieai/tibc-go/modules/tibc/core/02-client/types" 6 | "github.com/bianjieai/tibc-go/modules/tibc/core/exported" 7 | ) 8 | 9 | // ExportMetadata exports all the processed times in the client store so they can be included in clients genesis 10 | // and imported by a ClientKeeper 11 | func (cs ClientState) ExportMetadata(store storetypes.KVStore) []exported.GenesisMetadata { 12 | gm := make([]exported.GenesisMetadata, 0) 13 | IterateProcessedTime(store, func(key, val []byte) bool { 14 | gm = append(gm, clienttypes.NewGenesisMetadata(key, val)) 15 | return false 16 | }) 17 | if len(gm) == 0 { 18 | return nil 19 | } 20 | return gm 21 | } 22 | -------------------------------------------------------------------------------- /modules/tibc/light-clients/07-tendermint/types/genesis_test.go: -------------------------------------------------------------------------------- 1 | package types_test 2 | 3 | import ( 4 | "time" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | 8 | clienttypes "github.com/bianjieai/tibc-go/modules/tibc/core/02-client/types" 9 | commitmenttypes "github.com/bianjieai/tibc-go/modules/tibc/core/23-commitment/types" 10 | "github.com/bianjieai/tibc-go/modules/tibc/light-clients/07-tendermint/types" 11 | ) 12 | 13 | func (suite *TendermintTestSuite) TestExportMetadata() { 14 | clientState := types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), prefix, 0) 15 | suite.chainA.App.TIBCKeeper.ClientKeeper.SetClientState(suite.chainA.GetContext(), "clientA", clientState) 16 | 17 | gm := clientState.ExportMetadata(suite.chainA.App.TIBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), "clientA")) 18 | suite.Require().Nil(gm, "client with no metadata returned non-nil exported metadata") 19 | 20 | clientStore := suite.chainA.App.TIBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), "clientA") 21 | 22 | // set some processed times 23 | timestamp1 := uint64(time.Now().UnixNano()) 24 | timestamp2 := uint64(time.Now().Add(time.Minute).UnixNano()) 25 | timestampBz1 := sdk.Uint64ToBigEndian(timestamp1) 26 | timestampBz2 := sdk.Uint64ToBigEndian(timestamp2) 27 | types.SetProcessedTime(clientStore, clienttypes.NewHeight(0, 1), timestamp1) 28 | types.SetProcessedTime(clientStore, clienttypes.NewHeight(0, 2), timestamp2) 29 | 30 | gm = clientState.ExportMetadata(suite.chainA.App.TIBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), "clientA")) 31 | suite.Require().NotNil(gm, "client with metadata returned nil exported metadata") 32 | suite.Require().Len(gm, 2, "exported metadata has unexpected length") 33 | 34 | suite.Require().Equal(types.ProcessedTimeKey(clienttypes.NewHeight(0, 1)), gm[0].GetKey(), "metadata has unexpected key") 35 | suite.Require().Equal(timestampBz1, gm[0].GetValue(), "metadata has unexpected value") 36 | 37 | suite.Require().Equal(types.ProcessedTimeKey(clienttypes.NewHeight(0, 2)), gm[1].GetKey(), "metadata has unexpected key") 38 | suite.Require().Equal(timestampBz2, gm[1].GetValue(), "metadata has unexpected value") 39 | } 40 | -------------------------------------------------------------------------------- /modules/tibc/light-clients/08-bsc/module.go: -------------------------------------------------------------------------------- 1 | package bsc 2 | 3 | import ( 4 | "github.com/bianjieai/tibc-go/modules/tibc/light-clients/08-bsc/types" 5 | ) 6 | 7 | // Name returns the TIBC bsc client name 8 | func Name() string { 9 | return types.SubModuleName 10 | } 11 | -------------------------------------------------------------------------------- /modules/tibc/light-clients/08-bsc/types/bsc_test.go: -------------------------------------------------------------------------------- 1 | package types_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/suite" 7 | 8 | tmproto "github.com/cometbft/cometbft/proto/tendermint/types" 9 | 10 | sdk "github.com/cosmos/cosmos-sdk/types" 11 | 12 | "github.com/bianjieai/tibc-go/simapp" 13 | ) 14 | 15 | type BSCTestSuite struct { 16 | suite.Suite 17 | 18 | ctx sdk.Context 19 | app *simapp.SimApp 20 | } 21 | 22 | func (suite *BSCTestSuite) SetupTest() { 23 | app := simapp.Setup(suite.T()) 24 | 25 | suite.ctx = app.BaseApp.NewContextLegacy(false, tmproto.Header{}) 26 | suite.app = app 27 | } 28 | 29 | func TestBSCTestSuite(t *testing.T) { 30 | suite.Run(t, new(BSCTestSuite)) 31 | } 32 | -------------------------------------------------------------------------------- /modules/tibc/light-clients/08-bsc/types/codec.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | codectypes "github.com/cosmos/cosmos-sdk/codec/types" 5 | 6 | "github.com/bianjieai/tibc-go/modules/tibc/core/exported" 7 | ) 8 | 9 | // RegisterInterfaces registers the tendermint concrete client-related 10 | // implementations and interfaces. 11 | func RegisterInterfaces(registry codectypes.InterfaceRegistry) { 12 | registry.RegisterImplementations( 13 | (*exported.ClientState)(nil), 14 | &ClientState{}, 15 | ) 16 | registry.RegisterImplementations( 17 | (*exported.ConsensusState)(nil), 18 | &ConsensusState{}, 19 | ) 20 | registry.RegisterImplementations( 21 | (*exported.Header)(nil), 22 | &Header{}, 23 | ) 24 | } 25 | -------------------------------------------------------------------------------- /modules/tibc/light-clients/08-bsc/types/consensus_state.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | commitmenttypes "github.com/bianjieai/tibc-go/modules/tibc/core/23-commitment/types" 5 | "github.com/bianjieai/tibc-go/modules/tibc/core/exported" 6 | ) 7 | 8 | var _ exported.ConsensusState = (*ConsensusState)(nil) 9 | 10 | func (m *ConsensusState) ClientType() string { 11 | return exported.BSC 12 | } 13 | 14 | func (m *ConsensusState) GetRoot() exported.Root { 15 | return commitmenttypes.MerkleRoot{ 16 | Hash: m.Root, 17 | } 18 | } 19 | 20 | func (m *ConsensusState) GetTimestamp() uint64 { 21 | return m.Timestamp 22 | } 23 | 24 | func (m *ConsensusState) ValidateBasic() error { 25 | return nil 26 | } 27 | -------------------------------------------------------------------------------- /modules/tibc/light-clients/08-bsc/types/genesis_test.go: -------------------------------------------------------------------------------- 1 | package types_test 2 | 3 | func (suite *BSCTestSuite) TestExportMetadata() { 4 | // TODO 5 | } 6 | -------------------------------------------------------------------------------- /modules/tibc/light-clients/08-bsc/types/hashing.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The go-ethereum Authors 2 | // This file is part of the go-ethereum library. 3 | // 4 | // The go-ethereum library is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU Lesser General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // The go-ethereum library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU Lesser General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU Lesser General Public License 15 | // along with the go-ethereum library. If not, see . 16 | 17 | package types 18 | 19 | import ( 20 | "sync" 21 | 22 | "github.com/ethereum/go-ethereum/common" 23 | "github.com/ethereum/go-ethereum/crypto" 24 | "github.com/ethereum/go-ethereum/rlp" 25 | "golang.org/x/crypto/sha3" 26 | ) 27 | 28 | // hasherPool holds LegacyKeccak256 hashers for rlpHash. 29 | var hasherPool = sync.Pool{ 30 | New: func() interface{} { return sha3.NewLegacyKeccak256() }, 31 | } 32 | 33 | // rlpHash encodes x and hashes the encoded bytes. 34 | func rlpHash(x interface{}) (h common.Hash) { 35 | sha := hasherPool.Get().(crypto.KeccakState) 36 | defer hasherPool.Put(sha) 37 | sha.Reset() 38 | _ = rlp.Encode(sha, x) 39 | _, _ = sha.Read(h[:]) 40 | return h 41 | } 42 | -------------------------------------------------------------------------------- /modules/tibc/light-clients/08-bsc/types/keys.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "math/big" 5 | 6 | host "github.com/bianjieai/tibc-go/modules/tibc/core/24-host" 7 | 8 | "github.com/ethereum/go-ethereum/common" 9 | "github.com/ethereum/go-ethereum/crypto" 10 | ) 11 | 12 | const ( 13 | paramsIndex = 104 14 | paramsLenght = 32 15 | ) 16 | 17 | type ProofKeyConstructor struct { 18 | sourceChain string 19 | destChain string 20 | sequence uint64 21 | } 22 | 23 | func NewProofKeyConstructor(sourceChain string, destChain string, sequence uint64) ProofKeyConstructor { 24 | return ProofKeyConstructor{ 25 | sourceChain: sourceChain, 26 | destChain: destChain, 27 | sequence: sequence, 28 | } 29 | } 30 | 31 | func (k ProofKeyConstructor) GetPacketCommitmentProofKey() []byte { 32 | hash := crypto.Keccak256Hash( 33 | host.PacketCommitmentKey(k.sourceChain, k.destChain, k.sequence), 34 | common.LeftPadBytes(big.NewInt(paramsIndex).Bytes(), paramsLenght), 35 | ) 36 | return hash.Bytes() 37 | } 38 | 39 | func (k ProofKeyConstructor) GetAckProofKey() []byte { 40 | hash := crypto.Keccak256Hash( 41 | host.PacketAcknowledgementKey(k.sourceChain, k.destChain, k.sequence), 42 | common.LeftPadBytes(big.NewInt(paramsIndex).Bytes(), paramsLenght), 43 | ) 44 | return hash.Bytes() 45 | } 46 | 47 | func (k ProofKeyConstructor) GetCleanPacketCommitmentProofKey() []byte { 48 | hash := crypto.Keccak256Hash( 49 | host.CleanPacketCommitmentKey(k.sourceChain, k.destChain), 50 | common.LeftPadBytes(big.NewInt(paramsIndex).Bytes(), paramsLenght), 51 | ) 52 | return hash.Bytes() 53 | } 54 | -------------------------------------------------------------------------------- /modules/tibc/light-clients/08-bsc/types/snapshot.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "bytes" 5 | "sort" 6 | 7 | storetypes "cosmossdk.io/store/types" 8 | "github.com/cosmos/cosmos-sdk/codec" 9 | "github.com/ethereum/go-ethereum/common" 10 | ) 11 | 12 | // validatorsAscending implements the sort interface to allow sorting a list of addresses 13 | type validatorsAscending []common.Address 14 | 15 | func (s validatorsAscending) Len() int { return len(s) } 16 | func (s validatorsAscending) Less(i, j int) bool { return bytes.Compare(s[i][:], s[j][:]) < 0 } 17 | func (s validatorsAscending) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 18 | 19 | type snapshot struct { 20 | cdc codec.BinaryCodec 21 | store storetypes.KVStore 22 | // Block number where the snapshot was created 23 | Number uint64 24 | // Set of authorized validators at this moment 25 | Validators map[common.Address]struct{} 26 | Recents map[uint64]common.Address 27 | } 28 | 29 | func (m ClientState) snapshot(cdc codec.BinaryCodec, store storetypes.KVStore) (*snapshot, error) { 30 | 31 | recentSingers, err := GetRecentSigners(store) 32 | if err != nil { 33 | return nil, err 34 | } 35 | 36 | snap := &snapshot{ 37 | cdc: cdc, 38 | store: store, 39 | Number: m.Header.Height.RevisionHeight, 40 | Validators: make(map[common.Address]struct{}, len(m.Validators)), 41 | Recents: make(map[uint64]common.Address, len(recentSingers)), 42 | } 43 | 44 | for _, validator := range m.Validators { 45 | snap.Validators[common.BytesToAddress(validator)] = struct{}{} 46 | } 47 | 48 | for _, singer := range recentSingers { 49 | snap.Recents[singer.Height.RevisionHeight] = common.BytesToAddress(singer.Validator) 50 | } 51 | return snap, nil 52 | } 53 | 54 | // validators retrieves the list of validators in ascending order. 55 | func (s *snapshot) validators() []common.Address { 56 | validators := make([]common.Address, 0, len(s.Validators)) 57 | for v := range s.Validators { 58 | validators = append(validators, v) 59 | } 60 | sort.Sort(validatorsAscending(validators)) 61 | return validators 62 | } 63 | 64 | // inturn returns if a validator at a given block height is in-turn or not. 65 | func (s *snapshot) inturn(validator common.Address) bool { 66 | validators := s.validators() 67 | offset := (s.Number + 1) % uint64(len(validators)) 68 | return validators[offset] == validator 69 | } 70 | -------------------------------------------------------------------------------- /modules/tibc/light-clients/09-eth/module.go: -------------------------------------------------------------------------------- 1 | package eth 2 | 3 | import "github.com/bianjieai/tibc-go/modules/tibc/light-clients/09-eth/types" 4 | 5 | // Name returns the TIBC eth client name 6 | func Name() string { 7 | return types.SubModuleName 8 | } 9 | -------------------------------------------------------------------------------- /modules/tibc/light-clients/09-eth/types/codec.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | codectypes "github.com/cosmos/cosmos-sdk/codec/types" 5 | 6 | "github.com/bianjieai/tibc-go/modules/tibc/core/exported" 7 | ) 8 | 9 | // RegisterInterfaces registers the tendermint concrete client-related 10 | // implementations and interfaces. 11 | func RegisterInterfaces(registry codectypes.InterfaceRegistry) { 12 | registry.RegisterImplementations( 13 | (*exported.ClientState)(nil), 14 | &ClientState{}, 15 | ) 16 | registry.RegisterImplementations( 17 | (*exported.ConsensusState)(nil), 18 | &ConsensusState{}, 19 | ) 20 | registry.RegisterImplementations( 21 | (*exported.Header)(nil), 22 | &Header{}, 23 | ) 24 | } 25 | -------------------------------------------------------------------------------- /modules/tibc/light-clients/09-eth/types/consensus_state.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | commitmenttypes "github.com/bianjieai/tibc-go/modules/tibc/core/23-commitment/types" 5 | "github.com/bianjieai/tibc-go/modules/tibc/core/exported" 6 | ) 7 | 8 | var _ exported.ConsensusState = (*ConsensusState)(nil) 9 | 10 | func (m *ConsensusState) ClientType() string { 11 | return exported.BSC 12 | } 13 | 14 | func (m *ConsensusState) GetRoot() exported.Root { 15 | return commitmenttypes.MerkleRoot{ 16 | Hash: m.Root, 17 | } 18 | } 19 | 20 | func (m *ConsensusState) GetTimestamp() uint64 { 21 | return m.Timestamp 22 | } 23 | 24 | func (m *ConsensusState) ValidateBasic() error { 25 | return nil 26 | } 27 | -------------------------------------------------------------------------------- /modules/tibc/light-clients/09-eth/types/errors.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | errorsmod "cosmossdk.io/errors" 5 | host "github.com/bianjieai/tibc-go/modules/tibc/core/24-host" 6 | ) 7 | 8 | const ( 9 | SubModuleName = "eth-client" 10 | moduleName = host.ModuleName + "-" + SubModuleName 11 | ) 12 | 13 | // TIBC bsc client sentinel errors 14 | var ( 15 | ErrInvalidGenesisBlock = errorsmod.Register(moduleName, 2, "invalid genesis block") 16 | ErrFutureBlock = errorsmod.Register(moduleName, 3, "block in the future") 17 | 18 | // ErrInvalidMixDigest is returned if a block's mix digest is non-zero. 19 | ErrInvalidMixDigest = errorsmod.Register(moduleName, 4, "non-zero mix digest") 20 | 21 | // ErrInvalidDifficulty is returned if the difficulty of a block is missing. 22 | ErrInvalidDifficulty = errorsmod.Register(moduleName, 5, "invalid difficulty") 23 | ErrUnknownAncestor = errorsmod.Register(moduleName, 6, "unknown ancestor") 24 | 25 | // ErrWrongDifficulty is returned if the difficulty of a block doesn't match the 26 | // turn of the signer. 27 | ErrWrongDifficulty = errorsmod.Register(moduleName, 7, "wrong difficulty") 28 | ErrInvalidProof = errorsmod.Register(moduleName, 8, "invalid proof") 29 | 30 | // ErrHeaderIsExist is returned if the header already in store 31 | ErrHeaderIsExist = errorsmod.Register(moduleName, 9, "header already exist") 32 | 33 | // ErrUnmarshalInterface is returned if interface can not unmarshal 34 | ErrUnmarshalInterface = errorsmod.Register(moduleName, 10, "unmarshal field") 35 | 36 | // ErrExtraLenth is returned if extra data is to long 37 | ErrExtraLenth = errorsmod.Register(moduleName, 11, "extra-data to long") 38 | 39 | // ErrInvalidGas is returned if gas data is invalid 40 | ErrInvalidGas = errorsmod.Register(moduleName, 12, "gas invalid") 41 | 42 | // ErrHeader is returned if the header invalid 43 | ErrHeader = errorsmod.Register(moduleName, 13, "header invalid") 44 | 45 | // ErrMarshalInterface is returned if struct can not marshal 46 | ErrMarshalInterface = errorsmod.Register(moduleName, 14, "marshal field") 47 | ) 48 | -------------------------------------------------------------------------------- /modules/tibc/light-clients/09-eth/types/eth.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "math/big" 5 | 6 | "github.com/ethereum/go-ethereum/common" 7 | "github.com/ethereum/go-ethereum/core/types" 8 | 9 | clienttypes "github.com/bianjieai/tibc-go/modules/tibc/core/02-client/types" 10 | ) 11 | 12 | //EthHeader represents a block header in the Ethereum blockchain. 13 | type EthHeader struct { 14 | ParentHash common.Hash `json:"parentHash" gencodec:"required"` 15 | UncleHash common.Hash `json:"sha3Uncles" gencodec:"required"` 16 | Coinbase common.Address `json:"miner" gencodec:"required"` 17 | Root common.Hash `json:"stateRoot" gencodec:"required"` 18 | TxHash common.Hash `json:"transactionsRoot" gencodec:"required"` 19 | ReceiptHash common.Hash `json:"receiptsRoot" gencodec:"required"` 20 | Bloom types.Bloom `json:"logsBloom" gencodec:"required"` 21 | Difficulty *big.Int `json:"difficulty" gencodec:"required"` 22 | Number *big.Int `json:"number" gencodec:"required"` 23 | GasLimit uint64 `json:"gasLimit" gencodec:"required"` 24 | GasUsed uint64 `json:"gasUsed" gencodec:"required"` 25 | Time uint64 `json:"timestamp" gencodec:"required"` 26 | Extra []byte `json:"extraData" gencodec:"required"` 27 | MixDigest common.Hash `json:"mixHash"` 28 | Nonce types.BlockNonce `json:"nonce"` 29 | 30 | // BaseFee was added by EIP-1559 and is ignored in legacy headers. 31 | BaseFee *big.Int `json:"baseFeePerGas" rlp:"optional"` 32 | } 33 | 34 | func (h EthHeader) ToHeader() Header { 35 | return Header{ 36 | ParentHash: h.ParentHash[:], 37 | UncleHash: h.UncleHash[:], 38 | Coinbase: h.Coinbase[:], 39 | Root: h.Root[:], 40 | TxHash: h.TxHash[:], 41 | ReceiptHash: h.ReceiptHash[:], 42 | Bloom: h.Bloom[:], 43 | Difficulty: h.Difficulty.String(), 44 | Height: clienttypes.NewHeight(0, h.Number.Uint64()), 45 | GasLimit: h.GasLimit, 46 | GasUsed: h.GasUsed, 47 | Time: h.Time, 48 | Extra: h.Extra, 49 | MixDigest: h.MixDigest[:], 50 | Nonce: h.Nonce.Uint64(), 51 | BaseFee: h.BaseFee.String(), 52 | } 53 | } 54 | 55 | // ProofAccount ... 56 | type ProofAccount struct { 57 | Nonce *big.Int 58 | Balance *big.Int 59 | Storage common.Hash 60 | Codehash common.Hash 61 | } 62 | -------------------------------------------------------------------------------- /modules/tibc/light-clients/09-eth/types/eth_test.go: -------------------------------------------------------------------------------- 1 | package types_test 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | 7 | sdk "github.com/cosmos/cosmos-sdk/types" 8 | "github.com/stretchr/testify/suite" 9 | 10 | "github.com/bianjieai/tibc-go/simapp" 11 | 12 | tmproto "github.com/cometbft/cometbft/proto/tendermint/types" 13 | ) 14 | 15 | type ETHTestSuite struct { 16 | suite.Suite 17 | 18 | ctx sdk.Context 19 | app *simapp.SimApp 20 | } 21 | 22 | func (suite *ETHTestSuite) SetupTest() { 23 | app := simapp.Setup(suite.T()) 24 | 25 | suite.ctx = app.BaseApp.NewContextLegacy(false, tmproto.Header{Time: time.Now()}) 26 | suite.app = app 27 | } 28 | 29 | func TestETHTestSuite(t *testing.T) { 30 | suite.Run(t, new(ETHTestSuite)) 31 | } 32 | -------------------------------------------------------------------------------- /modules/tibc/light-clients/09-eth/types/genesis_test.go: -------------------------------------------------------------------------------- 1 | package types_test 2 | 3 | import ( 4 | "encoding/json" 5 | "io/ioutil" 6 | 7 | "github.com/ethereum/go-ethereum/common" 8 | 9 | "github.com/bianjieai/tibc-go/modules/tibc/core/exported" 10 | tibcethtypes "github.com/bianjieai/tibc-go/modules/tibc/light-clients/09-eth/types" 11 | ) 12 | 13 | func (suite *ETHTestSuite) TestExportMetadata() { 14 | var updateHeaders []*tibcethtypes.EthHeader 15 | updateHeadersBz, _ := ioutil.ReadFile("testdata/update_headers.json") 16 | err := json.Unmarshal(updateHeadersBz, &updateHeaders) 17 | suite.NoError(err) 18 | suite.GreaterOrEqual(len(updateHeaders), 1) 19 | header := updateHeaders[0] 20 | clientState := exported.ClientState(&tibcethtypes.ClientState{ 21 | Header: header.ToHeader(), 22 | ChainId: 1, 23 | ContractAddress: []byte("0x00"), 24 | TrustingPeriod: 200000, 25 | TimeDelay: 0, 26 | BlockDelay: 1, 27 | }) 28 | suite.app.TIBCKeeper.ClientKeeper.SetClientState(suite.ctx, chainName, clientState) 29 | gm := clientState.ExportMetadata(suite.app.TIBCKeeper.ClientKeeper.ClientStore(suite.ctx, chainName)) 30 | suite.Require().Nil(gm, "client with no metadata returned non-nil exported metadata") 31 | 32 | protoHeader := header.ToHeader() 33 | store := suite.app.TIBCKeeper.ClientKeeper.ClientStore(suite.ctx, chainName) 34 | headerBytes, err := suite.app.AppCodec().MarshalInterface(&protoHeader) 35 | suite.NoError(err) 36 | 37 | tibcethtypes.SetEthHeaderIndex(store, protoHeader, headerBytes) 38 | tibcethtypes.SetEthConsensusRoot(store, protoHeader.Height.RevisionHeight, protoHeader.ToEthHeader().Root, header.Hash()) 39 | 40 | gm = clientState.ExportMetadata(suite.app.TIBCKeeper.ClientKeeper.ClientStore(suite.ctx, chainName)) 41 | suite.Require().NotNil(gm, "client with metadata returned nil exported metadata") 42 | suite.Require().Len(gm, 2, "exported metadata has unexpected length") 43 | 44 | suite.Require().Equal(tibcethtypes.EthHeaderIndexKey(protoHeader.Hash(), protoHeader.Height.RevisionHeight), gm[0].GetKey(), "metadata has unexpected key") 45 | suite.Require().Equal(headerBytes, gm[0].GetValue(), "metadata has unexpected value") 46 | 47 | suite.Require().Equal(tibcethtypes.EthRootMainKey(common.BytesToHash(protoHeader.Root), protoHeader.Height.RevisionHeight), gm[1].GetKey(), "metadata has unexpected key") 48 | suite.Require().Equal(gm[0].GetKey(), gm[1].GetValue(), "metadata has unexpected value") 49 | } 50 | -------------------------------------------------------------------------------- /modules/tibc/light-clients/09-eth/types/hashing.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The go-ethereum Authors 2 | // This file is part of the go-ethereum library. 3 | // 4 | // The go-ethereum library is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU Lesser General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // The go-ethereum library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU Lesser General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU Lesser General Public License 15 | // along with the go-ethereum library. If not, see . 16 | 17 | package types 18 | 19 | import ( 20 | "sync" 21 | 22 | "github.com/ethereum/go-ethereum/common" 23 | "github.com/ethereum/go-ethereum/crypto" 24 | "github.com/ethereum/go-ethereum/rlp" 25 | "golang.org/x/crypto/sha3" 26 | ) 27 | 28 | // hasherPool holds LegacyKeccak256 hashers for rlpHash. 29 | var hasherPool = sync.Pool{ 30 | New: func() interface{} { return sha3.NewLegacyKeccak256() }, 31 | } 32 | 33 | // rlpHash encodes x and hashes the encoded bytes. 34 | func rlpHash(x interface{}) (h common.Hash) { 35 | sha := hasherPool.Get().(crypto.KeccakState) 36 | defer hasherPool.Put(sha) 37 | sha.Reset() 38 | _ = rlp.Encode(sha, x) 39 | _, _ = sha.Read(h[:]) 40 | return h 41 | } 42 | -------------------------------------------------------------------------------- /modules/tibc/light-clients/09-eth/types/keys.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "math/big" 5 | 6 | host "github.com/bianjieai/tibc-go/modules/tibc/core/24-host" 7 | 8 | "github.com/ethereum/go-ethereum/common" 9 | "github.com/ethereum/go-ethereum/crypto" 10 | ) 11 | 12 | const ( 13 | paramsIndex = 104 14 | paramsLenght = 32 15 | ) 16 | 17 | type ProofKeyConstructor struct { 18 | sourceChain string 19 | destChain string 20 | sequence uint64 21 | } 22 | 23 | func NewProofKeyConstructor(sourceChain string, destChain string, sequence uint64) ProofKeyConstructor { 24 | return ProofKeyConstructor{ 25 | sourceChain: sourceChain, 26 | destChain: destChain, 27 | sequence: sequence, 28 | } 29 | } 30 | 31 | func (k ProofKeyConstructor) GetPacketCommitmentProofKey() []byte { 32 | hash := crypto.Keccak256Hash( 33 | host.PacketCommitmentKey(k.sourceChain, k.destChain, k.sequence), 34 | common.LeftPadBytes(big.NewInt(paramsIndex).Bytes(), paramsLenght), 35 | ) 36 | return hash.Bytes() 37 | } 38 | 39 | func (k ProofKeyConstructor) GetAckProofKey() []byte { 40 | hash := crypto.Keccak256Hash( 41 | host.PacketAcknowledgementKey(k.sourceChain, k.destChain, k.sequence), 42 | common.LeftPadBytes(big.NewInt(paramsIndex).Bytes(), paramsLenght), 43 | ) 44 | return hash.Bytes() 45 | } 46 | 47 | func (k ProofKeyConstructor) GetCleanPacketCommitmentProofKey() []byte { 48 | hash := crypto.Keccak256Hash( 49 | host.CleanPacketCommitmentKey(k.sourceChain, k.destChain), 50 | common.LeftPadBytes(big.NewInt(paramsIndex).Bytes(), paramsLenght), 51 | ) 52 | return hash.Bytes() 53 | } 54 | -------------------------------------------------------------------------------- /modules/tibc/testing/chain_test.go: -------------------------------------------------------------------------------- 1 | package tibctesting_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | 8 | tmtypes "github.com/cometbft/cometbft/types" 9 | 10 | tibctesting "github.com/bianjieai/tibc-go/modules/tibc/testing" 11 | "github.com/bianjieai/tibc-go/modules/tibc/testing/mock" 12 | ) 13 | 14 | func TestCreateSortedSignerArray(t *testing.T) { 15 | privVal1 := mock.NewPV() 16 | pubKey1, err := privVal1.GetPubKey() 17 | require.NoError(t, err) 18 | 19 | privVal2 := mock.NewPV() 20 | pubKey2, err := privVal2.GetPubKey() 21 | require.NoError(t, err) 22 | 23 | validator1 := tmtypes.NewValidator(pubKey1, 1) 24 | validator2 := tmtypes.NewValidator(pubKey2, 2) 25 | 26 | expected := []tmtypes.PrivValidator{privVal2, privVal1} 27 | 28 | actual := tibctesting.CreateSortedSignerArray(privVal1, privVal2, validator1, validator2) 29 | require.Equal(t, expected, actual) 30 | 31 | // swap order 32 | actual = tibctesting.CreateSortedSignerArray(privVal2, privVal1, validator2, validator1) 33 | require.Equal(t, expected, actual) 34 | 35 | // smaller address 36 | validator1.Address = []byte{1} 37 | validator2.Address = []byte{2} 38 | validator2.VotingPower = 1 39 | 40 | expected = []tmtypes.PrivValidator{privVal1, privVal2} 41 | 42 | actual = tibctesting.CreateSortedSignerArray(privVal1, privVal2, validator1, validator2) 43 | require.Equal(t, expected, actual) 44 | 45 | // swap order 46 | actual = tibctesting.CreateSortedSignerArray(privVal2, privVal1, validator2, validator1) 47 | require.Equal(t, expected, actual) 48 | } 49 | -------------------------------------------------------------------------------- /modules/tibc/testing/config.go: -------------------------------------------------------------------------------- 1 | package tibctesting 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/bianjieai/tibc-go/modules/tibc/core/exported" 7 | ibctmtypes "github.com/bianjieai/tibc-go/modules/tibc/light-clients/07-tendermint/types" 8 | ) 9 | 10 | type ClientConfig interface { 11 | GetClientType() string 12 | } 13 | 14 | type TendermintConfig struct { 15 | TrustLevel ibctmtypes.Fraction 16 | TrustingPeriod time.Duration 17 | UnbondingPeriod time.Duration 18 | MaxClockDrift time.Duration 19 | AllowUpdateAfterExpiry bool 20 | AllowUpdateAfterMisbehaviour bool 21 | } 22 | 23 | func NewTendermintConfig() *TendermintConfig { 24 | return &TendermintConfig{ 25 | TrustLevel: DefaultTrustLevel, 26 | TrustingPeriod: TrustingPeriod, 27 | UnbondingPeriod: UnbondingPeriod, 28 | MaxClockDrift: MaxClockDrift, 29 | AllowUpdateAfterExpiry: false, 30 | AllowUpdateAfterMisbehaviour: false, 31 | } 32 | } 33 | 34 | func (tmcfg *TendermintConfig) GetClientType() string { 35 | return exported.Tendermint 36 | } 37 | -------------------------------------------------------------------------------- /modules/tibc/testing/mock/README.md: -------------------------------------------------------------------------------- 1 | This package is only intended to be used for testing core TIBC. In order to maintain secure 2 | testing, we need to do message passing and execution which requires connecting an TIBC application 3 | module that fulfills all the callbacks. We cannot connect to tibc-transfer which does not support 4 | all channel types so instead we create a mock application module which does nothing. It simply 5 | return nil in all cases so no error ever occurs. It is intended to be as minimal and lightweight 6 | as possible and should never import simapp. 7 | -------------------------------------------------------------------------------- /modules/tibc/testing/mock/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | This package is only intended to be used for testing core TIBC. In order to maintain secure 3 | testing, we need to do message passing and execution which requires connecting an TIBC application 4 | module that fulfills all the callbacks. We cannot connect to tibc-transfer which does not support 5 | all channel types so instead we create a mock application module which does nothing. It simply 6 | return nil in all cases so no error ever occurs. It is intended to be as minimal and lightweight 7 | as possible and should never import simapp. 8 | */ 9 | package mock 10 | -------------------------------------------------------------------------------- /modules/tibc/testing/mock/privval.go: -------------------------------------------------------------------------------- 1 | package mock 2 | 3 | import ( 4 | "github.com/cometbft/cometbft/crypto" 5 | tmproto "github.com/cometbft/cometbft/proto/tendermint/types" 6 | tmtypes "github.com/cometbft/cometbft/types" 7 | 8 | cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" 9 | "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" 10 | cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" 11 | ) 12 | 13 | var _ tmtypes.PrivValidator = PV{} 14 | 15 | // MockPV implements PrivValidator without any safety or persistence. 16 | // Only use it for testing. 17 | type PV struct { 18 | PrivKey cryptotypes.PrivKey 19 | } 20 | 21 | func NewPV() PV { 22 | return PV{ed25519.GenPrivKey()} 23 | } 24 | 25 | // GetPubKey implements PrivValidator interface 26 | func (pv PV) GetPubKey() (crypto.PubKey, error) { 27 | return cryptocodec.ToTmPubKeyInterface(pv.PrivKey.PubKey()) 28 | } 29 | 30 | // SignVote implements PrivValidator interface 31 | func (pv PV) SignVote(chainID string, vote *tmproto.Vote) error { 32 | signBytes := tmtypes.VoteSignBytes(chainID, vote) 33 | sig, err := pv.PrivKey.Sign(signBytes) 34 | if err != nil { 35 | return err 36 | } 37 | vote.Signature = sig 38 | return nil 39 | } 40 | 41 | // SignProposal implements PrivValidator interface 42 | func (pv PV) SignProposal(chainID string, proposal *tmproto.Proposal) error { 43 | signBytes := tmtypes.ProposalSignBytes(chainID, proposal) 44 | sig, err := pv.PrivKey.Sign(signBytes) 45 | if err != nil { 46 | return err 47 | } 48 | proposal.Signature = sig 49 | return nil 50 | } 51 | -------------------------------------------------------------------------------- /modules/tibc/testing/mock/privval_test.go: -------------------------------------------------------------------------------- 1 | package mock_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | 8 | tmproto "github.com/cometbft/cometbft/proto/tendermint/types" 9 | tmtypes "github.com/cometbft/cometbft/types" 10 | 11 | "github.com/bianjieai/tibc-go/modules/tibc/testing/mock" 12 | ) 13 | 14 | const chainID = "testChain" 15 | 16 | func TestGetPubKey(t *testing.T) { 17 | pv := mock.NewPV() 18 | pk, err := pv.GetPubKey() 19 | require.NoError(t, err) 20 | require.Equal(t, "ed25519", pk.Type()) 21 | } 22 | 23 | func TestSignVote(t *testing.T) { 24 | pv := mock.NewPV() 25 | pk, _ := pv.GetPubKey() 26 | 27 | vote := &tmproto.Vote{Height: 2} 28 | _ = pv.SignVote(chainID, vote) 29 | 30 | msg := tmtypes.VoteSignBytes(chainID, vote) 31 | ok := pk.VerifySignature(msg, vote.Signature) 32 | require.True(t, ok) 33 | } 34 | 35 | func TestSignProposal(t *testing.T) { 36 | pv := mock.NewPV() 37 | pk, _ := pv.GetPubKey() 38 | 39 | proposal := &tmproto.Proposal{Round: 2} 40 | _ = pv.SignProposal(chainID, proposal) 41 | 42 | msg := tmtypes.ProposalSignBytes(chainID, proposal) 43 | ok := pk.VerifySignature(msg, proposal.Signature) 44 | require.True(t, ok) 45 | } 46 | -------------------------------------------------------------------------------- /modules/tibc/testing/path.go: -------------------------------------------------------------------------------- 1 | package tibctesting 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | 7 | packettypes "github.com/bianjieai/tibc-go/modules/tibc/core/04-packet/types" 8 | ) 9 | 10 | // Path contains two endpoints representing two chains connected over TIBC 11 | type Path struct { 12 | EndpointA *Endpoint 13 | EndpointB *Endpoint 14 | } 15 | 16 | // NewPath constructs an endpoint for each chain using the default values 17 | // for the endpoints. Each endpoint is updated to have a pointer to the 18 | // counterparty endpoint. 19 | func NewPath(chainA, chainB *TestChain) *Path { 20 | endpointA := NewDefaultEndpoint(chainA) 21 | endpointB := NewDefaultEndpoint(chainB) 22 | 23 | endpointA.Counterparty = endpointB 24 | endpointB.Counterparty = endpointA 25 | 26 | return &Path{ 27 | EndpointA: endpointA, 28 | EndpointB: endpointB, 29 | } 30 | } 31 | 32 | // RelayPacket attempts to relay the packet first on EndpointA and then on EndpointB 33 | // if EndpointA does not contain a packet commitment for that packet. An error is returned 34 | // if a relay step fails or the packet commitment does not exist on either endpoint. 35 | func (path *Path) RelayPacket(packet packettypes.Packet, ack []byte) error { 36 | pc := path.EndpointA.Chain.App.TIBCKeeper.PacketKeeper.GetPacketCommitment( 37 | path.EndpointA.Chain.GetContext(), packet.GetSourceChain(), packet.GetDestChain(), packet.GetSequence(), 38 | ) 39 | if bytes.Equal(pc, packettypes.CommitPacket(packet)) { 40 | 41 | // packet found, relay from A to B 42 | _ = path.EndpointB.UpdateClient() 43 | 44 | if err := path.EndpointB.RecvPacket(packet); err != nil { 45 | return err 46 | } 47 | 48 | if err := path.EndpointA.AcknowledgePacket(packet, ack); err != nil { 49 | return err 50 | } 51 | return nil 52 | 53 | } 54 | 55 | pc = path.EndpointB.Chain.App.TIBCKeeper.PacketKeeper.GetPacketCommitment( 56 | path.EndpointB.Chain.GetContext(), packet.GetSourceChain(), packet.GetDestChain(), packet.GetSequence(), 57 | ) 58 | if bytes.Equal(pc, packettypes.CommitPacket(packet)) { 59 | // packet found, relay B to A 60 | _ = path.EndpointA.UpdateClient() 61 | 62 | if err := path.EndpointA.RecvPacket(packet); err != nil { 63 | return err 64 | } 65 | if err := path.EndpointB.AcknowledgePacket(packet, ack); err != nil { 66 | return err 67 | } 68 | return nil 69 | } 70 | 71 | return fmt.Errorf("packet commitment does not exist on either endpoint for provided packet") 72 | } 73 | -------------------------------------------------------------------------------- /modules/tibc/testing/utils.go: -------------------------------------------------------------------------------- 1 | package tibctesting 2 | 3 | import ( 4 | "testing" 5 | 6 | abci "github.com/cometbft/cometbft/abci/types" 7 | tmtypes "github.com/cometbft/cometbft/types" 8 | "github.com/stretchr/testify/require" 9 | ) 10 | 11 | // ApplyValSetChanges takes in tmtypes.ValidatorSet and []abci.ValidatorUpdate and will return a new tmtypes.ValidatorSet which has the 12 | // provided validator updates applied to the provided validator set. 13 | func ApplyValSetChanges( 14 | t *testing.T, 15 | valSet *tmtypes.ValidatorSet, 16 | valUpdates []abci.ValidatorUpdate, 17 | ) *tmtypes.ValidatorSet { 18 | updates, err := tmtypes.PB2TM.ValidatorUpdates(valUpdates) 19 | require.NoError(t, err) 20 | 21 | // must copy since validator set will mutate with UpdateWithChangeSet 22 | newVals := valSet.Copy() 23 | err = newVals.UpdateWithChangeSet(updates) 24 | require.NoError(t, err) 25 | 26 | return newVals 27 | } 28 | -------------------------------------------------------------------------------- /proto/buf.gen.gogo.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | plugins: 3 | - name: gocosmos 4 | out: .. 5 | opt: plugins=grpc,Mgoogle/protobuf/any.proto=github.com/cosmos/cosmos-sdk/codec/types 6 | - name: grpc-gateway 7 | out: .. 8 | opt: logtostderr=true,allow_colon_final_segments=true -------------------------------------------------------------------------------- /proto/buf.gen.pulsar.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | managed: 3 | enabled: true 4 | go_package_prefix: 5 | default: cosmossdk.io/api 6 | except: 7 | - buf.build/googleapis/googleapis 8 | - buf.build/cosmos/gogo-proto 9 | - buf.build/cosmos/cosmos-proto 10 | - buf.build/cosmos/ics23 11 | override: 12 | buf.build/irisnet/tibc-go: github.com/bianjieai/tibc-go/api 13 | plugins: 14 | - name: go-pulsar 15 | out: ../api 16 | opt: paths=source_relative 17 | - name: go-grpc 18 | out: ../api 19 | opt: paths=source_relative 20 | -------------------------------------------------------------------------------- /proto/buf.lock: -------------------------------------------------------------------------------- 1 | # Generated by buf. DO NOT EDIT. 2 | version: v1 3 | deps: 4 | - remote: buf.build 5 | owner: cosmos 6 | repository: cosmos-proto 7 | commit: 1935555c206d4afb9e94615dfd0fad31 8 | - remote: buf.build 9 | owner: cosmos 10 | repository: cosmos-sdk 11 | commit: 954f7b05f38440fc8250134b15adec47 12 | - remote: buf.build 13 | owner: cosmos 14 | repository: gogo-proto 15 | commit: 34d970b699f84aa382f3c29773a60836 16 | - remote: buf.build 17 | owner: cosmos 18 | repository: ics23 19 | commit: dc427cb4519143d8996361c045a29ad7 20 | - remote: buf.build 21 | owner: googleapis 22 | repository: googleapis 23 | commit: 8d7204855ec14631a499bd7393ce1970 24 | -------------------------------------------------------------------------------- /proto/buf.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | name: buf.build/irisnet/tibc-go 3 | deps: 4 | - buf.build/cosmos/cosmos-sdk:aa25660f4ff746388669ce36b3778442 5 | - buf.build/cosmos/cosmos-proto:1935555c206d4afb9e94615dfd0fad31 6 | - buf.build/cosmos/gogo-proto:a14993478f40695898ed8a86931094b6656e8a5d 7 | - buf.build/googleapis/googleapis:8d7204855ec14631a499bd7393ce1970 8 | - buf.build/cosmos/ics23:dc427cb4519143d8996361c045a29ad7 9 | breaking: 10 | use: 11 | - FILE 12 | lint: 13 | use: 14 | - DEFAULT 15 | - COMMENTS 16 | - FILE_LOWER_SNAKE_CASE 17 | except: 18 | - UNARY_RPC 19 | - COMMENT_FIELD 20 | - SERVICE_SUFFIX 21 | - PACKAGE_VERSION_SUFFIX 22 | - RPC_REQUEST_STANDARD_NAME 23 | - RPC_RESPONSE_STANDARD_NAME 24 | -------------------------------------------------------------------------------- /proto/tibc/apps/mt_transfer/module/v1/module.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package tibc.apps.mt_transfer.module.v1; 4 | 5 | import "cosmos/app/v1alpha1/module.proto"; 6 | 7 | // Module is the config object of the tibc module. 8 | message Module { 9 | option (cosmos.app.v1alpha1.module) = { 10 | go_import : "github.com/bianjieai/tibc-go/modules/tibc/apps/mt_transfer" 11 | }; 12 | } -------------------------------------------------------------------------------- /proto/tibc/apps/mt_transfer/v1/mt_transfer.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package tibc.apps.mt_transfer.v1; 4 | option go_package = "github.com/bianjieai/tibc-go/modules/tibc/apps/mt_transfer/types"; 5 | 6 | message MultiTokenPacketData { 7 | // the class to which the Mt to be transferred belongs 8 | string class = 1; 9 | // the mt id 10 | string id = 2; 11 | // the address defined by MT outside the chain 12 | bytes data = 3; 13 | // the mt sender 14 | string sender = 4; 15 | // the mt receiver 16 | string receiver = 5; 17 | // identify whether it is far away from the source chain 18 | bool away_from_origin = 6; 19 | // the destination contract address to receive the nft 20 | string dest_contract = 7; 21 | // the amount defined by MT outside the chain 22 | uint64 amount = 8; 23 | } 24 | // ClassTrace contains the base class for Multi Token and the 25 | // source tracing information path. 26 | message ClassTrace { 27 | // path defines the chain of sourceChain/destChain 28 | // identifiers used for tracing the source of the Non fungible token. 29 | string path = 1; 30 | // base class of the relayed non fungible token. 31 | string base_class = 2; 32 | } -------------------------------------------------------------------------------- /proto/tibc/apps/mt_transfer/v1/query.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package tibc.apps.mt_transfer.v1; 3 | 4 | option go_package = "github.com/bianjieai/tibc-go/modules/tibc/apps/mt_transfer/types"; 5 | 6 | import "gogoproto/gogo.proto"; 7 | import "cosmos/base/query/v1beta1/pagination.proto"; 8 | import "tibc/apps/mt_transfer/v1/mt_transfer.proto"; 9 | import "google/api/annotations.proto"; 10 | 11 | // Query provides defines the gRPC querier service. 12 | service Query { 13 | // ClassTrace queries a class trace information. 14 | rpc ClassTrace(QueryClassTraceRequest) returns (QueryClassTraceResponse) { 15 | option (google.api.http).get = 16 | "/tibc/apps/mt_transfer/v1/class_traces/{hash}"; 17 | } 18 | 19 | // ClassTraces queries all class traces. 20 | rpc ClassTraces(QueryClassTracesRequest) returns (QueryClassTracesResponse) { 21 | option (google.api.http).get = "/tibc/apps/mt_transfer/v1/class_traces"; 22 | } 23 | } 24 | 25 | // QueryClassTraceRequest is the request type for the Query/ClassTrace RPC 26 | // method 27 | message QueryClassTraceRequest { 28 | // hash (in hex format) of the class trace information. 29 | string hash = 1; 30 | } 31 | 32 | // QueryClassTraceResponse is the response type for the Query/ClassTrace RPC 33 | // method. 34 | message QueryClassTraceResponse { 35 | // class_trace returns the requested class trace information. 36 | ClassTrace class_trace = 1; 37 | } 38 | 39 | // QueryConnectionsRequest is the request type for the Query/ClassTraces RPC 40 | // method 41 | message QueryClassTracesRequest { 42 | // pagination defines an optional pagination for the request. 43 | cosmos.base.query.v1beta1.PageRequest pagination = 1; 44 | } 45 | 46 | // QueryConnectionsResponse is the response type for the Query/ClassTraces RPC 47 | // method. 48 | message QueryClassTracesResponse { 49 | // class_traces returns all class trace information. 50 | repeated ClassTrace class_traces = 1 51 | [ (gogoproto.castrepeated) = "Traces", (gogoproto.nullable) = false ]; 52 | // pagination defines the pagination in the response. 53 | cosmos.base.query.v1beta1.PageResponse pagination = 2; 54 | } 55 | -------------------------------------------------------------------------------- /proto/tibc/apps/mt_transfer/v1/tx.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package tibc.apps.mt_transfer.v1; 3 | 4 | option go_package = "github.com/bianjieai/tibc-go/modules/tibc/apps/mt_transfer/types"; 5 | 6 | import "gogoproto/gogo.proto"; 7 | import "cosmos/msg/v1/msg.proto"; 8 | 9 | // Msg defines the tibc/MtTransfer Msg service. 10 | service Msg { 11 | option (cosmos.msg.v1.service) = true; 12 | 13 | // MtTransfer defines a rpc handler method for MsgMtTransfer. 14 | rpc MtTransfer(MsgMtTransfer) returns (MsgMtTransferResponse); 15 | } 16 | 17 | // MsgMtTransfer defines the Msg/MtTransfer request type. 18 | message MsgMtTransfer { 19 | option (gogoproto.equal) = false; 20 | option (gogoproto.goproto_getters) = false; 21 | option (cosmos.msg.v1.signer) = "sender"; 22 | 23 | // the class to which the mt to be transferred belongs 24 | string class = 1; 25 | // the mt id 26 | string id = 2; 27 | // the mt sender 28 | string sender = 3; 29 | // the mt receiver 30 | string receiver = 4; 31 | // target chain of transmission 32 | string dest_chain = 5; 33 | // relay chain during transmission 34 | string realay_chain = 6; 35 | // the destination contract address to receive the nft 36 | string dest_contract = 7; 37 | // the amount defined by MT outside the chain 38 | uint64 amount = 8; 39 | } 40 | 41 | // MsgMtTransferResponse defines the Msg/MtTransfer response type. 42 | message MsgMtTransferResponse {} -------------------------------------------------------------------------------- /proto/tibc/apps/nft_transfer/module/v1/module.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package tibc.apps.nft_transfer.module.v1; 4 | 5 | import "cosmos/app/v1alpha1/module.proto"; 6 | 7 | // Module is the config object of the tibc module. 8 | message Module { 9 | option (cosmos.app.v1alpha1.module) = { 10 | go_import : "github.com/bianjieai/tibc-go/modules/tibc/apps/nft_transfer" 11 | }; 12 | } -------------------------------------------------------------------------------- /proto/tibc/apps/nft_transfer/v1/nft_transfer.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package tibc.apps.nft_transfer.v1; 4 | option go_package = "github.com/bianjieai/tibc-go/modules/tibc/apps/nft_transfer/types"; 5 | 6 | import "gogoproto/gogo.proto"; 7 | 8 | message NonFungibleTokenPacketData { 9 | // the class to which the NFT to be transferred belongs 10 | string class = 1; 11 | // the nft id 12 | string id = 2; 13 | // the address defined by NFT outside the chain 14 | string uri = 3; 15 | // the nft sender 16 | string sender = 4; 17 | // the nft receiver 18 | string receiver = 5; 19 | // identify whether it is far away from the source chain 20 | bool away_from_origin = 6; 21 | // the destination contract address to receive the nft 22 | string dest_contract = 7; 23 | } 24 | // ClassTrace contains the base class for TICS30 Non fungible tokens and the 25 | // source tracing information path. 26 | message ClassTrace { 27 | // path defines the chain of sourceChain/destChain 28 | // identifiers used for tracing the source of the Non fungible token. 29 | string path = 1; 30 | // base class of the relayed non fungible token. 31 | string base_class = 2; 32 | } -------------------------------------------------------------------------------- /proto/tibc/apps/nft_transfer/v1/query.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package tibc.apps.nft_transfer.v1; 3 | 4 | option go_package = "github.com/bianjieai/tibc-go/modules/tibc/apps/nft_transfer/types"; 5 | 6 | import "gogoproto/gogo.proto"; 7 | import "cosmos/base/query/v1beta1/pagination.proto"; 8 | import "tibc/apps/nft_transfer/v1/nft_transfer.proto"; 9 | import "google/api/annotations.proto"; 10 | 11 | // Query provides defines the gRPC querier service. 12 | service Query { 13 | // ClassTrace queries a class trace information. 14 | rpc ClassTrace(QueryClassTraceRequest) returns (QueryClassTraceResponse) { 15 | option (google.api.http).get = 16 | "/tibc/apps/nft_transfer/v1/class_traces/{hash}"; 17 | } 18 | 19 | // ClassTraces queries all class traces. 20 | rpc ClassTraces(QueryClassTracesRequest) returns (QueryClassTracesResponse) { 21 | option (google.api.http).get = "/tibc/apps/nft_transfer/v1/class_traces"; 22 | } 23 | } 24 | 25 | // QueryClassTraceRequest is the request type for the Query/ClassTrace RPC 26 | // method 27 | message QueryClassTraceRequest { 28 | // hash (in hex format) of the class trace information. 29 | string hash = 1; 30 | } 31 | 32 | // QueryClassTraceResponse is the response type for the Query/ClassTrace RPC 33 | // method. 34 | message QueryClassTraceResponse { 35 | // class_trace returns the requested class trace information. 36 | ClassTrace class_trace = 1; 37 | } 38 | 39 | // QueryConnectionsRequest is the request type for the Query/ClassTraces RPC 40 | // method 41 | message QueryClassTracesRequest { 42 | // pagination defines an optional pagination for the request. 43 | cosmos.base.query.v1beta1.PageRequest pagination = 1; 44 | } 45 | 46 | // QueryConnectionsResponse is the response type for the Query/ClassTraces RPC 47 | // method. 48 | message QueryClassTracesResponse { 49 | // class_traces returns all class trace information. 50 | repeated ClassTrace class_traces = 1 51 | [ (gogoproto.castrepeated) = "Traces", (gogoproto.nullable) = false ]; 52 | // pagination defines the pagination in the response. 53 | cosmos.base.query.v1beta1.PageResponse pagination = 2; 54 | } 55 | -------------------------------------------------------------------------------- /proto/tibc/apps/nft_transfer/v1/tx.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package tibc.apps.nft_transfer.v1; 3 | 4 | option go_package = "github.com/bianjieai/tibc-go/modules/tibc/apps/nft_transfer/types"; 5 | 6 | import "gogoproto/gogo.proto"; 7 | import "cosmos/msg/v1/msg.proto"; 8 | 9 | // Msg defines the tibc/nftTransfer Msg service. 10 | service Msg { 11 | option (cosmos.msg.v1.service) = true; 12 | 13 | // NftTransfer defines a rpc handler method for MsgNftTransfer. 14 | rpc NftTransfer(MsgNftTransfer) returns (MsgNftTransferResponse); 15 | } 16 | 17 | // MsgNftTransfer defines the Msg/NftTransfer request type. 18 | message MsgNftTransfer { 19 | option (gogoproto.equal) = false; 20 | option (gogoproto.goproto_getters) = false; 21 | option (cosmos.msg.v1.signer) = "sender"; 22 | 23 | // the class to which the NFT to be transferred belongs 24 | string class = 1; 25 | // the nft id 26 | string id = 2; 27 | // the nft sender 28 | string sender = 3; 29 | // the nft receiver 30 | string receiver = 4; 31 | // target chain of transmission 32 | string dest_chain = 5; 33 | // relay chain during transmission 34 | string realay_chain = 6; 35 | // the destination contract address to receive the nft 36 | string dest_contract = 7; 37 | } 38 | 39 | // MsgTransferResponse defines the Msg/NftTransfer response type. 40 | message MsgNftTransferResponse {} -------------------------------------------------------------------------------- /proto/tibc/core/client/v1/genesis.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package tibc.core.client.v1; 3 | 4 | option go_package = "github.com/bianjieai/tibc-go/modules/tibc/core/02-client/types"; 5 | 6 | import "tibc/core/client/v1/client.proto"; 7 | import "gogoproto/gogo.proto"; 8 | 9 | // GenesisState defines the tibc client submodule's genesis state. 10 | message GenesisState { 11 | // client states with their corresponding identifiers 12 | repeated IdentifiedClientState clients = 1 [ 13 | (gogoproto.nullable) = false, 14 | (gogoproto.castrepeated) = "IdentifiedClientStates" 15 | ]; 16 | // consensus states from each client 17 | repeated ClientConsensusStates clients_consensus = 2 [ 18 | (gogoproto.nullable) = false, 19 | (gogoproto.castrepeated) = "ClientsConsensusStates" 20 | ]; 21 | // metadata from each client 22 | repeated IdentifiedGenesisMetadata clients_metadata = 3 23 | [ (gogoproto.nullable) = false ]; 24 | // the chain name of the current chain 25 | string native_chain_name = 5; 26 | 27 | // IdentifiedRelayer defines a list of authorized relayers for the specified 28 | // client. 29 | repeated IdentifiedRelayers relayers = 6 [ (gogoproto.nullable) = false ]; 30 | } 31 | 32 | // GenesisMetadata defines the genesis type for metadata that clients may return 33 | // with ExportMetadata 34 | message GenesisMetadata { 35 | option (gogoproto.goproto_getters) = false; 36 | 37 | // store key of metadata without chainName-prefix 38 | bytes key = 1; 39 | // metadata value 40 | bytes value = 2; 41 | } 42 | 43 | // IdentifiedGenesisMetadata has the client metadata with the corresponding 44 | // chain name. 45 | message IdentifiedGenesisMetadata { 46 | string chain_name = 1; 47 | repeated GenesisMetadata metadata = 2 [ (gogoproto.nullable) = false ]; 48 | } -------------------------------------------------------------------------------- /proto/tibc/core/commitment/v1/commitment.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package tibc.core.commitment.v1; 3 | 4 | option go_package = "github.com/bianjieai/tibc-go/modules/tibc/core/23-commitment/types"; 5 | 6 | import "gogoproto/gogo.proto"; 7 | import "cosmos/ics23/v1/proofs.proto"; 8 | 9 | // MerkleRoot defines a merkle root hash. 10 | // In the Cosmos SDK, the AppHash of a block header becomes the root. 11 | message MerkleRoot { 12 | option (gogoproto.goproto_getters) = false; 13 | 14 | bytes hash = 1; 15 | } 16 | 17 | // MerklePrefix is merkle path prefixed to the key. 18 | // The constructed key from the Path and the key will be append(Path.KeyPath, 19 | // append(Path.KeyPrefix, key...)) 20 | message MerklePrefix { 21 | bytes key_prefix = 1; 22 | } 23 | 24 | // MerklePath is the path used to verify commitment proofs, which can be an 25 | // arbitrary structured object (defined by a commitment type). 26 | // MerklePath is represented from root-to-leaf 27 | message MerklePath { 28 | option (gogoproto.goproto_stringer) = false; 29 | 30 | repeated string key_path = 1; 31 | } 32 | 33 | // MerkleProof is a wrapper type over a chain of CommitmentProofs. 34 | // It demonstrates membership or non-membership for an element or set of 35 | // elements, verifiable in conjunction with a known commitment root. Proofs 36 | // should be succinct. 37 | // MerkleProofs are ordered from leaf-to-root 38 | message MerkleProof { repeated cosmos.ics23.v1.CommitmentProof proofs = 1; } -------------------------------------------------------------------------------- /proto/tibc/core/module/v1/module.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package tibc.core.module.v1; 4 | 5 | import "cosmos/app/v1alpha1/module.proto"; 6 | 7 | // Module is the config object of the tibc module. 8 | message Module { 9 | option (cosmos.app.v1alpha1.module) = { 10 | go_import: "github.com/bianjieai/tibc-go/modules/tibc/core" 11 | }; 12 | 13 | // authority defines the custom module authority. If not set, defaults to the governance module. 14 | string authority = 1; 15 | } -------------------------------------------------------------------------------- /proto/tibc/core/packet/v1/genesis.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package tibc.core.packet.v1; 3 | 4 | option go_package = "github.com/bianjieai/tibc-go/modules/tibc/core/04-packet/types"; 5 | 6 | import "gogoproto/gogo.proto"; 7 | import "tibc/core/packet/v1/packet.proto"; 8 | 9 | // GenesisState defines the tibc channel submodule's genesis state. 10 | message GenesisState { 11 | repeated PacketState acknowledgements = 2 [ (gogoproto.nullable) = false ]; 12 | repeated PacketState commitments = 3 [ (gogoproto.nullable) = false ]; 13 | repeated PacketState receipts = 4 [ (gogoproto.nullable) = false ]; 14 | repeated PacketSequence send_sequences = 5 [ 15 | (gogoproto.nullable) = false, 16 | (gogoproto.moretags) = "yaml:\"send_sequences\"" 17 | ]; 18 | repeated PacketSequence recv_sequences = 6 [ 19 | (gogoproto.nullable) = false, 20 | (gogoproto.moretags) = "yaml:\"recv_sequences\"" 21 | ]; 22 | repeated PacketSequence ack_sequences = 7 [ 23 | (gogoproto.nullable) = false, 24 | (gogoproto.moretags) = "yaml:\"ack_sequences\"" 25 | ]; 26 | } 27 | 28 | // PacketSequence defines the genesis type necessary to retrieve and store 29 | // next send and receive sequences. 30 | message PacketSequence { 31 | string source_chain = 1 [ (gogoproto.moretags) = "yaml:\"source_chain\"" ]; 32 | string destination_chain = 2 33 | [ (gogoproto.moretags) = "yaml:\"destination_chain\"" ]; 34 | uint64 sequence = 3; 35 | } 36 | -------------------------------------------------------------------------------- /proto/tibc/core/routing/v1/genesis.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package tibc.core.routing.v1; 3 | 4 | option go_package = "github.com/bianjieai/tibc-go/modules/tibc/core/26-routing/types"; 5 | 6 | // GenesisState defines the tibc channel submodule's genesis state. 7 | message GenesisState { repeated string rules = 1; } 8 | -------------------------------------------------------------------------------- /proto/tibc/core/routing/v1/query.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package tibc.core.routing.v1; 3 | 4 | import "google/api/annotations.proto"; 5 | 6 | option go_package = "github.com/bianjieai/tibc-go/modules/tibc/core/26-routing/types"; 7 | 8 | // Query provides defines the gRPC querier service 9 | service Query { 10 | // RoutingRules queries all routing rules. 11 | rpc RoutingRules(QueryRoutingRulesRequest) 12 | returns (QueryRoutingRulesResponse) { 13 | option (google.api.http).get = "/tibc/core/routing/v1beta1/routing_rules"; 14 | } 15 | } 16 | 17 | // QueryRoutingRulesRequest is the request type for the 18 | // RoutingRules RPC method 19 | message QueryRoutingRulesRequest {} 20 | 21 | // QueryRoutingRulesResponse defines the routing rules query response 22 | message QueryRoutingRulesResponse { 23 | // rule string array 24 | repeated string rules = 1; 25 | } 26 | -------------------------------------------------------------------------------- /proto/tibc/core/routing/v1/routing.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package tibc.core.routing.v1; 3 | 4 | option go_package = "github.com/bianjieai/tibc-go/modules/tibc/core/26-routing/types"; 5 | 6 | import "gogoproto/gogo.proto"; 7 | 8 | // SetRoutingRulesProposal defines a proposal to set routing rules 9 | message SetRoutingRulesProposal { 10 | option (gogoproto.goproto_getters) = false; 11 | // the title of the update proposal 12 | string title = 1; 13 | // the description of the proposal 14 | string description = 2; 15 | // routing rules list 16 | repeated string rules = 3; 17 | } -------------------------------------------------------------------------------- /proto/tibc/core/routing/v1/tx.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package tibc.core.routing.v1; 3 | 4 | option go_package = "github.com/bianjieai/tibc-go/modules/tibc/core/26-routing/types"; 5 | 6 | import "gogoproto/gogo.proto"; 7 | import "cosmos/msg/v1/msg.proto"; 8 | import "cosmos_proto/cosmos.proto"; 9 | 10 | // Msg defines the tibc/routing Msg service. 11 | service Msg { 12 | option (cosmos.msg.v1.service) = true; 13 | 14 | // SetRoutingRules defines a rpc handler method for MsgSetRoutingRules. 15 | rpc SetRoutingRules(MsgSetRoutingRules) returns (MsgSetRoutingRulesResponse); 16 | 17 | } 18 | 19 | // MsgSetRoutingRules defines a proposal to set routing rules 20 | message MsgSetRoutingRules { 21 | option (gogoproto.goproto_getters) = false; 22 | option (cosmos.msg.v1.signer) = "authority"; 23 | // the title of the update proposal 24 | string title = 1; 25 | // the description of the proposal 26 | string description = 2; 27 | // routing rules list 28 | repeated string rules = 3; 29 | // authority is the address that controls the module (defaults to x/gov unless 30 | // overwritten). 31 | string authority = 4 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; 32 | } 33 | 34 | // MsgSetRoutingRulesResponse defines the Msg/SetRoutingRules response type. 35 | message MsgSetRoutingRulesResponse {} -------------------------------------------------------------------------------- /proto/tibc/core/types/v1/genesis.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package tibc.core.types.v1; 3 | 4 | option go_package = "github.com/bianjieai/tibc-go/modules/tibc/core/types"; 5 | 6 | import "gogoproto/gogo.proto"; 7 | import "tibc/core/client/v1/genesis.proto"; 8 | import "tibc/core/packet/v1/genesis.proto"; 9 | import "tibc/core/routing/v1/genesis.proto"; 10 | 11 | // GenesisState defines the tibc module's genesis state. 12 | message GenesisState { 13 | // TICS002 - Clients genesis state 14 | tibc.core.client.v1.GenesisState client_genesis = 1 [ 15 | (gogoproto.nullable) = false, 16 | (gogoproto.moretags) = "yaml:\"client_genesis\"" 17 | ]; 18 | // TICS004 - Packet genesis state 19 | tibc.core.packet.v1.GenesisState packet_genesis = 3 [ 20 | (gogoproto.nullable) = false, 21 | (gogoproto.moretags) = "yaml:\"packet_genesis\"" 22 | ]; 23 | // TICS026 - Routing genesis state 24 | tibc.core.routing.v1.GenesisState routing_genesis = 4 [ 25 | (gogoproto.nullable) = false, 26 | (gogoproto.moretags) = "yaml:\"routing_genesis\"" 27 | ]; 28 | } 29 | -------------------------------------------------------------------------------- /proto/tibc/lightclients/eth/v1/eth.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package tibc.lightclients.eth.v1; 3 | 4 | option go_package = "github.com/bianjieai/tibc-go/modules/tibc/light-clients/09-eth/types"; 5 | 6 | import "gogoproto/gogo.proto"; 7 | import "tibc/core/client/v1/client.proto"; 8 | 9 | // Header defines the eth client consensus Header. 10 | message Header { 11 | option (gogoproto.goproto_getters) = false; 12 | 13 | bytes parent_hash = 1; 14 | bytes uncle_hash = 2; 15 | bytes coinbase = 3; 16 | bytes root = 4; 17 | bytes tx_hash = 5; 18 | bytes receipt_hash = 6; 19 | bytes bloom = 7; 20 | string difficulty = 8; 21 | tibc.core.client.v1.Height height = 9 [ (gogoproto.nullable) = false ]; 22 | uint64 gas_limit = 10; 23 | uint64 gas_used = 11; 24 | uint64 time = 12; 25 | bytes extra = 13; 26 | bytes mix_digest = 14; 27 | uint64 nonce = 15; 28 | string baseFee = 16; 29 | } 30 | 31 | // ClientState from eth tracks the current validator set, latest height, 32 | // and a possible frozen height. 33 | message ClientState { 34 | option (gogoproto.goproto_getters) = false; 35 | 36 | Header header = 1 [ (gogoproto.nullable) = false ]; 37 | uint64 chain_id = 2; 38 | bytes contract_address = 3; 39 | uint64 trusting_period = 4; 40 | uint64 timeDelay = 5; 41 | uint64 blockDelay = 6; 42 | } 43 | 44 | // ConsensusState defines the consensus state from eth. 45 | message ConsensusState { 46 | option (gogoproto.goproto_getters) = false; 47 | 48 | // timestamp that corresponds to the block height in which the ConsensusState 49 | // was stored. 50 | uint64 timestamp = 1; 51 | tibc.core.client.v1.Height number = 2 [ (gogoproto.nullable) = false ]; 52 | bytes root = 3; 53 | } 54 | 55 | message StorageResult { 56 | option (gogoproto.goproto_getters) = false; 57 | 58 | string key = 1; 59 | string value = 2; 60 | repeated string proof = 3; 61 | } 62 | 63 | message Proof { 64 | option (gogoproto.goproto_getters) = false; 65 | 66 | string address = 1; 67 | string balance = 2; 68 | string code_hash = 3; 69 | string nonce = 4; 70 | string storage_hash = 5; 71 | repeated string account_proof = 6; 72 | repeated StorageResult storage_proof = 7; 73 | } -------------------------------------------------------------------------------- /scripts/protocgen-pulsar.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | protoc_install_gopulsar() { 6 | go install github.com/cosmos/cosmos-proto/cmd/protoc-gen-go-pulsar@latest 7 | go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest 8 | } 9 | 10 | protoc_install_gopulsar 11 | 12 | echo "Cleaning API directory" 13 | (cd api; find ./ -type f \( -iname \*.pulsar.go -o -iname \*.pb.go -o -iname \*.cosmos_orm.go -o -iname \*.pb.gw.go \) -delete; find . -empty -type d -delete; cd ..) 14 | 15 | echo "Generating API module" 16 | (cd proto; buf generate --template buf.gen.pulsar.yaml) 17 | -------------------------------------------------------------------------------- /scripts/protocgen.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | echo "Generating gogo proto code" 6 | cd proto 7 | proto_dirs=$(find ./tibc -path -prune -o -name '*.proto' -print0 | xargs -0 -n1 dirname | sort | uniq) 8 | for dir in $proto_dirs; do 9 | for file in $(find "${dir}" -maxdepth 1 -name '*.proto'); do 10 | # this regex checks if a proto file has its go_package set to cosmossdk.io/api/... 11 | # gogo proto files SHOULD ONLY be generated if this is false 12 | # we don't want gogo proto to run for proto files which are natively built for google.golang.org/protobuf 13 | if grep -q "option go_package" "$file" && grep -H -o -c 'option go_package.*cosmossdk.io/api' "$file" | grep -q ':0$'; then 14 | buf generate --template buf.gen.gogo.yaml $file 15 | fi 16 | done 17 | done 18 | 19 | cd .. 20 | 21 | # move proto files to the right places 22 | cp -r github.com/bianjieai/tibc-go/* ./ 23 | rm -rf github.com 24 | 25 | ./scripts/protocgen-pulsar.sh -------------------------------------------------------------------------------- /simapp/address.go: -------------------------------------------------------------------------------- 1 | package simapp 2 | 3 | import sdk "github.com/cosmos/cosmos-sdk/types" 4 | 5 | const ( 6 | 7 | // Bech32ChainPrefix defines the prefix of this chain 8 | Bech32ChainPrefix = "i" 9 | 10 | // PrefixAcc is the prefix for account 11 | PrefixAcc = "a" 12 | 13 | // PrefixValidator is the prefix for validator keys 14 | PrefixValidator = "v" 15 | 16 | // PrefixConsensus is the prefix for consensus keys 17 | PrefixConsensus = "c" 18 | 19 | // PrefixPublic is the prefix for public 20 | PrefixPublic = "p" 21 | 22 | // PrefixAddress is the prefix for address 23 | PrefixAddress = "a" 24 | 25 | // Bech32PrefixAccAddr defines the Bech32 prefix of an account's address 26 | Bech32PrefixAccAddr = Bech32ChainPrefix + PrefixAcc + PrefixAddress 27 | // Bech32PrefixAccPub defines the Bech32 prefix of an account's public key 28 | Bech32PrefixAccPub = Bech32ChainPrefix + PrefixAcc + PrefixPublic 29 | // Bech32PrefixValAddr defines the Bech32 prefix of a validator's operator address 30 | Bech32PrefixValAddr = Bech32ChainPrefix + PrefixValidator + PrefixAddress 31 | // Bech32PrefixValPub defines the Bech32 prefix of a validator's operator public key 32 | Bech32PrefixValPub = Bech32ChainPrefix + PrefixValidator + PrefixPublic 33 | // Bech32PrefixConsAddr defines the Bech32 prefix of a consensus node address 34 | Bech32PrefixConsAddr = Bech32ChainPrefix + PrefixConsensus + PrefixAddress 35 | // Bech32PrefixConsPub defines the Bech32 prefix of a consensus node public key 36 | Bech32PrefixConsPub = Bech32ChainPrefix + PrefixConsensus + PrefixPublic 37 | ) 38 | 39 | func ConfigureBech32Prefix() { 40 | config := sdk.GetConfig() 41 | config.SetBech32PrefixForAccount(Bech32PrefixAccAddr, Bech32PrefixAccPub) 42 | config.SetBech32PrefixForValidator(Bech32PrefixValAddr, Bech32PrefixValPub) 43 | config.SetBech32PrefixForConsensusNode(Bech32PrefixConsAddr, Bech32PrefixConsPub) 44 | config.Seal() 45 | } 46 | -------------------------------------------------------------------------------- /simapp/encoding.go: -------------------------------------------------------------------------------- 1 | package simapp 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/std" 5 | 6 | simappparams "github.com/bianjieai/tibc-go/simapp/params" 7 | ) 8 | 9 | // MakeTestEncodingConfig creates an EncodingConfig for testing. 10 | // This function should be used only internally (in the SDK). 11 | // App user should'nt create new codecs - use the app.AppCodec instead. 12 | // [DEPRECATED] 13 | func MakeTestEncodingConfig() simappparams.EncodingConfig { 14 | encodingConfig := simappparams.MakeTestEncodingConfig() 15 | std.RegisterLegacyAminoCodec(encodingConfig.Amino) 16 | std.RegisterInterfaces(encodingConfig.InterfaceRegistry) 17 | ModuleBasics.RegisterLegacyAminoCodec(encodingConfig.Amino) 18 | ModuleBasics.RegisterInterfaces(encodingConfig.InterfaceRegistry) 19 | return encodingConfig 20 | } 21 | -------------------------------------------------------------------------------- /simapp/genesis.go: -------------------------------------------------------------------------------- 1 | package simapp 2 | 3 | import ( 4 | "encoding/json" 5 | 6 | "github.com/cosmos/cosmos-sdk/codec" 7 | ) 8 | 9 | // The genesis state of the blockchain is represented here as a map of raw json 10 | // messages key'd by a identifier string. 11 | // The identifier is used to determine which module genesis information belongs 12 | // to so it may be appropriately routed during init chain. 13 | // Within this application default genesis information is retrieved from 14 | // the ModuleBasicManager which populates json from each BasicModule 15 | // object provided to it during init. 16 | type GenesisState map[string]json.RawMessage 17 | 18 | // NewDefaultGenesisState generates the default state for the application. 19 | func NewDefaultGenesisState(cdc codec.JSONCodec) GenesisState { 20 | return ModuleBasics.DefaultGenesis(cdc) 21 | } 22 | -------------------------------------------------------------------------------- /simapp/genesis_account.go: -------------------------------------------------------------------------------- 1 | package simapp 2 | 3 | import ( 4 | "errors" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" 8 | ) 9 | 10 | var _ authtypes.GenesisAccount = (*SimGenesisAccount)(nil) 11 | 12 | // SimGenesisAccount defines a type that implements the GenesisAccount interface 13 | // to be used for simulation accounts in the genesis state. 14 | type SimGenesisAccount struct { 15 | *authtypes.BaseAccount 16 | 17 | // vesting account fields 18 | OriginalVesting sdk.Coins `json:"original_vesting" yaml:"original_vesting"` // total vesting coins upon initialization 19 | DelegatedFree sdk.Coins `json:"delegated_free" yaml:"delegated_free"` // delegated vested coins at time of delegation 20 | DelegatedVesting sdk.Coins `json:"delegated_vesting" yaml:"delegated_vesting"` // delegated vesting coins at time of delegation 21 | StartTime int64 `json:"start_time" yaml:"start_time"` // vesting start time (UNIX Epoch time) 22 | EndTime int64 `json:"end_time" yaml:"end_time"` // vesting end time (UNIX Epoch time) 23 | 24 | // module account fields 25 | ModuleName string `json:"module_name" yaml:"module_name"` // name of the module account 26 | ModulePermissions []string `json:"module_permissions" yaml:"module_permissions"` // permissions of module account 27 | } 28 | 29 | // Validate checks for errors on the vesting and module account parameters 30 | func (sga SimGenesisAccount) Validate() error { 31 | if !sga.OriginalVesting.IsZero() { 32 | if sga.StartTime >= sga.EndTime { 33 | return errors.New("vesting start-time cannot be before end-time") 34 | } 35 | } 36 | 37 | if sga.ModuleName != "" { 38 | ma := authtypes.ModuleAccount{ 39 | BaseAccount: sga.BaseAccount, Name: sga.ModuleName, Permissions: sga.ModulePermissions, 40 | } 41 | if err := ma.Validate(); err != nil { 42 | return err 43 | } 44 | } 45 | 46 | return sga.BaseAccount.Validate() 47 | } 48 | -------------------------------------------------------------------------------- /simapp/params/amino.go: -------------------------------------------------------------------------------- 1 | //go:build test_amino 2 | // +build test_amino 3 | 4 | package params 5 | 6 | import ( 7 | "github.com/cosmos/cosmos-sdk/codec" 8 | "github.com/cosmos/cosmos-sdk/codec/types" 9 | "github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx" 10 | ) 11 | 12 | // MakeTestEncodingConfig creates an EncodingConfig for an amino based test configuration. 13 | // This function should be used only internally (in the SDK). 14 | // App user should'nt create new codecs - use the app.AppCodec instead. 15 | // [DEPRECATED] 16 | func MakeTestEncodingConfig() EncodingConfig { 17 | cdc := codec.NewLegacyAmino() 18 | interfaceRegistry := types.NewInterfaceRegistry() 19 | marshaler := codec.NewAminoCodec(cdc) 20 | 21 | return EncodingConfig{ 22 | InterfaceRegistry: interfaceRegistry, 23 | Marshaler: marshaler, 24 | TxConfig: legacytx.StdTxConfig{Cdc: cdc}, 25 | Amino: cdc, 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /simapp/params/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package params defines the simulation parameters in the simapp. 3 | 4 | It contains the default weights used for each transaction used on the module's 5 | simulation. These weights define the chance for a transaction to be simulated at 6 | any given operation. 7 | 8 | You can replace the default values for the weights by providing a params.json 9 | file with the weights defined for each of the transaction operations: 10 | 11 | { 12 | "op_weight_msg_send": 60, 13 | "op_weight_msg_delegate": 100, 14 | } 15 | 16 | In the example above, the `MsgSend` has 60% chance to be simulated, while the 17 | `MsgDelegate` will always be simulated. 18 | */ 19 | package params 20 | -------------------------------------------------------------------------------- /simapp/params/encoding.go: -------------------------------------------------------------------------------- 1 | package params 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/client" 5 | "github.com/cosmos/cosmos-sdk/codec" 6 | "github.com/cosmos/cosmos-sdk/codec/types" 7 | ) 8 | 9 | // EncodingConfig specifies the concrete encoding types to use for a given app. 10 | // This is provided for compatibility between protobuf and amino implementations. 11 | type EncodingConfig struct { 12 | InterfaceRegistry types.InterfaceRegistry 13 | Codec codec.Codec 14 | TxConfig client.TxConfig 15 | Amino *codec.LegacyAmino 16 | } 17 | -------------------------------------------------------------------------------- /simapp/params/params.go: -------------------------------------------------------------------------------- 1 | package params 2 | 3 | // Simulation parameter constants 4 | const ( 5 | StakePerAccount = "stake_per_account" 6 | InitiallyBondedValidators = "initially_bonded_validators" 7 | ) 8 | -------------------------------------------------------------------------------- /simapp/params/proto.go: -------------------------------------------------------------------------------- 1 | //go:build !test_amino 2 | // +build !test_amino 3 | 4 | package params 5 | 6 | import ( 7 | "github.com/cosmos/cosmos-sdk/codec" 8 | "github.com/cosmos/cosmos-sdk/codec/types" 9 | "github.com/cosmos/cosmos-sdk/x/auth/tx" 10 | ) 11 | 12 | // MakeTestEncodingConfig creates an EncodingConfig for a non-amino based test configuration. 13 | // This function should be used only internally (in the SDK). 14 | // App user should'nt create new codecs - use the app.AppCodec instead. 15 | // [DEPRECATED] 16 | func MakeTestEncodingConfig() EncodingConfig { 17 | cdc := codec.NewLegacyAmino() 18 | interfaceRegistry := types.NewInterfaceRegistry() 19 | codec := codec.NewProtoCodec(interfaceRegistry) 20 | 21 | return EncodingConfig{ 22 | InterfaceRegistry: interfaceRegistry, 23 | Codec: codec, 24 | TxConfig: tx.NewTxConfig(codec, tx.DefaultSignModes), 25 | Amino: cdc, 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /simapp/params/weights.go: -------------------------------------------------------------------------------- 1 | package params 2 | 3 | // Default simulation operation weights for messages and gov proposals 4 | const ( 5 | DefaultWeightMsgSend int = 100 6 | DefaultWeightMsgMultiSend int = 10 7 | DefaultWeightMsgSetWithdrawAddress int = 50 8 | DefaultWeightMsgWithdrawDelegationReward int = 50 9 | DefaultWeightMsgWithdrawValidatorCommission int = 50 10 | DefaultWeightMsgFundCommunityPool int = 50 11 | DefaultWeightMsgDeposit int = 100 12 | DefaultWeightMsgVote int = 67 13 | DefaultWeightMsgUnjail int = 100 14 | DefaultWeightMsgCreateValidator int = 100 15 | DefaultWeightMsgEditValidator int = 5 16 | DefaultWeightMsgDelegate int = 100 17 | DefaultWeightMsgUndelegate int = 100 18 | DefaultWeightMsgBeginRedelegate int = 100 19 | 20 | DefaultWeightCommunitySpendProposal int = 5 21 | DefaultWeightTextProposal int = 5 22 | DefaultWeightParamChangeProposal int = 5 23 | ) 24 | --------------------------------------------------------------------------------