From 816a9a4fafc6aa4ca9113fba105a57be38f5087c Mon Sep 17 00:00:00 2001 From: Blas Rodriguez Irizar Date: Wed, 23 Aug 2023 04:11:02 +0200 Subject: [PATCH 01/43] scripts: add docker-compose to execute ethereum devnet --- .gitignore | 9 ++ scripts/eth-bridge/consensus/config.yml | 24 ++++ scripts/eth-bridge/docker-compose.yaml | 110 ++++++++++++++++++ scripts/eth-bridge/execution/genesis.json | 109 +++++++++++++++++ .../eth-bridge/execution/geth_password.txt | 0 scripts/eth-bridge/execution/jwtsecret | 0 scripts/eth-bridge/execution/sk.json | 1 + scripts/eth-bridge/jwtsecret | 1 + 8 files changed, 254 insertions(+) create mode 100644 scripts/eth-bridge/consensus/config.yml create mode 100644 scripts/eth-bridge/docker-compose.yaml create mode 100644 scripts/eth-bridge/execution/genesis.json create mode 100644 scripts/eth-bridge/execution/geth_password.txt create mode 100755 scripts/eth-bridge/execution/jwtsecret create mode 100644 scripts/eth-bridge/execution/sk.json create mode 100644 scripts/eth-bridge/jwtsecret diff --git a/.gitignore b/.gitignore index f0656bac9..f40d0764f 100644 --- a/.gitignore +++ b/.gitignore @@ -73,3 +73,12 @@ typechain-types/ # foundry cache/ out/ + + +# eth-bridge +scripts/eth-bridge/execution/geth +scripts/eth-bridge/execution/keystore +scripts/eth-bridge/execution/geth.ipc +scripts/eth-bridge/consensus/genesis.ssz +scripts/eth-bridge/consensus/beacondata +scripts/eth-bridge/consensus/validatordata \ No newline at end of file diff --git a/scripts/eth-bridge/consensus/config.yml b/scripts/eth-bridge/consensus/config.yml new file mode 100644 index 000000000..78d669be6 --- /dev/null +++ b/scripts/eth-bridge/consensus/config.yml @@ -0,0 +1,24 @@ +CONFIG_NAME: interop +PRESET_BASE: interop + +# Genesis +GENESIS_FORK_VERSION: 0x20000089 + +# Altair +ALTAIR_FORK_EPOCH: 0 +ALTAIR_FORK_VERSION: 0x20000090 + +# Merge +BELLATRIX_FORK_EPOCH: 0 +BELLATRIX_FORK_VERSION: 0x20000091 +TERMINAL_TOTAL_DIFFICULTY: 0 + +CAPELLA_FORK_EPOCH: 2 +CAPELLA_FORK_VERSION: 0x20000092 + +# Time parameters +SECONDS_PER_SLOT: 12 +SLOTS_PER_EPOCH: 6 + +# Deposit contract +DEPOSIT_CONTRACT_ADDRESS: 0x4242424242424242424242424242424242424242 \ No newline at end of file diff --git a/scripts/eth-bridge/docker-compose.yaml b/scripts/eth-bridge/docker-compose.yaml new file mode 100644 index 000000000..0278bbcbb --- /dev/null +++ b/scripts/eth-bridge/docker-compose.yaml @@ -0,0 +1,110 @@ +version: "3.9" +services: + #Creates a genesis state for the beacon chain using a YAML configuration file and + # a deterministic set of 64 validators. + create-beacon-chain-genesis: + image: "gcr.io/prysmaticlabs/prysm/cmd/prysmctl:latest" + command: + - testnet + - generate-genesis + - --fork=bellatrix + - --num-validators=64 + - --output-ssz=/consensus/genesis.ssz + - --chain-config-file=/consensus/config.yml + - --geth-genesis-json-in=/execution/genesis.json + - --geth-genesis-json-out=/execution/genesis.json + volumes: + - ./consensus:/consensus + - ./execution:/execution + + # Sets up the genesis configuration for the go-ethereum client from a JSON file. + geth-genesis: + image: "ethereum/client-go:latest" + command: --datadir=/execution init /execution/genesis.json + volumes: + - ./execution:/execution + - ./execution/genesis.json:/execution/genesis.json + depends_on: + create-beacon-chain-genesis: + condition: service_completed_successfully + + # Runs the go-ethereum execution client with the specified, unlocked account and necessary + # APIs to allow for proof-of-stake consensus via Prysm. + geth: + image: "ethereum/client-go:latest" + command: + - --http + - --http.api=eth + - --http.addr=0.0.0.0 + - --authrpc.vhosts=* + - --authrpc.addr=0.0.0.0 + - --authrpc.jwtsecret=/execution/jwtsecret + - --datadir=/execution + - --allow-insecure-unlock + - --unlock=0x123463a4b065722e99115d6c222f267d9cabb524 + - --password=/execution/geth_password.txt + - --nodiscover + - --syncmode=full + ports: + - 8551:8551 + - 8545:8545 + depends_on: + geth-genesis: + condition: service_completed_successfully + volumes: + - ./execution:/execution + - ./execution/geth_password.txt:/execution/geth_password.txt + - ./jwtsecret:/execution/jwtsecret + + # Runs a Prysm beacon chain from a specified genesis state created in the previous step + # and connects to go-ethereum in the same network as the execution client. + # The account used in go-ethereum is set as the suggested fee recipient for transactions + # proposed via the validators attached to the beacon node. + beacon-chain: + image: "gcr.io/prysmaticlabs/prysm/beacon-chain:latest" + command: + - --datadir=/consensus/beacondata + # No peers to sync with in this testnet, so setting to 0 + - --min-sync-peers=0 + - --genesis-state=/consensus/genesis.ssz + - --bootstrap-node= + # The chain configuration file used for setting up Prysm + - --chain-config-file=/consensus/config.yml + # We specify the chain id used by our execution client + - --chain-id=${CHAIN_ID:-32382} + - --rpc-host=0.0.0.0 + - --contract-deployment-block=0 + - --grpc-gateway-host=0.0.0.0 + - --execution-endpoint=http://geth:8551 + - --accept-terms-of-use + - --jwt-secret=/execution/jwtsecret + - --suggested-fee-recipient=0x123463a4b065722e99115d6c222f267d9cabb524 + depends_on: + geth: + condition: service_started + create-beacon-chain-genesis: + condition: service_completed_successfully + ports: + - 4000:4000 + - 3500:3500 + - 8080:8080 + volumes: + - ./consensus:/consensus + - ./jwtsecret:/execution/jwtsecret + + # We run a validator client with 64, deterministically-generated keys that match + # The validator keys present in the beacon chain genesis state generated a few steps above. + validator: + image: "gcr.io/prysmaticlabs/prysm/validator:latest" + command: + - --beacon-rpc-provider=beacon-chain:4000 + - --datadir=/consensus/validatordata + - --accept-terms-of-use + - --interop-num-validators=64 + - --interop-start-index=0 + - --chain-config-file=/consensus/config.yml + depends_on: + beacon-chain: + condition: service_started + volumes: + - ./consensus:/consensus diff --git a/scripts/eth-bridge/execution/genesis.json b/scripts/eth-bridge/execution/genesis.json new file mode 100644 index 000000000..5357449b4 --- /dev/null +++ b/scripts/eth-bridge/execution/genesis.json @@ -0,0 +1,109 @@ +{ + "config": { + "chainId": 32382, + "homesteadBlock": 0, + "daoForkSupport": true, + "eip150Block": 0, + "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "eip155Block": 0, + "eip158Block": 0, + "byzantiumBlock": 0, + "constantinopleBlock": 0, + "petersburgBlock": 0, + "istanbulBlock": 0, + "muirGlacierBlock": 0, + "berlinBlock": 0, + "londonBlock": 0, + "arrowGlacierBlock": 0, + "grayGlacierBlock": 0, + "shanghaiTime": 1692756641, + "terminalTotalDifficulty": 0, + "clique": { + "period": 5, + "epoch": 30000 + } + }, + "nonce": "0x0", + "timestamp": "0x64e56a11", + "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000123463a4b065722e99115d6c222f267d9cabb5240000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "gasLimit": "0x1c9c380", + "difficulty": "0x1", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase": "0x0000000000000000000000000000000000000000", + "alloc": { + "123463a4b065722e99115d6c222f267d9cabb524": { + "balance": "0x43c33c1937564800000" + }, + "14dc79964da2c08b23698b3d3cc7ca32193d9955": { + "balance": "0x21e19e0c9bab2400000" + }, + "15d34aaf54267db7d7c367839aaf71a00a2c6a65": { + "balance": "0x21e19e0c9bab2400000" + }, + "1cbd3b2770909d4e10f157cabc84c7264073c9ec": { + "balance": "0x21e19e0c9bab2400000" + }, + "23618e81e3f5cdf7f54c3d65f7fbc0abf5b21e8f": { + "balance": "0x21e19e0c9bab2400000" + }, + "2546bcd3c84621e976d8185a91a922ae77ecec30": { + "balance": "0x21e19e0c9bab2400000" + }, + "3c44cdddb6a900fa2b585dd299e03d12fa4293bc": { + "balance": "0x21e19e0c9bab2400000" + }, + "4242424242424242424242424242424242424242": { + "code": "0x60806040526004361061003f5760003560e01c806301ffc9a71461004457806322895118146100b6578063621fd130146101e3578063c5f2892f14610273575b600080fd5b34801561005057600080fd5b5061009c6004803603602081101561006757600080fd5b8101908080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916906020019092919050505061029e565b604051808215151515815260200191505060405180910390f35b6101e1600480360360808110156100cc57600080fd5b81019080803590602001906401000000008111156100e957600080fd5b8201836020820111156100fb57600080fd5b8035906020019184600183028401116401000000008311171561011d57600080fd5b90919293919293908035906020019064010000000081111561013e57600080fd5b82018360208201111561015057600080fd5b8035906020019184600183028401116401000000008311171561017257600080fd5b90919293919293908035906020019064010000000081111561019357600080fd5b8201836020820111156101a557600080fd5b803590602001918460018302840111640100000000831117156101c757600080fd5b909192939192939080359060200190929190505050610370565b005b3480156101ef57600080fd5b506101f8610fd0565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561023857808201518184015260208101905061021d565b50505050905090810190601f1680156102655780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561027f57600080fd5b50610288610fe2565b6040518082815260200191505060405180910390f35b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061036957507f85640907000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b603087879050146103cc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806116ec6026913960400191505060405180910390fd5b60208585905014610428576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260368152602001806116836036913960400191505060405180910390fd5b60608383905014610484576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602981526020018061175f6029913960400191505060405180910390fd5b670de0b6b3a76400003410156104e5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806117396026913960400191505060405180910390fd5b6000633b9aca0034816104f457fe5b061461054b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260338152602001806116b96033913960400191505060405180910390fd5b6000633b9aca00348161055a57fe5b04905067ffffffffffffffff80168111156105c0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260278152602001806117126027913960400191505060405180910390fd5b60606105cb82611314565b90507f649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c589898989858a8a610600602054611314565b60405180806020018060200180602001806020018060200186810386528e8e82818152602001925080828437600081840152601f19601f82011690508083019250505086810385528c8c82818152602001925080828437600081840152601f19601f82011690508083019250505086810384528a818151815260200191508051906020019080838360005b838110156106a657808201518184015260208101905061068b565b50505050905090810190601f1680156106d35780820380516001836020036101000a031916815260200191505b508681038352898982818152602001925080828437600081840152601f19601f820116905080830192505050868103825287818151815260200191508051906020019080838360005b8381101561073757808201518184015260208101905061071c565b50505050905090810190601f1680156107645780820380516001836020036101000a031916815260200191505b509d505050505050505050505050505060405180910390a1600060028a8a600060801b6040516020018084848082843780830192505050826fffffffffffffffffffffffffffffffff19166fffffffffffffffffffffffffffffffff1916815260100193505050506040516020818303038152906040526040518082805190602001908083835b6020831061080e57805182526020820191506020810190506020830392506107eb565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa158015610850573d6000803e3d6000fd5b5050506040513d602081101561086557600080fd5b8101908080519060200190929190505050905060006002808888600090604092610891939291906115da565b6040516020018083838082843780830192505050925050506040516020818303038152906040526040518082805190602001908083835b602083106108eb57805182526020820191506020810190506020830392506108c8565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa15801561092d573d6000803e3d6000fd5b5050506040513d602081101561094257600080fd5b8101908080519060200190929190505050600289896040908092610968939291906115da565b6000801b604051602001808484808284378083019250505082815260200193505050506040516020818303038152906040526040518082805190602001908083835b602083106109cd57805182526020820191506020810190506020830392506109aa565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa158015610a0f573d6000803e3d6000fd5b5050506040513d6020811015610a2457600080fd5b810190808051906020019092919050505060405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b60208310610a8e5780518252602082019150602081019050602083039250610a6b565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa158015610ad0573d6000803e3d6000fd5b5050506040513d6020811015610ae557600080fd5b810190808051906020019092919050505090506000600280848c8c604051602001808481526020018383808284378083019250505093505050506040516020818303038152906040526040518082805190602001908083835b60208310610b615780518252602082019150602081019050602083039250610b3e565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa158015610ba3573d6000803e3d6000fd5b5050506040513d6020811015610bb857600080fd5b8101908080519060200190929190505050600286600060401b866040516020018084805190602001908083835b60208310610c085780518252602082019150602081019050602083039250610be5565b6001836020036101000a0380198251168184511680821785525050505050509050018367ffffffffffffffff191667ffffffffffffffff1916815260180182815260200193505050506040516020818303038152906040526040518082805190602001908083835b60208310610c935780518252602082019150602081019050602083039250610c70565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa158015610cd5573d6000803e3d6000fd5b5050506040513d6020811015610cea57600080fd5b810190808051906020019092919050505060405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b60208310610d545780518252602082019150602081019050602083039250610d31565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa158015610d96573d6000803e3d6000fd5b5050506040513d6020811015610dab57600080fd5b81019080805190602001909291905050509050858114610e16576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252605481526020018061162f6054913960600191505060405180910390fd5b6001602060020a0360205410610e77576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602181526020018061160e6021913960400191505060405180910390fd5b60016020600082825401925050819055506000602054905060008090505b6020811015610fb75760018083161415610ec8578260008260208110610eb757fe5b018190555050505050505050610fc7565b600260008260208110610ed757fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b60208310610f335780518252602082019150602081019050602083039250610f10565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa158015610f75573d6000803e3d6000fd5b5050506040513d6020811015610f8a57600080fd5b8101908080519060200190929190505050925060028281610fa757fe5b0491508080600101915050610e95565b506000610fc057fe5b5050505050505b50505050505050565b6060610fdd602054611314565b905090565b6000806000602054905060008090505b60208110156111d057600180831614156110e05760026000826020811061101557fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b60208310611071578051825260208201915060208101905060208303925061104e565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa1580156110b3573d6000803e3d6000fd5b5050506040513d60208110156110c857600080fd5b810190808051906020019092919050505092506111b6565b600283602183602081106110f057fe5b015460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061114b5780518252602082019150602081019050602083039250611128565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa15801561118d573d6000803e3d6000fd5b5050506040513d60208110156111a257600080fd5b810190808051906020019092919050505092505b600282816111c057fe5b0491508080600101915050610ff2565b506002826111df602054611314565b600060401b6040516020018084815260200183805190602001908083835b6020831061122057805182526020820191506020810190506020830392506111fd565b6001836020036101000a0380198251168184511680821785525050505050509050018267ffffffffffffffff191667ffffffffffffffff1916815260180193505050506040516020818303038152906040526040518082805190602001908083835b602083106112a55780518252602082019150602081019050602083039250611282565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa1580156112e7573d6000803e3d6000fd5b5050506040513d60208110156112fc57600080fd5b81019080805190602001909291905050509250505090565b6060600867ffffffffffffffff8111801561132e57600080fd5b506040519080825280601f01601f1916602001820160405280156113615781602001600182028036833780820191505090505b50905060008260c01b90508060076008811061137957fe5b1a60f81b8260008151811061138a57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350806006600881106113c657fe5b1a60f81b826001815181106113d757fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060056008811061141357fe5b1a60f81b8260028151811061142457fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060046008811061146057fe5b1a60f81b8260038151811061147157fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350806003600881106114ad57fe5b1a60f81b826004815181106114be57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350806002600881106114fa57fe5b1a60f81b8260058151811061150b57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060016008811061154757fe5b1a60f81b8260068151811061155857fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060006008811061159457fe5b1a60f81b826007815181106115a557fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535050919050565b600080858511156115ea57600080fd5b838611156115f757600080fd5b600185028301915084860390509450949250505056fe4465706f736974436f6e74726163743a206d65726b6c6520747265652066756c6c4465706f736974436f6e74726163743a207265636f6e7374727563746564204465706f7369744461746120646f6573206e6f74206d6174636820737570706c696564206465706f7369745f646174615f726f6f744465706f736974436f6e74726163743a20696e76616c6964207769746864726177616c5f63726564656e7469616c73206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c7565206e6f74206d756c7469706c65206f6620677765694465706f736974436f6e74726163743a20696e76616c6964207075626b6579206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f20686967684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f206c6f774465706f736974436f6e74726163743a20696e76616c6964207369676e6174757265206c656e677468a2646970667358221220230afd4b6e3551329e50f1239e08fa3ab7907b77403c4f237d9adf679e8e43cf64736f6c634300060b0033", + "balance": "0x0" + }, + "5678e9e827b3be0e3d4b910126a64a697a148267": { + "balance": "0x43c33c1937564800000" + }, + "70997970c51812dc3a010c7d01b50e0d17dc79c8": { + "balance": "0x21e19e0c9bab2400000" + }, + "71be63f3384f5fb98995898a86b02fb2426c5788": { + "balance": "0x21e19e0c9bab2400000" + }, + "8626f6940e2eb28930efb4cef49b2d1f2c9c1199": { + "balance": "0x21e19e0c9bab2400000" + }, + "90f79bf6eb2c4f870365e785982e1f101e93b906": { + "balance": "0x21e19e0c9bab2400000" + }, + "976ea74026e726554db657fa54763abd0c3a0aa9": { + "balance": "0x21e19e0c9bab2400000" + }, + "9965507d1a55bcc2695c58ba16fb37d819b0a4dc": { + "balance": "0x21e19e0c9bab2400000" + }, + "a0ee7a142d267c1f36714e4a8f75612f20a79720": { + "balance": "0x21e19e0c9bab2400000" + }, + "bcd4042de499d14e55001ccbb24a551f3b954096": { + "balance": "0x21e19e0c9bab2400000" + }, + "bda5747bfd65f08deb54cb465eb87d40e51b197e": { + "balance": "0x21e19e0c9bab2400000" + }, + "cd3b766ccdd6ae721141f452c550ca635964ce71": { + "balance": "0x21e19e0c9bab2400000" + }, + "dd2fd4581271e230360230f9337d5c0430bf44c0": { + "balance": "0x21e19e0c9bab2400000" + }, + "df3e18d64bc6a983f673ab319ccae4f1a57c7097": { + "balance": "0x21e19e0c9bab2400000" + }, + "f39fd6e51aad88f6f4ce6ab8827279cfffb92266": { + "balance": "0x21e19e0c9bab2400000" + }, + "fabb0ac9d68b0b445fb7357272ff202c5651694a": { + "balance": "0x21e19e0c9bab2400000" + } + }, + "number": "0x0", + "gasUsed": "0x0", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "baseFeePerGas": null +} \ No newline at end of file diff --git a/scripts/eth-bridge/execution/geth_password.txt b/scripts/eth-bridge/execution/geth_password.txt new file mode 100644 index 000000000..e69de29bb diff --git a/scripts/eth-bridge/execution/jwtsecret b/scripts/eth-bridge/execution/jwtsecret new file mode 100755 index 000000000..e69de29bb diff --git a/scripts/eth-bridge/execution/sk.json b/scripts/eth-bridge/execution/sk.json new file mode 100644 index 000000000..8fe79fab5 --- /dev/null +++ b/scripts/eth-bridge/execution/sk.json @@ -0,0 +1 @@ +2e0834786285daccd064ca17f1654f67b4aef298acbb82cef9ec422fb4975622 diff --git a/scripts/eth-bridge/jwtsecret b/scripts/eth-bridge/jwtsecret new file mode 100644 index 000000000..75f37fa86 --- /dev/null +++ b/scripts/eth-bridge/jwtsecret @@ -0,0 +1 @@ +0xd2853d11bd0383a21ea98d3e53e6625f0871f041374c3ec186ee3aa0f53a5505 \ No newline at end of file From c72dc2c1422016c6dd62cb2f6a9f50c5f3226b13 Mon Sep 17 00:00:00 2001 From: Blas Rodriguez Irizar Date: Wed, 23 Aug 2023 05:08:55 +0200 Subject: [PATCH 02/43] add cosmos chain --- scripts/eth-bridge/centauri-testnode.sh | 47 +++++++++++++++++++++++++ scripts/eth-bridge/docker-compose.yaml | 9 +++++ 2 files changed, 56 insertions(+) create mode 100644 scripts/eth-bridge/centauri-testnode.sh diff --git a/scripts/eth-bridge/centauri-testnode.sh b/scripts/eth-bridge/centauri-testnode.sh new file mode 100644 index 000000000..3915c46a1 --- /dev/null +++ b/scripts/eth-bridge/centauri-testnode.sh @@ -0,0 +1,47 @@ +KEY="mykey" +CHAINID="centauri-testnet-1" +MONIKER="localtestnet" +KEYALGO="secp256k1" +KEYRING="test" +LOGLEVEL="info" +# to trace evm +#TRACE="--trace" +TRACE="" + +# validate dependencies are installed +command -v jq > /dev/null 2>&1 || { echo >&2 "jq not installed. More info: https://stedolan.github.io/jq/download/"; exit 1; } + +# remove existing daemon +rm -rf ~/.banksy* + +centaurid config keyring-backend $KEYRING +centaurid config chain-id $CHAINID + +# if $KEY exists it should be deleted +echo "taste shoot adapt slow truly grape gift need suggest midnight burger horn whisper hat vast aspect exit scorpion jewel axis great area awful blind" | centaurid keys add $KEY --keyring-backend $KEYRING --algo $KEYALGO --recover + +centaurid init $MONIKER --chain-id $CHAINID + +# Allocate genesis accounts (centauri formatted addresses) +centaurid add-genesis-account $KEY 10000000000000000000stake --keyring-backend $KEYRING + +# Sign genesis transaction centauri1594tdya20hxz7kjenkn5w09jljyvdfk8kx5rd6 +centaurid gentx $KEY 100000000000000000stake --keyring-backend $KEYRING --chain-id $CHAINID + +# Collect genesis tx +centaurid collect-gentxs + +# Run this to ensure everything worked and that the genesis file is setup correctly +centaurid validate-genesis + +if [[ $1 == "pending" ]]; then + echo "pending mode is on, please wait for the first block committed." +fi + +# update request max size so that we can upload the light client +# '' -e is a must have params on mac, if use linux please delete before run +sed -i'' -e 's/max_body_bytes = /max_body_bytes = 1/g' ~/.banksy/config/config.toml +cat $HOME/.banksy/config/genesis.json | jq '.app_state["gov"]["params"]["voting_period"]="45s"' > $HOME/.banksy/config/tmp_genesis.json && mv $HOME/.banksy/config/tmp_genesis.json $HOME/.banksy/config/genesis.json + +# Start the node (remove the --pruning=nothing flag if historical queries are not needed) +centaurid start --pruning=nothing --minimum-gas-prices=0stake \ No newline at end of file diff --git a/scripts/eth-bridge/docker-compose.yaml b/scripts/eth-bridge/docker-compose.yaml index 0278bbcbb..0696237ee 100644 --- a/scripts/eth-bridge/docker-compose.yaml +++ b/scripts/eth-bridge/docker-compose.yaml @@ -108,3 +108,12 @@ services: condition: service_started volumes: - ./consensus:/consensus + centauri: + image: "composable-centauri:latest" + command: sh testnode.sh + volumes: + - "./centauri-testnode.sh:/centauri/testnode.sh" + ports: + - 1317:1317 # rest + - 26656:26656 # p2p + - 26657:26657 # rpc From 8d457480cbc9aa7b828fa00ca4b65837df8f5ca7 Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Wed, 23 Aug 2023 20:01:21 -0300 Subject: [PATCH 03/43] Diamond pattern (EIP-2535) Use [ERC-2535: Diamonds, Multi-Facet Proxy](https://eips.ethereum.org/EIPS/eip-2535) to make IBC contracts more flexible in terms of upgradability and deployment Instead of one contract (OwnableIBCHandler) that inherits all other contract handlers (IBCClientHandler, IBCConnectionHandler, ...), we now deploy each of the handlers separately and register their functions in the Diamond contract. It allows to deploy as many contracts as possible not depending on the code size anymore --- hyperspace/core/src/command.rs | 3 +- hyperspace/core/src/macros.rs | 1 + hyperspace/cosmos/src/provider.rs | 2 + .../ethereum/src/abi/ibc-handler-abi.json | 6 +- hyperspace/ethereum/src/bin/launch-yui-ibc.rs | 34 +-- hyperspace/ethereum/src/client.rs | 9 +- hyperspace/ethereum/src/config.rs | 24 +- hyperspace/ethereum/src/ibc_provider.rs | 283 ++++++++++++++++-- .../tests/contracts/proto/Channel.sol | 2 - .../ethereum/tests/contracts/proto/Client.sol | 1 - .../tests/contracts/proto/MockClient.sol | 1 - hyperspace/ethereum/tests/sanity_checks.rs | 75 +++-- hyperspace/ethereum/tests/utils.rs | 236 +++++++++++---- hyperspace/parachain/src/provider.rs | 2 + hyperspace/primitives/src/lib.rs | 13 +- 15 files changed, 530 insertions(+), 162 deletions(-) diff --git a/hyperspace/core/src/command.rs b/hyperspace/core/src/command.rs index 704511348..c59073e5c 100644 --- a/hyperspace/core/src/command.rs +++ b/hyperspace/core/src/command.rs @@ -191,8 +191,7 @@ impl Cmd { } pub async fn create_connection(&self) -> Result { - let delay_period_seconds: NonZeroU64 = self.delay_period_seconds.into() - .into(); + let delay_period_seconds: NonZeroU64 = self.delay_period.into().into(); let delay = Duration::from_secs(delay_period_seconds.into()); let mut config = self.parse_config().await?; let mut chain_a = config.chain_a.clone().into_client().await?; diff --git a/hyperspace/core/src/macros.rs b/hyperspace/core/src/macros.rs index 057e66fe4..8ef627984 100644 --- a/hyperspace/core/src/macros.rs +++ b/hyperspace/core/src/macros.rs @@ -395,6 +395,7 @@ macro_rules! chains { async fn query_send_packets( &self, + at: Height, channel_id: ChannelId, port_id: PortId, seqs: Vec, diff --git a/hyperspace/cosmos/src/provider.rs b/hyperspace/cosmos/src/provider.rs index 1d8bbaa29..179b35cc6 100644 --- a/hyperspace/cosmos/src/provider.rs +++ b/hyperspace/cosmos/src/provider.rs @@ -616,6 +616,7 @@ where self.channel_whitelist.lock().unwrap().clone() } + #[cfg(test)] async fn query_connection_channels( &self, _at: Height, @@ -648,6 +649,7 @@ where async fn query_send_packets( &self, + at: Height, channel_id: ChannelId, port_id: PortId, seqs: Vec, diff --git a/hyperspace/ethereum/src/abi/ibc-handler-abi.json b/hyperspace/ethereum/src/abi/ibc-handler-abi.json index 58e0e88a1..3f9d135ea 100644 --- a/hyperspace/ethereum/src/abi/ibc-handler-abi.json +++ b/hyperspace/ethereum/src/abi/ibc-handler-abi.json @@ -473,19 +473,19 @@ "anonymous": false, "inputs": [ { - "indexed": false, + "indexed": true, "internalType": "uint64", "name": "sequence", "type": "uint64" }, { - "indexed": false, + "indexed": true, "internalType": "string", "name": "sourcePort", "type": "string" }, { - "indexed": false, + "indexed": true, "internalType": "string", "name": "sourceChannel", "type": "string" diff --git a/hyperspace/ethereum/src/bin/launch-yui-ibc.rs b/hyperspace/ethereum/src/bin/launch-yui-ibc.rs index bc3202f50..6fe1cbea1 100644 --- a/hyperspace/ethereum/src/bin/launch-yui-ibc.rs +++ b/hyperspace/ethereum/src/bin/launch-yui-ibc.rs @@ -1,32 +1,22 @@ - #[path = "../../tests/utils.rs"] mod utils; #[tokio::main] async fn main() { - tracing_subscriber::fmt::init(); + tracing_subscriber::fmt::init(); - let path = utils::yui_ibc_solidity_path(); - let project_output = utils::compile_yui(&path, "contracts/core"); - let (anvil, client) = utils::spawn_anvil(); + let path = utils::yui_ibc_solidity_path(); + let project_output = utils::compile_yui(&path, "contracts/core"); + let diamond_project_output = utils::compile_yui(&path, "contracts/diamond"); + let (anvil, client) = utils::spawn_anvil(); - println!("address: {:?}", anvil.endpoint()); - println!("chain-id: {:?}", anvil.chain_id()); + println!("address: {:?}", anvil.endpoint()); + println!("chain-id: {:?}", anvil.chain_id()); - let utils::DeployYuiIbc { - ibc_client, - ibc_connection, - ibc_channel_handshake, - ibc_packet, - ibc_handler, - } = utils::deploy_yui_ibc(&project_output, client).await; + let yui_ibc = utils::deploy_yui_ibc(&project_output, &diamond_project_output, client).await; - println!("ibc_client: {:?}", ibc_client.address()); - println!("ibc_connection: {:?}", ibc_connection.address()); - println!("ibc_channel_handshake: {:?}", ibc_channel_handshake.address()); - println!("ibc_packet: {:?}", ibc_packet.address()); - println!("ibc_handler: {:?}", ibc_handler.address()); + println!("diamond address: {:?}", yui_ibc.diamond.address()); - let _ = tokio::signal::ctrl_c().await; - drop(anvil); -} \ No newline at end of file + let _ = tokio::signal::ctrl_c().await; + drop(anvil); +} diff --git a/hyperspace/ethereum/src/client.rs b/hyperspace/ethereum/src/client.rs index 99ede8b51..61fb2b4d2 100644 --- a/hyperspace/ethereum/src/client.rs +++ b/hyperspace/ethereum/src/client.rs @@ -33,6 +33,7 @@ pub(crate) type WsEth = Provider; pub const COMMITMENTS_STORAGE_INDEX: u32 = 0; pub const CLIENT_IMPLS_STORAGE_INDEX: u32 = 3; pub const CONNECTIONS_STORAGE_INDEX: u32 = 4; +pub const CHANNELS_STORAGE_INDEX: u32 = 5; #[derive(Debug, Clone)] pub struct EthereumClient { @@ -389,17 +390,13 @@ impl EthereumClient { block_height: Option, storage_index: u32, ) -> impl Future> { - let key1 = ethers::utils::keccak256( - ðers::abi::encode_packed(&[Token::String(key1.into())]).unwrap(), - ); + let key1 = ethers::utils::keccak256(key1.as_bytes()); let combined_key1 = [key1.as_slice(), storage_index.to_be_bytes().as_ref()].concat(); let key1_hashed = ethers::utils::keccak256(&combined_key1); let key1_hashed_hex = hex::encode(&key1_hashed); - let key2 = ethers::utils::keccak256( - ðers::abi::encode_packed(&[Token::String(key2.into())]).unwrap(), - ); + let key2 = ethers::utils::keccak256(key2.as_bytes()); let combined_key2 = [key2.as_slice(), key1_hashed_hex.as_bytes()].concat(); let key2_hashed = ethers::utils::keccak256(&combined_key2); diff --git a/hyperspace/ethereum/src/config.rs b/hyperspace/ethereum/src/config.rs index ce5ebd2fa..3142a4d18 100644 --- a/hyperspace/ethereum/src/config.rs +++ b/hyperspace/ethereum/src/config.rs @@ -71,18 +71,18 @@ pub struct Config { /// address of the OwnableIBCHandler contract. #[serde(deserialize_with = "address_de")] pub ibc_handler_address: Address, - /// address of the IBCPacket contract. - #[serde(deserialize_with = "address_de")] - pub ibc_packet_address: Address, - /// address of the IBCClient contract. - #[serde(deserialize_with = "address_de")] - pub ibc_client_address: Address, - /// address of the IBCConnection contract. - #[serde(deserialize_with = "address_de")] - pub ibc_connection_address: Address, - /// address of the IBCChannelHandshake contract. - #[serde(deserialize_with = "address_de")] - pub ibc_channel_handshake_address: Address, + // /// address of the IBCPacket contract. + // #[serde(deserialize_with = "address_de")] + // pub ibc_packet_address: Address, + // /// address of the IBCClient contract. + // #[serde(deserialize_with = "address_de")] + // pub ibc_client_address: Address, + // /// address of the IBCConnection contract. + // #[serde(deserialize_with = "address_de")] + // pub ibc_connection_address: Address, + // /// address of the IBCChannelHandshake contract. + // #[serde(deserialize_with = "address_de")] + // pub ibc_channel_handshake_address: Address, /// mnemonic for the wallet pub mnemonic: Option, /// private key for the wallet diff --git a/hyperspace/ethereum/src/ibc_provider.rs b/hyperspace/ethereum/src/ibc_provider.rs index 61d297b95..30e264b18 100644 --- a/hyperspace/ethereum/src/ibc_provider.rs +++ b/hyperspace/ethereum/src/ibc_provider.rs @@ -4,10 +4,17 @@ use std::{ use cast::executor::Output; use ethers::{ - abi::{encode, Abi, AbiEncode, Detokenize, InvalidOutputType, ParamType, Token, Tokenizable}, + abi::{ + encode, encode_packed, ethabi, Abi, AbiEncode, Detokenize, InvalidOutputType, ParamType, + Token, Tokenizable, Topic, + }, + contract::abigen, middleware::contract::Contract, providers::Middleware, - types::{BlockId, BlockNumber, EIP1186ProofResponse, Filter, StorageProof, H256, I256, U256}, + types::{ + BlockId, BlockNumber, EIP1186ProofResponse, Filter, StorageProof, ValueOrArray, H256, I256, + U256, + }, utils::keccak256, }; use ibc::{ @@ -31,12 +38,14 @@ use ibc_proto::{ google, ibc::core::{ channel::v1::{ - QueryChannelResponse, QueryChannelsResponse, QueryNextSequenceReceiveResponse, - QueryPacketCommitmentResponse, QueryPacketReceiptResponse, + Counterparty as ChannelCounterparty, QueryChannelResponse, QueryChannelsResponse, + QueryNextSequenceReceiveResponse, QueryPacketCommitmentResponse, + QueryPacketReceiptResponse, }, client::v1::{QueryClientStateResponse, QueryConsensusStateResponse}, connection::v1::{ - ConnectionEnd, Counterparty, IdentifiedConnection, QueryConnectionResponse, Version, + ConnectionEnd, Counterparty as ConnectionCounterparty, IdentifiedConnection, + QueryConnectionResponse, Version, }, }, }; @@ -44,17 +53,170 @@ use primitives::{IbcProvider, UpdateType}; use prost::Message; use futures::{FutureExt, Stream, StreamExt}; -use ibc::{applications::transfer::PrefixedCoin, events::IbcEvent}; -use ibc_proto::google::protobuf::Any; -use ibc_rpc::PacketInfo; +use ibc::{ + applications::transfer::PrefixedCoin, + core::ics04_channel::channel::{Order, State}, + events::IbcEvent, +}; +use ibc_proto::{google::protobuf::Any, ibc::core::channel::v1::Channel}; +use ibc_rpc::{IbcApiClient, PacketInfo}; use pallet_ibc::light_clients::{AnyClientState, AnyConsensusState}; use thiserror::Error; use crate::client::{ - ClientError, EthereumClient, CLIENT_IMPLS_STORAGE_INDEX, COMMITMENTS_STORAGE_INDEX, - CONNECTIONS_STORAGE_INDEX, + ClientError, EthereumClient, CHANNELS_STORAGE_INDEX, CLIENT_IMPLS_STORAGE_INDEX, + COMMITMENTS_STORAGE_INDEX, CONNECTIONS_STORAGE_INDEX, }; +abigen!( + IbcHandlerAbi, + r#"[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "sequence", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "string", + "name": "sourcePort", + "type": "string" + }, + { + "indexed": true, + "internalType": "string", + "name": "sourceChannel", + "type": "string" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "revision_number", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "revision_height", + "type": "uint64" + } + ], + "indexed": false, + "internalType": "struct HeightData", + "name": "timeoutHeight", + "type": "tuple" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "timeoutTimestamp", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "SendPacket", + "type": "event" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "components": [ + { + "internalType": "enum ChannelState", + "name": "state", + "type": "uint8" + }, + { + "internalType": "enum ChannelOrder", + "name": "ordering", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "string", + "name": "port_id", + "type": "string" + }, + { + "internalType": "string", + "name": "channel_id", + "type": "string" + } + ], + "internalType": "struct ChannelCounterpartyData", + "name": "counterparty", + "type": "tuple" + }, + { + "internalType": "string[]", + "name": "connection_hops", + "type": "string[]" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + } + ], + "internalType": "struct ChannelData", + "name": "channel", + "type": "tuple" + } + ], + "internalType": "struct IBCMsgs.MsgChannelOpenInit", + "name": "msg_", + "type": "tuple" + } + ], + "name": "channelOpenInit", + "outputs": [ + { + "internalType": "string", + "name": "channelId", + "type": "string" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ]"# +); + +impl From for Height { + fn from(value: HeightData) -> Self { + Self { + revision_number: value.revision_number.into(), + revision_height: value.revision_height.into(), + } + } +} + +impl From for ibc_proto::ibc::core::client::v1::Height { + fn from(value: HeightData) -> Self { + Self { + revision_number: value.revision_number.into(), + revision_height: value.revision_height.into(), + } + } +} + #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)] pub struct BlockHeight(pub(crate) ethers::types::BlockNumber); @@ -286,6 +448,7 @@ impl IbcProvider for EthereumClient { Arc::clone(&self.http_rpc), ); + /* let binding = contract .method("getConnectionEnd", (connection_id.as_str().to_owned(),)) .expect("contract is missing getConnectionEnd"); @@ -303,7 +466,7 @@ impl IbcProvider for EthereumClient { connection: Some(ConnectionEnd { state: connection_end.state as i32, client_id: connection_end.client_id, - counterparty: Some(Counterparty { + counterparty: Some(ConnectionCounterparty { client_id: connection_end.counterparty.client_id, connection_id: connection_end.counterparty.connection_id, prefix: Some(ibc_proto::ibc::core::commitment::v1::MerklePrefix { @@ -323,6 +486,8 @@ impl IbcProvider for EthereumClient { proof, proof_height, }) + */ + todo!() } else { todo!("error: client address is zero") } @@ -342,19 +507,40 @@ impl IbcProvider for EthereumClient { ); let binding = contract - .method::<_, crate::contract::ChannelEnd>( + .method::<_, (ChannelData, bool)>( "getChannel", (channel_id.to_string(), port_id.as_str().to_owned()), ) .expect("contract is missing getChannel"); - let channel_data = binding + let (channel_data, exists) = binding .block(BlockId::Number(BlockNumber::Number(at.revision_height.into()))) .call() .await .unwrap(); + if !exists { + todo!("error: channel does not exist") + } - Ok(QueryChannelResponse { channel: None, proof: todo!(), proof_height: todo!() }) + let state = State::from_i32(channel_data.state as _).expect("invalid channel state"); + let counterparty = match state { + State::Init | State::TryOpen => None, + State::Open | State::Closed => Some(ChannelCounterparty { + port_id: channel_data.counterparty.port_id, + channel_id: channel_data.counterparty.channel_id, + }), + }; + Ok(QueryChannelResponse { + channel: Some(Channel { + state: channel_data.state as _, + ordering: channel_data.ordering as _, + counterparty, + connection_hops: channel_data.connection_hops, + version: channel_data.version, + }), + proof: vec![], + proof_height: None, + }) } async fn query_proof(&self, at: Height, keys: Vec>) -> Result, Self::Error> { @@ -394,7 +580,6 @@ impl IbcProvider for EthereumClient { .eth_query_proof(&path, Some(at.revision_height), COMMITMENTS_STORAGE_INDEX) .await?; let storage = proof.storage_proof.first().unwrap(); - let bytes = u256_to_bytes(&storage.value); Ok(QueryPacketCommitmentResponse { @@ -651,21 +836,82 @@ impl IbcProvider for EthereumClient { self.config.channel_whitelist.clone().into_iter().collect() } + #[cfg(test)] async fn query_connection_channels( &self, at: Height, connection_id: &ConnectionId, ) -> Result { - todo!("query_connection_channels") + unimplemented!("query_connection_channels") } async fn query_send_packets( &self, + at: Height, channel_id: ChannelId, port_id: PortId, seqs: Vec, ) -> Result, Self::Error> { - todo!() + let contract = crate::contract::ibc_handler( + self.config.ibc_handler_address.clone(), + Arc::clone(&self.http_rpc), + ); + + // hash.0. + let event_filter = contract + .event_for_name::( + "SendPacket", + // "SendPacket(uint64,string,string,(uint64,uint64),uint64,bytes)", + ) + .expect("contract is missing SendPacket event") + .address(ValueOrArray::Value(self.config.ibc_handler_address.clone())) + .from_block(BlockNumber::Earliest) // TODO: use contract creation height + .to_block(BlockNumber::Latest) + .topic1(ValueOrArray::Array( + seqs.into_iter() + .map(|seq| { + let bytes = encode(&[Token::Uint(seq.into())]); + H256::from_slice(bytes.as_slice()) + }) + .collect(), + )) + .topic2({ + let hash = H256::from_slice(&encode(&[Token::FixedBytes( + port_id.to_string().into_bytes(), + )])); + ValueOrArray::Value(hash) + }) + .topic3({ + let hash = H256::from_slice(&encode(&[Token::FixedBytes( + channel_id.to_string().into_bytes(), + )])); + ValueOrArray::Value(hash) + }); + + let events = event_filter.query().await.unwrap(); + let channel = self.query_channel_end(at, channel_id, port_id).await?; + + let channel = channel.channel.expect("channel is none"); + let counterparty = channel.counterparty.expect("counterparty is none"); + Ok(events + .into_iter() + .map(|value| PacketInfo { + height: None, + source_port: String::from_utf8_lossy(&value.source_port.0).to_string(), + source_channel: String::from_utf8_lossy(&value.source_channel.0).to_string(), + destination_port: counterparty.port_id.clone(), + destination_channel: counterparty.channel_id.clone(), + sequence: value.sequence, + timeout_height: value.timeout_height.into(), + timeout_timestamp: value.timeout_timestamp, + data: value.data.to_vec(), + channel_order: Order::from_i32(channel.ordering) + .map_err(|_| Self::Error::Other("invalid channel order".to_owned())) + .unwrap() + .to_string(), + ack: None, + }) + .collect()) } async fn query_received_packets( @@ -686,9 +932,6 @@ impl IbcProvider for EthereumClient { client_id: ClientId, client_height: Height, ) -> Result<(Height, Timestamp), Self::Error> { - let ibc_handler = - crate::contract::ibc_handler(self.config.ibc_client_address, self.http_rpc.clone()); - todo!(); } diff --git a/hyperspace/ethereum/tests/contracts/proto/Channel.sol b/hyperspace/ethereum/tests/contracts/proto/Channel.sol index c8a7f1936..8e6c720f5 100644 --- a/hyperspace/ethereum/tests/contracts/proto/Channel.sol +++ b/hyperspace/ethereum/tests/contracts/proto/Channel.sol @@ -163,7 +163,6 @@ library Packet { uint64 timeout_timestamp; } } -//library Packet library PacketState { @@ -176,4 +175,3 @@ library PacketState { bytes data; } } -//library PacketState \ No newline at end of file diff --git a/hyperspace/ethereum/tests/contracts/proto/Client.sol b/hyperspace/ethereum/tests/contracts/proto/Client.sol index 17ab720ad..dada85df4 100644 --- a/hyperspace/ethereum/tests/contracts/proto/Client.sol +++ b/hyperspace/ethereum/tests/contracts/proto/Client.sol @@ -265,4 +265,3 @@ library Height { } } } -//library Height \ No newline at end of file diff --git a/hyperspace/ethereum/tests/contracts/proto/MockClient.sol b/hyperspace/ethereum/tests/contracts/proto/MockClient.sol index c1fcd5ace..878e906e7 100644 --- a/hyperspace/ethereum/tests/contracts/proto/MockClient.sol +++ b/hyperspace/ethereum/tests/contracts/proto/MockClient.sol @@ -736,4 +736,3 @@ library IbcLightclientsMockV1Header { } } } -//library IbcLightclientsMockV1Header \ No newline at end of file diff --git a/hyperspace/ethereum/tests/sanity_checks.rs b/hyperspace/ethereum/tests/sanity_checks.rs index 30ba39dc5..80bc7ca73 100644 --- a/hyperspace/ethereum/tests/sanity_checks.rs +++ b/hyperspace/ethereum/tests/sanity_checks.rs @@ -3,6 +3,7 @@ use std::{future::Future, ops::Deref, path::PathBuf, str::FromStr, sync::Arc, ti use crate::utils::USE_GETH; use ethers::{ abi::{encode_packed, Token}, + contract::MultiAbigen, core::k256::sha2::{Digest, Sha256}, prelude::{ContractInstance, LocalWallet, TransactionReceipt}, types::{H256, U256}, @@ -21,6 +22,7 @@ use ibc::{ }, timestamp::Timestamp, }; +use ibc_rpc::PacketInfo; use primitives::IbcProvider; use prost::Message; use tracing::log; @@ -29,13 +31,7 @@ mod utils; async fn hyperspace_ethereum_client_fixture( anvil: ðers::utils::AnvilInstance, - utils::DeployYuiIbc { - ibc_client, - ibc_connection, - ibc_channel_handshake, - ibc_packet, - ibc_handler, - }: &utils::DeployYuiIbc, M>, + utils::DeployYuiIbc { facet_cuts, deployed_facets, diamond }: &utils::DeployYuiIbc, M>, ) -> hyperspace_ethereum::client::EthereumClient { let endpoint = if USE_GETH { "http://localhost:6001".to_string() } else { anvil.endpoint() }; let wallet_path = if USE_GETH { @@ -48,11 +44,7 @@ async fn hyperspace_ethereum_client_fixture( hyperspace_ethereum::client::EthereumClient::new(Config { http_rpc_url: endpoint.parse().unwrap(), ws_rpc_url: Default::default(), - ibc_handler_address: ibc_handler.address(), - ibc_packet_address: ibc_packet.address(), - ibc_client_address: ibc_client.address(), - ibc_connection_address: ibc_connection.address(), - ibc_channel_handshake_address: ibc_channel_handshake.address(), + ibc_handler_address: diamond.address(), mnemonic: None, max_block_weight: 1, private_key: wallet, @@ -67,7 +59,7 @@ async fn hyperspace_ethereum_client_fixture( .unwrap() } -type ProviderImpl = ethers::prelude::SignerMiddleware< +pub type ProviderImpl = ethers::prelude::SignerMiddleware< ethers::providers::Provider, ethers::signers::LocalWallet, >; @@ -134,9 +126,11 @@ impl DeployYuiIbcMockClient { async fn deploy_yui_ibc_and_mock_client_fixture() -> DeployYuiIbcMockClient { let path = utils::yui_ibc_solidity_path(); let project_output = utils::compile_yui(&path, "contracts/core"); + let diamond_project_output = utils::compile_yui(&path, "contracts/diamond"); let (anvil, client) = utils::spawn_anvil(); log::warn!("{}", anvil.endpoint()); - let yui_ibc = utils::deploy_yui_ibc(&project_output, client.clone()).await; + let yui_ibc = + utils::deploy_yui_ibc(&project_output, &diamond_project_output, client.clone()).await; let ibc_mock_client = utils::compile_solc({ let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); @@ -150,7 +144,7 @@ async fn deploy_yui_ibc_and_mock_client_fixture() -> DeployYuiIbcMockClient { let ibc_mock_client = utils::deploy_contract( ibc_mock_client.find_first("MockClient").unwrap(), - (Token::Address(yui_ibc.ibc_handler.address()),), + (Token::Address(yui_ibc.diamond.address()),), client.clone(), ) .await; @@ -201,7 +195,7 @@ async fn deploy_mock_client_fixture(deploy: &DeployYuiIbcMockClient) -> ClientId .create_client(utils::mock::create_client_msg("mock-client")) .await; println!("client id: {}", string); - println!("ibc_handler contract addr: {:?}", deploy.yui_ibc.ibc_handler.address()); + println!("ibc_handler contract addr: {:?}", deploy.yui_ibc.diamond.address()); ClientId(string) } @@ -221,7 +215,7 @@ fn deploy_mock_module_fixture( }); let contract = clients.find_first("MockModule").expect("no MockModule in project output"); - let constructor_args = (Token::Address(deploy.yui_ibc.ibc_handler.address()),); + let constructor_args = (Token::Address(deploy.yui_ibc.diamond.address()),); utils::deploy_contract(contract, constructor_args, deploy.client.clone()).await } } @@ -297,15 +291,15 @@ async fn test_ibc_connection() { .await; // hyperspace.query_connection_channels(at, connection_id) - let channels = hyperspace - .query_connection_channels( - ibc::Height { revision_number: 0, revision_height: 1 }, - &connection_id.parse().unwrap(), - ) - .await - .unwrap(); - - assert!(channels.channels.is_empty()); + // let channels = hyperspace + // .query_connection_channels( + // ibc::Height { revision_number: 0, revision_height: 1 }, + // &connection_id.parse().unwrap(), + // ) + // .await + // .unwrap(); + // + // assert!(channels.channels.is_empty()); // hyperspace.query_connection_end(at, connection_id) let connection_end = hyperspace @@ -524,6 +518,35 @@ async fn test_ibc_packet() { .await .unwrap(); assert_eq!(unreceived, vec![1, 2]); + + let send_packet = hyperspace + .query_send_packets( + ibc::Height { revision_number: 0, revision_height: height }, + ChannelId::from_str("channel-0").unwrap(), + PortId::from_str("port-0").unwrap(), + vec![1], + ) + .await + .unwrap() + .pop() + .unwrap(); + + assert_eq!( + dbg!(send_packet), + PacketInfo { + height: None, + sequence: 1, + source_port: "port-0".to_string(), + source_channel: "channel-0".to_string(), + destination_port: "port-0".to_string(), + destination_channel: "channel-0".to_string(), + channel_order: "0".to_string(), + data: "hello_send".as_bytes().to_vec(), + timeout_height: Height::new(0, 1000000).into(), + timeout_timestamp: 0, + ack: None, + } + ); } fn u64_to_token(x: u64) -> Token { diff --git a/hyperspace/ethereum/tests/utils.rs b/hyperspace/ethereum/tests/utils.rs index ea1108870..6d82050b4 100644 --- a/hyperspace/ethereum/tests/utils.rs +++ b/hyperspace/ethereum/tests/utils.rs @@ -1,13 +1,15 @@ #![allow(dead_code)] +use cast::hashbrown::HashSet; use std::{ + collections::HashMap, path::{Path, PathBuf}, sync::Arc, time::Duration, }; use ethers::{ - abi::Token, + abi::{Detokenize, Token, Tokenize}, contract::ContractFactory, core::{rand::rngs::ThreadRng, utils::Anvil}, middleware::SignerMiddleware, @@ -24,6 +26,7 @@ use ethers_solc::{ Artifact, ConfigurableContractArtifact, EvmVersion, Project, ProjectCompileOutput, ProjectPathsConfig, SolcConfig, }; +use futures::SinkExt; use hyperspace_ethereum::contract::UnwrapContractError; use ibc::{ core::{ @@ -33,6 +36,7 @@ use ibc::{ timestamp::Timestamp, Height, }; +use tracing::log; pub const USE_GETH: bool = true; @@ -81,7 +85,7 @@ pub fn compile_solc(project_paths: ProjectPathsConfig) -> ProjectCompileOutput { stop_after: None, remappings: vec![], optimizer: Optimizer { - enabled: Some(false), + enabled: Some(true), runs: Some(256), details: Some(OptimizerDetails { peephole: Some(true), @@ -100,10 +104,11 @@ pub fn compile_solc(project_paths: ProjectPathsConfig) -> ProjectCompileOutput { output_selection: OutputSelection::default_output_selection(), evm_version: Some(EvmVersion::Paris), via_ir: Some(false), - debug: Some(DebuggingSettings { - revert_strings: Some(RevertStrings::Debug), - debug_info: vec!["location".to_string()], - }), + // debug: Some(DebuggingSettings { + // revert_strings: Some(RevertStrings::Debug), + // debug_info: vec!["location".to_string()], + // }), + debug: None, libraries: Libraries { libs: Default::default() }, }, }; @@ -216,11 +221,14 @@ pub mod mock { #[derive(Debug)] pub struct DeployYuiIbc { - pub ibc_client: ContractInstance, - pub ibc_connection: ContractInstance, - pub ibc_channel_handshake: ContractInstance, - pub ibc_packet: ContractInstance, - pub ibc_handler: ContractInstance, + // pub ibc_client: ContractInstance, + // pub ibc_connection: ContractInstance, + // pub ibc_channel_handshake: ContractInstance, + // pub ibc_packet: ContractInstance, + // pub ibc_handler: ContractInstance, + pub facet_cuts: Vec, + pub deployed_facets: Vec>, + pub diamond: ContractInstance, } impl DeployYuiIbc @@ -230,7 +238,6 @@ where { pub async fn bind_port(&self, port_id: &str, address: Address) { let bind_port = self - .ibc_handler .method::<_, ()>("bindPort", (Token::String(port_id.into()), Token::Address(address))) .unwrap(); let () = bind_port.call().await.unwrap_contract_error(); @@ -240,7 +247,6 @@ where pub async fn connection_open_init(&self, client_id: &str) -> String { let connection_open_init = self - .ibc_handler .method::<_, String>( "connectionOpenInit", (Token::Tuple(vec![ @@ -268,7 +274,6 @@ where pub async fn connection_open_ack(&self, connection_id: &str, client_state_bytes: Vec) { let connection_open_ack = self - .ibc_handler .method::<_, ()>( "connectionOpenAck", (Token::Tuple(vec![ @@ -296,7 +301,6 @@ where pub async fn channel_open_init(&self, port_id: &str, connection_id: &str) -> String { let fut = self - .ibc_handler .method::<_, String>( "channelOpenInit", (Token::Tuple(vec![ @@ -324,7 +328,6 @@ where pub async fn channel_open_ack(&self, channel_id: &str, port_id: &str) { let fut = self - .ibc_handler .method::<_, ()>( "channelOpenAck", (Token::Tuple(vec![ @@ -349,7 +352,6 @@ where pub async fn recv_packet(&self, packet: Packet) -> TransactionReceipt { let fut = self - .ibc_handler .method::<_, ()>( "recvPacket", (Token::Tuple(vec![ @@ -404,9 +406,36 @@ where tx } + pub fn method( + &self, + name: &str, + args: T, + ) -> Result, AbiError> { + let mut contract: Option<&ContractInstance> = None; + + let lookup_contracts = self.deployed_facets.iter().chain(std::iter::once(&self.diamond)); + + for lookup_contract in lookup_contracts { + if lookup_contract.abi().function(name).is_ok() { + if contract.is_some() { + panic!("ambiguous method name: {}", name); + } + contract = Some(lookup_contract); + } + } + let contract = contract.take().ok_or_else(|| AbiError::WrongSelector)?; + + let mut f = contract.method(name, args); + + if let Ok(f) = &mut f { + f.tx.set_to(self.diamond.address()); + } + + f + } + pub async fn register_client(&self, kind: &str, address: Address) { let method = self - .ibc_handler .method::<_, ()>( "registerClient", (Token::String(kind.into()), Token::Address(address)), @@ -420,7 +449,7 @@ where } pub async fn create_client(&self, msg: Token) -> String { - let method = self.ibc_handler.method::<_, String>("createClient", (msg,)).unwrap(); + let method = self.method::<_, String>("createClient", (msg,)).unwrap(); let client_id = method.call().await.unwrap_contract_error(); @@ -437,70 +466,149 @@ where { fn clone(&self) -> Self { Self { - ibc_client: self.ibc_client.clone(), - ibc_connection: self.ibc_connection.clone(), - ibc_channel_handshake: self.ibc_channel_handshake.clone(), - ibc_packet: self.ibc_packet.clone(), - ibc_handler: self.ibc_handler.clone(), + // ibc_client: self.ibc_client.clone(), + // ibc_connection: self.ibc_connection.clone(), + // ibc_channel_handshake: self.ibc_channel_handshake.clone(), + // ibc_packet: self.ibc_packet.clone(), + facet_cuts: self.facet_cuts.clone(), + deployed_facets: self.deployed_facets.clone(), + diamond: self.diamond.clone(), } } } +#[repr(u32)] +#[derive(Clone, Copy, Debug)] +pub enum FacetCutAction { + Add = 0, + Replace = 1, + Remove = 2, +} + +#[derive(Clone, Debug)] +pub struct FacetCut { + address: Address, + action: FacetCutAction, + selectors: Vec<(String, [u8; 4])>, +} + +impl FacetCut { + pub fn into_token(self) -> Token { + Token::Tuple(vec![ + Token::Address(self.address), + Token::Uint((FacetCutAction::Add as u32).into()), + Token::Array( + self.selectors.into_iter().map(|(_, x)| Token::FixedBytes(x.to_vec())).collect(), + ), + ]) + } +} + +fn get_selectors(contract: &ContractInstance, M>) -> Vec<(String, [u8; 4])> +where + M: Middleware, +{ + let signatures = contract.abi().functions.keys().cloned().collect::>(); + signatures + .into_iter() + .inspect(|x| { + dbg!(x); + }) + .filter(|val| val != "init(bytes)") + .map(|val| (val.clone(), contract.abi().function(&val).unwrap().short_signature())) + .collect() +} + pub async fn deploy_yui_ibc( project_output: &ProjectCompileOutput, + diamond_project_output: &ProjectCompileOutput, client: Arc, ) -> DeployYuiIbc, M> where M: Middleware, { - let contract = project_output.find_first("OwnableIBCHandler").unwrap(); - let (abi, bytecode, _) = contract.clone().into_parts(); - let handler_bytecode = bytecode.unwrap(); - let handler_abi = abi.unwrap(); - dbg!(&handler_bytecode.len() / 1); - - if handler_bytecode.len() > dbg!(24 * 1024) { - panic!("handler bytecode too large"); - } + let facet_names = [ + "IBCClient", + "IBCConnection", + "IBCChannelHandshake", + "IBCPacket", + "IBCQuerier", + "DiamondCutFacet", + "DiamondLoupeFacet", + "OwnershipFacet", + ]; + + project_output.artifacts().for_each(|(name, artifact)| { + let size = artifact.bytecode.as_ref().unwrap().object.as_bytes().unwrap().len(); + let max = 24 * 1024; + if size > max { + panic!("{} size is too big: {}/{}", name, size, max); + } + log::info!("{} size: {}/{}", name, size, max); + }); + diamond_project_output.artifacts().for_each(|(name, artifact)| { + let size = artifact.bytecode.as_ref().unwrap().object.as_bytes().unwrap().len(); + let max = 24 * 1024; + if size > max { + panic!("{} size is too big: {}/{}", name, size, max); + } + log::info!("{} size: {}/{}", name, size, max); + }); - let contract = project_output.find_first("IBCClient").unwrap(); - let (abi, bytecode, _) = contract.clone().into_parts(); - let factory = ContractFactory::new(abi.unwrap(), bytecode.unwrap(), client.clone()); - let deployer1 = factory.deploy(()).unwrap(); - let acc = deployer1.client().default_sender().unwrap(); - dbg!(client.get_balance(acc, None).await.unwrap()); - let ibc_client = deployer1.send().await.unwrap(); + let acc = client.default_sender().unwrap(); - let contract = project_output.find_first("IBCConnection").unwrap(); + let contract = diamond_project_output.find_first("DiamondInit").unwrap(); let (abi, bytecode, _) = contract.clone().into_parts(); let factory = ContractFactory::new(abi.unwrap(), bytecode.unwrap(), client.clone()); - let ibc_connection = factory.deploy(()).unwrap().send().await.unwrap(); + let diamond_init = factory.deploy(()).unwrap().send().await.unwrap(); + + let mut sigs = HashMap::<[u8; 4], (String, String)>::new(); + let mut facet_cuts = vec![]; + let mut deployed_facets = vec![]; + for facet_name in facet_names { + let contract = project_output + .find_first(facet_name) + .or_else(|| diamond_project_output.find_first(facet_name)) + .unwrap(); + let (abi, bytecode, _) = contract.clone().into_parts(); + let factory = ContractFactory::new(abi.unwrap(), bytecode.unwrap(), client.clone()); + let facet = factory.deploy(()).unwrap().send().await.unwrap(); + let facet_address = facet.address(); + deployed_facets.push(facet.clone()); + let selectors = get_selectors(&facet); + + for (name, selector) in &selectors { + if sigs.contains_key(selector) { + let (contract_name, fn_name) = &sigs[selector]; + panic!( + "duplicate selector: {}:{} and {}:{}", + contract_name, fn_name, facet_name, name + ); + } + sigs.insert(*selector, (facet_name.to_owned(), name.clone())); + } - let contract = project_output.find_first("IBCChannelHandshake").unwrap(); - let (abi, bytecode, _) = contract.clone().into_parts(); - let factory = ContractFactory::new(abi.unwrap(), bytecode.unwrap(), client.clone()); - let ibc_channel_handshake = factory.deploy(()).unwrap().send().await.unwrap(); + let facet_cut = FacetCut { address: facet_address, action: FacetCutAction::Add, selectors }; + facet_cuts.push(facet_cut); + } + let init_calldata = diamond_init.method::<_, ()>("init", ()).unwrap().calldata().unwrap(); - let contract = project_output.find_first("IBCPacket").unwrap(); + let contract = diamond_project_output.find_first("Diamond").unwrap(); let (abi, bytecode, _) = contract.clone().into_parts(); let factory = ContractFactory::new(abi.unwrap(), bytecode.unwrap(), client.clone()); - let ibc_packet = factory.deploy(()).unwrap().send().await.unwrap(); - - let factory = ContractFactory::new(handler_abi, handler_bytecode, client.clone()); - let mut deployer = factory - .deploy(( - Token::Address(ibc_client.address()), - Token::Address(ibc_connection.address()), - Token::Address(ibc_channel_handshake.address()), - Token::Address(ibc_packet.address()), - )) + let diamond = factory + .deploy(Token::Tuple(vec![ + Token::Array(facet_cuts.clone().into_iter().map(|x| x.into_token()).collect()), + Token::Tuple(vec![ + Token::Address(acc), + Token::Address(diamond_init.address()), + Token::Bytes(init_calldata.0.into()), + ]), + ])) + .unwrap() + .send() + .await .unwrap(); - // let estimated_gas = client.estimate_gas(&deployer.tx, None).await.unwrap(); - // dbg!(estimated_gas); - dbg!(client.get_balance(acc, None).await.unwrap()); - let ibc_handler = deployer.clone().send().await.expect("failed to deploy OwnableIBCHandler"); - - println!("IBC Handler address: {:?}", ibc_handler.address()); - DeployYuiIbc { ibc_client, ibc_connection, ibc_channel_handshake, ibc_packet, ibc_handler } + DeployYuiIbc { diamond, facet_cuts, deployed_facets } } diff --git a/hyperspace/parachain/src/provider.rs b/hyperspace/parachain/src/provider.rs index 7fb8f9338..20e2ad6f1 100644 --- a/hyperspace/parachain/src/provider.rs +++ b/hyperspace/parachain/src/provider.rs @@ -452,6 +452,7 @@ where self.channel_whitelist.lock().unwrap().iter().cloned().collect() } + #[cfg(test)] async fn query_connection_channels( &self, at: Height, @@ -470,6 +471,7 @@ where async fn query_send_packets( &self, + at: Height, channel_id: ChannelId, port_id: PortId, seqs: Vec, diff --git a/hyperspace/primitives/src/lib.rs b/hyperspace/primitives/src/lib.rs index d89ccdd45..34bae1e33 100644 --- a/hyperspace/primitives/src/lib.rs +++ b/hyperspace/primitives/src/lib.rs @@ -340,6 +340,7 @@ pub trait IbcProvider { fn channel_whitelist(&self) -> HashSet<(ChannelId, PortId)>; /// Query all channels for a connection + #[cfg(test)] async fn query_connection_channels( &self, at: Height, @@ -350,6 +351,7 @@ pub trait IbcProvider { /// This represents packets that for which the `SendPacket` event was emitted async fn query_send_packets( &self, + at: Height, channel_id: ChannelId, port_id: PortId, seqs: Vec, @@ -759,7 +761,10 @@ pub async fn find_suitable_proof_height_for_client( let temp_height = Height::new(start_height.revision_number, mid); let consensus_state = sink.query_client_consensus(at, client_id.clone(), temp_height).await.ok(); - let Some(Ok(consensus_state)) = consensus_state.map(|x| x.consensus_state.map(AnyConsensusState::try_from)).flatten() else { + let Some(Ok(consensus_state)) = consensus_state + .map(|x| x.consensus_state.map(AnyConsensusState::try_from)) + .flatten() + else { start += 1; continue }; @@ -831,8 +836,10 @@ pub async fn query_maximum_height_for_timeout_proofs( .rev() .take(source.common_state().max_packets_to_process) .collect(); - let send_packets = - source.query_send_packets(channel, port_id, undelivered_sequences).await.ok()?; + let send_packets = source + .query_send_packets(source_height, channel, port_id, undelivered_sequences) + .await + .ok()?; for send_packet in send_packets { let source = source.clone(); let sink = sink.clone(); From ccca42a5a901e629e78572506ff7a60c59cb95da Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Wed, 23 Aug 2023 21:41:19 -0300 Subject: [PATCH 04/43] fix compilation --- Cargo.lock | 3837 ++++++++++++++--------- Cargo.toml | 4 +- hyperspace/ethereum/src/ibc_provider.rs | 8 +- 3 files changed, 2386 insertions(+), 1463 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ec3b92fad..273e2e270 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -27,7 +27,7 @@ version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" dependencies = [ - "gimli 0.27.2", + "gimli 0.27.1", ] [[package]] @@ -115,9 +115,9 @@ dependencies = [ [[package]] name = "aes-gcm" -version = "0.10.2" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "209b47e8954a928e1d72e86eca7000ebb6655fe1436d33eefc2201cad027e237" +checksum = "82e1366e0c69c9f927b1fa5ce2c7bf9eafc8f9268c0b9800729e8b267612447c" dependencies = [ "aead 0.5.2", "aes 0.8.2", @@ -153,7 +153,7 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" dependencies = [ - "getrandom 0.2.9", + "getrandom 0.2.8", "once_cell", "version_check", ] @@ -165,7 +165,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" dependencies = [ "cfg-if 1.0.0", - "getrandom 0.2.9", + "getrandom 0.2.8", "once_cell", "version_check", ] @@ -181,9 +181,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04" +checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" dependencies = [ "memchr", ] @@ -206,60 +206,11 @@ dependencies = [ "winapi", ] -[[package]] -name = "anstream" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "is-terminal", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d" - -[[package]] -name = "anstyle-parse" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e765fd216e48e067936442276d1d57399e37bce53c264d6fefbe298080cb57ee" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" -dependencies = [ - "windows-sys 0.48.0", -] - -[[package]] -name = "anstyle-wincon" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" -dependencies = [ - "anstyle", - "windows-sys 0.48.0", -] - [[package]] name = "anyhow" -version = "1.0.71" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" +checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800" [[package]] name = "approx" @@ -283,7 +234,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "367fd0ad87307588d087544707bc5fbf4805ded96c7db922b70d368fa1cb5702" dependencies = [ "unicode-width", - "yansi", + "yansi 0.5.1", ] [[package]] @@ -292,11 +243,20 @@ version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f52f63c5c1316a16a4b35eaac8b76a98248961a533f061684cb2a7cb0eafb6c6" +[[package]] +name = "array-init" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23589ecb866b460d3a0f1278834750268c607e8e28a1b982c907219f3178cd72" +dependencies = [ + "nodrop", +] + [[package]] name = "arrayref" -version = "0.3.7" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" +checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" [[package]] name = "arrayvec" @@ -332,7 +292,7 @@ dependencies = [ "num-traits", "rusticata-macros", "thiserror", - "time 0.3.21", + "time 0.3.17", ] [[package]] @@ -348,7 +308,7 @@ dependencies = [ "num-traits", "rusticata-macros", "thiserror", - "time 0.3.21", + "time 0.3.17", ] [[package]] @@ -388,37 +348,38 @@ dependencies = [ [[package]] name = "asn1_der" -version = "0.7.6" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "155a5a185e42c6b77ac7b88a15143d930a9e9727a5b7b77eed417404ab15c247" +checksum = "e22d1f4b888c298a027c99dc9048015fac177587de20fc30232a057dfbe24a21" [[package]] name = "async-io" -version = "1.13.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" +checksum = "8c374dda1ed3e7d8f0d9ba58715f924862c63eae6849c92d3a18e7fbde9e2794" dependencies = [ "async-lock", "autocfg", - "cfg-if 1.0.0", "concurrent-queue", "futures-lite", + "libc", "log", "parking", "polling", - "rustix 0.37.19", "slab", "socket2", "waker-fn", + "windows-sys 0.42.0", ] [[package]] name = "async-lock" -version = "2.7.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa24f727524730b077666307f2734b4a1a1c57acb79193127dcc8914d5242dd7" +checksum = "c8101efe8695a6c17e02911402145357e718ac92d3ff88ae8419e84b1707b685" dependencies = [ "event-listener", + "futures-lite", ] [[package]] @@ -440,18 +401,18 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.28", ] [[package]] name = "async-trait" -version = "0.1.68" +version = "0.1.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" +checksum = "cc6dde6e4ed435a4c1ee4e73592f5ba9da2151af10076cc04858746af9352d09" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.28", ] [[package]] @@ -502,9 +463,9 @@ checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba" [[package]] name = "atomic-waker" -version = "1.1.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1181e1e0d1fce796a03db1ae795d67167da795f9cf4a39c37589e85ef57f26d3" +checksum = "debc29dde2e69f9e47506b525f639ed42300fc014a3e007832592448fa8e4599" [[package]] name = "atty" @@ -537,13 +498,13 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "axum" -version = "0.6.18" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8175979259124331c1d7bf6586ee7e0da434155e4b2d48ec2c8386281d8df39" +checksum = "e5694b64066a2459918d8074c2ce0d5a88f409431994c2356617c8ae0c4721fc" dependencies = [ "async-trait", "axum-core", - "bitflags", + "bitflags 1.3.2", "bytes", "futures-util", "http", @@ -559,15 +520,16 @@ dependencies = [ "serde", "sync_wrapper", "tower", + "tower-http", "tower-layer", "tower-service", ] [[package]] name = "axum-core" -version = "0.3.4" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" +checksum = "1cae3e661676ffbacb30f1a824089a8c9150e71017f7e1e38f2aa32009188d34" dependencies = [ "async-trait", "bytes", @@ -590,7 +552,7 @@ dependencies = [ "cc", "cfg-if 1.0.0", "libc", - "miniz_oxide 0.6.2", + "miniz_oxide", "object 0.30.3", "rustc-demangle", ] @@ -627,15 +589,15 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f1e31e207a6b8fb791a38ea3105e6cb541f55e4d029902d3039a4ad07cc4105" +checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" [[package]] name = "base64ct" -version = "1.6.0" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf" [[package]] name = "bech32" @@ -661,7 +623,7 @@ dependencies = [ [[package]] name = "beefy-gadget" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "array-bytes", "async-trait", @@ -695,7 +657,7 @@ dependencies = [ [[package]] name = "beefy-gadget-rpc" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "beefy-gadget", "futures", @@ -760,16 +722,6 @@ dependencies = [ "sp-std 5.0.0", ] -[[package]] -name = "beefy-merkle-tree" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" -dependencies = [ - "sp-api", - "sp-beefy", - "sp-runtime 7.0.0", -] - [[package]] name = "beefy-prover" version = "0.1.0" @@ -802,6 +754,15 @@ dependencies = [ "tokio", ] +[[package]] +name = "binary-merkle-tree" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +dependencies = [ + "hash-db 0.15.2", + "log", +] + [[package]] name = "bincode" version = "1.3.3" @@ -850,6 +811,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" + [[package]] name = "bitvec" version = "0.17.4" @@ -879,7 +846,18 @@ version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" dependencies = [ - "digest 0.10.7", + "digest 0.10.6", +] + +[[package]] +name = "blake2b_simd" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c2f0dc9a68c6317d884f97cc36cf5a3d20ba14ce404227df55e1af708ab04bc" +dependencies = [ + "arrayref", + "arrayvec 0.7.2", + "constant_time_eq 0.2.4", ] [[package]] @@ -905,9 +883,9 @@ dependencies = [ [[package]] name = "block-buffer" -version = "0.10.4" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" dependencies = [ "generic-array 0.14.7", ] @@ -937,6 +915,18 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" +[[package]] +name = "bounded-collections" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3888522b497857eb606bf51695988dba7096941822c1bcf676e3a929a9ae7a0" +dependencies = [ + "log", + "parity-scale-codec", + "scale-info", + "serde", +] + [[package]] name = "bs58" version = "0.4.0" @@ -948,9 +938,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.5.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a246e68bb43f6cd9db24bea052a53e40405417c5fb372e3d1a8a7f770a564ef5" +checksum = "b7f0778972c64420fdedc63f09919c8a88bda7b25135357fd25a5d9f3257e832" dependencies = [ "memchr", "serde", @@ -964,9 +954,9 @@ checksum = "b4ae4235e6dac0694637c763029ecea1a2ec9e4e06ec2729bd21ba4d9c863eb7" [[package]] name = "bumpalo" -version = "3.13.0" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" +checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" [[package]] name = "byte-slice-cast" @@ -980,6 +970,12 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" +[[package]] +name = "bytemuck" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea" + [[package]] name = "byteorder" version = "1.4.3" @@ -1018,9 +1014,9 @@ dependencies = [ [[package]] name = "camino" -version = "1.1.4" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c530edf18f37068ac2d977409ed5cd50d53d73bc653c7647b48eb78976ac9ae2" +checksum = "c77df041dc383319cc661b428b6961a005db4d6808d5e12536931b1ca9556055" dependencies = [ "serde", ] @@ -1048,17 +1044,31 @@ dependencies = [ "thiserror", ] +[[package]] +name = "cargo_metadata" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7daec1a2a2129eeba1644b220b4647ec537b0b5d4bfd6876fcc5a540056b592" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror", +] + [[package]] name = "cast" version = "0.2.0" -source = "git+https://github.com/foundry-rs/foundry#558238ae9f8144e0ca8a88e9365880ebf747e796" +source = "git+https://github.com/foundry-rs/foundry#d4f626bb7f96d46358997d4b27f79358cb2b3401" dependencies = [ "chrono", - "ethers-contract", - "ethers-core", - "ethers-etherscan", - "ethers-providers", - "ethers-signers", + "ethers-contract 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-core 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-etherscan 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-providers 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-signers 2.0.8 (git+https://github.com/gakonst/ethers-rs)", "evm-disassembler", "eyre", "foundry-common", @@ -1067,7 +1077,6 @@ dependencies = [ "foundry-utils", "futures", "hex", - "num_cpus", "rayon", "rusoto_core", "rusoto_kms", @@ -1102,7 +1111,7 @@ version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0aacacf4d96c24b2ad6eb8ee6df040e4f27b0d0b39a5710c30091baa830485db" dependencies = [ - "smallvec", + "smallvec 1.10.0", ] [[package]] @@ -1144,9 +1153,9 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.24" +version = "0.4.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b" +checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" dependencies = [ "iana-time-zone", "js-sys", @@ -1206,15 +1215,15 @@ dependencies = [ [[package]] name = "clap" -version = "3.2.25" +version = "3.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" +checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5" dependencies = [ "atty", - "bitflags", - "clap_derive 3.2.25", + "bitflags 1.3.2", + "clap_derive 3.2.18", "clap_lex 0.2.4", - "indexmap", + "indexmap 1.9.2", "once_cell", "strsim", "termcolor", @@ -1223,26 +1232,26 @@ dependencies = [ [[package]] name = "clap" -version = "4.3.0" +version = "4.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93aae7a4192245f70fe75dd9157fc7b4a5bf53e88d30bd4396f7d8f9284d5acc" +checksum = "906f7fe1da4185b7a282b2bc90172a496f9def1aca4545fe7526810741591e14" dependencies = [ "clap_builder", - "clap_derive 4.3.0", + "clap_derive 4.1.14", "once_cell", ] [[package]] name = "clap_builder" -version = "4.3.0" +version = "4.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f423e341edefb78c9caba2d9c7f7687d0e72e89df3ce3394554754393ac3990" +checksum = "351f9ad9688141ed83dfd8f5fb998a06225ef444b48ff4dc43de6d409b7fd10b" dependencies = [ - "anstream", - "anstyle", - "bitflags", - "clap_lex 0.5.0", + "bitflags 1.3.2", + "clap_lex 0.4.1", + "is-terminal", "strsim", + "termcolor", "terminal_size", "unicase", "unicode-width", @@ -1254,14 +1263,14 @@ version = "3.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f7a2e0a962c45ce25afce14220bc24f9dade0a1787f185cecf96bfba7847cd8" dependencies = [ - "clap 3.2.25", + "clap 3.2.23", ] [[package]] name = "clap_derive" -version = "3.2.25" +version = "3.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008" +checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65" dependencies = [ "heck", "proc-macro-error", @@ -1272,14 +1281,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.3.0" +version = "4.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "191d9573962933b4027f932c600cd252ce27a8ad5979418fe78e43c07996f27b" +checksum = "81d7dc0031c3a59a04fc2ba395c8e2dd463cba1859275f065d225f6122221b45" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.28", ] [[package]] @@ -1293,18 +1302,19 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.5.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" +checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1" [[package]] name = "codegen" version = "0.1.0" dependencies = [ "anyhow", - "clap 3.2.25", + "clap 3.2.23", "frame-metadata", "hex", + "http", "jsonrpsee", "parity-scale-codec", "serde_json", @@ -1314,6 +1324,16 @@ dependencies = [ "wasm-testbed", ] +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + [[package]] name = "coins-bip32" version = "0.8.3" @@ -1323,8 +1343,8 @@ dependencies = [ "bincode", "bs58", "coins-core", - "digest 0.10.7", - "getrandom 0.2.9", + "digest 0.10.6", + "getrandom 0.2.8", "hmac 0.12.1", "k256 0.13.1", "lazy_static", @@ -1341,7 +1361,7 @@ checksum = "84f4d04ee18e58356accd644896aeb2094ddeafb6a713e056cef0c0a8e468c15" dependencies = [ "bitvec 0.17.4", "coins-bip32", - "getrandom 0.2.9", + "getrandom 0.2.8", "hmac 0.12.1", "once_cell", "pbkdf2 0.12.1", @@ -1356,10 +1376,10 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b949a1c63fb7eb591eb7ba438746326aedf0ae843e51ec92ba6bec5bb382c4f" dependencies = [ - "base64 0.21.1", + "base64 0.21.0", "bech32 0.7.3", "bs58", - "digest 0.10.7", + "digest 0.10.6", "generic-array 0.14.7", "hex", "ripemd", @@ -1396,12 +1416,6 @@ dependencies = [ "wasm-bindgen-futures", ] -[[package]] -name = "colorchoice" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" - [[package]] name = "comfy-table" version = "6.1.4" @@ -1409,25 +1423,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e7b787b0dc42e8111badfdbe4c3059158ccb2db8780352fa1b01e8ccf45cc4d" dependencies = [ "crossterm", - "strum", - "strum_macros", + "strum 0.24.1", + "strum_macros 0.24.3", "unicode-width", ] [[package]] name = "concurrent-queue" -version = "2.2.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62ec6771ecfa0762d24683ee5a32ad78487a3d3afdc0fb8cae19d2c5deb50b7c" +checksum = "c278839b831783b70278b14df4d45e1beb1aad306c07bb796637de9a0e323e8e" dependencies = [ - "crossbeam-utils 0.8.15", + "crossbeam-utils 0.8.14", ] [[package]] name = "const-oid" -version = "0.9.2" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520fbf3c07483f94e3e3ca9d0cfd913d7718ef2483d2cfd91c0d9e91474ab913" +checksum = "795bc6e66a8e340f075fcf6227e417a2dc976b92b91f3cdc778bb858778b6747" [[package]] name = "constant_time_eq" @@ -1435,6 +1449,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" +[[package]] +name = "constant_time_eq" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3ad85c1f65dc7b37604eb0e89748faf0b9653065f2a8ef69f96a687ec1e9279" + [[package]] name = "contracts" version = "0.6.3" @@ -1473,9 +1493,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" [[package]] name = "core2" @@ -1486,6 +1506,30 @@ dependencies = [ "memchr", ] +[[package]] +name = "cosmwasm-schema" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63c337e097a089e5b52b5d914a7ff6613332777f38ea6d9d36e1887cd0baa72e" +dependencies = [ + "cosmwasm-schema-derive", + "schemars", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "cosmwasm-schema-derive" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "766cc9e7c1762d8fc9c0265808910fcad755200cd0e624195a491dd885a61169" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "cpp_demangle" version = "0.3.5" @@ -1497,27 +1541,27 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.7" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e4c1eaa2012c47becbbad2ab175484c2a84d1185b566fb2cc5b8707343dfe58" +checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" dependencies = [ "libc", ] [[package]] name = "cranelift-bforest" -version = "0.88.2" +version = "0.93.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52056f6d0584484b57fa6c1a65c1fcb15f3780d8b6a758426d9e3084169b2ddd" +checksum = "2bc42ba2e232e5b20ff7dc299a812d53337dadce9a7e39a238e6a5cb82d2e57b" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.88.2" +version = "0.93.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fed94c8770dc25d01154c3ffa64ed0b3ba9d583736f305fed7beebe5d9cf74" +checksum = "253531aca9b6f56103c9420369db3263e784df39aa1c90685a1f69cfbba0623e" dependencies = [ "arrayvec 0.7.2", "bumpalo", @@ -1527,59 +1571,60 @@ dependencies = [ "cranelift-entity", "cranelift-isle", "gimli 0.26.2", + "hashbrown 0.12.3", "log", "regalloc2", - "smallvec", + "smallvec 1.10.0", "target-lexicon", ] [[package]] name = "cranelift-codegen-meta" -version = "0.88.2" +version = "0.93.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c451b81faf237d11c7e4f3165eeb6bac61112762c5cfe7b4c0fb7241474358f" +checksum = "72f2154365e2bff1b1b8537a7181591fdff50d8e27fa6e40d5c69c3bad0ca7c8" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.88.2" +version = "0.93.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7c940133198426d26128f08be2b40b0bd117b84771fd36798969c4d712d81fc" +checksum = "687e14e3f5775248930e0d5a84195abef8b829958e9794bf8d525104993612b4" [[package]] name = "cranelift-entity" -version = "0.88.2" +version = "0.93.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87a0f1b2fdc18776956370cf8d9b009ded3f855350c480c1c52142510961f352" +checksum = "f42ea692c7b450ad18b8c9889661505d51c09ec4380cf1c2d278dbb2da22cae1" dependencies = [ "serde", ] [[package]] name = "cranelift-frontend" -version = "0.88.2" +version = "0.93.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34897538b36b216cc8dd324e73263596d51b8cf610da6498322838b2546baf8a" +checksum = "8483c2db6f45fe9ace984e5adc5d058102227e4c62e5aa2054e16b0275fd3a6e" dependencies = [ "cranelift-codegen", "log", - "smallvec", + "smallvec 1.10.0", "target-lexicon", ] [[package]] name = "cranelift-isle" -version = "0.88.2" +version = "0.93.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b2629a569fae540f16a76b70afcc87ad7decb38dc28fa6c648ac73b51e78470" +checksum = "e9793158837678902446c411741d87b43f57dadfb944f2440db4287cda8cbd59" [[package]] name = "cranelift-native" -version = "0.88.2" +version = "0.93.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20937dab4e14d3e225c5adfc9c7106bafd4ac669bdb43027b911ff794c6fb318" +checksum = "72668c7755f2b880665cb422c8ad2d56db58a88b9bebfef0b73edc2277c13c49" dependencies = [ "cranelift-codegen", "libc", @@ -1588,16 +1633,16 @@ dependencies = [ [[package]] name = "cranelift-wasm" -version = "0.88.2" +version = "0.93.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80fc2288957a94fd342a015811479de1837850924166d1f1856d8406e6f3609b" +checksum = "3852ce4b088b44ac4e29459573943009a70d1b192c8d77ef949b4e814f656fc1" dependencies = [ "cranelift-codegen", "cranelift-entity", "cranelift-frontend", "itertools", "log", - "smallvec", + "smallvec 1.10.0", "wasmparser", "wasmtime-types", ] @@ -1638,35 +1683,35 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.8" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" dependencies = [ "cfg-if 1.0.0", - "crossbeam-utils 0.8.15", + "crossbeam-utils 0.8.14", ] [[package]] name = "crossbeam-deque" -version = "0.8.3" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" dependencies = [ "cfg-if 1.0.0", "crossbeam-epoch", - "crossbeam-utils 0.8.15", + "crossbeam-utils 0.8.14", ] [[package]] name = "crossbeam-epoch" -version = "0.9.14" +version = "0.9.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" +checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" dependencies = [ "autocfg", "cfg-if 1.0.0", - "crossbeam-utils 0.8.15", - "memoffset 0.8.0", + "crossbeam-utils 0.8.14", + "memoffset 0.7.1", "scopeguard", ] @@ -1683,9 +1728,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.15" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" +checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" dependencies = [ "cfg-if 1.0.0", ] @@ -1696,7 +1741,7 @@ version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e64e6c0fbe2c17357405f7c758c1ef960fce08bdfb2c03d88d2a18d7e09c4b67" dependencies = [ - "bitflags", + "bitflags 1.3.2", "crossterm_winapi", "libc", "mio", @@ -1708,9 +1753,9 @@ dependencies = [ [[package]] name = "crossterm_winapi" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ae1b35a484aa10e07fe0638d02301c5ad24de82d310ccbd2f3693da5f09bf1c" +checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" dependencies = [ "winapi", ] @@ -1806,7 +1851,7 @@ dependencies = [ [[package]] name = "cumulus-primitives-core" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.38#9b4e0247137f158d1a35118197d34adfa58858b7" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" dependencies = [ "parity-scale-codec", "polkadot-core-primitives", @@ -1847,9 +1892,9 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "4.0.0-rc.1" +version = "4.0.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d4ba9852b42210c7538b75484f9daa0655e9a3ac04f693747bb0f02cf3cfe16" +checksum = "8da00a7a9a4eb92a0a0f8e75660926d48f0d0f3c537e455c457bcdaa1e16b1ac" dependencies = [ "cfg-if 1.0.0", "fiat-crypto", @@ -1872,6 +1917,50 @@ dependencies = [ "zeroize", ] +[[package]] +name = "cxx" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc831ee6a32dd495436e317595e639a587aa9907bef96fe6e6abc290ab6204e9" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94331d54f1b1a8895cd81049f7eaaaef9d05a7dcb4d1fd08bf3ff0806246789d" +dependencies = [ + "cc", + "codespan-reporting", + "once_cell", + "proc-macro2", + "quote", + "scratch", + "syn 1.0.109", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48dcd35ba14ca9b40d6e4b4b39961f23d835dbb8eed74565ded361d93e1feb8a" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81bbeb29798b407ccd82a3324ade1a7286e0d29851475990b612670f6f5124d2" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "darling" version = "0.14.4" @@ -1909,15 +1998,15 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.4.0" +version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" +checksum = "23d8666cb01533c39dde32bcbab8e227b4ed6679b2c925eba05feabea39508fb" [[package]] name = "data-encoding-macro" -version = "0.1.13" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c904b33cc60130e1aeea4956ab803d08a3f4a0ca82d64ed757afac3891f2bb99" +checksum = "86927b7cd2fe88fa698b87404b287ab98d1a0063a34071d92e575b72d3029aca" dependencies = [ "data-encoding", "data-encoding-macro-internal", @@ -1925,9 +2014,9 @@ dependencies = [ [[package]] name = "data-encoding-macro-internal" -version = "0.1.11" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fdf3fce3ce863539ec1d7fd1b6dcc3c645663376b43ed376bbf887733e4f772" +checksum = "a5bbed42daaa95e780b60a50546aa345b8413a1e46f9a40a12907d3598f038db" dependencies = [ "data-encoding", "syn 1.0.109", @@ -1946,9 +2035,9 @@ dependencies = [ [[package]] name = "der" -version = "0.7.6" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56acb310e15652100da43d130af8d97b509e95af61aab1c5a7939ef24337ee17" +checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" dependencies = [ "const-oid", "pem-rfc7468 0.7.0", @@ -2081,11 +2170,11 @@ dependencies = [ [[package]] name = "digest" -version = "0.10.7" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" dependencies = [ - "block-buffer 0.10.4", + "block-buffer 0.10.3", "const-oid", "crypto-common", "subtle", @@ -2097,7 +2186,7 @@ version = "4.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f51c5d4ddabd36886dd3e1438cb358cdcb0d7c499cb99cb4ac2e38e18b5cb210" dependencies = [ - "dirs-sys", + "dirs-sys 0.3.7", ] [[package]] @@ -2110,6 +2199,15 @@ dependencies = [ "dirs-sys-next", ] +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys 0.4.1", +] + [[package]] name = "dirs-next" version = "2.0.0" @@ -2131,6 +2229,18 @@ dependencies = [ "winapi", ] +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + [[package]] name = "dirs-sys-next" version = "0.1.2" @@ -2144,13 +2254,13 @@ dependencies = [ [[package]] name = "displaydoc" -version = "0.2.4" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" +checksum = "3bf95dc3f046b9da4f2d51833c0d3547d8564ef6910f5c1ed130306a75b92886" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 1.0.109", ] [[package]] @@ -2167,9 +2277,9 @@ checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" [[package]] name = "dtoa" -version = "1.0.6" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65d09067bfacaa79114679b279d7f5885b53295b1e2cfb4e79c8e4bd3d633169" +checksum = "c00704156a7de8df8da0911424e30c2049957b0a714542a44e05fe693dd85313" [[package]] name = "dunce" @@ -2200,9 +2310,9 @@ dependencies = [ [[package]] name = "dyn-clone" -version = "1.0.11" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b0cf012f1230e43cd00ebb729c6bb58707ecfa8ad08b52ef3a4ccd2697fc30" +checksum = "c9b0705efd4599c15a38151f4721f7bc388306f61084d3bfd50bd07fbca5cb60" [[package]] name = "ecdsa" @@ -2222,8 +2332,8 @@ version = "0.16.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0997c976637b606099b9985693efa3581e84e41f5c11ba5255f88711058ad428" dependencies = [ - "der 0.7.6", - "digest 0.10.7", + "der 0.7.8", + "digest 0.10.6", "elliptic-curve 0.13.5", "rfc6979 0.4.0", "signature 2.1.0", @@ -2296,7 +2406,7 @@ dependencies = [ "base16ct 0.1.1", "crypto-bigint 0.4.9", "der 0.6.1", - "digest 0.10.7", + "digest 0.10.6", "ff 0.12.1", "generic-array 0.14.7", "group 0.12.1", @@ -2317,14 +2427,14 @@ checksum = "968405c8fdc9b3bf4df0a6638858cc0b52462836ab6b1c87377785dd09cf1c0b" dependencies = [ "base16ct 0.2.0", "crypto-bigint 0.5.2", - "digest 0.10.7", + "digest 0.10.6", "ff 0.13.0", "generic-array 0.14.7", "group 0.13.0", "pem-rfc7468 0.7.0", "pkcs8 0.10.2", "rand_core 0.6.4", - "sec1 0.7.2", + "sec1 0.7.3", "subtle", "zeroize", ] @@ -2365,6 +2475,25 @@ dependencies = [ "zeroize", ] +[[package]] +name = "enr" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0be7b2ac146c1f99fe245c02d16af0696450d8e06c135db75e10eeb9e642c20d" +dependencies = [ + "base64 0.21.0", + "bytes", + "hex", + "k256 0.13.1", + "log", + "rand 0.8.5", + "rlp", + "serde", + "serde-hex", + "sha3", + "zeroize", +] + [[package]] name = "enum-as-inner" version = "0.5.1" @@ -2379,13 +2508,13 @@ dependencies = [ [[package]] name = "enumn" -version = "0.1.8" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48016319042fb7c87b78d2993084a831793a897a5cd1a2a67cab9d1eeb4b7d76" +checksum = "e88bcb3a067a6555d577aba299e75eff9942da276e6506fc6274327daa026132" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 1.0.109", ] [[package]] @@ -2420,6 +2549,12 @@ version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e48c92028aaa870e83d51c64e5d4e0b6981b360c522198c23959f219a4e1b15b" +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "errno" version = "0.2.8" @@ -2433,9 +2568,9 @@ dependencies = [ [[package]] name = "errno" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f" dependencies = [ "errno-dragonfly", "libc", @@ -2460,7 +2595,7 @@ checksum = "1fda3bf123be441da5260717e0661c25a2fd9cb2b2c1d20bf2e05580047158ab" dependencies = [ "aes 0.8.2", "ctr 0.9.2", - "digest 0.10.7", + "digest 0.10.6", "hex", "hmac 0.12.1", "pbkdf2 0.11.0", @@ -2524,42 +2659,88 @@ dependencies = [ [[package]] name = "ethers" -version = "2.0.4" +version = "2.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d5486fdc149826f38c388f26a7df72534ee3f20d3a3f72539376fa7b3bbc43d" +checksum = "96b4026b97da8281276744741fac7eb385da905f6093c583331fa2953fdd4253" dependencies = [ - "ethers-addressbook", - "ethers-contract", - "ethers-core", - "ethers-etherscan", - "ethers-middleware", - "ethers-providers", - "ethers-signers", - "ethers-solc", + "ethers-addressbook 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ethers-contract 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ethers-core 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ethers-etherscan 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ethers-middleware 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ethers-providers 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ethers-signers 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ethers-solc 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "ethers-addressbook" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c66a426b824a0f6d1361ad74b6b01adfd26c44ee1e14c3662dcf28406763ec5" +name = "ethers" +version = "2.0.8" +source = "git+https://github.com/gakonst/ethers-rs#5145992e4b03fdaebcc4d35aa7ee44504ca82b5a" dependencies = [ - "ethers-core", - "once_cell", + "ethers-addressbook 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-contract 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-core 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-etherscan 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-middleware 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-providers 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-signers 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-solc 2.0.8 (git+https://github.com/gakonst/ethers-rs)", +] + +[[package]] +name = "ethers-addressbook" +version = "2.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edcb6ffefc230d8c42874c51b28dc11dbb8de50b27a8fdf92648439d6baa68dc" +dependencies = [ + "ethers-core 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "once_cell", + "serde", + "serde_json", +] + +[[package]] +name = "ethers-addressbook" +version = "2.0.8" +source = "git+https://github.com/gakonst/ethers-rs#5145992e4b03fdaebcc4d35aa7ee44504ca82b5a" +dependencies = [ + "ethers-core 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "once_cell", "serde", "serde_json", ] [[package]] name = "ethers-contract" -version = "2.0.4" +version = "2.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfa43e2e69632492d7b38e59465d125a0066cf4c477390ece00d3acbd11b338b" +checksum = "0d4719a44c3d37ab07c6dea99ab174068d8c35e441b60b6c20ce4e48357273e8" dependencies = [ - "ethers-contract-abigen", - "ethers-contract-derive", - "ethers-core", - "ethers-providers", + "ethers-contract-abigen 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ethers-contract-derive 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ethers-core 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ethers-providers 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ethers-signers 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util", + "hex", + "once_cell", + "pin-project", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "ethers-contract" +version = "2.0.8" +source = "git+https://github.com/gakonst/ethers-rs#5145992e4b03fdaebcc4d35aa7ee44504ca82b5a" +dependencies = [ + "ethers-contract-abigen 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-contract-derive 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-core 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-providers 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-signers 2.0.8 (git+https://github.com/gakonst/ethers-rs)", "futures-util", "hex", "once_cell", @@ -2571,61 +2752,122 @@ dependencies = [ [[package]] name = "ethers-contract-abigen" -version = "2.0.4" +version = "2.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2edb8fdbf77459819a443234b461171a024476bfc12f1853b889a62c6e1185ff" +checksum = "155ea1b84d169d231317ed86e307af6f2bed6b40dd17e5e94bc84da21cadb21c" dependencies = [ "Inflector", "dunce", - "ethers-core", - "ethers-etherscan", + "ethers-core 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ethers-etherscan 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "eyre", - "getrandom 0.2.9", "hex", - "prettyplease 0.2.6", + "prettyplease 0.2.12", "proc-macro2", "quote", "regex", "reqwest", "serde", "serde_json", - "syn 2.0.16", - "tokio", - "toml 0.7.4", - "url", + "syn 2.0.28", + "toml 0.7.6", + "walkdir", +] + +[[package]] +name = "ethers-contract-abigen" +version = "2.0.8" +source = "git+https://github.com/gakonst/ethers-rs#5145992e4b03fdaebcc4d35aa7ee44504ca82b5a" +dependencies = [ + "Inflector", + "dunce", + "ethers-core 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "eyre", + "hex", + "prettyplease 0.2.12", + "proc-macro2", + "quote", + "regex", + "serde", + "serde_json", + "syn 2.0.28", + "toml 0.7.6", "walkdir", ] [[package]] name = "ethers-contract-derive" -version = "2.0.4" +version = "2.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "939b0c37746929f869285ee37d270b7c998d80cc7404c2e20dda8efe93e3b295" +checksum = "8567ff196c4a37c1a8c90ec73bda0ad2062e191e4f0a6dc4d943e2ec4830fc88" +dependencies = [ + "Inflector", + "ethers-contract-abigen 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ethers-core 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "hex", + "proc-macro2", + "quote", + "serde_json", + "syn 2.0.28", +] + +[[package]] +name = "ethers-contract-derive" +version = "2.0.8" +source = "git+https://github.com/gakonst/ethers-rs#5145992e4b03fdaebcc4d35aa7ee44504ca82b5a" dependencies = [ "Inflector", - "ethers-contract-abigen", - "ethers-core", + "ethers-contract-abigen 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-core 2.0.8 (git+https://github.com/gakonst/ethers-rs)", "hex", "proc-macro2", "quote", "serde_json", - "syn 2.0.16", + "syn 2.0.28", ] [[package]] name = "ethers-core" -version = "2.0.4" +version = "2.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "198ea9efa8480fa69f73d31d41b1601dace13d053c6fe4be6f5878d9dfcf0108" +checksum = "60ca2514feb98918a0a31de7e1983c29f2267ebf61b2dc5d4294f91e5b866623" +dependencies = [ + "arrayvec 0.7.2", + "bytes", + "cargo_metadata 0.15.4", + "chrono", + "elliptic-curve 0.13.5", + "ethabi", + "generic-array 0.14.7", + "hex", + "k256 0.13.1", + "num_enum", + "once_cell", + "open-fastrlp", + "rand 0.8.5", + "rlp", + "serde", + "serde_json", + "strum 0.25.0", + "syn 2.0.28", + "tempfile", + "thiserror", + "tiny-keccak", + "unicode-xid", +] + +[[package]] +name = "ethers-core" +version = "2.0.8" +source = "git+https://github.com/gakonst/ethers-rs#5145992e4b03fdaebcc4d35aa7ee44504ca82b5a" dependencies = [ "arrayvec 0.7.2", "bytes", - "cargo_metadata", + "cargo_metadata 0.17.0", "chrono", "elliptic-curve 0.13.5", "ethabi", "generic-array 0.14.7", - "getrandom 0.2.9", "hex", "k256 0.13.1", "num_enum", @@ -2635,8 +2877,8 @@ dependencies = [ "rlp", "serde", "serde_json", - "strum", - "syn 2.0.16", + "strum 0.25.0", + "syn 2.0.28", "tempfile", "thiserror", "tiny-keccak", @@ -2645,13 +2887,26 @@ dependencies = [ [[package]] name = "ethers-etherscan" -version = "2.0.4" +version = "2.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "196a21d6939ab78b7a1e4c45c2b33b0c2dd821a2e1af7c896f06721e1ba2a0c7" +checksum = "22b3a8269d3df0ed6364bc05b4735b95f4bf830ce3aef87d5e760fb0e93e5b91" +dependencies = [ + "ethers-core 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "reqwest", + "semver", + "serde", + "serde_json", + "thiserror", + "tracing", +] + +[[package]] +name = "ethers-etherscan" +version = "2.0.8" +source = "git+https://github.com/gakonst/ethers-rs#5145992e4b03fdaebcc4d35aa7ee44504ca82b5a" dependencies = [ - "ethers-core", - "ethers-solc", - "getrandom 0.2.9", + "ethers-core 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-solc 2.0.8 (git+https://github.com/gakonst/ethers-rs)", "reqwest", "semver", "serde", @@ -2662,17 +2917,43 @@ dependencies = [ [[package]] name = "ethers-middleware" -version = "2.0.4" +version = "2.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75594cc450992fc7de701c9145de612325fd8a18be765b8ae78767ba2b74876f" +checksum = "e0c339aad74ae5c451d27e0e49c7a3c7d22620b119b4f9291d7aa21f72d7f366" +dependencies = [ + "async-trait", + "auto_impl", + "ethers-contract 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ethers-core 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ethers-etherscan 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ethers-providers 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ethers-signers 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-channel", + "futures-locks", + "futures-util", + "instant", + "reqwest", + "serde", + "serde_json", + "thiserror", + "tokio", + "tracing", + "tracing-futures", + "url", +] + +[[package]] +name = "ethers-middleware" +version = "2.0.8" +source = "git+https://github.com/gakonst/ethers-rs#5145992e4b03fdaebcc4d35aa7ee44504ca82b5a" dependencies = [ "async-trait", "auto_impl", - "ethers-contract", - "ethers-core", - "ethers-etherscan", - "ethers-providers", - "ethers-signers", + "ethers-contract 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-core 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-etherscan 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-providers 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-signers 2.0.8 (git+https://github.com/gakonst/ethers-rs)", "futures-channel", "futures-locks", "futures-util", @@ -2689,21 +2970,20 @@ dependencies = [ [[package]] name = "ethers-providers" -version = "2.0.4" +version = "2.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1009041f40476b972b5d79346cc512e97c662b1a0a2f78285eabe9a122909783" +checksum = "b411b119f1cf0efb69e2190883dee731251882bb21270f893ee9513b3a697c48" dependencies = [ "async-trait", "auto_impl", - "base64 0.21.1", + "base64 0.21.0", "bytes", - "enr", - "ethers-core", + "enr 0.8.1", + "ethers-core 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "futures-channel", "futures-core", "futures-timer", "futures-util", - "getrandom 0.2.9", "hashers", "hex", "http", @@ -2725,11 +3005,64 @@ dependencies = [ "ws_stream_wasm", ] +[[package]] +name = "ethers-providers" +version = "2.0.8" +source = "git+https://github.com/gakonst/ethers-rs#5145992e4b03fdaebcc4d35aa7ee44504ca82b5a" +dependencies = [ + "async-trait", + "auto_impl", + "base64 0.21.0", + "bytes", + "enr 0.9.0", + "ethers-core 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "futures-core", + "futures-timer", + "futures-util", + "hashers", + "hex", + "http", + "instant", + "jsonwebtoken", + "once_cell", + "pin-project", + "reqwest", + "serde", + "serde_json", + "thiserror", + "tokio", + "tracing", + "tracing-futures", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "ws_stream_wasm", +] + [[package]] name = "ethers-signers" -version = "2.0.4" +version = "2.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3bd11ad6929f01f01be74bb00d02bbd6552f22de030865c898b340a3a592db1" +checksum = "4864d387456a9c09a1157fa10e1528b29d90f1d859443acf06a1b23365fb518c" +dependencies = [ + "async-trait", + "coins-bip32", + "coins-bip39", + "elliptic-curve 0.13.5", + "eth-keystore", + "ethers-core 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "hex", + "rand 0.8.5", + "sha2 0.10.6", + "thiserror", + "tracing", +] + +[[package]] +name = "ethers-signers" +version = "2.0.8" +source = "git+https://github.com/gakonst/ethers-rs#5145992e4b03fdaebcc4d35aa7ee44504ca82b5a" dependencies = [ "async-trait", "coins-bip32", @@ -2737,7 +3070,7 @@ dependencies = [ "coins-ledger", "elliptic-curve 0.13.5", "eth-keystore", - "ethers-core", + "ethers-core 2.0.8 (git+https://github.com/gakonst/ethers-rs)", "futures-executor", "futures-util", "hex", @@ -2755,15 +3088,45 @@ dependencies = [ [[package]] name = "ethers-solc" -version = "2.0.4" +version = "2.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2284784306de73d8ad1bc792ecc1b87da0268185683698d60fd096d23d168c99" +checksum = "7a6c2b9625a2c639d46625f88acc2092a3cb35786c37f7c2128b3ca20f639b3c" +dependencies = [ + "cfg-if 1.0.0", + "dunce", + "ethers-core 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "glob", + "hex", + "home", + "md-5 0.10.5", + "num_cpus", + "once_cell", + "path-slash", + "rayon", + "regex", + "semver", + "serde", + "serde_json", + "solang-parser", + "svm-rs 0.2.23", + "thiserror", + "tiny-keccak", + "tokio", + "tracing", + "walkdir", + "yansi 0.5.1", +] + +[[package]] +name = "ethers-solc" +version = "2.0.8" +source = "git+https://github.com/gakonst/ethers-rs#5145992e4b03fdaebcc4d35aa7ee44504ca82b5a" dependencies = [ "cfg-if 1.0.0", + "dirs", "dunce", - "ethers-core", + "ethers-core 2.0.8 (git+https://github.com/gakonst/ethers-rs)", "futures-util", - "getrandom 0.2.9", "glob", "hex", "home", @@ -2778,14 +3141,14 @@ dependencies = [ "serde_json", "sha2 0.10.6", "solang-parser", - "svm-rs", + "svm-rs 0.3.0", "svm-rs-builds", "thiserror", "tiny-keccak", "tokio", "tracing", "walkdir", - "yansi", + "yansi 0.5.1", ] [[package]] @@ -2828,13 +3191,19 @@ checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" [[package]] name = "fastrand" -version = "1.9.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" dependencies = [ "instant", ] +[[package]] +name = "fastrand" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" + [[package]] name = "ff" version = "0.12.1" @@ -2857,20 +3226,20 @@ dependencies = [ [[package]] name = "fiat-crypto" -version = "0.1.20" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e825f6987101665dea6ec934c09ec6d721de7bc1bf92248e1d5810c8cd636b77" +checksum = "a214f5bb88731d436478f3ae1f8a277b62124089ba9fb67f4f93fb100ef73c90" [[package]] name = "figment" -version = "0.10.8" +version = "0.10.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e56602b469b2201400dec66a66aec5a9b8761ee97cd1b8c96ab2483fcc16cc9" +checksum = "4547e226f4c9ab860571e070a9034192b3175580ecea38da34fcdb53a018c9a5" dependencies = [ "atomic", "pear", "serde", - "toml 0.5.11", + "toml 0.7.6", "uncased", "version_check", ] @@ -2887,9 +3256,9 @@ dependencies = [ [[package]] name = "finality-grandpa" -version = "0.16.2" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36530797b9bf31cd4ff126dcfee8170f86b00cfdcea3269d73133cc0415945c3" +checksum = "e24e6c429951433ccb7c87fd528c60084834dcd14763182c1f83291bcde24c34" dependencies = [ "either", "futures", @@ -2921,13 +3290,13 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.26" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" +checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" dependencies = [ "crc32fast", "libz-sys", - "miniz_oxide 0.7.1", + "miniz_oxide", ] [[package]] @@ -2958,10 +3327,10 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "forge-fmt" version = "0.2.0" -source = "git+https://github.com/foundry-rs/foundry#558238ae9f8144e0ca8a88e9365880ebf747e796" +source = "git+https://github.com/foundry-rs/foundry#d4f626bb7f96d46358997d4b27f79358cb2b3401" dependencies = [ "ariadne", - "ethers-core", + "ethers-core 2.0.8 (git+https://github.com/gakonst/ethers-rs)", "foundry-config", "itertools", "semver", @@ -2973,7 +3342,7 @@ dependencies = [ [[package]] name = "fork-tree" version = "3.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "parity-scale-codec", ] @@ -2990,34 +3359,35 @@ dependencies = [ [[package]] name = "foundry-abi" version = "0.1.0" -source = "git+https://github.com/foundry-rs/foundry#558238ae9f8144e0ca8a88e9365880ebf747e796" +source = "git+https://github.com/foundry-rs/foundry#d4f626bb7f96d46358997d4b27f79358cb2b3401" dependencies = [ - "ethers-contract", - "ethers-contract-abigen", - "ethers-core", - "ethers-providers", + "ethers-contract 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-contract-abigen 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-core 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-providers 2.0.8 (git+https://github.com/gakonst/ethers-rs)", "eyre", "foundry-macros", - "syn 2.0.16", + "syn 2.0.28", ] [[package]] name = "foundry-common" version = "0.1.0" -source = "git+https://github.com/foundry-rs/foundry#558238ae9f8144e0ca8a88e9365880ebf747e796" +source = "git+https://github.com/foundry-rs/foundry#d4f626bb7f96d46358997d4b27f79358cb2b3401" dependencies = [ - "clap 4.3.0", + "auto_impl", + "clap 4.1.14", "comfy-table", "dunce", - "ethers-core", - "ethers-etherscan", - "ethers-middleware", - "ethers-providers", - "ethers-solc", + "ethers-core 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-etherscan 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-middleware 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-providers 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-solc 2.0.8 (git+https://github.com/gakonst/ethers-rs)", "eyre", "foundry-config", "foundry-macros", - "is-terminal", + "globset", "once_cell", "regex", "reqwest", @@ -3028,19 +3398,19 @@ dependencies = [ "thiserror", "tracing", "walkdir", - "yansi", + "yansi 0.5.1", ] [[package]] name = "foundry-config" version = "0.2.0" -source = "git+https://github.com/foundry-rs/foundry#558238ae9f8144e0ca8a88e9365880ebf747e796" +source = "git+https://github.com/foundry-rs/foundry#d4f626bb7f96d46358997d4b27f79358cb2b3401" dependencies = [ "Inflector", "dirs-next", - "ethers-core", - "ethers-etherscan", - "ethers-solc", + "ethers-core 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-etherscan 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-solc 2.0.8 (git+https://github.com/gakonst/ethers-rs)", "eyre", "figment", "globset", @@ -3055,8 +3425,8 @@ dependencies = [ "serde_json", "serde_regex", "thiserror", - "toml 0.7.4", - "toml_edit", + "toml 0.7.6", + "toml_edit 0.19.14", "tracing", "walkdir", ] @@ -3064,16 +3434,17 @@ dependencies = [ [[package]] name = "foundry-evm" version = "0.2.0" -source = "git+https://github.com/foundry-rs/foundry#558238ae9f8144e0ca8a88e9365880ebf747e796" +source = "git+https://github.com/foundry-rs/foundry#d4f626bb7f96d46358997d4b27f79358cb2b3401" dependencies = [ "auto_impl", "bytes", - "ethers", + "ethers 2.0.8 (git+https://github.com/gakonst/ethers-rs)", "eyre", "foundry-abi", "foundry-common", "foundry-config", "foundry-macros", + "foundry-utils", "futures", "hashbrown 0.13.2", "hex", @@ -3092,15 +3463,15 @@ dependencies = [ "tracing", "url", "walkdir", - "yansi", + "yansi 0.5.1", ] [[package]] name = "foundry-macros" -version = "0.1.0" -source = "git+https://github.com/foundry-rs/foundry#558238ae9f8144e0ca8a88e9365880ebf747e796" +version = "0.2.0" +source = "git+https://github.com/foundry-rs/foundry#d4f626bb7f96d46358997d4b27f79358cb2b3401" dependencies = [ - "ethers-core", + "ethers-core 2.0.8 (git+https://github.com/gakonst/ethers-rs)", "foundry-macros-impl", "serde", "serde_json", @@ -3109,24 +3480,25 @@ dependencies = [ [[package]] name = "foundry-macros-impl" version = "0.0.0" -source = "git+https://github.com/foundry-rs/foundry#558238ae9f8144e0ca8a88e9365880ebf747e796" +source = "git+https://github.com/foundry-rs/foundry#d4f626bb7f96d46358997d4b27f79358cb2b3401" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.28", ] [[package]] name = "foundry-utils" version = "0.2.0" -source = "git+https://github.com/foundry-rs/foundry#558238ae9f8144e0ca8a88e9365880ebf747e796" -dependencies = [ - "ethers-addressbook", - "ethers-contract", - "ethers-core", - "ethers-etherscan", - "ethers-providers", - "ethers-solc", +source = "git+https://github.com/foundry-rs/foundry#d4f626bb7f96d46358997d4b27f79358cb2b3401" +dependencies = [ + "dunce", + "ethers-addressbook 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-contract 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-core 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-etherscan 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-providers 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-solc 2.0.8 (git+https://github.com/gakonst/ethers-rs)", "eyre", "forge-fmt", "futures", @@ -3152,7 +3524,7 @@ checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa" [[package]] name = "frame-benchmarking" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-support", "frame-support-procedural", @@ -3176,9 +3548,9 @@ dependencies = [ [[package]] name = "frame-metadata" -version = "15.1.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "878babb0b136e731cc77ec2fd883ff02745ff21e6fb662729953d44923df009c" +checksum = "df6bb8542ef006ef0de09a5c4420787d79823c0ed7924225822362fd2bf2ff2d" dependencies = [ "cfg-if 1.0.0", "parity-scale-codec", @@ -3189,9 +3561,9 @@ dependencies = [ [[package]] name = "frame-support" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ - "bitflags", + "bitflags 1.3.2", "frame-metadata", "frame-support-procedural", "impl-trait-for-tuples", @@ -3202,11 +3574,11 @@ dependencies = [ "paste", "scale-info", "serde", - "smallvec", + "smallvec 1.10.0", "sp-api", "sp-arithmetic 6.0.0", "sp-core 7.0.0", - "sp-core-hashing-proc-macro 5.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38)", + "sp-core-hashing-proc-macro", "sp-inherents", "sp-io 7.0.0", "sp-runtime 7.0.0", @@ -3221,7 +3593,7 @@ dependencies = [ [[package]] name = "frame-support-procedural" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "Inflector", "cfg-expr", @@ -3236,7 +3608,7 @@ dependencies = [ [[package]] name = "frame-support-procedural-tools" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-support-procedural-tools-derive", "proc-macro-crate", @@ -3248,7 +3620,7 @@ dependencies = [ [[package]] name = "frame-support-procedural-tools-derive" version = "3.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "proc-macro2", "quote", @@ -3258,7 +3630,7 @@ dependencies = [ [[package]] name = "frame-system" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-support", "log", @@ -3340,11 +3712,11 @@ checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" [[package]] name = "futures-lite" -version = "1.13.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48" dependencies = [ - "fastrand", + "fastrand 1.8.0", "futures-core", "futures-io", "memchr", @@ -3371,7 +3743,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.28", ] [[package]] @@ -3467,9 +3839,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.9" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -3505,23 +3877,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" dependencies = [ "fallible-iterator", - "indexmap", + "indexmap 1.9.2", "stable_deref_trait", ] [[package]] name = "gimli" -version = "0.27.2" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" +checksum = "221996f774192f0f718773def8201c4ae31f02616a54ccfc2d358bb0e5cefdec" [[package]] name = "git2" -version = "0.17.1" +version = "0.17.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b7905cdfe33d31a88bb2e8419ddd054451f5432d1da9eaf2ac7804ee1ea12d5" +checksum = "7b989d6a7ca95a362cf2cfc5ad688b3a467be1f87e480b8dad07fee8c79b0044" dependencies = [ - "bitflags", + "bitflags 1.3.2", "libc", "libgit2-sys", "log", @@ -3602,7 +3974,7 @@ dependencies = [ "derive_more", "finality-grandpa", "frame-support", - "hash-db", + "hash-db 0.15.2", "light-client-common", "log", "parity-scale-codec", @@ -3626,7 +3998,7 @@ dependencies = [ "futures", "grandpa-light-client-primitives", "grandpa-prover", - "hash-db", + "hash-db 0.15.2", "hex", "hex-literal 0.3.4", "hyperspace-core", @@ -3720,9 +4092,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.19" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d357c7ae988e7d2182f7d7871d0b963962420b0678b0997ce7de72001aeab782" +checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4" dependencies = [ "bytes", "fnv", @@ -3730,7 +4102,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap", + "indexmap 1.9.2", "slab", "tokio", "tokio-util", @@ -3749,6 +4121,12 @@ version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d23bd4e7b5eda0d0f3a307e8b381fdc8ba9000f26fbe912250c0a4cc3956364a" +[[package]] +name = "hash-db" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e7d7786361d7425ae2fe4f9e407eb0efaa0840f5212d109cc018c40c35c6ab4" + [[package]] name = "hash256-std-hasher" version = "0.15.2" @@ -3777,6 +4155,12 @@ dependencies = [ "serde", ] +[[package]] +name = "hashbrown" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" + [[package]] name = "hashers" version = "1.0.1" @@ -3793,7 +4177,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3e372db8e5c0d213e0cd0b9be18be2aca3d44cf2fe30a9d46a65581cd454584" dependencies = [ "base64 0.13.1", - "bitflags", + "bitflags 1.3.2", "bytes", "headers-core", "http", @@ -3837,9 +4221,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" +checksum = "856b5cb0902c2b6d65d5fd97dfa30f9b70c7538e770b98eab5ed52d8db923e01" [[package]] name = "hex" @@ -3909,7 +4293,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest 0.10.7", + "digest 0.10.6", ] [[package]] @@ -3991,9 +4375,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.26" +version = "0.14.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab302d72a6f11a3b910431ff93aae7e773078c769f0a3ef15fb9ec692ed147d4" +checksum = "5e011372fa0b68db8350aa7a248930ecc7839bf46d8485577d69f117a75f164c" dependencies = [ "bytes", "futures-channel", @@ -4068,15 +4452,16 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.24.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0646026eb1b3eea4cd9ba47912ea5ce9cc07713d105b1a14698f4e6433d348b7" +checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97" dependencies = [ + "futures-util", "http", "hyper", - "rustls 0.21.1", + "rustls 0.21.6", "tokio", - "tokio-rustls 0.24.0", + "tokio-rustls 0.24.1", ] [[package]] @@ -4096,10 +4481,10 @@ name = "hyperspace" version = "0.1.0" dependencies = [ "anyhow", - "clap 3.2.25", + "clap 3.2.23", "hyperspace-core", "tokio", - "toml 0.5.11", + "toml 0.7.6", ] [[package]] @@ -4108,7 +4493,7 @@ version = "0.1.0" dependencies = [ "anyhow", "async-trait", - "clap 3.2.25", + "clap 3.2.23", "codegen", "derive_more", "env_logger 0.9.3", @@ -4124,6 +4509,7 @@ dependencies = [ "ibc", "ibc-proto", "ibc-rpc", + "ics08-wasm", "ics10-grandpa", "ics11-beefy", "itertools", @@ -4136,6 +4522,8 @@ dependencies = [ "prometheus", "prost", "rand 0.8.5", + "scale-decode", + "scale-encode", "serde", "sp-beefy", "sp-core 7.0.0", @@ -4149,7 +4537,7 @@ dependencies = [ "tendermint-proto", "thiserror", "tokio", - "toml 0.5.11", + "toml 0.7.6", ] [[package]] @@ -4161,7 +4549,7 @@ dependencies = [ "bech32 0.9.1", "bip32", "derive_more", - "digest 0.10.7", + "digest 0.10.6", "ed25519-zebra", "futures", "hex", @@ -4172,12 +4560,15 @@ dependencies = [ "ibc-proto", "ibc-rpc", "ics07-tendermint", + "ics08-wasm", "itertools", "k256 0.11.6", "log", "pallet-ibc", "parity-scale-codec", "prost", + "quick_cache", + "rand 0.8.5", "ripemd", "rs_merkle", "serde", @@ -4205,7 +4596,9 @@ dependencies = [ "async-trait", "cast", "elliptic-curve 0.13.5", - "ethers", + "env_logger 0.10.0", + "ethers 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ethers-solc 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "futures", "git2", "hex", @@ -4222,7 +4615,7 @@ dependencies = [ "serde_json", "thiserror", "tokio", - "toml 0.7.4", + "toml 0.7.6", "tracing", "tracing-subscriber 0.3.17", ] @@ -4253,7 +4646,7 @@ dependencies = [ "beefy-light-client", "beefy-light-client-primitives", "beefy-prover", - "clap 3.2.25", + "clap 3.2.23", "derive_more", "finality-grandpa", "frame-support", @@ -4284,6 +4677,7 @@ dependencies = [ "parity-scale-codec", "polkadot-core-primitives", "prost", + "rand 0.8.5", "rs_merkle", "sc-finality-grandpa-rpc", "serde", @@ -4317,10 +4711,12 @@ dependencies = [ "ibc", "ibc-proto", "ibc-rpc", + "ics08-wasm", "log", "pallet-ibc", "parity-scale-codec", "rand 0.8.5", + "serde", "subxt", "thiserror", "tokio", @@ -4328,31 +4724,33 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.56" +version = "0.1.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0722cd7114b7de04316e7ea5456a0bbb20e4adb46fd27a3697adb812cff0f37c" +checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows 0.48.0", + "winapi", ] [[package]] name = "iana-time-zone-haiku" -version = "0.1.2" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" dependencies = [ - "cc", + "cxx", + "cxx-build", ] [[package]] name = "ibc" version = "0.15.0" dependencies = [ + "cosmwasm-schema", "derive_more", "env_logger 0.9.3", "flex-error", @@ -4379,7 +4777,7 @@ dependencies = [ "tendermint", "tendermint-proto", "test-log", - "time 0.3.21", + "time 0.3.17", "tokio", "tracing", "tracing-subscriber 0.3.17", @@ -4477,6 +4875,7 @@ dependencies = [ "bytes", "env_logger 0.9.3", "flex-error", + "hex", "ibc", "ibc-derive", "ibc-proto", @@ -4494,11 +4893,24 @@ dependencies = [ "tendermint-rpc", "tendermint-testgen", "test-log", - "time 0.3.21", + "time 0.3.17", "tracing", "tracing-subscriber 0.3.17", ] +[[package]] +name = "ics08-wasm" +version = "0.1.0" +dependencies = [ + "cosmwasm-schema", + "hex", + "ibc", + "ibc-proto", + "prost", + "serde", + "tendermint-proto", +] + [[package]] name = "ics10-grandpa" version = "0.1.0" @@ -4577,8 +4989,8 @@ dependencies = [ [[package]] name = "ics23" -version = "0.8.1" -source = "git+https://github.com/confio/ics23?rev=a4daeb4c24ce1be827829c0841446abc690c4f11#a4daeb4c24ce1be827829c0841446abc690c4f11" +version = "0.10.0" +source = "git+https://github.com/cosmos/ics23?rev=74ce807b7be39a7e0afb4e2efb8e28a57965f57b#74ce807b7be39a7e0afb4e2efb8e28a57965f57b" dependencies = [ "anyhow", "bytes", @@ -4642,7 +5054,7 @@ dependencies = [ "rtnetlink", "system-configuration", "tokio", - "windows 0.34.0", + "windows", ] [[package]] @@ -4700,15 +5112,25 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" [[package]] name = "indexmap" -version = "1.9.3" +version = "1.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" dependencies = [ "autocfg", "hashbrown 0.12.3", "serde", ] +[[package]] +name = "indexmap" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +dependencies = [ + "equivalent", + "hashbrown 0.14.0", +] + [[package]] name = "inlinable_string" version = "0.1.15" @@ -4763,19 +5185,12 @@ dependencies = [ [[package]] name = "io-lifetimes" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ce5ef949d49ee85593fc4d3f3f95ad61657076395cbbce23e2121fc5542074" - -[[package]] -name = "io-lifetimes" -version = "1.0.10" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" +checksum = "1abeb7a0dd0f8181267ff8adc397075586500b81b28a73e8a0208b00fc170fb3" dependencies = [ - "hermit-abi 0.3.1", "libc", - "windows-sys 0.48.0", + "windows-sys 0.45.0", ] [[package]] @@ -4798,20 +5213,20 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.7.2" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f" +checksum = "30e22bd8629359895450b59ea7a776c850561b96a3b1d31321c1949d9e6c9146" [[package]] name = "is-terminal" -version = "0.4.7" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" +checksum = "22e18b0a45d56fe973d6db23972bf5bc46f988a4a2385deac9cc29572f09daef" dependencies = [ - "hermit-abi 0.3.1", - "io-lifetimes 1.0.10", - "rustix 0.37.19", - "windows-sys 0.48.0", + "hermit-abi 0.3.0", + "io-lifetimes", + "rustix 0.36.8", + "windows-sys 0.45.0", ] [[package]] @@ -4825,24 +5240,24 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" [[package]] name = "jobserver" -version = "0.1.26" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" +checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b" dependencies = [ "libc", ] [[package]] name = "js-sys" -version = "0.3.63" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f37a4a5928311ac501dee68b3c7613a1037d0edb30c8e5427bd832d55d1b790" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" dependencies = [ "wasm-bindgen", ] @@ -5020,6 +5435,20 @@ dependencies = [ "jsonrpsee-types", ] +[[package]] +name = "jsonwebtoken" +version = "8.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6971da4d9c3aa03c3d8f3ff0f4155b534aad021292003895a469716b2a230378" +dependencies = [ + "base64 0.21.0", + "pem", + "ring", + "serde", + "serde_json", + "simple_asn1", +] + [[package]] name = "k256" version = "0.11.6" @@ -5062,14 +5491,14 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7d770dcb02bf6835887c3a979b5107a04ff4bbde97a5f0928d27404a155add9" dependencies = [ - "smallvec", + "smallvec 1.10.0", ] [[package]] name = "lalrpop" -version = "0.19.12" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a1cbf952127589f2851ab2046af368fd20645491bb4b376f04b7f94d7a9837b" +checksum = "da4081d44f4611b66c6dd725e6de3169f9f63905421e8626fcb86b6a898998b8" dependencies = [ "ascii-canvas", "bit-set", @@ -5080,7 +5509,7 @@ dependencies = [ "lalrpop-util", "petgraph", "regex", - "regex-syntax 0.6.29", + "regex-syntax 0.7.4", "string_cache", "term", "tiny-keccak", @@ -5089,12 +5518,9 @@ dependencies = [ [[package]] name = "lalrpop-util" -version = "0.19.12" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3c48237b9604c5a4702de6b824e02006c3214327564636aef27c1028a8fa0ed" -dependencies = [ - "regex", -] +checksum = "3f35c735096c0293d313e8f2a641627472b83d01b937177fe76e5e2708d31e0d" [[package]] name = "lazy_static" @@ -5107,15 +5533,15 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.144" +version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "libgit2-sys" -version = "0.15.1+1.6.4" +version = "0.15.2+1.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb4577bde8cdfc7d6a2a4bcb7b049598597de33ffd337276e9c7db6cd4a2cee7" +checksum = "a80df2e11fb4a61f4ba2ab42dbe7f74468da143f1a75c74e11dee7c813f694fa" dependencies = [ "cc", "libc", @@ -5133,9 +5559,9 @@ checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a" [[package]] name = "libm" -version = "0.2.7" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" +checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" [[package]] name = "libp2p" @@ -5146,9 +5572,9 @@ dependencies = [ "bytes", "futures", "futures-timer", - "getrandom 0.2.9", + "getrandom 0.2.8", "instant", - "libp2p-core 0.38.0", + "libp2p-core", "libp2p-dns", "libp2p-identify", "libp2p-kad", @@ -5165,10 +5591,10 @@ dependencies = [ "libp2p-webrtc", "libp2p-websocket", "libp2p-yamux", - "multiaddr 0.16.0", + "multiaddr", "parking_lot 0.12.1", "pin-project", - "smallvec", + "smallvec 1.10.0", ] [[package]] @@ -5186,8 +5612,8 @@ dependencies = [ "futures-timer", "instant", "log", - "multiaddr 0.16.0", - "multihash 0.16.3", + "multiaddr", + "multihash", "multistream-select", "once_cell", "parking_lot 0.12.1", @@ -5198,41 +5624,13 @@ dependencies = [ "rw-stream-sink", "sec1 0.3.0", "sha2 0.10.6", - "smallvec", + "smallvec 1.10.0", "thiserror", "unsigned-varint", "void", "zeroize", ] -[[package]] -name = "libp2p-core" -version = "0.39.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c1df63c0b582aa434fb09b2d86897fa2b419ffeccf934b36f87fcedc8e835c2" -dependencies = [ - "either", - "fnv", - "futures", - "futures-timer", - "instant", - "libp2p-identity", - "log", - "multiaddr 0.17.1", - "multihash 0.17.0", - "multistream-select", - "once_cell", - "parking_lot 0.12.1", - "pin-project", - "quick-protobuf", - "rand 0.8.5", - "rw-stream-sink", - "smallvec", - "thiserror", - "unsigned-varint", - "void", -] - [[package]] name = "libp2p-dns" version = "0.38.0" @@ -5240,10 +5638,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e42a271c1b49f789b92f7fc87749fa79ce5c7bdc88cbdfacb818a4bca47fec5" dependencies = [ "futures", - "libp2p-core 0.38.0", + "libp2p-core", "log", "parking_lot 0.12.1", - "smallvec", + "smallvec 1.10.0", "trust-dns-resolver", ] @@ -5256,36 +5654,18 @@ dependencies = [ "asynchronous-codec", "futures", "futures-timer", - "libp2p-core 0.38.0", + "libp2p-core", "libp2p-swarm", "log", "lru", "prost", "prost-build", "prost-codec", - "smallvec", + "smallvec 1.10.0", "thiserror", "void", ] -[[package]] -name = "libp2p-identity" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e2d584751cecb2aabaa56106be6be91338a60a0f4e420cf2af639204f596fc1" -dependencies = [ - "bs58", - "ed25519-dalek", - "log", - "multiaddr 0.17.1", - "multihash 0.17.0", - "quick-protobuf", - "rand 0.8.5", - "sha2 0.10.6", - "thiserror", - "zeroize", -] - [[package]] name = "libp2p-kad" version = "0.42.1" @@ -5300,14 +5680,14 @@ dependencies = [ "futures", "futures-timer", "instant", - "libp2p-core 0.38.0", + "libp2p-core", "libp2p-swarm", "log", "prost", "prost-build", "rand 0.8.5", "sha2 0.10.6", - "smallvec", + "smallvec 1.10.0", "thiserror", "uint", "unsigned-varint", @@ -5323,11 +5703,11 @@ dependencies = [ "data-encoding", "futures", "if-watch", - "libp2p-core 0.38.0", + "libp2p-core", "libp2p-swarm", "log", "rand 0.8.5", - "smallvec", + "smallvec 1.10.0", "socket2", "tokio", "trust-dns-proto", @@ -5340,7 +5720,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ad8a64f29da86005c86a4d2728b8a0719e9b192f4092b609fd8790acb9dec55" dependencies = [ - "libp2p-core 0.38.0", + "libp2p-core", "libp2p-identify", "libp2p-kad", "libp2p-ping", @@ -5357,12 +5737,12 @@ dependencies = [ "asynchronous-codec", "bytes", "futures", - "libp2p-core 0.38.0", + "libp2p-core", "log", "nohash-hasher", "parking_lot 0.12.1", "rand 0.8.5", - "smallvec", + "smallvec 1.10.0", "unsigned-varint", ] @@ -5375,7 +5755,7 @@ dependencies = [ "bytes", "curve25519-dalek 3.2.0", "futures", - "libp2p-core 0.38.0", + "libp2p-core", "log", "once_cell", "prost", @@ -5398,7 +5778,7 @@ dependencies = [ "futures", "futures-timer", "instant", - "libp2p-core 0.38.0", + "libp2p-core", "libp2p-swarm", "log", "rand 0.8.5", @@ -5415,7 +5795,7 @@ dependencies = [ "futures", "futures-timer", "if-watch", - "libp2p-core 0.38.0", + "libp2p-core", "libp2p-tls", "log", "parking_lot 0.12.1", @@ -5436,11 +5816,11 @@ dependencies = [ "bytes", "futures", "instant", - "libp2p-core 0.38.0", + "libp2p-core", "libp2p-swarm", "log", "rand 0.8.5", - "smallvec", + "smallvec 1.10.0", "unsigned-varint", ] @@ -5455,12 +5835,12 @@ dependencies = [ "futures", "futures-timer", "instant", - "libp2p-core 0.38.0", + "libp2p-core", "libp2p-swarm-derive", "log", "pin-project", "rand 0.8.5", - "smallvec", + "smallvec 1.10.0", "thiserror", "tokio", "void", @@ -5487,7 +5867,7 @@ dependencies = [ "futures-timer", "if-watch", "libc", - "libp2p-core 0.38.0", + "libp2p-core", "log", "socket2", "tokio", @@ -5495,14 +5875,13 @@ dependencies = [ [[package]] name = "libp2p-tls" -version = "0.1.0" +version = "0.1.0-alpha" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff08d13d0dc66e5e9ba6279c1de417b84fa0d0adc3b03e5732928c180ec02781" +checksum = "f7905ce0d040576634e8a3229a7587cc8beab83f79db6023800f1792895defa8" dependencies = [ "futures", "futures-rustls", - "libp2p-core 0.39.2", - "libp2p-identity", + "libp2p-core", "rcgen 0.10.0", "ring", "rustls 0.20.8", @@ -5520,7 +5899,7 @@ checksum = "1bb1a35299860e0d4b3c02a3e74e3b293ad35ae0cee8a056363b0c862d082069" dependencies = [ "futures", "js-sys", - "libp2p-core 0.38.0", + "libp2p-core", "parity-send-wrapper", "wasm-bindgen", "wasm-bindgen-futures", @@ -5539,10 +5918,10 @@ dependencies = [ "futures-timer", "hex", "if-watch", - "libp2p-core 0.38.0", + "libp2p-core", "libp2p-noise", "log", - "multihash 0.16.3", + "multihash", "prost", "prost-build", "prost-codec", @@ -5566,7 +5945,7 @@ dependencies = [ "either", "futures", "futures-rustls", - "libp2p-core 0.38.0", + "libp2p-core", "log", "parking_lot 0.12.1", "quicksink", @@ -5583,7 +5962,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4f63594a0aa818642d9d4915c791945053877253f08a3626f13416b5cd928a29" dependencies = [ "futures", - "libp2p-core 0.38.0", + "libp2p-core", "log", "parking_lot 0.12.1", "thiserror", @@ -5666,9 +6045,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.9" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56ee889ecc9568871456d42f603d6a0ce59ff328d291063a45cbdf0036baf6db" +checksum = "9702761c3935f8cc2f101793272e202c72b99da8f4224a19ddcf1279a6450bbf" dependencies = [ "cc", "libc", @@ -5683,7 +6062,7 @@ dependencies = [ "anyhow", "async-trait", "derive_more", - "hash-db", + "hash-db 0.15.2", "ibc", "ibc-proto", "parity-scale-codec", @@ -5696,6 +6075,15 @@ dependencies = [ "subxt", ] +[[package]] +name = "link-cplusplus" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" +dependencies = [ + "cc", +] + [[package]] name = "linked-hash-map" version = "0.5.6" @@ -5713,19 +6101,18 @@ dependencies = [ [[package]] name = "linregress" -version = "0.4.4" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6c601a85f5ecd1aba625247bca0031585fb1c446461b142878a16f8245ddeb8" +checksum = "475015a7f8f017edb28d2e69813be23500ad4b32cfe3421c4148efc97324ee52" dependencies = [ "nalgebra", - "statrs", ] [[package]] name = "linux-raw-sys" -version = "0.0.46" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4d2456c373231a208ad294c33dc5bff30051eafd954cd4caae83a712b12854d" +checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" [[package]] name = "linux-raw-sys" @@ -5733,6 +6120,12 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" +[[package]] +name = "linux-raw-sys" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" + [[package]] name = "lock_api" version = "0.4.9" @@ -5791,7 +6184,7 @@ version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1" dependencies = [ - "regex-automata", + "regex-automata 0.1.10", ] [[package]] @@ -5800,7 +6193,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" dependencies = [ - "regex-automata", + "regex-automata 0.1.10", ] [[package]] @@ -5817,11 +6210,10 @@ checksum = "b87248edafb776e59e6ee64a79086f65890d3510f2c656c000bf2a7e8a0aea40" [[package]] name = "matrixmultiply" -version = "0.3.7" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "090126dc04f95dc0d1c1c91f61bdd474b3930ca064c1edc8a849da2c6cbe1e77" +checksum = "add85d4dd35074e6fedc608f8c8f513a3548619a9024b751949ef0e8e45a4d84" dependencies = [ - "autocfg", "rawpointer", ] @@ -5848,7 +6240,7 @@ version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6365506850d44bff6e2fbcb5176cf63650e48bd45ef2fe2665ae1570e0f4b9ca" dependencies = [ - "digest 0.10.7", + "digest 0.10.6", ] [[package]] @@ -5859,18 +6251,18 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memfd" -version = "0.6.3" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffc89ccdc6e10d6907450f753537ebc5c5d3460d2e4e62ea74bd571db62c0f9e" +checksum = "b20a59d985586e4a5aef64564ac77299f8586d8be6cf9106a5a40207e8908efb" dependencies = [ - "rustix 0.37.19", + "rustix 0.36.8", ] [[package]] name = "memmap2" -version = "0.5.10" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" +checksum = "4b182332558b18d807c4ce1ca8ca983b34c3ee32765e47b3f0f69b90355cc1dc" dependencies = [ "libc", ] @@ -5894,22 +6286,22 @@ dependencies = [ ] [[package]] -name = "memoffset" -version = "0.8.0" +name = "memory-db" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" +checksum = "5e0c7cba9ce19ac7ffd2053ac9f49843bbd3f4318feedfd74e85c19d5fb0ba66" dependencies = [ - "autocfg", + "hash-db 0.15.2", + "hashbrown 0.12.3", ] [[package]] name = "memory-db" -version = "0.31.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e0c7cba9ce19ac7ffd2053ac9f49843bbd3f4318feedfd74e85c19d5fb0ba66" +checksum = "808b50db46293432a45e63bc15ea51e0ab4c0a1647b8eb114e31a3e698dd6fbe" dependencies = [ - "hash-db", - "hashbrown 0.12.3", + "hash-db 0.16.0", ] [[package]] @@ -5930,11 +6322,17 @@ dependencies = [ "zeroize", ] +[[package]] +name = "micromath" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39617bc909d64b068dcffd0e3e31679195b5576d0c83fadc52690268cc2b2b55" + [[package]] name = "mime" -version = "0.3.17" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" [[package]] name = "minimal-lexical" @@ -5951,31 +6349,22 @@ dependencies = [ "adler", ] -[[package]] -name = "miniz_oxide" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" -dependencies = [ - "adler", -] - [[package]] name = "mio" -version = "0.8.6" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", "log", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] name = "mmr-gadget" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "futures", "log", @@ -5994,7 +6383,7 @@ dependencies = [ [[package]] name = "mmr-rpc" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "anyhow", "jsonrpsee", @@ -6009,9 +6398,9 @@ dependencies = [ [[package]] name = "mockall" -version = "0.11.4" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c84490118f2ee2d74570d114f3d0493cbf02790df303d2707606c3e14e07c96" +checksum = "50e4a1c770583dac7ab5e2f6c139153b783a53a1bbee9729613f193e59828326" dependencies = [ "cfg-if 1.0.0", "downcast", @@ -6024,9 +6413,9 @@ dependencies = [ [[package]] name = "mockall_derive" -version = "0.11.4" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ce75669015c4f47b289fd4d4f56e894e4c96003ffdf3ac51313126f94c6cbb" +checksum = "832663583d5fa284ca8810bf7015e46c9fff9622d3cf34bd1eea5003fec06dd0" dependencies = [ "cfg-if 1.0.0", "proc-macro2", @@ -6040,7 +6429,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "698fbc4b1fd2af323ed1711664a873b332faa4dc740e0f810f40210573ba36fd" dependencies = [ - "clap 3.2.25", + "clap 3.2.23", "clap_complete", "directories", "hex", @@ -6069,26 +6458,7 @@ dependencies = [ "byteorder", "data-encoding", "multibase", - "multihash 0.16.3", - "percent-encoding", - "serde", - "static_assertions", - "unsigned-varint", - "url", -] - -[[package]] -name = "multiaddr" -version = "0.17.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b36f567c7099511fa8612bbbb52dda2419ce0bdbacf31714e3a5ffdb766d3bd" -dependencies = [ - "arrayref", - "byteorder", - "data-encoding", - "log", - "multibase", - "multihash 0.17.0", + "multihash", "percent-encoding", "serde", "static_assertions", @@ -6114,23 +6484,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c346cf9999c631f002d8f977c4eaeaa0e6386f16007202308d0b3757522c2cc" dependencies = [ "core2", - "digest 0.10.7", + "digest 0.10.6", "multihash-derive", "sha2 0.10.6", "unsigned-varint", ] -[[package]] -name = "multihash" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "835d6ff01d610179fbce3de1694d007e500bf33a7f29689838941d6bf783ae40" -dependencies = [ - "core2", - "multihash-derive", - "unsigned-varint", -] - [[package]] name = "multihash-derive" version = "0.8.0" @@ -6161,15 +6520,15 @@ dependencies = [ "futures", "log", "pin-project", - "smallvec", + "smallvec 1.10.0", "unsigned-varint", ] [[package]] name = "nalgebra" -version = "0.27.1" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "462fffe4002f4f2e1f6a9dcf12cc1a6fc0e15989014efc02a941d3e0f5dc2120" +checksum = "d68d47bba83f9e2006d117a9a33af1524e655516b8919caac694427a6fb1e511" dependencies = [ "approx", "matrixmultiply", @@ -6177,17 +6536,15 @@ dependencies = [ "num-complex", "num-rational", "num-traits", - "rand 0.8.5", - "rand_distr", "simba", "typenum", ] [[package]] name = "nalgebra-macros" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01fcc0b8149b4632adc89ac3b7b31a12fb6099a0317a4eb2ebff574ef7de7218" +checksum = "d232c68884c0c99810a5a4d333ef7e47689cfd0edc85efc9e54e1e6bf5212766" dependencies = [ "proc-macro2", "quote", @@ -6213,7 +6570,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9ea4302b9759a7a88242299225ea3688e63c85ea136371bb6cf94fd674efaab" dependencies = [ "anyhow", - "bitflags", + "bitflags 1.3.2", "byteorder", "libc", "netlink-packet-core", @@ -6249,9 +6606,9 @@ dependencies = [ [[package]] name = "netlink-sys" -version = "0.8.5" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6471bf08e7ac0135876a9581bf3217ef0333c191c128d34878079f42ee150411" +checksum = "260e21fbb6f3d253a14df90eb0000a6066780a15dd901a7519ce02d77a94985b" dependencies = [ "bytes", "futures", @@ -6272,7 +6629,7 @@ version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cfg-if 1.0.0", "libc", "memoffset 0.6.5", @@ -6284,7 +6641,7 @@ version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cfg-if 1.0.0", "libc", "memoffset 0.7.1", @@ -6292,6 +6649,12 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "nodrop" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" + [[package]] name = "nohash-hasher" version = "0.2.0" @@ -6308,6 +6671,15 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "nom8" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8" +dependencies = [ + "memchr", +] + [[package]] name = "normalize-line-endings" version = "0.3.0" @@ -6326,9 +6698,9 @@ dependencies = [ [[package]] name = "num" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43db66d1170d347f9a065114077f7dccb00c1b9478c89384490a3425279a4606" +checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" dependencies = [ "num-bigint", "num-complex", @@ -6419,7 +6791,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ "autocfg", - "libm 0.2.7", + "libm 0.2.6", ] [[package]] @@ -6450,7 +6822,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.28", ] [[package]] @@ -6467,7 +6839,7 @@ checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" dependencies = [ "crc32fast", "hashbrown 0.12.3", - "indexmap", + "indexmap 1.9.2", "memchr", ] @@ -6500,9 +6872,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.17.1" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "opaque-debug" @@ -6549,9 +6921,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.87" +version = "0.9.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e17f59264b2809d77ae94f0e1ebabc434773f370d6ca667bd223ea10e06cc7e" +checksum = "866b5f16f90776b9bb8dc1e1802ac6f0513de3a7a7465867bfbc563dc737faac" dependencies = [ "cc", "libc", @@ -6559,6 +6931,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + [[package]] name = "ordered-float" version = "3.7.0" @@ -6571,7 +6949,7 @@ dependencies = [ [[package]] name = "orml-tokens" version = "0.4.1-dev" -source = "git+https://github.com/open-web3-stack/open-runtime-module-library?branch=polkadot-v0.9.38#241d5cdc98cca53b8cf990853943c9ae1193a70e" +source = "git+https://github.com/open-web3-stack/open-runtime-module-library?branch=polkadot-v0.9.39#a0751540591c88ccc2d4029464de887933727183" dependencies = [ "frame-support", "frame-system", @@ -6586,7 +6964,7 @@ dependencies = [ [[package]] name = "orml-traits" version = "0.4.1-dev" -source = "git+https://github.com/open-web3-stack/open-runtime-module-library?branch=polkadot-v0.9.38#241d5cdc98cca53b8cf990853943c9ae1193a70e" +source = "git+https://github.com/open-web3-stack/open-runtime-module-library?branch=polkadot-v0.9.39#a0751540591c88ccc2d4029464de887933727183" dependencies = [ "frame-support", "impl-trait-for-tuples", @@ -6605,7 +6983,7 @@ dependencies = [ [[package]] name = "orml-utilities" version = "0.4.1-dev" -source = "git+https://github.com/open-web3-stack/open-runtime-module-library?branch=polkadot-v0.9.38#241d5cdc98cca53b8cf990853943c9ae1193a70e" +source = "git+https://github.com/open-web3-stack/open-runtime-module-library?branch=polkadot-v0.9.39#a0751540591c88ccc2d4029464de887933727183" dependencies = [ "frame-support", "parity-scale-codec", @@ -6618,9 +6996,9 @@ dependencies = [ [[package]] name = "os_str_bytes" -version = "6.5.0" +version = "6.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ceedf44fb00f2d1984b0bc98102627ce622e083e49a5bacdb3e514fa4238e267" +checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" [[package]] name = "overload" @@ -6663,7 +7041,7 @@ dependencies = [ [[package]] name = "pallet-assets" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-benchmarking", "frame-support", @@ -6675,11 +7053,42 @@ dependencies = [ "sp-std 5.0.0", ] +[[package]] +name = "pallet-aura" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +dependencies = [ + "frame-support", + "frame-system", + "pallet-timestamp", + "parity-scale-codec", + "scale-info", + "sp-application-crypto 7.0.0", + "sp-consensus-aura", + "sp-runtime 7.0.0", + "sp-std 5.0.0", +] + +[[package]] +name = "pallet-authorship" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +dependencies = [ + "frame-support", + "frame-system", + "impl-trait-for-tuples", + "parity-scale-codec", + "scale-info", + "sp-runtime 7.0.0", + "sp-std 5.0.0", +] + [[package]] name = "pallet-balances" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ + "frame-benchmarking", "frame-support", "frame-system", "log", @@ -6692,26 +7101,29 @@ dependencies = [ [[package]] name = "pallet-beefy" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-support", "frame-system", + "pallet-authorship", "pallet-session", "parity-scale-codec", "scale-info", "serde", "sp-beefy", "sp-runtime 7.0.0", + "sp-session", + "sp-staking", "sp-std 5.0.0", ] [[package]] name = "pallet-beefy-mmr" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "array-bytes", - "beefy-merkle-tree", + "binary-merkle-tree", "frame-support", "frame-system", "log", @@ -6721,6 +7133,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", + "sp-api", "sp-beefy", "sp-core 7.0.0", "sp-io 7.0.0", @@ -6736,6 +7149,7 @@ dependencies = [ "chrono", "cumulus-primitives-core", "derive_more", + "env_logger 0.10.0", "finality-grandpa", "frame-benchmarking", "frame-support", @@ -6748,6 +7162,7 @@ dependencies = [ "ibc-primitives", "ibc-proto", "ics07-tendermint", + "ics08-wasm", "ics10-grandpa", "ics11-beefy", "ics23", @@ -6756,8 +7171,10 @@ dependencies = [ "orml-tokens", "orml-traits", "pallet-assets", + "pallet-aura", "pallet-balances", "pallet-ibc-ping", + "pallet-membership", "pallet-timestamp", "parachain-info", "parity-scale-codec", @@ -6767,6 +7184,8 @@ dependencies = [ "serde_json", "sha2 0.10.6", "simple-iavl", + "sp-consensus-aura", + "sp-consensus-slots", "sp-core 7.0.0", "sp-finality-grandpa", "sp-io 7.0.0", @@ -6797,10 +7216,27 @@ dependencies = [ "sp-std 5.0.0", ] +[[package]] +name = "pallet-membership" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-core 7.0.0", + "sp-io 7.0.0", + "sp-runtime 7.0.0", + "sp-std 5.0.0", +] + [[package]] name = "pallet-mmr" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-benchmarking", "frame-support", @@ -6817,7 +7253,7 @@ dependencies = [ [[package]] name = "pallet-session" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-support", "frame-system", @@ -6838,7 +7274,7 @@ dependencies = [ [[package]] name = "pallet-timestamp" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-benchmarking", "frame-support", @@ -6856,7 +7292,7 @@ dependencies = [ [[package]] name = "pallet-transaction-payment" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-support", "frame-system", @@ -6872,7 +7308,7 @@ dependencies = [ [[package]] name = "pallet-transaction-payment-rpc" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "jsonrpsee", "pallet-transaction-payment-rpc-runtime-api", @@ -6888,7 +7324,7 @@ dependencies = [ [[package]] name = "pallet-transaction-payment-rpc-runtime-api" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "pallet-transaction-payment", "parity-scale-codec", @@ -6900,7 +7336,7 @@ dependencies = [ [[package]] name = "parachain-info" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.38#9b4e0247137f158d1a35118197d34adfa58858b7" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" dependencies = [ "cumulus-primitives-core", "frame-support", @@ -6950,9 +7386,9 @@ checksum = "e1ad0aff30c1da14b1254fcb2af73e1fa9a28670e584a626f53a369d0e157304" [[package]] name = "parking" -version = "2.1.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14f2252c834a40ed9bb5422029649578e63aa341ac401f74e719dd1afda8394e" +checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" [[package]] name = "parking_lot" @@ -6985,7 +7421,7 @@ dependencies = [ "instant", "libc", "redox_syscall 0.2.16", - "smallvec", + "smallvec 1.10.0", "winapi", ] @@ -6998,7 +7434,7 @@ dependencies = [ "cfg-if 1.0.0", "libc", "redox_syscall 0.2.16", - "smallvec", + "smallvec 1.10.0", "windows-sys 0.45.0", ] @@ -7015,9 +7451,9 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.12" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" +checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba" [[package]] name = "path-slash" @@ -7040,7 +7476,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" dependencies = [ - "digest 0.10.7", + "digest 0.10.6", "hmac 0.12.1", "password-hash", "sha2 0.10.6", @@ -7052,31 +7488,31 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0ca0b5a68607598bf3bad68f32227a8164f6254833f84eafaac409cd6746c31" dependencies = [ - "digest 0.10.7", + "digest 0.10.6", "hmac 0.12.1", ] [[package]] name = "pear" -version = "0.2.4" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ec95680a7087503575284e5063e14b694b7a9c0b065e5dceec661e0497127e8" +checksum = "61a386cd715229d399604b50d1361683fe687066f42d56f54be995bc6868f71c" dependencies = [ "inlinable_string", "pear_codegen", - "yansi", + "yansi 1.0.0-rc", ] [[package]] name = "pear_codegen" -version = "0.2.4" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9661a3a53f93f09f2ea882018e4d7c88f6ff2956d809a276060476fd8c879d3c" +checksum = "da9f0f13dac8069c139e8300a6510e3f4143ecf5259c60b116a9b271b4ca0d54" dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.16", + "syn 2.0.28", ] [[package]] @@ -7146,7 +7582,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" dependencies = [ "fixedbitset", - "indexmap", + "indexmap 1.9.2", ] [[package]] @@ -7161,35 +7597,35 @@ dependencies = [ [[package]] name = "phf" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "928c6535de93548188ef63bb7c4036bd415cd8f36ad25af44b9789b2ee72a48c" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ "phf_macros", - "phf_shared 0.11.1", + "phf_shared 0.11.2", ] [[package]] name = "phf_generator" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1181c94580fa345f50f19d738aaa39c0ed30a600d95cb2d3e23f94266f14fbf" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" dependencies = [ - "phf_shared 0.11.1", + "phf_shared 0.11.2", "rand 0.8.5", ] [[package]] name = "phf_macros" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92aacdc5f16768709a569e913f7451034034178b05bdc8acda226659a3dccc66" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" dependencies = [ "phf_generator", - "phf_shared 0.11.1", + "phf_shared 0.11.2", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.28", ] [[package]] @@ -7203,31 +7639,31 @@ dependencies = [ [[package]] name = "phf_shared" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1fb5f6f826b772a8d4c0394209441e7d37cbbb967ae9c7e0e8134365c9ee676" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" dependencies = [ "siphasher", ] [[package]] name = "pin-project" -version = "1.1.0" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c95a7476719eab1e366eaf73d0260af3021184f18177925b07f54b30089ceead" +checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.0" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07" +checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.28", ] [[package]] @@ -7264,15 +7700,15 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ - "der 0.7.6", + "der 0.7.8", "spki 0.7.2", ] [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" [[package]] name = "platforms" @@ -7282,8 +7718,8 @@ checksum = "e3d7ddaed09e0eb771a79ab0fd64609ba0afb0a8366421957936ad14cbd13630" [[package]] name = "polkadot-core-primitives" -version = "0.9.38" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.38#097ffd245c42aeff28cf80f8a3568e1bee2e7da7" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "parity-scale-codec", "scale-info", @@ -7294,9 +7730,10 @@ dependencies = [ [[package]] name = "polkadot-parachain" -version = "0.9.38" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.38#097ffd245c42aeff28cf80f8a3568e1bee2e7da7" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ + "bounded-collections", "derive_more", "frame-support", "parity-scale-codec", @@ -7310,8 +7747,8 @@ dependencies = [ [[package]] name = "polkadot-primitives" -version = "0.9.38" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.38#097ffd245c42aeff28cf80f8a3568e1bee2e7da7" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "bitvec 1.0.1", "hex-literal 0.3.4", @@ -7336,18 +7773,16 @@ dependencies = [ [[package]] name = "polling" -version = "2.8.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" +checksum = "22122d5ec4f9fe1b3916419b76be1e80bcb93f618d071d2edf841b137b2a2bd6" dependencies = [ "autocfg", - "bitflags", "cfg-if 1.0.0", - "concurrent-queue", "libc", "log", - "pin-project-lite 0.2.9", - "windows-sys 0.48.0", + "wepoll-ffi", + "windows-sys 0.42.0", ] [[package]] @@ -7382,7 +7817,7 @@ dependencies = [ "cfg-if 1.0.0", "cpufeatures", "opaque-debug 0.3.0", - "universal-hash 0.5.1", + "universal-hash 0.5.0", ] [[package]] @@ -7413,15 +7848,15 @@ dependencies = [ [[package]] name = "predicates-core" -version = "1.0.6" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174" +checksum = "72f883590242d3c6fc5bf50299011695fa6590c2c70eac95ee1bdb9a733ad1a2" [[package]] name = "predicates-tree" -version = "1.0.9" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368ba315fb8c5052ab692e68a0eefec6ec57b23a36959c14496f0b0df2c0cecf" +checksum = "54ff541861505aabf6ea722d2131ee980b8276e10a1297b94e896dd8b621850d" dependencies = [ "predicates-core", "termtree", @@ -7429,9 +7864,9 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.1.25" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86" +checksum = "e97e3215779627f01ee256d2fad52f3d95e8e1c11e9fc6fd08f7cd455d5d5c78" dependencies = [ "proc-macro2", "syn 1.0.109", @@ -7439,12 +7874,12 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.6" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b69d39aab54d069e7f2fe8cb970493e7834601ca2d8c65fd7bbd183578080d1" +checksum = "6c64d9ba0963cdcea2e1b2230fbae2bab30eb25a174be395c41e764bfb65dd62" dependencies = [ "proc-macro2", - "syn 2.0.16", + "syn 2.0.28", ] [[package]] @@ -7463,12 +7898,12 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "1.3.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +checksum = "66618389e4ec1c7afe67d51a9bf34ff9236480f8d51e7489b7d5ab0303c13f34" dependencies = [ "once_cell", - "toml_edit", + "toml_edit 0.18.1", ] [[package]] @@ -7506,15 +7941,15 @@ dependencies = [ [[package]] name = "proc-macro2-diagnostics" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "606c4ba35817e2922a308af55ad51bab3645b59eae5c570d4a6cf07e36bd493b" +checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.28", "version_check", - "yansi", + "yansi 1.0.0-rc", ] [[package]] @@ -7556,19 +7991,20 @@ dependencies = [ [[package]] name = "proptest" -version = "1.2.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e35c06b98bf36aba164cc17cb25f7e232f5c4aeea73baa14b8a9f0d92dbfa65" +checksum = "29f1b898011ce9595050a68e60f90bad083ff2987a695a42357134c8381fba70" dependencies = [ "bit-set", - "bitflags", + "bitflags 1.3.2", "byteorder", "lazy_static", "num-traits", + "quick-error 2.0.1", "rand 0.8.5", "rand_chacha 0.3.1", "rand_xorshift", - "regex-syntax 0.6.29", + "regex-syntax 0.6.28", "rusty-fork", "tempfile", "unarray", @@ -7576,9 +8012,9 @@ dependencies = [ [[package]] name = "prost" -version = "0.11.9" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" +checksum = "21dc42e00223fc37204bd4aa177e69420c604ca4a183209a8f9de30c6d934698" dependencies = [ "bytes", "prost-derive", @@ -7586,9 +8022,9 @@ dependencies = [ [[package]] name = "prost-build" -version = "0.11.9" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270" +checksum = "a3f8ad728fb08fe212df3c05169e940fbb6d9d16a877ddde14644a983ba2012e" dependencies = [ "bytes", "heck", @@ -7597,7 +8033,7 @@ dependencies = [ "log", "multimap", "petgraph", - "prettyplease 0.1.25", + "prettyplease 0.1.23", "prost", "prost-types", "regex", @@ -7621,9 +8057,9 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.11.9" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" +checksum = "8bda8c0881ea9f722eb9629376db3d0b903b462477c1aafcb0566610ac28ac5d" dependencies = [ "anyhow", "itertools", @@ -7634,18 +8070,33 @@ dependencies = [ [[package]] name = "prost-types" -version = "0.11.9" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13" +checksum = "a5e0526209433e96d83d750dd81a99118edbc55739e7e61a46764fd2ad537788" dependencies = [ + "bytes", "prost", ] [[package]] name = "protobuf" -version = "2.28.0" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b55bad9126f378a853655831eb7363b7b01b81d19f8cb1218861086ca4a1a61e" +dependencies = [ + "once_cell", + "protobuf-support", + "thiserror", +] + +[[package]] +name = "protobuf-support" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" +checksum = "a5d4d7b8601c814cfb36bcebb79f0e61e45e1e93640cf778837833bbed05c372" +dependencies = [ + "thiserror", +] [[package]] name = "psm" @@ -7663,12 +8114,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] -name = "quick-protobuf" -version = "0.8.1" +name = "quick-error" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d6da84cc204722a989e01ba2f6e1e276e190f22263d0cb6ce8526fcdb0d2e1f" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + +[[package]] +name = "quick_cache" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5253a3a0d56548d5b0be25414171dc780cc6870727746d05bd2bde352eee96c5" dependencies = [ - "byteorder", + "ahash 0.8.3", + "hashbrown 0.13.2", + "parking_lot 0.12.1", ] [[package]] @@ -7702,9 +8161,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.27" +version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500" +checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" dependencies = [ "proc-macro2", ] @@ -7780,17 +8239,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.9", -] - -[[package]] -name = "rand_distr" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" -dependencies = [ - "num-traits", - "rand 0.8.5", + "getrandom 0.2.8", ] [[package]] @@ -7833,9 +8282,9 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" dependencies = [ - "crossbeam-channel 0.5.8", + "crossbeam-channel 0.5.6", "crossbeam-deque", - "crossbeam-utils 0.8.15", + "crossbeam-utils 0.8.14", "num_cpus", ] @@ -7847,7 +8296,7 @@ checksum = "6413f3de1edee53342e6138e75b56d32e7bc6e332b3bd62d497b1929d4cfbcdd" dependencies = [ "pem", "ring", - "time 0.3.21", + "time 0.3.17", "x509-parser 0.13.2", "yasna", ] @@ -7860,7 +8309,7 @@ checksum = "ffbe84efe2f38dea12e9bfc1f65377fdf03e53a18cb3b995faedf7934c7e785b" dependencies = [ "pem", "ring", - "time 0.3.21", + "time 0.3.17", "yasna", ] @@ -7870,7 +8319,7 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -7879,7 +8328,7 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -7888,52 +8337,53 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ - "getrandom 0.2.9", + "getrandom 0.2.8", "redox_syscall 0.2.16", "thiserror", ] [[package]] name = "ref-cast" -version = "1.0.16" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43faa91b1c8b36841ee70e97188a869d37ae21759da6846d4be66de5bf7b12c" +checksum = "8c78fb8c9293bcd48ef6fce7b4ca950ceaf21210de6e105a883ee280c0f7b9ed" dependencies = [ "ref-cast-impl", ] [[package]] name = "ref-cast-impl" -version = "1.0.16" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d2275aab483050ab2a7364c1a46604865ee7d6906684e08db0f090acf74f9e7" +checksum = "9f9c0c92af03644e4806106281fe2e068ac5bc0ae74a707266d06ea27bccee5f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 1.0.109", ] [[package]] name = "regalloc2" -version = "0.3.2" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d43a209257d978ef079f3d446331d0f1794f5e0fc19b306a199983857833a779" +checksum = "300d4fbfb40c1c66a78ba3ddd41c1110247cf52f97b87d0f2fc9209bd49b030c" dependencies = [ "fxhash", "log", "slice-group-by", - "smallvec", + "smallvec 1.10.0", ] [[package]] name = "regex" -version = "1.8.2" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1a59b5d8e97dee33696bf13c5ba8ab85341c002922fba050069326b9c498974" +checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a" dependencies = [ - "aho-corasick 1.0.1", + "aho-corasick 1.0.2", "memchr", - "regex-syntax 0.7.2", + "regex-automata 0.3.6", + "regex-syntax 0.7.4", ] [[package]] @@ -7942,20 +8392,43 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" dependencies = [ - "regex-syntax 0.6.29", + "regex-syntax 0.6.28", +] + +[[package]] +name = "regex-automata" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69" +dependencies = [ + "aho-corasick 1.0.2", + "memchr", + "regex-syntax 0.7.4", ] [[package]] name = "regex-syntax" -version = "0.6.29" +version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" [[package]] name = "regex-syntax" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" +checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" + +[[package]] +name = "region" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76e189c2369884dce920945e2ddf79b3dff49e071a167dd1817fa9c4c00d512e" +dependencies = [ + "bitflags 1.3.2", + "libc", + "mach", + "winapi", +] [[package]] name = "reqwest" @@ -7963,7 +8436,7 @@ version = "0.11.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" dependencies = [ - "base64 0.21.1", + "base64 0.21.0", "bytes", "encoding_rs", "futures-core", @@ -7972,7 +8445,7 @@ dependencies = [ "http", "http-body", "hyper", - "hyper-rustls 0.24.0", + "hyper-rustls 0.24.1", "ipnet", "js-sys", "log", @@ -7980,13 +8453,13 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite 0.2.9", - "rustls 0.21.1", + "rustls 0.21.6", "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", "tokio", - "tokio-rustls 0.24.0", + "tokio-rustls 0.24.1", "tower-service", "url", "wasm-bindgen", @@ -8003,7 +8476,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" dependencies = [ "hostname", - "quick-error", + "quick-error 1.2.3", ] [[package]] @@ -8112,7 +8585,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" dependencies = [ - "digest 0.10.7", + "digest 0.10.6", ] [[package]] @@ -8139,10 +8612,11 @@ dependencies = [ [[package]] name = "rs_merkle" -version = "1.4.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05225752ca6ede4cb1b73aa37ce3904affd042e98f28246f56f438ebfd47a810" +checksum = "a632a43487c1332be8e183588079f89b6820fab24e04db49521eacd536837372" dependencies = [ + "micromath", "sha2 0.10.6", ] @@ -8188,24 +8662,22 @@ dependencies = [ [[package]] name = "ruint" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d470e29e933dac4101180fd6574971892315c414cf2961a192729089687cc9b" +checksum = "77e1574d439643c8962edf612a888e7cc5581bcdf36cb64e6bc88466b03b2daa" dependencies = [ - "derive_more", "primitive-types", "rlp", "ruint-macro", - "rustc_version", "serde", "thiserror", ] [[package]] name = "ruint-macro" -version = "1.0.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62cc5760263ea229d367e7dff3c0cbf09e4797a125bd87059a6c095804f3b2d1" +checksum = "e666a5496a0b2186dbcd0ff6106e29e093c15591bde62c20d3842007c6978a09" [[package]] name = "rusb" @@ -8302,9 +8774,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" [[package]] name = "rustc-hash" @@ -8338,29 +8810,42 @@ dependencies = [ [[package]] name = "rustix" -version = "0.35.13" +version = "0.36.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "727a1a6d65f786ec22df8a81ca3121107f235970dc1705ed681d3e6e8b9cd5f9" +checksum = "f43abb88211988493c1abb44a70efa56ff0ce98f233b7b276146f1f3f7ba9644" dependencies = [ - "bitflags", + "bitflags 1.3.2", "errno 0.2.8", - "io-lifetimes 0.7.5", + "io-lifetimes", "libc", - "linux-raw-sys 0.0.46", - "windows-sys 0.42.0", + "linux-raw-sys 0.1.4", + "windows-sys 0.45.0", ] [[package]] name = "rustix" -version = "0.37.19" +version = "0.37.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d" +checksum = "2aae838e49b3d63e9274e1c01833cc8139d3fec468c3b84688c628f44b1ae11d" dependencies = [ - "bitflags", - "errno 0.3.1", - "io-lifetimes 1.0.10", + "bitflags 1.3.2", + "errno 0.3.2", + "io-lifetimes", "libc", "linux-raw-sys 0.3.8", + "windows-sys 0.45.0", +] + +[[package]] +name = "rustix" +version = "0.38.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "172891ebdceb05aa0005f533a6cbfca599ddd7d966f6f5d4d9b2e70478e70399" +dependencies = [ + "bitflags 2.3.3", + "errno 0.3.2", + "libc", + "linux-raw-sys 0.4.5", "windows-sys 0.48.0", ] @@ -8391,13 +8876,13 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.1" +version = "0.21.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c911ba11bc8433e811ce56fde130ccf32f5127cab0e0194e9c68c5a5b671791e" +checksum = "1d1feddffcfcc0b33f5c6ce9a29e341e4cd59c3f78e7ee45f4a40c038b1d6cbb" dependencies = [ "log", "ring", - "rustls-webpki", + "rustls-webpki 0.101.3", "sct 0.7.0", ] @@ -8431,7 +8916,7 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b" dependencies = [ - "base64 0.21.1", + "base64 0.21.0", ] [[package]] @@ -8444,11 +8929,21 @@ dependencies = [ "untrusted", ] +[[package]] +name = "rustls-webpki" +version = "0.101.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "261e9e0888cba427c3316e6322805653c9425240b6fd96cee7cb671ab70ab8d0" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "rustversion" -version = "1.0.12" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06" +checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70" [[package]] name = "rusty-fork" @@ -8457,7 +8952,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" dependencies = [ "fnv", - "quick-error", + "quick-error 1.2.3", "tempfile", "wait-timeout", ] @@ -8475,9 +8970,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" [[package]] name = "safe-proc-macro2" @@ -8526,6 +9021,15 @@ dependencies = [ "safe-regex-compiler", ] +[[package]] +name = "safe_arch" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "794821e4ccb0d9f979512f9c1973480123f9bd62a90d74ab0f9426fcf8f4a529" +dependencies = [ + "bytemuck", +] + [[package]] name = "salsa20" version = "0.10.2" @@ -8547,7 +9051,7 @@ dependencies = [ [[package]] name = "sc-allocator" version = "4.1.0-dev" -source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "log", "sp-core 7.0.0", @@ -8558,7 +9062,7 @@ dependencies = [ [[package]] name = "sc-block-builder" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "parity-scale-codec", "sc-client-api", @@ -8574,7 +9078,7 @@ dependencies = [ [[package]] name = "sc-chain-spec" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "memmap2", "sc-chain-spec-derive", @@ -8589,7 +9093,7 @@ dependencies = [ [[package]] name = "sc-chain-spec-derive" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -8600,7 +9104,7 @@ dependencies = [ [[package]] name = "sc-client-api" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "fnv", "futures", @@ -8626,7 +9130,7 @@ dependencies = [ [[package]] name = "sc-consensus" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "async-trait", "futures", @@ -8651,7 +9155,7 @@ dependencies = [ [[package]] name = "sc-executor" version = "0.10.0-dev" -source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "lru", "parity-scale-codec", @@ -8675,10 +9179,10 @@ dependencies = [ [[package]] name = "sc-executor-common" version = "0.10.0-dev" -source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "sc-allocator", - "sp-maybe-compressed-blob 4.1.0-dev (git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.38)", + "sp-maybe-compressed-blob", "sp-wasm-interface 7.0.0", "thiserror", "wasm-instrument", @@ -8688,7 +9192,7 @@ dependencies = [ [[package]] name = "sc-executor-wasmi" version = "0.10.0-dev" -source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "log", "sc-allocator", @@ -8701,13 +9205,14 @@ dependencies = [ [[package]] name = "sc-executor-wasmtime" version = "0.10.0-dev" -source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ + "anyhow", "cfg-if 1.0.0", "libc", "log", "once_cell", - "rustix 0.35.13", + "rustix 0.36.8", "sc-allocator", "sc-executor-common", "sp-runtime-interface 7.0.0", @@ -8718,7 +9223,7 @@ dependencies = [ [[package]] name = "sc-finality-grandpa" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "ahash 0.8.3", "array-bytes", @@ -8758,7 +9263,7 @@ dependencies = [ [[package]] name = "sc-finality-grandpa-rpc" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "finality-grandpa", "futures", @@ -8778,7 +9283,7 @@ dependencies = [ [[package]] name = "sc-keystore" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "array-bytes", "async-trait", @@ -8793,7 +9298,7 @@ dependencies = [ [[package]] name = "sc-network" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "array-bytes", "async-trait", @@ -8808,6 +9313,7 @@ dependencies = [ "libp2p", "log", "lru", + "mockall", "parity-scale-codec", "parking_lot 0.12.1", "pin-project", @@ -8820,7 +9326,7 @@ dependencies = [ "sc-utils", "serde", "serde_json", - "smallvec", + "smallvec 1.10.0", "sp-arithmetic 6.0.0", "sp-blockchain", "sp-consensus", @@ -8835,10 +9341,10 @@ dependencies = [ [[package]] name = "sc-network-common" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "async-trait", - "bitflags", + "bitflags 1.3.2", "bytes", "futures", "futures-timer", @@ -8849,7 +9355,7 @@ dependencies = [ "sc-consensus", "sc-peerset", "serde", - "smallvec", + "smallvec 1.10.0", "sp-blockchain", "sp-consensus", "sp-finality-grandpa", @@ -8861,7 +9367,7 @@ dependencies = [ [[package]] name = "sc-network-gossip" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "ahash 0.8.3", "futures", @@ -8879,7 +9385,7 @@ dependencies = [ [[package]] name = "sc-offchain" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "array-bytes", "bytes", @@ -8909,7 +9415,7 @@ dependencies = [ [[package]] name = "sc-peerset" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "futures", "libp2p", @@ -8922,7 +9428,7 @@ dependencies = [ [[package]] name = "sc-rpc" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "futures", "jsonrpsee", @@ -8952,7 +9458,7 @@ dependencies = [ [[package]] name = "sc-rpc-api" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "jsonrpsee", "parity-scale-codec", @@ -8971,7 +9477,7 @@ dependencies = [ [[package]] name = "sc-rpc-server" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "http", "jsonrpsee", @@ -8986,7 +9492,7 @@ dependencies = [ [[package]] name = "sc-telemetry" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "chrono", "futures", @@ -9005,7 +9511,7 @@ dependencies = [ [[package]] name = "sc-tracing" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "ansi_term", "atty", @@ -9036,7 +9542,7 @@ dependencies = [ [[package]] name = "sc-tracing-proc-macro" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -9047,7 +9553,7 @@ dependencies = [ [[package]] name = "sc-transaction-pool-api" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "async-trait", "futures", @@ -9061,7 +9567,7 @@ dependencies = [ [[package]] name = "sc-utils" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "backtrace", "futures", @@ -9085,21 +9591,63 @@ dependencies = [ [[package]] name = "scale-decode" -version = "0.4.0" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7e5527e4b3bf079d4c0b2f253418598c380722ba37ef20fac9088081407f2b6" +dependencies = [ + "parity-scale-codec", + "primitive-types", + "scale-bits", + "scale-decode-derive", + "scale-info", + "thiserror", +] + +[[package]] +name = "scale-decode-derive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b38741b2f78e4391b94eac6b102af0f6ea2b0f7fe65adb55d7f4004f507854db" +dependencies = [ + "darling", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "scale-encode" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d823d4be477fc33321f93d08fb6c2698273d044f01362dc27573a750deb7c233" +checksum = "15546e5efbb45f0fc2291f7e202dee8623274c5d8bbfdf9c6886cc8b44a7ced3" dependencies = [ "parity-scale-codec", + "primitive-types", "scale-bits", + "scale-encode-derive", "scale-info", "thiserror", ] +[[package]] +name = "scale-encode-derive" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd983cf0a9effd76138554ead18a6de542d1af175ac12fd5e91836c5c0268082" +dependencies = [ + "darling", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "scale-info" -version = "2.7.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b569c32c806ec3abdf3b5869fb8bf1e0d275a7c1c9b0b05603d9464632649edf" +checksum = "dfdef77228a4c05dc94211441595746732131ad7f6530c6c18f045da7b7ab937" dependencies = [ "bitvec 1.0.1", "cfg-if 1.0.0", @@ -9123,15 +9671,16 @@ dependencies = [ [[package]] name = "scale-value" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16a5e7810815bd295da73e4216d1dfbced3c7c7c7054d70fa5f6e4c58123fff4" +checksum = "11f549769261561e6764218f847e500588f9a79a289de49ce92f9e26642a3574" dependencies = [ "either", "frame-metadata", "parity-scale-codec", "scale-bits", "scale-decode", + "scale-encode", "scale-info", "serde", "thiserror", @@ -9149,9 +9698,9 @@ dependencies = [ [[package]] name = "schemars" -version = "0.8.12" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02c613288622e5f0c3fdc5dbd4db1c5fbe752746b1d1a56a0630b78fd00de44f" +checksum = "2a5fb6c61f29e723026dc8e923d94c694313212abbecbbe5f55a7748eec5b307" dependencies = [ "dyn-clone", "schemars_derive", @@ -9161,9 +9710,9 @@ dependencies = [ [[package]] name = "schemars_derive" -version = "0.8.12" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "109da1e6b197438deb6db99952990c7f959572794b80ff93707d55a232545e7c" +checksum = "f188d036977451159430f3b8dc82ec76364a42b7e289c2b18a9a18f4470058e9" dependencies = [ "proc-macro2", "quote", @@ -9206,6 +9755,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "scratch" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2" + [[package]] name = "scrypt" version = "0.10.0" @@ -9266,12 +9821,12 @@ dependencies = [ [[package]] name = "sec1" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0aec48e813d6b90b15f0b8948af3c63483992dee44c03e9930b3eebdabe046e" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ "base16ct 0.2.0", - "der 0.7.6", + "der 0.7.8", "generic-array 0.14.7", "pkcs8 0.10.2", "subtle", @@ -9307,11 +9862,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.9.1" +version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8" +checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation", "core-foundation-sys", "libc", @@ -9320,9 +9875,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7" +checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4" dependencies = [ "core-foundation-sys", "libc", @@ -9330,9 +9885,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.17" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" +checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" dependencies = [ "serde", ] @@ -9351,13 +9906,24 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.163" +version = "1.0.164" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2" +checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d" dependencies = [ "serde_derive", ] +[[package]] +name = "serde-hex" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca37e3e4d1b39afd7ff11ee4e947efae85adfddf4841787bfa47c470e96dc26d" +dependencies = [ + "array-init", + "serde", + "smallvec 0.6.14", +] + [[package]] name = "serde_bytes" version = "0.11.9" @@ -9379,13 +9945,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.163" +version = "1.0.164" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" +checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.28", ] [[package]] @@ -9405,7 +9971,7 @@ version = "1.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" dependencies = [ - "indexmap", + "indexmap 1.9.2", "itoa", "ryu", "serde", @@ -9423,20 +9989,20 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.12" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcec881020c684085e55a25f7fd888954d56609ef363479dc5a1305eb0d40cab" +checksum = "9a5ec9fa74a20ebbe5d9ac23dac1fc96ba0ecfe9f50f2843b52e537b10fbcb4e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 1.0.109", ] [[package]] name = "serde_spanned" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93107647184f6027e3b7dcb2e11034cf95ffa1e3a682c67951963ac69c1c007d" +checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" dependencies = [ "serde", ] @@ -9474,7 +10040,7 @@ checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.7", + "digest 0.10.6", ] [[package]] @@ -9485,7 +10051,7 @@ checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.7", + "digest 0.10.6", ] [[package]] @@ -9521,7 +10087,7 @@ checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.7", + "digest 0.10.6", ] [[package]] @@ -9530,7 +10096,7 @@ version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" dependencies = [ - "digest 0.10.7", + "digest 0.10.6", "keccak", ] @@ -9551,9 +10117,9 @@ checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" [[package]] name = "signal-hook" -version = "0.3.15" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "732768f1176d21d09e076c23a93123d40bba92d50c4058da34d45c8de8e682b9" +checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" dependencies = [ "libc", "signal-hook-registry", @@ -9572,9 +10138,9 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" dependencies = [ "libc", ] @@ -9585,7 +10151,7 @@ version = "1.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" dependencies = [ - "digest 0.10.7", + "digest 0.10.6", "rand_core 0.6.4", ] @@ -9595,20 +10161,21 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" dependencies = [ - "digest 0.10.7", + "digest 0.10.6", "rand_core 0.6.4", ] [[package]] name = "simba" -version = "0.5.1" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e82063457853d00243beda9952e910b82593e4b07ae9f721b9278a99a0d3d5c" +checksum = "061507c94fc6ab4ba1c9a0305018408e312e17c041eb63bef8aa726fa33aceae" dependencies = [ "approx", "num-complex", "num-traits", "paste", + "wide", ] [[package]] @@ -9624,11 +10191,23 @@ dependencies = [ "bytes", "ics23", "proptest", - "rand 0.8.5", + "rand 0.7.3", "sha2 0.10.6", "tendermint", ] +[[package]] +name = "simple_asn1" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085" +dependencies = [ + "num-bigint", + "num-traits", + "thiserror", + "time 0.3.17", +] + [[package]] name = "siphasher" version = "0.3.10" @@ -9637,18 +10216,27 @@ checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" [[package]] name = "slab" -version = "0.4.8" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" dependencies = [ "autocfg", ] [[package]] name = "slice-group-by" -version = "0.3.1" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03b634d87b960ab1a38c4fe143b508576f075e7c978bfad18217645ebfdfa2ec" + +[[package]] +name = "smallvec" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7" +checksum = "b97fcaeba89edba30f044a10c6a3cc39df9c3f17d7cd829dd1446cab35f890e0" +dependencies = [ + "maybe-uninit", +] [[package]] name = "smallvec" @@ -9658,14 +10246,14 @@ checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "snow" -version = "0.9.2" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ccba027ba85743e09d15c03296797cad56395089b832b48b5a5217880f57733" +checksum = "12ba5f4d4ff12bdb6a169ed51b7c48c0e0ac4b0b4b31012b2571e97d78d3201d" dependencies = [ "aes-gcm 0.9.4", "blake2", "chacha20poly1305", - "curve25519-dalek 4.0.0-rc.1", + "curve25519-dalek 4.0.0-rc.0", "rand_core 0.6.4", "ring", "rustc_version", @@ -9702,9 +10290,9 @@ dependencies = [ [[package]] name = "solang-parser" -version = "0.2.4" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c5ead679f39243782be98c2689e592fc0fc9489ca2e47c9e027bd30f948df31" +checksum = "9c792fe9fae2a2f716846f214ca10d5a1e21133e0bf36cef34bcc4a852467b21" dependencies = [ "itertools", "lalrpop", @@ -9717,9 +10305,9 @@ dependencies = [ [[package]] name = "sp-api" version = "4.0.0-dev" -source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ - "hash-db", + "hash-db 0.15.2", "log", "parity-scale-codec", "sp-api-proc-macro", @@ -9735,7 +10323,7 @@ dependencies = [ [[package]] name = "sp-api-proc-macro" version = "4.0.0-dev" -source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "blake2", "proc-macro-crate", @@ -9747,7 +10335,7 @@ dependencies = [ [[package]] name = "sp-application-crypto" version = "7.0.0" -source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "parity-scale-codec", "scale-info", @@ -9759,22 +10347,22 @@ dependencies = [ [[package]] name = "sp-application-crypto" -version = "12.0.0" +version = "22.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a72575f160b1b134ee277a2ab46af4361c072a3fe661c48e474255406cb01c97" +checksum = "8cf23435a4bbd6eeec2bbbc346719ba4f3200e0ddb5f9e9f06c1724db03a8410" dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-core 11.0.0", - "sp-io 12.0.0", - "sp-std 6.0.0", + "sp-core 20.0.0", + "sp-io 22.0.0", + "sp-std 7.0.0", ] [[package]] name = "sp-arithmetic" version = "6.0.0" -source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "integer-sqrt", "num-traits", @@ -9787,23 +10375,23 @@ dependencies = [ [[package]] name = "sp-arithmetic" -version = "9.0.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2038010f7514d50775dcbd3edb569e17fa9bda63128580a9e172abb1795f2c1d" +checksum = "2c3d3507a803e8bc332fa290ed3015a7b51d4436ce2b836744642fc412040456" dependencies = [ "integer-sqrt", "num-traits", "parity-scale-codec", "scale-info", "serde", - "sp-std 6.0.0", + "sp-std 7.0.0", "static_assertions", ] [[package]] name = "sp-authority-discovery" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "parity-scale-codec", "scale-info", @@ -9816,8 +10404,9 @@ dependencies = [ [[package]] name = "sp-beefy" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ + "lazy_static", "parity-scale-codec", "scale-info", "serde", @@ -9828,12 +10417,13 @@ dependencies = [ "sp-mmr-primitives", "sp-runtime 7.0.0", "sp-std 5.0.0", + "strum 0.24.1", ] [[package]] name = "sp-block-builder" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "parity-scale-codec", "sp-api", @@ -9845,7 +10435,7 @@ dependencies = [ [[package]] name = "sp-blockchain" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "futures", "log", @@ -9863,7 +10453,7 @@ dependencies = [ [[package]] name = "sp-consensus" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "async-trait", "futures", @@ -9878,10 +10468,28 @@ dependencies = [ "thiserror", ] +[[package]] +name = "sp-consensus-aura" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +dependencies = [ + "async-trait", + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-application-crypto 7.0.0", + "sp-consensus", + "sp-consensus-slots", + "sp-inherents", + "sp-runtime 7.0.0", + "sp-std 5.0.0", + "sp-timestamp", +] + [[package]] name = "sp-consensus-slots" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "parity-scale-codec", "scale-info", @@ -9893,16 +10501,17 @@ dependencies = [ [[package]] name = "sp-core" version = "7.0.0" -source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "array-bytes", "base58", - "bitflags", + "bitflags 1.3.2", "blake2", + "bounded-collections", "dyn-clonable", "ed25519-zebra", "futures", - "hash-db", + "hash-db 0.15.2", "hash256-std-hasher", "impl-serde 0.4.0", "lazy_static", @@ -9934,18 +10543,19 @@ dependencies = [ [[package]] name = "sp-core" -version = "11.0.0" +version = "20.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d99984f57c9eb858d29fbe0e4cf44092eec484b2ff72176d5afa4ab7bf1dc8b1" +checksum = "7789372146f8ad40d0b40fad0596cb1db5771187a258eabe19b06f00767fcbd6" dependencies = [ "array-bytes", - "base58", - "bitflags", + "bitflags 1.3.2", "blake2", + "bounded-collections", + "bs58", "dyn-clonable", "ed25519-zebra", "futures", - "hash-db", + "hash-db 0.16.0", "hash256-std-hasher", "impl-serde 0.4.0", "lazy_static", @@ -9962,12 +10572,12 @@ dependencies = [ "secp256k1", "secrecy", "serde", - "sp-core-hashing 6.0.0", - "sp-debug-derive 6.0.0", - "sp-externalities 0.15.0", - "sp-runtime-interface 10.0.0", - "sp-std 6.0.0", - "sp-storage 9.0.0", + "sp-core-hashing 8.0.0", + "sp-debug-derive 7.0.0", + "sp-externalities 0.18.0", + "sp-runtime-interface 16.0.0", + "sp-std 7.0.0", + "sp-storage 12.0.0", "ss58-registry", "substrate-bip39", "thiserror", @@ -9978,11 +10588,11 @@ dependencies = [ [[package]] name = "sp-core-hashing" version = "5.0.0" -source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "blake2", "byteorder", - "digest 0.10.7", + "digest 0.10.6", "sha2 0.10.6", "sha3", "sp-std 5.0.0", @@ -9991,34 +10601,23 @@ dependencies = [ [[package]] name = "sp-core-hashing" -version = "6.0.0" +version = "8.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbc2d1947252b7a4e403b0a260f596920443742791765ec111daa2bbf98eff25" +checksum = "27449abdfbe41b473e625bce8113745e81d65777dd1d5a8462cf24137930dad8" dependencies = [ - "blake2", + "blake2b_simd", "byteorder", - "digest 0.10.7", + "digest 0.10.6", "sha2 0.10.6", "sha3", - "sp-std 6.0.0", + "sp-std 7.0.0", "twox-hash", ] [[package]] name = "sp-core-hashing-proc-macro" version = "5.0.0" -source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" -dependencies = [ - "proc-macro2", - "quote", - "sp-core-hashing 5.0.0", - "syn 1.0.109", -] - -[[package]] -name = "sp-core-hashing-proc-macro" -version = "5.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "proc-macro2", "quote", @@ -10029,7 +10628,7 @@ dependencies = [ [[package]] name = "sp-database" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "kvdb", "parking_lot 0.12.1", @@ -10049,7 +10648,7 @@ dependencies = [ [[package]] name = "sp-debug-derive" version = "5.0.0" -source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "proc-macro2", "quote", @@ -10058,9 +10657,9 @@ dependencies = [ [[package]] name = "sp-debug-derive" -version = "6.0.0" +version = "7.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66fb9dc63d54de7d7bed62a505b6e0bd66c122525ea1abb348f6564717c3df2d" +checksum = "62211eed9ef9dac4b9d837c56ccc9f8ee4fc49d9d9b7e6b9daf098fe173389ab" dependencies = [ "proc-macro2", "quote", @@ -10070,7 +10669,7 @@ dependencies = [ [[package]] name = "sp-externalities" version = "0.13.0" -source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "environmental", "parity-scale-codec", @@ -10080,20 +10679,20 @@ dependencies = [ [[package]] name = "sp-externalities" -version = "0.15.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc754e1cec66b93df0b48a8986d019c1a2a90431c42cf2614cc35a291597c329" +checksum = "8ae0f275760689aaefe967943331d458cd99f5169d18364365d4cb584b246d1c" dependencies = [ "environmental", "parity-scale-codec", - "sp-std 6.0.0", - "sp-storage 9.0.0", + "sp-std 7.0.0", + "sp-storage 12.0.0", ] [[package]] name = "sp-finality-grandpa" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "finality-grandpa", "log", @@ -10111,11 +10710,12 @@ dependencies = [ [[package]] name = "sp-inherents" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "async-trait", "impl-trait-for-tuples", "parity-scale-codec", + "scale-info", "sp-core 7.0.0", "sp-runtime 7.0.0", "sp-std 5.0.0", @@ -10125,7 +10725,7 @@ dependencies = [ [[package]] name = "sp-io" version = "7.0.0" -source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "bytes", "ed25519", @@ -10149,9 +10749,9 @@ dependencies = [ [[package]] name = "sp-io" -version = "12.0.0" +version = "22.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ac917b37c7733e3778e7ffc3958f1181a151ac3b14116d65fb10fe7b08db10e" +checksum = "bd3431c245992fe51b8256c838fc2e981f8d3b0afc1d1377ca7dbe0a3287a764" dependencies = [ "bytes", "ed25519", @@ -10160,15 +10760,16 @@ dependencies = [ "libsecp256k1", "log", "parity-scale-codec", + "rustversion", "secp256k1", - "sp-core 11.0.0", - "sp-externalities 0.15.0", - "sp-keystore 0.17.0", - "sp-runtime-interface 10.0.0", - "sp-state-machine 0.17.0", - "sp-std 6.0.0", - "sp-tracing 7.0.0", - "sp-trie 11.0.0", + "sp-core 20.0.0", + "sp-externalities 0.18.0", + "sp-keystore 0.26.0", + "sp-runtime-interface 16.0.0", + "sp-state-machine 0.27.0", + "sp-std 7.0.0", + "sp-tracing 9.0.0", + "sp-trie 21.0.0", "tracing", "tracing-core", ] @@ -10176,18 +10777,18 @@ dependencies = [ [[package]] name = "sp-keyring" version = "7.0.0" -source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "lazy_static", "sp-core 7.0.0", "sp-runtime 7.0.0", - "strum", + "strum 0.24.1", ] [[package]] name = "sp-keystore" version = "0.13.0" -source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "async-trait", "futures", @@ -10203,34 +10804,24 @@ dependencies = [ [[package]] name = "sp-keystore" -version = "0.17.0" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ada8b7a72404bda58b3353830bc42f027ec764e13a28b4cd4386cf34fb1ae7c" +checksum = "452d079f592c97369c9ca8a5083b25f146751c6b5af10cbcacc2b24dc53fd72a" dependencies = [ - "async-trait", "futures", "merlin", "parity-scale-codec", "parking_lot 0.12.1", "schnorrkel", - "sp-core 11.0.0", - "sp-externalities 0.15.0", - "thiserror", -] - -[[package]] -name = "sp-maybe-compressed-blob" -version = "4.1.0-dev" -source = "git+https://github.com/paritytech/substrate?tag=monthly-2023-01#55c64bcc2af5a6e5fc3eb245e638379ebe18a58d" -dependencies = [ + "sp-core 20.0.0", + "sp-externalities 0.18.0", "thiserror", - "zstd", ] [[package]] name = "sp-maybe-compressed-blob" version = "4.1.0-dev" -source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "thiserror", "zstd", @@ -10239,7 +10830,7 @@ dependencies = [ [[package]] name = "sp-mmr-primitives" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "ckb-merkle-mountain-range 0.5.2", "log", @@ -10257,7 +10848,7 @@ dependencies = [ [[package]] name = "sp-offchain" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "sp-api", "sp-core 7.0.0", @@ -10267,7 +10858,7 @@ dependencies = [ [[package]] name = "sp-panic-handler" version = "5.0.0" -source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "backtrace", "lazy_static", @@ -10276,9 +10867,9 @@ dependencies = [ [[package]] name = "sp-panic-handler" -version = "6.0.0" +version = "7.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4abed79c3d5b3622f65ab065676addd9923b9b122cd257df23e2757ce487c6d2" +checksum = "75986cc917d897e0f6d0c848088064df4c74ccbb8f1c1848700b725f5ca7fe04" dependencies = [ "backtrace", "lazy_static", @@ -10288,7 +10879,7 @@ dependencies = [ [[package]] name = "sp-rpc" version = "6.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "rustc-hash", "serde", @@ -10298,7 +10889,7 @@ dependencies = [ [[package]] name = "sp-runtime" version = "7.0.0" -source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "either", "hash256-std-hasher", @@ -10319,9 +10910,9 @@ dependencies = [ [[package]] name = "sp-runtime" -version = "12.0.0" +version = "23.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c86578c67b060a6ecab52af64f1cf18b3892fca7fba5ffc5c49934b2e76b1929" +checksum = "6220216caa67e3d931c693b06a3590dfcaa255f19bb3c3e3150f1672b8bc53f6" dependencies = [ "either", "hash256-std-hasher", @@ -10332,18 +10923,18 @@ dependencies = [ "rand 0.8.5", "scale-info", "serde", - "sp-application-crypto 12.0.0", - "sp-arithmetic 9.0.0", - "sp-core 11.0.0", - "sp-io 12.0.0", - "sp-std 6.0.0", - "sp-weights 8.0.0", + "sp-application-crypto 22.0.0", + "sp-arithmetic 15.0.0", + "sp-core 20.0.0", + "sp-io 22.0.0", + "sp-std 7.0.0", + "sp-weights 19.0.0", ] [[package]] name = "sp-runtime-interface" version = "7.0.0" -source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "bytes", "impl-trait-for-tuples", @@ -10360,27 +10951,27 @@ dependencies = [ [[package]] name = "sp-runtime-interface" -version = "10.0.0" +version = "16.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3858935567385728ea45f6d159f9970b0b278eb22a8e77625bbf4a63e43a85a" +checksum = "ca5d0cd80200bf85b8b064238b2508b69b6146b13adf36066ec5d924825af737" dependencies = [ "bytes", "impl-trait-for-tuples", "parity-scale-codec", "primitive-types", - "sp-externalities 0.15.0", - "sp-runtime-interface-proc-macro 7.0.0", - "sp-std 6.0.0", - "sp-storage 9.0.0", - "sp-tracing 7.0.0", - "sp-wasm-interface 8.0.0", + "sp-externalities 0.18.0", + "sp-runtime-interface-proc-macro 10.0.0", + "sp-std 7.0.0", + "sp-storage 12.0.0", + "sp-tracing 9.0.0", + "sp-wasm-interface 13.0.0", "static_assertions", ] [[package]] name = "sp-runtime-interface-proc-macro" version = "6.0.0" -source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "Inflector", "proc-macro-crate", @@ -10391,9 +10982,9 @@ dependencies = [ [[package]] name = "sp-runtime-interface-proc-macro" -version = "7.0.0" +version = "10.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00083a77e938c4f35d0bde7ca0b6e5f616158ebe11af6063795aa664d92a238b" +checksum = "05ae5b00aef477127ddb6177b3464ad1e2bdcc12ee913fc5dfc9d065c6cea89b" dependencies = [ "Inflector", "proc-macro-crate", @@ -10405,7 +10996,7 @@ dependencies = [ [[package]] name = "sp-session" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "parity-scale-codec", "scale-info", @@ -10419,7 +11010,7 @@ dependencies = [ [[package]] name = "sp-staking" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "parity-scale-codec", "scale-info", @@ -10431,14 +11022,14 @@ dependencies = [ [[package]] name = "sp-state-machine" version = "0.13.0" -source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ - "hash-db", + "hash-db 0.15.2", "log", "parity-scale-codec", "parking_lot 0.12.1", "rand 0.8.5", - "smallvec", + "smallvec 1.10.0", "sp-core 7.0.0", "sp-externalities 0.13.0", "sp-panic-handler 5.0.0", @@ -10450,21 +11041,21 @@ dependencies = [ [[package]] name = "sp-state-machine" -version = "0.17.0" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1fd4c600df0b5abf26c19b6c61d928b64e0c2b8a709a3dbef872be0507cd1ca" +checksum = "b1e49c3bfcc8c832c34552cd8194180cc60508c6d3d9b0b9615d6b7c3e275019" dependencies = [ - "hash-db", + "hash-db 0.16.0", "log", "parity-scale-codec", "parking_lot 0.12.1", "rand 0.8.5", - "smallvec", - "sp-core 11.0.0", - "sp-externalities 0.15.0", - "sp-panic-handler 6.0.0", - "sp-std 6.0.0", - "sp-trie 11.0.0", + "smallvec 1.10.0", + "sp-core 20.0.0", + "sp-externalities 0.18.0", + "sp-panic-handler 7.0.0", + "sp-std 7.0.0", + "sp-trie 21.0.0", "thiserror", "tracing", ] @@ -10478,13 +11069,13 @@ checksum = "14804d6069ee7a388240b665f17908d98386ffb0b5d39f89a4099fc7a2a4c03f" [[package]] name = "sp-std" version = "5.0.0" -source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" [[package]] name = "sp-std" -version = "6.0.0" +version = "7.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af0ee286f98455272f64ac5bb1384ff21ac029fbb669afbaf48477faff12760e" +checksum = "1de8eef39962b5b97478719c493bed2926cf70cb621005bbf68ebe58252ff986" [[package]] name = "sp-storage" @@ -10503,7 +11094,7 @@ dependencies = [ [[package]] name = "sp-storage" version = "7.0.0" -source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "impl-serde 0.4.0", "parity-scale-codec", @@ -10515,22 +11106,22 @@ dependencies = [ [[package]] name = "sp-storage" -version = "9.0.0" +version = "12.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9acb4059eb0ae4fa8cf9ca9119b0178ad312a592d4c6054bd17b411034f233e9" +checksum = "9ad1f8c52d4700ac7bc42b3375679a6c6fc1fe876f4b40c6efdf36f933ef0291" dependencies = [ "impl-serde 0.4.0", "parity-scale-codec", "ref-cast", "serde", - "sp-debug-derive 6.0.0", - "sp-std 6.0.0", + "sp-debug-derive 7.0.0", + "sp-std 7.0.0", ] [[package]] name = "sp-timestamp" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "async-trait", "futures-timer", @@ -10545,7 +11136,7 @@ dependencies = [ [[package]] name = "sp-tracing" version = "6.0.0" -source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "parity-scale-codec", "sp-std 5.0.0", @@ -10556,12 +11147,12 @@ dependencies = [ [[package]] name = "sp-tracing" -version = "7.0.0" +version = "9.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b22d28a0bc2365dfb86644d14f2682a79da35891d4656d4896fb09fb05ff1e6c" +checksum = "00fab60bf3d42255ce3f678903d3a2564662371c75623de4a1ffc7cac46143df" dependencies = [ "parity-scale-codec", - "sp-std 6.0.0", + "sp-std 7.0.0", "tracing", "tracing-core", "tracing-subscriber 0.2.25", @@ -10570,13 +11161,13 @@ dependencies = [ [[package]] name = "sp-trie" version = "7.0.0" -source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "ahash 0.8.3", - "hash-db", + "hash-db 0.15.2", "hashbrown 0.12.3", "lazy_static", - "memory-db", + "memory-db 0.31.0", "nohash-hasher", "parity-scale-codec", "parking_lot 0.12.1", @@ -10586,45 +11177,45 @@ dependencies = [ "sp-std 5.0.0", "thiserror", "tracing", - "trie-db", - "trie-root", + "trie-db 0.25.1", + "trie-root 0.17.0", ] [[package]] name = "sp-trie" -version = "11.0.0" +version = "21.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db085f134cb444e52ca569a442d12c84bd17667532613d78dd6f568942632da4" +checksum = "58401c53c08b6ecad83acd7e14534c8bbcb3fa73e81e26685e0ac70e51b00c56" dependencies = [ - "ahash 0.7.6", - "hash-db", - "hashbrown 0.12.3", + "ahash 0.8.3", + "hash-db 0.16.0", + "hashbrown 0.13.2", "lazy_static", - "lru", - "memory-db", + "memory-db 0.32.0", "nohash-hasher", "parity-scale-codec", "parking_lot 0.12.1", "scale-info", - "sp-core 11.0.0", - "sp-std 6.0.0", + "schnellru", + "sp-core 20.0.0", + "sp-std 7.0.0", "thiserror", "tracing", - "trie-db", - "trie-root", + "trie-db 0.27.1", + "trie-root 0.18.0", ] [[package]] name = "sp-version" version = "5.0.0" -source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "impl-serde 0.4.0", "parity-scale-codec", "parity-wasm", "scale-info", "serde", - "sp-core-hashing-proc-macro 5.0.0 (git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.38)", + "sp-core-hashing-proc-macro", "sp-runtime 7.0.0", "sp-std 5.0.0", "sp-version-proc-macro", @@ -10634,7 +11225,7 @@ dependencies = [ [[package]] name = "sp-version-proc-macro" version = "4.0.0-dev" -source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "parity-scale-codec", "proc-macro2", @@ -10645,8 +11236,9 @@ dependencies = [ [[package]] name = "sp-wasm-interface" version = "7.0.0" -source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ + "anyhow", "impl-trait-for-tuples", "log", "parity-scale-codec", @@ -10657,14 +11249,15 @@ dependencies = [ [[package]] name = "sp-wasm-interface" -version = "8.0.0" +version = "13.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ebc377987d42f8fc20e3f4ec4fd1147dd098fe90bcb4269e1eddb04e920f889" +checksum = "153b7374179439e2aa783c66ed439bd86920c67bbc95d34c76390561972bc02f" dependencies = [ + "anyhow", "impl-trait-for-tuples", "log", "parity-scale-codec", - "sp-std 6.0.0", + "sp-std 7.0.0", "wasmi", "wasmtime", ] @@ -10672,12 +11265,12 @@ dependencies = [ [[package]] name = "sp-weights" version = "4.0.0" -source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "parity-scale-codec", "scale-info", "serde", - "smallvec", + "smallvec 1.10.0", "sp-arithmetic 6.0.0", "sp-core 7.0.0", "sp-debug-derive 5.0.0", @@ -10686,18 +11279,18 @@ dependencies = [ [[package]] name = "sp-weights" -version = "8.0.0" +version = "19.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90eca2a19f48978e9cd605e23905d0602419f7880a9360ac717b03412e9c7916" +checksum = "123c661915e1bf328e21f8ecbe4e5247feba86f9149b782ea4348004547ce8ef" dependencies = [ "parity-scale-codec", "scale-info", "serde", - "smallvec", - "sp-arithmetic 9.0.0", - "sp-core 11.0.0", - "sp-debug-derive 6.0.0", - "sp-std 6.0.0", + "smallvec 1.10.0", + "sp-arithmetic 15.0.0", + "sp-core 20.0.0", + "sp-debug-derive 7.0.0", + "sp-std 7.0.0", ] [[package]] @@ -10723,14 +11316,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" dependencies = [ "base64ct", - "der 0.7.6", + "der 0.7.8", ] [[package]] name = "ss58-registry" -version = "1.40.0" +version = "1.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb47a8ad42e5fc72d5b1eb104a5546937eaf39843499948bb666d6e93c62423b" +checksum = "e40c020d72bc0a9c5660bb71e4a6fdef081493583062c474740a7d59f55f0e7b" dependencies = [ "Inflector", "num-format", @@ -10753,19 +11346,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" -[[package]] -name = "statrs" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05bdbb8e4e78216a85785a85d3ec3183144f98d0097b9281802c019bb07a6f05" -dependencies = [ - "approx", - "lazy_static", - "nalgebra", - "num-traits", - "rand 0.8.5", -] - [[package]] name = "string_cache" version = "0.8.7" @@ -10791,12 +11371,21 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" dependencies = [ - "strum_macros", + "strum_macros 0.24.3", ] [[package]] -name = "strum_macros" -version = "0.24.3" +name = "strum" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" +dependencies = [ + "strum_macros 0.25.2", +] + +[[package]] +name = "strum_macros" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" dependencies = [ @@ -10807,6 +11396,19 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "strum_macros" +version = "0.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad8d03b598d3d0fff69bf533ee3ef19b8eeb342729596df84bcc7e1f96ec4059" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.28", +] + [[package]] name = "stun" version = "0.4.4" @@ -10855,7 +11457,7 @@ dependencies = [ [[package]] name = "substrate-prometheus-endpoint" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "hyper", "log", @@ -10910,15 +11512,16 @@ checksum = "734676eb262c623cec13c3155096e08d1f8f29adce39ba17948b18dad1e54142" [[package]] name = "subxt" -version = "0.26.0" -source = "git+https://github.com/paritytech/subxt?rev=d92352ad739836a4100e1ef1db607acc82ed8c5a#d92352ad739836a4100e1ef1db607acc82ed8c5a" +version = "0.28.0" +source = "git+https://github.com/paritytech/subxt?rev=2a4da618a033bb82f768e4ef67b093b371f8b492#2a4da618a033bb82f768e4ef67b093b371f8b492" dependencies = [ "base58", "blake2", "derivative", + "either", "frame-metadata", "futures", - "getrandom 0.2.9", + "getrandom 0.2.8", "hex", "impl-serde 0.4.0", "jsonrpsee", @@ -10927,13 +11530,14 @@ dependencies = [ "primitive-types", "scale-bits", "scale-decode", + "scale-encode", "scale-info", "scale-value", "serde", "serde_json", - "sp-core 11.0.0", - "sp-core-hashing 6.0.0", - "sp-runtime 12.0.0", + "sp-core 20.0.0", + "sp-core-hashing 8.0.0", + "sp-runtime 23.0.0", "subxt-macro", "subxt-metadata", "thiserror", @@ -10942,8 +11546,8 @@ dependencies = [ [[package]] name = "subxt-codegen" -version = "0.26.0" -source = "git+https://github.com/paritytech/subxt?rev=d92352ad739836a4100e1ef1db607acc82ed8c5a#d92352ad739836a4100e1ef1db607acc82ed8c5a" +version = "0.28.0" +source = "git+https://github.com/paritytech/subxt?rev=2a4da618a033bb82f768e4ef67b093b371f8b492#2a4da618a033bb82f768e4ef67b093b371f8b492" dependencies = [ "darling", "frame-metadata", @@ -10951,12 +11555,12 @@ dependencies = [ "hex", "jsonrpsee", "parity-scale-codec", - "proc-macro-error", "proc-macro2", "quote", "scale-info", "subxt-metadata", "syn 1.0.109", + "thiserror", "tokio", ] @@ -10970,8 +11574,8 @@ dependencies = [ [[package]] name = "subxt-macro" -version = "0.26.0" -source = "git+https://github.com/paritytech/subxt?rev=d92352ad739836a4100e1ef1db607acc82ed8c5a#d92352ad739836a4100e1ef1db607acc82ed8c5a" +version = "0.28.0" +source = "git+https://github.com/paritytech/subxt?rev=2a4da618a033bb82f768e4ef67b093b371f8b492#2a4da618a033bb82f768e4ef67b093b371f8b492" dependencies = [ "darling", "proc-macro-error", @@ -10981,13 +11585,13 @@ dependencies = [ [[package]] name = "subxt-metadata" -version = "0.26.0" -source = "git+https://github.com/paritytech/subxt?rev=d92352ad739836a4100e1ef1db607acc82ed8c5a#d92352ad739836a4100e1ef1db607acc82ed8c5a" +version = "0.28.0" +source = "git+https://github.com/paritytech/subxt?rev=2a4da618a033bb82f768e4ef67b093b371f8b492#2a4da618a033bb82f768e4ef67b093b371f8b492" dependencies = [ "frame-metadata", "parity-scale-codec", "scale-info", - "sp-core-hashing 6.0.0", + "sp-core-hashing 8.0.0", ] [[package]] @@ -11010,17 +11614,37 @@ dependencies = [ "zip", ] +[[package]] +name = "svm-rs" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597e3a746727984cb7ea2487b6a40726cad0dbe86628e7d429aa6b8c4c153db4" +dependencies = [ + "dirs", + "fs2", + "hex", + "once_cell", + "reqwest", + "semver", + "serde", + "serde_json", + "sha2 0.10.6", + "thiserror", + "url", + "zip", +] + [[package]] name = "svm-rs-builds" -version = "0.1.15" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32deae08684d03d8a4ba99b8a3b0a1575364820339930f6fa2afdfa3a6d98c84" +checksum = "2271abd7d01895a3e5bfa4b578e32f09155002ce1ec239532e297f82aafad06b" dependencies = [ "build_const", "hex", "semver", "serde_json", - "svm-rs", + "svm-rs 0.3.0", ] [[package]] @@ -11036,9 +11660,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.16" +version = "2.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6f671d4b5ffdb8eadec19c0ae67fe2639df8684bd7bc4b83d986b8db549cf01" +checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567" dependencies = [ "proc-macro2", "quote", @@ -11065,11 +11689,11 @@ dependencies = [ [[package]] name = "system-configuration" -version = "0.5.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +checksum = "d75182f12f490e953596550b65ee31bda7c8e043d9386174b353bda50838c3fd" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation", "system-configuration-sys", ] @@ -11092,21 +11716,21 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "target-lexicon" -version = "0.12.7" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd1ba337640d60c3e96bc6f0638a939b9c9a7f2c316a1598c279828b3d1dc8c5" +checksum = "9410d0f6853b1d94f0e519fb95df60f29d2c1eff2d921ffdf01a4c8a3b54f12d" [[package]] name = "tempfile" -version = "3.5.0" +version = "3.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998" +checksum = "dc02fddf48964c42031a0b3fe0428320ecf3a73c401040fc0096f97794310651" dependencies = [ "cfg-if 1.0.0", - "fastrand", + "fastrand 2.0.0", "redox_syscall 0.3.5", - "rustix 0.37.19", - "windows-sys 0.45.0", + "rustix 0.38.7", + "windows-sys 0.48.0", ] [[package]] @@ -11115,7 +11739,7 @@ version = "0.28.0" source = "git+https://github.com/informalsystems/tendermint-rs?rev=e81f7bf23d63ffbcd242381d1ce5e35da3515ff1#e81f7bf23d63ffbcd242381d1ce5e35da3515ff1" dependencies = [ "bytes", - "digest 0.10.7", + "digest 0.10.6", "ed25519", "ed25519-consensus", "flex-error", @@ -11135,7 +11759,7 @@ dependencies = [ "subtle", "subtle-encoding", "tendermint-proto", - "time 0.3.21", + "time 0.3.17", "zeroize", ] @@ -11169,7 +11793,7 @@ dependencies = [ "tendermint", "tendermint-light-client-verifier", "tendermint-rpc", - "time 0.3.21", + "time 0.3.17", "tokio", ] @@ -11182,7 +11806,7 @@ dependencies = [ "flex-error", "serde", "tendermint", - "time 0.3.21", + "time 0.3.17", ] [[package]] @@ -11199,7 +11823,7 @@ dependencies = [ "serde", "serde_bytes", "subtle-encoding", - "time 0.3.21", + "time 0.3.17", ] [[package]] @@ -11212,7 +11836,7 @@ dependencies = [ "bytes", "flex-error", "futures", - "getrandom 0.2.9", + "getrandom 0.2.8", "http", "hyper", "hyper-proxy", @@ -11227,7 +11851,7 @@ dependencies = [ "tendermint", "tendermint-config", "thiserror", - "time 0.3.21", + "time 0.3.17", "tokio", "tracing", "url", @@ -11247,7 +11871,7 @@ dependencies = [ "simple-error", "tempfile", "tendermint", - "time 0.3.21", + "time 0.3.17", ] [[package]] @@ -11276,15 +11900,15 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e6bf6f19e9f8ed8d4048dc22981458ebcf406d67e94cd422e5ecd73d63b3237" dependencies = [ - "rustix 0.37.19", + "rustix 0.37.7", "windows-sys 0.48.0", ] [[package]] name = "termtree" -version = "0.4.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" +checksum = "95059e91184749cb66be6dc994f67f182b6d897cb3df74a5bf66b5e709295fd8" [[package]] name = "test-log" @@ -11320,16 +11944,15 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.28", ] [[package]] name = "thread_local" -version = "1.1.7" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" dependencies = [ - "cfg-if 1.0.0", "once_cell", ] @@ -11355,9 +11978,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.21" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3403384eaacbca9923fa06940178ac13e4edb725486d70e8e15881d0c836cc" +checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376" dependencies = [ "itoa", "serde", @@ -11367,15 +11990,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.1" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" +checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" [[package]] name = "time-macros" -version = "0.2.9" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b" +checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2" dependencies = [ "time-core", ] @@ -11435,11 +12058,12 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.28.1" +version = "1.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0aa32867d44e6f2ce3385e89dceb990188b8bb0fb25b0cf576647a6f98ac5105" +checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" dependencies = [ "autocfg", + "backtrace", "bytes", "libc", "mio", @@ -11470,7 +12094,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.28", ] [[package]] @@ -11497,19 +12121,19 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.24.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0d409377ff5b1e3ca6437aa86c1eb7d40c134bfec254e44c830defa92669db5" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "rustls 0.21.1", + "rustls 0.21.6", "tokio", ] [[package]] name = "tokio-stream" -version = "0.1.14" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +checksum = "d660770404473ccd7bc9f8b28494a811bc18542b915c0855c51e8f419d5223ce" dependencies = [ "futures-core", "pin-project-lite 0.2.9", @@ -11519,25 +12143,24 @@ dependencies = [ [[package]] name = "tokio-tungstenite" -version = "0.18.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54319c93411147bced34cb5609a80e0a8e44c5999c93903a81cd866630ec0bfd" +checksum = "ec509ac96e9a0c43427c74f003127d953a265737636129424288d27cb5c4b12c" dependencies = [ "futures-util", "log", - "rustls 0.20.8", + "rustls 0.21.6", "tokio", - "tokio-rustls 0.23.4", - "tungstenite 0.18.0", - "webpki 0.22.0", - "webpki-roots 0.22.6", + "tokio-rustls 0.24.1", + "tungstenite 0.19.0", + "webpki-roots 0.23.1", ] [[package]] name = "tokio-util" -version = "0.7.8" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" +checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" dependencies = [ "bytes", "futures-core", @@ -11559,36 +12182,53 @@ dependencies = [ [[package]] name = "toml" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6135d499e69981f9ff0ef2167955a5333c35e36f6937d382974566b3d5b94ec" +checksum = "c17e963a819c331dcacd7ab957d80bc2b9a9c1e71c804826d2f283dd65306542" dependencies = [ - "indexmap", + "indexmap 2.0.0", "serde", "serde_spanned", - "toml_datetime", - "toml_edit", + "toml_datetime 0.6.3", + "toml_edit 0.19.14", ] [[package]] name = "toml_datetime" -version = "0.6.2" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a76a9312f5ba4c2dec6b9161fdf25d87ad8a09256ccea5a556fef03c706a10f" +checksum = "4553f467ac8e3d374bc9a177a26801e5d0f9b211aa1673fb137a403afd1c9cf5" + +[[package]] +name = "toml_datetime" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.19.10" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2380d56e8670370eee6566b0bfd4265f65b3f432e8c6d85623f728d4fa31f739" +checksum = "56c59d8dd7d0dcbc6428bf7aa2f0e823e26e43b3c9aca15bbc9475d23e5fa12b" dependencies = [ - "indexmap", + "indexmap 1.9.2", + "nom8", + "toml_datetime 0.5.1", +] + +[[package]] +name = "toml_edit" +version = "0.19.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a" +dependencies = [ + "indexmap 2.0.0", "serde", "serde_spanned", - "toml_datetime", + "toml_datetime 0.6.3", "winnow", ] @@ -11635,7 +12275,7 @@ checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" dependencies = [ "futures-core", "futures-util", - "indexmap", + "indexmap 1.9.2", "pin-project", "pin-project-lite 0.2.9", "rand 0.8.5", @@ -11653,7 +12293,7 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f873044bf02dd1e8239e9c1293ea39dad76dc594ec16185d0a1bf31d8dc8d858" dependencies = [ - "bitflags", + "bitflags 1.3.2", "bytes", "futures-core", "futures-util", @@ -11661,6 +12301,7 @@ dependencies = [ "http-body", "http-range-header", "pin-project-lite 0.2.9", + "tower", "tower-layer", "tower-service", ] @@ -11692,20 +12333,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.24" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74" +checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 1.0.109", ] [[package]] name = "tracing-core" -version = "0.1.31" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" dependencies = [ "once_cell", "valuable", @@ -11757,7 +12398,7 @@ dependencies = [ "serde", "serde_json", "sharded-slab", - "smallvec", + "smallvec 1.10.0", "thread_local", "tracing", "tracing-core", @@ -11778,7 +12419,7 @@ dependencies = [ "serde", "serde_json", "sharded-slab", - "smallvec", + "smallvec 1.10.0", "thread_local", "tracing", "tracing-core", @@ -11788,30 +12429,43 @@ dependencies = [ [[package]] name = "trezor-client" -version = "0.0.7" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d3e4b569b95a8d24d10b2e8f60196348eb15023d50d2b38a4463e7f150afd27" +checksum = "2cddb76a030b141d9639470eca2a236f3057a651bba78227cfa77830037a8286" dependencies = [ "byteorder", "hex", - "hidapi-rusb", - "log", "primitive-types", "protobuf", "rusb", + "thiserror", + "tracing", ] [[package]] name = "trie-db" -version = "0.24.0" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "004e1e8f92535694b4cb1444dc5a8073ecf0815e3357f729638b9f8fc4062908" +checksum = "3390c0409daaa6027d6681393316f4ccd3ff82e1590a1e4725014e3ae2bf1920" dependencies = [ - "hash-db", - "hashbrown 0.12.3", + "hash-db 0.15.2", + "hashbrown 0.13.2", "log", "rustc-hex", - "smallvec", + "smallvec 1.10.0", +] + +[[package]] +name = "trie-db" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "767abe6ffed88a1889671a102c2861ae742726f52e0a5a425b92c9fbfa7e9c85" +dependencies = [ + "hash-db 0.16.0", + "hashbrown 0.13.2", + "log", + "rustc-hex", + "smallvec 1.10.0", ] [[package]] @@ -11820,7 +12474,16 @@ version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a36c5ca3911ed3c9a5416ee6c679042064b93fc637ded67e25f92e68d783891" dependencies = [ - "hash-db", + "hash-db 0.15.2", +] + +[[package]] +name = "trie-root" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4ed310ef5ab98f5fa467900ed906cb9232dd5376597e00fd4cba2a449d06c0b" +dependencies = [ + "hash-db 0.16.0", ] [[package]] @@ -11840,7 +12503,7 @@ dependencies = [ "ipnet", "lazy_static", "rand 0.8.5", - "smallvec", + "smallvec 1.10.0", "socket2", "thiserror", "tinyvec", @@ -11862,7 +12525,7 @@ dependencies = [ "lru-cache", "parking_lot 0.12.1", "resolv-conf", - "smallvec", + "smallvec 1.10.0", "thiserror", "tokio", "tracing", @@ -11904,18 +12567,18 @@ dependencies = [ [[package]] name = "tungstenite" -version = "0.18.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ee6ab729cd4cf0fd55218530c4522ed30b7b6081752839b68fcec8d0960788" +checksum = "15fba1a6d6bb030745759a9a2a588bfe8490fc8b4751a277db3a0be1c9ebbf67" dependencies = [ - "base64 0.13.1", "byteorder", "bytes", + "data-encoding", "http", "httparse", "log", "rand 0.8.5", - "rustls 0.20.8", + "rustls 0.21.6", "sha1", "thiserror", "url", @@ -11948,9 +12611,9 @@ version = "1.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ - "cfg-if 1.0.0", - "digest 0.10.7", - "rand 0.8.5", + "cfg-if 0.1.10", + "digest 0.10.6", + "rand 0.7.3", "static_assertions", ] @@ -11998,15 +12661,15 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.13" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58" [[package]] name = "unicode-ident" -version = "1.0.8" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" [[package]] name = "unicode-normalization" @@ -12047,9 +12710,9 @@ dependencies = [ [[package]] name = "universal-hash" -version = "0.5.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +checksum = "7d3160b73c9a19f7e2939a2fdad446c57c1bbbbf4d919d3213ff1267a580d8b5" dependencies = [ "crypto-common", "subtle", @@ -12106,29 +12769,23 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" -[[package]] -name = "utf8parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" - [[package]] name = "uuid" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" dependencies = [ - "getrandom 0.2.9", + "getrandom 0.2.8", "serde", ] [[package]] name = "uuid" -version = "1.3.3" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "345444e32442451b267fc254ae85a209c64be56d2890e601a0c37ff0c3c5ecd2" +checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79" dependencies = [ - "getrandom 0.2.9", + "getrandom 0.2.8", ] [[package]] @@ -12181,11 +12838,12 @@ checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" [[package]] name = "walkdir" -version = "2.3.3" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" dependencies = [ "same-file", + "winapi", "winapi-util", ] @@ -12219,9 +12877,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.86" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -12229,24 +12887,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.86" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b04bc93f9d6bdee709f6bd2118f57dd6679cf1176a1af464fca3ab0d66d8fb" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.16", + "syn 1.0.109", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.36" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d1985d03709c53167ce907ff394f5316aa22cb4e12761295c5dc57dacb6297e" +checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -12256,9 +12914,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.86" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -12266,22 +12924,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.86" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 1.0.109", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.86" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" [[package]] name = "wasm-instrument" @@ -12301,7 +12959,7 @@ dependencies = [ "jsonrpsee", "log", "serde", - "sp-maybe-compressed-blob 4.1.0-dev (git+https://github.com/paritytech/substrate?tag=monthly-2023-01)", + "sp-maybe-compressed-blob", "tokio", ] @@ -12368,31 +13026,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57d20cb3c59b788653d99541c646c561c9dd26506f25c0cebfe810659c54c6d7" dependencies = [ "downcast-rs", - "libm 0.2.7", + "libm 0.2.6", "memory_units", "num-rational", "num-traits", + "region", ] [[package]] name = "wasmparser" -version = "0.89.1" +version = "0.100.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5d3e08b13876f96dd55608d03cd4883a0545884932d5adf11925876c96daef" +checksum = "64b20236ab624147dfbb62cf12a19aaf66af0e41b8398838b66e997d07d269d4" dependencies = [ - "indexmap", + "indexmap 1.9.2", + "url", ] [[package]] name = "wasmtime" -version = "1.0.2" +version = "6.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ad5af6ba38311282f2a21670d96e78266e8c8e2f38cbcd52c254df6ccbc7731" +checksum = "76a222f5fa1e14b2cefc286f1b68494d7a965f4bf57ec04c59bb62673d639af6" dependencies = [ "anyhow", "bincode", "cfg-if 1.0.0", - "indexmap", + "indexmap 1.9.2", "libc", "log", "object 0.29.0", @@ -12408,23 +13068,23 @@ dependencies = [ "wasmtime-environ", "wasmtime-jit", "wasmtime-runtime", - "windows-sys 0.36.1", + "windows-sys 0.42.0", ] [[package]] name = "wasmtime-asm-macros" -version = "1.0.2" +version = "6.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45de63ddfc8b9223d1adc8f7b2ee5f35d1f6d112833934ad7ea66e4f4339e597" +checksum = "4407a7246e7d2f3d8fb1cf0c72fda8dbafdb6dd34d555ae8bea0e5ae031089cc" dependencies = [ "cfg-if 1.0.0", ] [[package]] name = "wasmtime-cache" -version = "1.0.2" +version = "6.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcd849399d17d2270141cfe47fa0d91ee52d5f8ea9b98cf7ddde0d53e5f79882" +checksum = "5ceb3adf61d654be0be67fffdce42447b0880481348785be5fe40b5dd7663a4c" dependencies = [ "anyhow", "base64 0.13.1", @@ -12432,19 +13092,19 @@ dependencies = [ "directories-next", "file-per-thread-logger", "log", - "rustix 0.35.13", + "rustix 0.36.8", "serde", - "sha2 0.9.9", + "sha2 0.10.6", "toml 0.5.11", - "windows-sys 0.36.1", + "windows-sys 0.42.0", "zstd", ] [[package]] name = "wasmtime-cranelift" -version = "1.0.2" +version = "6.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bd91339b742ff20bfed4532a27b73c86b5bcbfedd6bea2dcdf2d64471e1b5c6" +checksum = "3c366bb8647e01fd08cb5589976284b00abfded5529b33d7e7f3f086c68304a4" dependencies = [ "anyhow", "cranelift-codegen", @@ -12463,14 +13123,14 @@ dependencies = [ [[package]] name = "wasmtime-environ" -version = "1.0.2" +version = "6.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebb881c61f4f627b5d45c54e629724974f8a8890d455bcbe634330cc27309644" +checksum = "47b8b50962eae38ee319f7b24900b7cf371f03eebdc17400c1dc8575fc10c9a7" dependencies = [ "anyhow", "cranelift-entity", "gimli 0.26.2", - "indexmap", + "indexmap 1.9.2", "log", "object 0.29.0", "serde", @@ -12482,9 +13142,9 @@ dependencies = [ [[package]] name = "wasmtime-jit" -version = "1.0.2" +version = "6.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1985c628011fe26adf5e23a5301bdc79b245e0e338f14bb58b39e4e25e4d8681" +checksum = "ffaed4f9a234ba5225d8e64eac7b4a5d13b994aeb37353cde2cbeb3febda9eaa" dependencies = [ "addr2line 0.17.0", "anyhow", @@ -12495,37 +13155,47 @@ dependencies = [ "log", "object 0.29.0", "rustc-demangle", - "rustix 0.35.13", "serde", "target-lexicon", - "thiserror", "wasmtime-environ", "wasmtime-jit-debug", + "wasmtime-jit-icache-coherence", "wasmtime-runtime", - "windows-sys 0.36.1", + "windows-sys 0.42.0", ] [[package]] name = "wasmtime-jit-debug" -version = "1.0.2" +version = "6.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f671b588486f5ccec8c5a3dba6b4c07eac2e66ab8c60e6f4e53717c77f709731" +checksum = "eed41cbcbf74ce3ff6f1d07d1b707888166dc408d1a880f651268f4f7c9194b2" dependencies = [ "object 0.29.0", "once_cell", - "rustix 0.35.13", + "rustix 0.36.8", +] + +[[package]] +name = "wasmtime-jit-icache-coherence" +version = "6.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a28ae1e648461bfdbb79db3efdaee1bca5b940872e4175390f465593a2e54c" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "windows-sys 0.42.0", ] [[package]] name = "wasmtime-runtime" -version = "1.0.2" +version = "6.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee8f92ad4b61736339c29361da85769ebc200f184361959d1792832e592a1afd" +checksum = "e704b126e4252788ccfc3526d4d4511d4b23c521bf123e447ac726c14545217b" dependencies = [ "anyhow", "cc", "cfg-if 1.0.0", - "indexmap", + "indexmap 1.9.2", "libc", "log", "mach", @@ -12533,19 +13203,18 @@ dependencies = [ "memoffset 0.6.5", "paste", "rand 0.8.5", - "rustix 0.35.13", - "thiserror", + "rustix 0.36.8", "wasmtime-asm-macros", "wasmtime-environ", "wasmtime-jit-debug", - "windows-sys 0.36.1", + "windows-sys 0.42.0", ] [[package]] name = "wasmtime-types" -version = "1.0.2" +version = "6.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d23d61cb4c46e837b431196dd06abb11731541021916d03476a178b54dc07aeb" +checksum = "83e5572c5727c1ee7e8f28717aaa8400e4d22dcbd714ea5457d85b5005206568" dependencies = [ "cranelift-entity", "serde", @@ -12555,9 +13224,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.63" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bdd9ef4e984da1187bf8110c5cf5b845fbc87a23602cdf912386a76fcd3a7c2" +checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" dependencies = [ "js-sys", "wasm-bindgen", @@ -12601,6 +13270,15 @@ dependencies = [ "webpki 0.22.0", ] +[[package]] +name = "webpki-roots" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b03058f88386e5ff5310d9111d53f48b17d732b401aeb83a8d5190f2ac459338" +dependencies = [ + "rustls-webpki 0.100.1", +] + [[package]] name = "webrtc" version = "0.6.0" @@ -12627,7 +13305,7 @@ dependencies = [ "sha2 0.10.6", "stun", "thiserror", - "time 0.3.21", + "time 0.3.17", "tokio", "turn", "url", @@ -12664,7 +13342,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "942be5bd85f072c3128396f6e5a9bfb93ca8c1939ded735d177b7bcba9a13d05" dependencies = [ "aes 0.6.0", - "aes-gcm 0.10.2", + "aes-gcm 0.10.1", "async-trait", "bincode", "block-modes", @@ -12716,7 +13394,7 @@ dependencies = [ "tokio", "turn", "url", - "uuid 1.3.3", + "uuid 1.3.0", "waitgroup", "webrtc-mdns", "webrtc-util", @@ -12737,15 +13415,18 @@ dependencies = [ [[package]] name = "webrtc-media" -version = "0.5.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f72e1650a8ae006017d1a5280efb49e2610c19ccc3c0905b03b648aee9554991" +checksum = "ee2a3c157a040324e5049bcbd644ffc9079e6738fa2cfab2bcff64e5cc4c00d7" dependencies = [ "byteorder", "bytes", + "derive_builder", + "displaydoc", "rand 0.8.5", "rtp", "thiserror", + "webrtc-util", ] [[package]] @@ -12796,7 +13477,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93f1db1727772c05cf7a2cfece52c3aca8045ca1e176cd517d323489aa3c6d87" dependencies = [ "async-trait", - "bitflags", + "bitflags 1.3.2", "bytes", "cc", "ipnet", @@ -12810,6 +13491,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "wepoll-ffi" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb" +dependencies = [ + "cc", +] + [[package]] name = "which" version = "4.4.0" @@ -12821,6 +13511,16 @@ dependencies = [ "once_cell", ] +[[package]] +name = "wide" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b689b6c49d6549434bf944e6b0f39238cf63693cb7a147e9d887507fffa3b223" +dependencies = [ + "bytemuck", + "safe_arch", +] + [[package]] name = "widestring" version = "0.5.1" @@ -12871,41 +13571,19 @@ dependencies = [ "windows_x86_64_msvc 0.34.0", ] -[[package]] -name = "windows" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" -dependencies = [ - "windows-targets 0.48.0", -] - -[[package]] -name = "windows-sys" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" -dependencies = [ - "windows_aarch64_msvc 0.36.1", - "windows_i686_gnu 0.36.1", - "windows_i686_msvc 0.36.1", - "windows_x86_64_gnu 0.36.1", - "windows_x86_64_msvc 0.36.1", -] - [[package]] name = "windows-sys" version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", + "windows_aarch64_gnullvm 0.42.1", + "windows_aarch64_msvc 0.42.1", + "windows_i686_gnu 0.42.1", + "windows_i686_msvc 0.42.1", + "windows_x86_64_gnu 0.42.1", + "windows_x86_64_gnullvm 0.42.1", + "windows_x86_64_msvc 0.42.1", ] [[package]] @@ -12914,7 +13592,7 @@ version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" dependencies = [ - "windows-targets 0.42.2", + "windows-targets 0.42.1", ] [[package]] @@ -12923,29 +13601,29 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.48.0", + "windows-targets 0.48.1", ] [[package]] name = "windows-targets" -version = "0.42.2" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", + "windows_aarch64_gnullvm 0.42.1", + "windows_aarch64_msvc 0.42.1", + "windows_i686_gnu 0.42.1", + "windows_i686_msvc 0.42.1", + "windows_x86_64_gnu 0.42.1", + "windows_x86_64_gnullvm 0.42.1", + "windows_x86_64_msvc 0.42.1", ] [[package]] name = "windows-targets" -version = "0.48.0" +version = "0.48.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" dependencies = [ "windows_aarch64_gnullvm 0.48.0", "windows_aarch64_msvc 0.48.0", @@ -12958,9 +13636,9 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.2" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" +checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" [[package]] name = "windows_aarch64_gnullvm" @@ -12976,15 +13654,9 @@ checksum = "17cffbe740121affb56fad0fc0e421804adf0ae00891205213b5cecd30db881d" [[package]] name = "windows_aarch64_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" +checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" [[package]] name = "windows_aarch64_msvc" @@ -13000,15 +13672,9 @@ checksum = "2564fde759adb79129d9b4f54be42b32c89970c18ebf93124ca8870a498688ed" [[package]] name = "windows_i686_gnu" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" - -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" +checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" [[package]] name = "windows_i686_gnu" @@ -13024,15 +13690,9 @@ checksum = "9cd9d32ba70453522332c14d38814bceeb747d80b3958676007acadd7e166956" [[package]] name = "windows_i686_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" - -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" +checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" [[package]] name = "windows_i686_msvc" @@ -13048,15 +13708,9 @@ checksum = "cfce6deae227ee8d356d19effc141a509cc503dfd1f850622ec4b0f84428e1f4" [[package]] name = "windows_x86_64_gnu" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" +checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" [[package]] name = "windows_x86_64_gnu" @@ -13066,9 +13720,9 @@ checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.2" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" +checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" [[package]] name = "windows_x86_64_gnullvm" @@ -13084,15 +13738,9 @@ checksum = "d19538ccc21819d01deaf88d6a17eae6596a12e9aafdbb97916fb49896d89de9" [[package]] name = "windows_x86_64_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" +checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" [[package]] name = "windows_x86_64_msvc" @@ -13102,9 +13750,9 @@ checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" [[package]] name = "winnow" -version = "0.4.6" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61de7bac303dc551fe038e2b3cef0f571087a47571ea6e79a87692ac99b99699" +checksum = "f46aab759304e4d7b2075a9aecba26228bb073ee8c50db796b2c72c676b5d807" dependencies = [ "memchr", ] @@ -13184,7 +13832,7 @@ dependencies = [ "ring", "rusticata-macros", "thiserror", - "time 0.3.21", + "time 0.3.17", ] [[package]] @@ -13202,29 +13850,29 @@ dependencies = [ "oid-registry 0.6.1", "rusticata-macros", "thiserror", - "time 0.3.21", + "time 0.3.17", ] [[package]] name = "xcm" -version = "0.9.38" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.38#097ffd245c42aeff28cf80f8a3568e1bee2e7da7" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ + "bounded-collections", "derivative", "impl-trait-for-tuples", "log", "parity-scale-codec", "scale-info", "serde", - "sp-core 7.0.0", "sp-weights 4.0.0", "xcm-procedural", ] [[package]] name = "xcm-procedural" -version = "0.9.38" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.38#097ffd245c42aeff28cf80f8a3568e1bee2e7da7" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "Inflector", "proc-macro2", @@ -13234,9 +13882,9 @@ dependencies = [ [[package]] name = "xml-rs" -version = "0.8.13" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d8f380ae16a37b30e6a2cf67040608071384b1450c189e61bea3ff57cde922d" +checksum = "47430998a7b5d499ccee752b41567bc3afc57e1327dc855b1a2aa44ce29b5fa1" [[package]] name = "yamux" @@ -13258,11 +13906,17 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" +[[package]] +name = "yansi" +version = "1.0.0-rc" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ee746ad3851dd3bc40e4a028ab3b00b99278d929e48957bcb2d111874a7e43e" + [[package]] name = "yap" -version = "0.7.2" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc77f52dc9e9b10d55d3f4462c3b7fc393c4f17975d641542833ab2d3bc26ef" +checksum = "e2a7eb6d82a11e4d0b8e6bda8347169aff4ccd8235d039bba7c47482d977dcf7" [[package]] name = "yasna" @@ -13270,27 +13924,28 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd" dependencies = [ - "time 0.3.21", + "time 0.3.17", ] [[package]] name = "zeroize" -version = "1.6.0" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f" dependencies = [ "zeroize_derive", ] [[package]] name = "zeroize_derive" -version = "1.4.2" +version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +checksum = "44bf07cb3e50ea2003396695d58bf46bc9887a1f362260446fad6bc4e79bd36c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 1.0.109", + "synstructure", ] [[package]] @@ -13302,14 +13957,14 @@ dependencies = [ "aes 0.8.2", "byteorder", "bzip2", - "constant_time_eq", + "constant_time_eq 0.1.5", "crc32fast", - "crossbeam-utils 0.8.15", + "crossbeam-utils 0.8.14", "flate2", "hmac 0.12.1", "pbkdf2 0.11.0", "sha1", - "time 0.3.21", + "time 0.3.17", "zstd", ] @@ -13334,9 +13989,9 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.8+zstd.1.5.5" +version = "2.0.6+zstd.1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5556e6ee25d32df2586c098bbfa278803692a20d0ab9565e049480d52707ec8c" +checksum = "68a3f9792c0c3dc6c165840a75f47ae1f4da402c2d006881129579f6597e801b" dependencies = [ "cc", "libc", @@ -13344,136 +13999,406 @@ dependencies = [ ] [[patch.unused]] -name = "sc-executor" +name = "frame-benchmarking-cli" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "frame-election-provider-solution-type" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "frame-election-provider-support" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "frame-executive" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "frame-system-benchmarking" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "frame-system-rpc-runtime-api" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "frame-try-runtime" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" [[patch.unused]] -name = "sp-api" +name = "pallet-authority-discovery" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" [[patch.unused]] -name = "sp-api-proc-macro" +name = "pallet-babe" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" [[patch.unused]] -name = "sp-application-crypto" -version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +name = "pallet-bags-list" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" [[patch.unused]] -name = "sp-arithmetic" -version = "6.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +name = "pallet-bounties" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" [[patch.unused]] -name = "sp-core" -version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +name = "pallet-child-bounties" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" [[patch.unused]] -name = "sp-core-hashing" -version = "5.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +name = "pallet-collective" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" [[patch.unused]] -name = "sp-debug-derive" -version = "5.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +name = "pallet-conviction-voting" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" [[patch.unused]] -name = "sp-externalities" -version = "0.13.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +name = "pallet-democracy" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" [[patch.unused]] -name = "sp-io" -version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +name = "pallet-election-provider-multi-phase" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" [[patch.unused]] -name = "sp-keyring" -version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +name = "pallet-election-provider-support-benchmarking" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" [[patch.unused]] -name = "sp-keystore" -version = "0.13.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +name = "pallet-elections-phragmen" +version = "5.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" [[patch.unused]] -name = "sp-panic-handler" -version = "5.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +name = "pallet-fast-unstake" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" [[patch.unused]] -name = "sp-runtime" -version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +name = "pallet-grandpa" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" [[patch.unused]] -name = "sp-runtime-interface" -version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +name = "pallet-identity" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" [[patch.unused]] -name = "sp-runtime-interface-proc-macro" -version = "6.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +name = "pallet-im-online" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" [[patch.unused]] -name = "sp-state-machine" -version = "0.13.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +name = "pallet-indices" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" [[patch.unused]] -name = "sp-std" -version = "5.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +name = "pallet-multisig" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" [[patch.unused]] -name = "sp-storage" -version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +name = "pallet-nis" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" [[patch.unused]] -name = "sp-tracing" -version = "6.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +name = "pallet-nomination-pools" +version = "1.0.0" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" [[patch.unused]] -name = "sp-trie" -version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +name = "pallet-nomination-pools-benchmarking" +version = "1.0.0" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" [[patch.unused]] -name = "sp-version" -version = "5.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +name = "pallet-nomination-pools-runtime-api" +version = "1.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" [[patch.unused]] -name = "sp-version-proc-macro" +name = "pallet-offences" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" [[patch.unused]] -name = "sp-wasm-interface" -version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +name = "pallet-offences-benchmarking" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" [[patch.unused]] -name = "sp-weights" -version = "4.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +name = "pallet-preimage" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" [[patch.unused]] -name = "try-runtime-cli" +name = "pallet-proxy" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "pallet-ranked-collective" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "pallet-recovery" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "pallet-referenda" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "pallet-scheduler" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "pallet-session-benchmarking" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "pallet-society" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "pallet-staking" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "pallet-staking-reward-curve" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "pallet-staking-reward-fn" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "pallet-staking-runtime-api" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "pallet-state-trie-migration" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "pallet-sudo" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "pallet-tips" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "pallet-treasury" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "pallet-utility" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "pallet-vesting" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "pallet-whitelist" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "sc-authority-discovery" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "sc-basic-authorship" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "sc-cli" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "sc-client-db" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "sc-consensus-aura" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "sc-consensus-babe" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "sc-consensus-babe-rpc" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "sc-consensus-epochs" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "sc-consensus-slots" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "sc-informant" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "sc-network-bitswap" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "sc-network-light" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "sc-network-sync" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "sc-network-transactions" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "sc-proposer-metrics" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "sc-rpc-spec-v2" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "sc-service" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "sc-state-db" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "sc-storage-monitor" +version = "0.1.0" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "sc-sync-state-rpc" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "sc-sysinfo" +version = "6.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "sc-transaction-pool" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "sp-consensus-babe" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "sp-consensus-vrf" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "sp-npos-elections" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "sp-transaction-pool" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "sp-transaction-storage-proof" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "substrate-build-script-utils" +version = "3.0.0" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "substrate-frame-rpc-system" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "substrate-state-trie-migration-rpc" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" + +[[patch.unused]] +name = "substrate-wasm-builder" +version = "5.0.0-dev" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" [[patch.unused]] name = "try-runtime-cli" version = "0.10.0-dev" -source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.38#bcff60a227d455d95b4712b6cb356ce56b1ff672" +source = "git+https://github.com/paritytech//substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" diff --git a/Cargo.toml b/Cargo.toml index 2c741f495..8ee076d45 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,8 +32,8 @@ members = [ # "light-clients/ics10-grandpa-cw", "light-clients/ics11-beefy", # "light-clients/ics13-near", - "light-clients/icsxx-ethereum", - "light-clients/icsxx-ethereum-cw", +# "light-clients/icsxx-ethereum", +# "light-clients/icsxx-ethereum-cw", # "light-clients/ics11-beefy", # "light-clients/ics13-near", diff --git a/hyperspace/ethereum/src/ibc_provider.rs b/hyperspace/ethereum/src/ibc_provider.rs index 30e264b18..e85ec552f 100644 --- a/hyperspace/ethereum/src/ibc_provider.rs +++ b/hyperspace/ethereum/src/ibc_provider.rs @@ -1,8 +1,3 @@ -use std::{ - collections::HashSet, future::Future, pin::Pin, str::FromStr, sync::Arc, time::Duration, -}; - -use cast::executor::Output; use ethers::{ abi::{ encode, encode_packed, ethabi, Abi, AbiEncode, Detokenize, InvalidOutputType, ParamType, @@ -51,6 +46,9 @@ use ibc_proto::{ }; use primitives::{IbcProvider, UpdateType}; use prost::Message; +use std::{ + collections::HashSet, future::Future, pin::Pin, str::FromStr, sync::Arc, time::Duration, +}; use futures::{FutureExt, Stream, StreamExt}; use ibc::{ From f788643d557e1bf243db89bb35c3c04751930ccc Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Fri, 25 Aug 2023 16:09:58 -0300 Subject: [PATCH 05/43] fix recvPacket --- Cargo.lock | 1 + hyperspace/ethereum/Cargo.toml | 1 + hyperspace/ethereum/src/client.rs | 30 ++++++++++++---------- hyperspace/ethereum/src/ibc_provider.rs | 1 + hyperspace/ethereum/tests/sanity_checks.rs | 9 +++++-- hyperspace/ethereum/tests/utils.rs | 7 ++--- 6 files changed, 30 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 273e2e270..39e11746f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4609,6 +4609,7 @@ dependencies = [ "ibc-proto", "ibc-rpc", "ics07-tendermint", + "once_cell", "pallet-ibc", "prost", "serde", diff --git a/hyperspace/ethereum/Cargo.toml b/hyperspace/ethereum/Cargo.toml index cba1d3c8f..6bee6645c 100644 --- a/hyperspace/ethereum/Cargo.toml +++ b/hyperspace/ethereum/Cargo.toml @@ -36,6 +36,7 @@ tokio = { version = "1.19.2", features = ["full"] } tracing = "0.1.36" tracing-subscriber = "0.3.17" env_logger = "0.10.0" +once_cell = "1.18.0" [dev-dependencies] toml = "0.7.3" diff --git a/hyperspace/ethereum/src/client.rs b/hyperspace/ethereum/src/client.rs index 61fb2b4d2..9bfef3410 100644 --- a/hyperspace/ethereum/src/client.rs +++ b/hyperspace/ethereum/src/client.rs @@ -1,15 +1,17 @@ use async_trait::async_trait; -use std::{future::Future, pin::Pin, str::FromStr, sync::Arc}; - use ethers::{ - abi::{Address, ParamType, ParseError, Token}, + abi::{AbiEncode, Address, ParamType, ParseError, Token}, prelude::signer::SignerMiddlewareError, providers::{Http, Middleware, Provider, ProviderError, ProviderExt, Ws}, signers::{coins_bip39::English, LocalWallet, MnemonicBuilder, Signer}, types::{ Block, BlockId, BlockNumber, EIP1186ProofResponse, Filter, Log, NameOrAddress, H160, H256, + U256, }, + utils::keccak256, }; +use once_cell::sync::{Lazy, OnceCell}; +use std::{future::Future, ops::Add, pin::Pin, str::FromStr, sync::Arc}; use futures::{Stream, TryFutureExt}; use ibc::{ @@ -29,6 +31,9 @@ pub(crate) type EthRpcClient = ethers::prelude::SignerMiddleware< >; pub(crate) type WsEth = Provider; +pub static IBC_STORAGE_SLOT: Lazy = + Lazy::new(|| U256::from_big_endian(&keccak256(b"ibc.core")[..])); + // TODO: generate this from the contract automatically pub const COMMITMENTS_STORAGE_INDEX: u32 = 0; pub const CLIENT_IMPLS_STORAGE_INDEX: u32 = 3; @@ -321,22 +326,19 @@ impl EthereumClient { block_height: Option, storage_index: u32, ) -> impl Future> { - let key = ethers::utils::keccak256(key.as_bytes()); - - let key = hex::encode(key); + let key = keccak256(key.as_bytes()); + let var_name = format!("0x{}", hex::encode(key)); - let var_name = format!("0x{key}"); - let storage_index = format!("{storage_index}"); - let index = - cast::SimpleCast::index("bytes32", dbg!(&var_name), dbg!(&storage_index)).unwrap(); + let index = cast::SimpleCast::index( + "bytes32", + &var_name, + &format!("0x{}", hex::encode(IBC_STORAGE_SLOT.add(U256::from(storage_index)).encode())), + ) + .unwrap(); let client = self.http_rpc.clone(); let address = self.config.ibc_handler_address.clone(); - dbg!(&address); - dbg!(&H256::from_str(&index).unwrap()); - dbg!(&block_height); - async move { Ok(client .get_proof( diff --git a/hyperspace/ethereum/src/ibc_provider.rs b/hyperspace/ethereum/src/ibc_provider.rs index e85ec552f..24c52728b 100644 --- a/hyperspace/ethereum/src/ibc_provider.rs +++ b/hyperspace/ethereum/src/ibc_provider.rs @@ -504,6 +504,7 @@ impl IbcProvider for EthereumClient { Arc::clone(&self.http_rpc), ); + // channels[portId][channelId] let binding = contract .method::<_, (ChannelData, bool)>( "getChannel", diff --git a/hyperspace/ethereum/tests/sanity_checks.rs b/hyperspace/ethereum/tests/sanity_checks.rs index 80bc7ca73..b81c8f611 100644 --- a/hyperspace/ethereum/tests/sanity_checks.rs +++ b/hyperspace/ethereum/tests/sanity_checks.rs @@ -149,6 +149,8 @@ async fn deploy_yui_ibc_and_mock_client_fixture() -> DeployYuiIbcMockClient { ) .await; + println!("Mock client address: {:?}", ibc_mock_client.address()); + // todo: some interactions between the mock client and the ibc handler to verify behaviour. DeployYuiIbcMockClient { @@ -195,7 +197,7 @@ async fn deploy_mock_client_fixture(deploy: &DeployYuiIbcMockClient) -> ClientId .create_client(utils::mock::create_client_msg("mock-client")) .await; println!("client id: {}", string); - println!("ibc_handler contract addr: {:?}", deploy.yui_ibc.diamond.address()); + println!("Diamond contract addr: {:?}", deploy.yui_ibc.diamond.address()); ClientId(string) } @@ -216,7 +218,10 @@ fn deploy_mock_module_fixture( let contract = clients.find_first("MockModule").expect("no MockModule in project output"); let constructor_args = (Token::Address(deploy.yui_ibc.diamond.address()),); - utils::deploy_contract(contract, constructor_args, deploy.client.clone()).await + let contract = + utils::deploy_contract(contract, constructor_args, deploy.client.clone()).await; + println!("Mock module address: {:?}", x.address()); + contract } } diff --git a/hyperspace/ethereum/tests/utils.rs b/hyperspace/ethereum/tests/utils.rs index 6d82050b4..0bf449a93 100644 --- a/hyperspace/ethereum/tests/utils.rs +++ b/hyperspace/ethereum/tests/utils.rs @@ -511,9 +511,6 @@ where let signatures = contract.abi().functions.keys().cloned().collect::>(); signatures .into_iter() - .inspect(|x| { - dbg!(x); - }) .filter(|val| val != "init(bytes)") .map(|val| (val.clone(), contract.abi().function(&val).unwrap().short_signature())) .collect() @@ -557,10 +554,13 @@ where let acc = client.default_sender().unwrap(); + println!("Sender account: {acc:?}"); + let contract = diamond_project_output.find_first("DiamondInit").unwrap(); let (abi, bytecode, _) = contract.clone().into_parts(); let factory = ContractFactory::new(abi.unwrap(), bytecode.unwrap(), client.clone()); let diamond_init = factory.deploy(()).unwrap().send().await.unwrap(); + println!("Diamond init address: {:?}", diamond_init.address()); let mut sigs = HashMap::<[u8; 4], (String, String)>::new(); let mut facet_cuts = vec![]; @@ -574,6 +574,7 @@ where let factory = ContractFactory::new(abi.unwrap(), bytecode.unwrap(), client.clone()); let facet = factory.deploy(()).unwrap().send().await.unwrap(); let facet_address = facet.address(); + println!("Deployed {facet_name} on {facet_address:?}"); deployed_facets.push(facet.clone()); let selectors = get_selectors(&facet); From 12ec8d231910638af8ff66a7fc98d0670bf9085d Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Fri, 25 Aug 2023 16:19:19 -0300 Subject: [PATCH 06/43] a little fix --- hyperspace/ethereum/tests/sanity_checks.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hyperspace/ethereum/tests/sanity_checks.rs b/hyperspace/ethereum/tests/sanity_checks.rs index b81c8f611..a28c86c31 100644 --- a/hyperspace/ethereum/tests/sanity_checks.rs +++ b/hyperspace/ethereum/tests/sanity_checks.rs @@ -220,7 +220,7 @@ fn deploy_mock_module_fixture( let constructor_args = (Token::Address(deploy.yui_ibc.diamond.address()),); let contract = utils::deploy_contract(contract, constructor_args, deploy.client.clone()).await; - println!("Mock module address: {:?}", x.address()); + println!("Mock module address: {:?}", contract.address()); contract } } From e718eaface1001ce038a658e2236a74056f5dce5 Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Thu, 31 Aug 2023 15:58:57 -0300 Subject: [PATCH 07/43] implement some queries --- Cargo.lock | 268 +++++------ hyperspace/core/src/chain.rs | 4 +- hyperspace/core/src/macros.rs | 1 + hyperspace/cosmos/src/provider.rs | 1 + hyperspace/ethereum/src/chain.rs | 16 +- hyperspace/ethereum/src/client.rs | 81 ++-- hyperspace/ethereum/src/ibc_provider.rs | 476 +++++++++++++------ hyperspace/ethereum/src/lib.rs | 1 + hyperspace/ethereum/src/light_client_sync.rs | 5 +- hyperspace/ethereum/src/utils.rs | 328 +++++++++++++ hyperspace/ethereum/tests/sanity_checks.rs | 264 +++++----- hyperspace/ethereum/tests/utils.rs | 347 +++----------- hyperspace/parachain/src/provider.rs | 1 + hyperspace/primitives/src/lib.rs | 1 + 14 files changed, 1040 insertions(+), 754 deletions(-) create mode 100644 hyperspace/ethereum/src/utils.rs diff --git a/Cargo.lock b/Cargo.lock index 39e11746f..e0c832a75 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -367,7 +367,7 @@ dependencies = [ "parking", "polling", "slab", - "socket2", + "socket2 0.4.9", "waker-fn", "windows-sys 0.42.0", ] @@ -390,7 +390,7 @@ checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" dependencies = [ "async-stream-impl", "futures-core", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.13", ] [[package]] @@ -424,7 +424,7 @@ dependencies = [ "futures-io", "futures-util", "log", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.13", "rustls-native-certs 0.6.2", "tokio", "tokio-rustls 0.23.4", @@ -452,7 +452,7 @@ dependencies = [ "futures-sink", "futures-util", "memchr", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.13", ] [[package]] @@ -515,7 +515,7 @@ dependencies = [ "memchr", "mime", "percent-encoding", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.13", "rustversion", "serde", "sync_wrapper", @@ -1030,20 +1030,6 @@ dependencies = [ "serde", ] -[[package]] -name = "cargo_metadata" -version = "0.15.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a" -dependencies = [ - "camino", - "cargo-platform", - "semver", - "serde", - "serde_json", - "thiserror", -] - [[package]] name = "cargo_metadata" version = "0.17.0" @@ -1065,7 +1051,7 @@ source = "git+https://github.com/foundry-rs/foundry#d4f626bb7f96d46358997d4b27f7 dependencies = [ "chrono", "ethers-contract 2.0.8 (git+https://github.com/gakonst/ethers-rs)", - "ethers-core 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-core 2.0.8", "ethers-etherscan 2.0.8 (git+https://github.com/gakonst/ethers-rs)", "ethers-providers 2.0.8 (git+https://github.com/gakonst/ethers-rs)", "ethers-signers 2.0.8 (git+https://github.com/gakonst/ethers-rs)", @@ -1437,6 +1423,18 @@ dependencies = [ "crossbeam-utils 0.8.14", ] +[[package]] +name = "const-hex" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08849ed393c907c90016652a01465a12d86361cd38ad2a7de026c56a520cc259" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures", + "hex", + "serde", +] + [[package]] name = "const-oid" version = "0.9.4" @@ -2665,12 +2663,12 @@ checksum = "96b4026b97da8281276744741fac7eb385da905f6093c583331fa2953fdd4253" dependencies = [ "ethers-addressbook 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "ethers-contract 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "ethers-core 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ethers-core 2.0.9", "ethers-etherscan 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "ethers-middleware 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "ethers-providers 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "ethers-signers 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "ethers-solc 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ethers-solc 2.0.9", ] [[package]] @@ -2680,12 +2678,12 @@ source = "git+https://github.com/gakonst/ethers-rs#5145992e4b03fdaebcc4d35aa7ee4 dependencies = [ "ethers-addressbook 2.0.8 (git+https://github.com/gakonst/ethers-rs)", "ethers-contract 2.0.8 (git+https://github.com/gakonst/ethers-rs)", - "ethers-core 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-core 2.0.8", "ethers-etherscan 2.0.8 (git+https://github.com/gakonst/ethers-rs)", "ethers-middleware 2.0.8 (git+https://github.com/gakonst/ethers-rs)", "ethers-providers 2.0.8 (git+https://github.com/gakonst/ethers-rs)", "ethers-signers 2.0.8 (git+https://github.com/gakonst/ethers-rs)", - "ethers-solc 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-solc 2.0.8", ] [[package]] @@ -2694,7 +2692,7 @@ version = "2.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edcb6ffefc230d8c42874c51b28dc11dbb8de50b27a8fdf92648439d6baa68dc" dependencies = [ - "ethers-core 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ethers-core 2.0.9", "once_cell", "serde", "serde_json", @@ -2705,7 +2703,7 @@ name = "ethers-addressbook" version = "2.0.8" source = "git+https://github.com/gakonst/ethers-rs#5145992e4b03fdaebcc4d35aa7ee44504ca82b5a" dependencies = [ - "ethers-core 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-core 2.0.8", "once_cell", "serde", "serde_json", @@ -2719,7 +2717,7 @@ checksum = "0d4719a44c3d37ab07c6dea99ab174068d8c35e441b60b6c20ce4e48357273e8" dependencies = [ "ethers-contract-abigen 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "ethers-contract-derive 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "ethers-core 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ethers-core 2.0.9", "ethers-providers 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "ethers-signers 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "futures-util", @@ -2738,7 +2736,7 @@ source = "git+https://github.com/gakonst/ethers-rs#5145992e4b03fdaebcc4d35aa7ee4 dependencies = [ "ethers-contract-abigen 2.0.8 (git+https://github.com/gakonst/ethers-rs)", "ethers-contract-derive 2.0.8 (git+https://github.com/gakonst/ethers-rs)", - "ethers-core 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-core 2.0.8", "ethers-providers 2.0.8 (git+https://github.com/gakonst/ethers-rs)", "ethers-signers 2.0.8 (git+https://github.com/gakonst/ethers-rs)", "futures-util", @@ -2758,7 +2756,7 @@ checksum = "155ea1b84d169d231317ed86e307af6f2bed6b40dd17e5e94bc84da21cadb21c" dependencies = [ "Inflector", "dunce", - "ethers-core 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ethers-core 2.0.9", "ethers-etherscan 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "eyre", "hex", @@ -2781,7 +2779,7 @@ source = "git+https://github.com/gakonst/ethers-rs#5145992e4b03fdaebcc4d35aa7ee4 dependencies = [ "Inflector", "dunce", - "ethers-core 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-core 2.0.8", "eyre", "hex", "prettyplease 0.2.12", @@ -2803,7 +2801,7 @@ checksum = "8567ff196c4a37c1a8c90ec73bda0ad2062e191e4f0a6dc4d943e2ec4830fc88" dependencies = [ "Inflector", "ethers-contract-abigen 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "ethers-core 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ethers-core 2.0.9", "hex", "proc-macro2", "quote", @@ -2818,7 +2816,7 @@ source = "git+https://github.com/gakonst/ethers-rs#5145992e4b03fdaebcc4d35aa7ee4 dependencies = [ "Inflector", "ethers-contract-abigen 2.0.8 (git+https://github.com/gakonst/ethers-rs)", - "ethers-core 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-core 2.0.8", "hex", "proc-macro2", "quote", @@ -2829,19 +2827,18 @@ dependencies = [ [[package]] name = "ethers-core" version = "2.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60ca2514feb98918a0a31de7e1983c29f2267ebf61b2dc5d4294f91e5b866623" +source = "git+https://github.com/gakonst/ethers-rs#5145992e4b03fdaebcc4d35aa7ee44504ca82b5a" dependencies = [ "arrayvec 0.7.2", "bytes", - "cargo_metadata 0.15.4", + "cargo_metadata", "chrono", "elliptic-curve 0.13.5", "ethabi", "generic-array 0.14.7", "hex", "k256 0.13.1", - "num_enum", + "num_enum 0.6.1", "once_cell", "open-fastrlp", "rand 0.8.5", @@ -2858,19 +2855,20 @@ dependencies = [ [[package]] name = "ethers-core" -version = "2.0.8" -source = "git+https://github.com/gakonst/ethers-rs#5145992e4b03fdaebcc4d35aa7ee44504ca82b5a" +version = "2.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c29523f73c12753165781c6e5dc11c84d3e44c080a15f7c6cfbd70b514cb6f1" dependencies = [ "arrayvec 0.7.2", "bytes", - "cargo_metadata 0.17.0", + "cargo_metadata", "chrono", + "const-hex", "elliptic-curve 0.13.5", "ethabi", "generic-array 0.14.7", - "hex", "k256 0.13.1", - "num_enum", + "num_enum 0.7.0", "once_cell", "open-fastrlp", "rand 0.8.5", @@ -2891,7 +2889,7 @@ version = "2.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22b3a8269d3df0ed6364bc05b4735b95f4bf830ce3aef87d5e760fb0e93e5b91" dependencies = [ - "ethers-core 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ethers-core 2.0.9", "reqwest", "semver", "serde", @@ -2905,8 +2903,8 @@ name = "ethers-etherscan" version = "2.0.8" source = "git+https://github.com/gakonst/ethers-rs#5145992e4b03fdaebcc4d35aa7ee44504ca82b5a" dependencies = [ - "ethers-core 2.0.8 (git+https://github.com/gakonst/ethers-rs)", - "ethers-solc 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-core 2.0.8", + "ethers-solc 2.0.8", "reqwest", "semver", "serde", @@ -2924,7 +2922,7 @@ dependencies = [ "async-trait", "auto_impl", "ethers-contract 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "ethers-core 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ethers-core 2.0.9", "ethers-etherscan 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "ethers-providers 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "ethers-signers 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2950,7 +2948,7 @@ dependencies = [ "async-trait", "auto_impl", "ethers-contract 2.0.8 (git+https://github.com/gakonst/ethers-rs)", - "ethers-core 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-core 2.0.8", "ethers-etherscan 2.0.8 (git+https://github.com/gakonst/ethers-rs)", "ethers-providers 2.0.8 (git+https://github.com/gakonst/ethers-rs)", "ethers-signers 2.0.8 (git+https://github.com/gakonst/ethers-rs)", @@ -2979,7 +2977,7 @@ dependencies = [ "base64 0.21.0", "bytes", "enr 0.8.1", - "ethers-core 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ethers-core 2.0.9", "futures-channel", "futures-core", "futures-timer", @@ -3015,7 +3013,7 @@ dependencies = [ "base64 0.21.0", "bytes", "enr 0.9.0", - "ethers-core 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-core 2.0.8", "futures-core", "futures-timer", "futures-util", @@ -3051,7 +3049,7 @@ dependencies = [ "coins-bip39", "elliptic-curve 0.13.5", "eth-keystore", - "ethers-core 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ethers-core 2.0.9", "hex", "rand 0.8.5", "sha2 0.10.6", @@ -3070,7 +3068,7 @@ dependencies = [ "coins-ledger", "elliptic-curve 0.13.5", "eth-keystore", - "ethers-core 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-core 2.0.8", "futures-executor", "futures-util", "hex", @@ -3089,12 +3087,13 @@ dependencies = [ [[package]] name = "ethers-solc" version = "2.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6c2b9625a2c639d46625f88acc2092a3cb35786c37f7c2128b3ca20f639b3c" +source = "git+https://github.com/gakonst/ethers-rs#5145992e4b03fdaebcc4d35aa7ee44504ca82b5a" dependencies = [ "cfg-if 1.0.0", + "dirs", "dunce", - "ethers-core 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ethers-core 2.0.8", + "futures-util", "glob", "hex", "home", @@ -3107,8 +3106,10 @@ dependencies = [ "semver", "serde", "serde_json", + "sha2 0.10.6", "solang-parser", - "svm-rs 0.2.23", + "svm-rs", + "svm-rs-builds", "thiserror", "tiny-keccak", "tokio", @@ -3119,16 +3120,16 @@ dependencies = [ [[package]] name = "ethers-solc" -version = "2.0.8" -source = "git+https://github.com/gakonst/ethers-rs#5145992e4b03fdaebcc4d35aa7ee44504ca82b5a" +version = "2.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66559c8f774712df303c907d087275a52a2046b256791aaa566d5abc8ea66731" dependencies = [ "cfg-if 1.0.0", + "const-hex", "dirs", "dunce", - "ethers-core 2.0.8 (git+https://github.com/gakonst/ethers-rs)", - "futures-util", + "ethers-core 2.0.9", "glob", - "hex", "home", "md-5 0.10.5", "num_cpus", @@ -3139,10 +3140,8 @@ dependencies = [ "semver", "serde", "serde_json", - "sha2 0.10.6", "solang-parser", - "svm-rs 0.3.0", - "svm-rs-builds", + "svm-rs", "thiserror", "tiny-keccak", "tokio", @@ -3330,7 +3329,7 @@ version = "0.2.0" source = "git+https://github.com/foundry-rs/foundry#d4f626bb7f96d46358997d4b27f79358cb2b3401" dependencies = [ "ariadne", - "ethers-core 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-core 2.0.8", "foundry-config", "itertools", "semver", @@ -3363,7 +3362,7 @@ source = "git+https://github.com/foundry-rs/foundry#d4f626bb7f96d46358997d4b27f7 dependencies = [ "ethers-contract 2.0.8 (git+https://github.com/gakonst/ethers-rs)", "ethers-contract-abigen 2.0.8 (git+https://github.com/gakonst/ethers-rs)", - "ethers-core 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-core 2.0.8", "ethers-providers 2.0.8 (git+https://github.com/gakonst/ethers-rs)", "eyre", "foundry-macros", @@ -3379,11 +3378,11 @@ dependencies = [ "clap 4.1.14", "comfy-table", "dunce", - "ethers-core 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-core 2.0.8", "ethers-etherscan 2.0.8 (git+https://github.com/gakonst/ethers-rs)", "ethers-middleware 2.0.8 (git+https://github.com/gakonst/ethers-rs)", "ethers-providers 2.0.8 (git+https://github.com/gakonst/ethers-rs)", - "ethers-solc 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-solc 2.0.8", "eyre", "foundry-config", "foundry-macros", @@ -3408,9 +3407,9 @@ source = "git+https://github.com/foundry-rs/foundry#d4f626bb7f96d46358997d4b27f7 dependencies = [ "Inflector", "dirs-next", - "ethers-core 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-core 2.0.8", "ethers-etherscan 2.0.8 (git+https://github.com/gakonst/ethers-rs)", - "ethers-solc 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-solc 2.0.8", "eyre", "figment", "globset", @@ -3471,7 +3470,7 @@ name = "foundry-macros" version = "0.2.0" source = "git+https://github.com/foundry-rs/foundry#d4f626bb7f96d46358997d4b27f79358cb2b3401" dependencies = [ - "ethers-core 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-core 2.0.8", "foundry-macros-impl", "serde", "serde_json", @@ -3495,10 +3494,10 @@ dependencies = [ "dunce", "ethers-addressbook 2.0.8 (git+https://github.com/gakonst/ethers-rs)", "ethers-contract 2.0.8 (git+https://github.com/gakonst/ethers-rs)", - "ethers-core 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-core 2.0.8", "ethers-etherscan 2.0.8 (git+https://github.com/gakonst/ethers-rs)", "ethers-providers 2.0.8 (git+https://github.com/gakonst/ethers-rs)", - "ethers-solc 2.0.8 (git+https://github.com/gakonst/ethers-rs)", + "ethers-solc 2.0.8", "eyre", "forge-fmt", "futures", @@ -3721,7 +3720,7 @@ dependencies = [ "futures-io", "memchr", "parking", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.13", "waker-fn", ] @@ -3792,7 +3791,7 @@ dependencies = [ "futures-sink", "futures-task", "memchr", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.13", "pin-utils", "slab", ] @@ -4210,15 +4209,6 @@ dependencies = [ "libc", ] -[[package]] -name = "hermit-abi" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] - [[package]] name = "hermit-abi" version = "0.3.0" @@ -4346,7 +4336,7 @@ checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" dependencies = [ "bytes", "http", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.13", ] [[package]] @@ -4389,8 +4379,8 @@ dependencies = [ "httparse", "httpdate", "itoa", - "pin-project-lite 0.2.9", - "socket2", + "pin-project-lite 0.2.13", + "socket2 0.4.9", "tokio", "tower-service", "tracing", @@ -4471,7 +4461,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" dependencies = [ "hyper", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.13", "tokio", "tokio-io-timeout", ] @@ -4598,7 +4588,7 @@ dependencies = [ "elliptic-curve 0.13.5", "env_logger 0.10.0", "ethers 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "ethers-solc 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ethers-solc 2.0.9", "futures", "git2", "hex", @@ -5206,7 +5196,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd302af1b90f2463a98fa5ad469fc212c8e3175a41c3068601bfa2727591c5be" dependencies = [ - "socket2", + "socket2 0.4.9", "widestring", "winapi", "winreg", @@ -5709,7 +5699,7 @@ dependencies = [ "log", "rand 0.8.5", "smallvec 1.10.0", - "socket2", + "socket2 0.4.9", "tokio", "trust-dns-proto", "void", @@ -5870,7 +5860,7 @@ dependencies = [ "libc", "libp2p-core", "log", - "socket2", + "socket2 0.4.9", "tokio", ] @@ -6797,11 +6787,11 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.2.6", + "hermit-abi 0.3.0", "libc", ] @@ -6811,7 +6801,16 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a015b430d3c108a207fd776d2e2196aaf8b1cf8cf93253e3a097ff3085076a1" dependencies = [ - "num_enum_derive", + "num_enum_derive 0.6.1", +] + +[[package]] +name = "num_enum" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70bf6736f74634d299d00086f02986875b3c2d924781a6a2cb6c201e73da0ceb" +dependencies = [ + "num_enum_derive 0.7.0", ] [[package]] @@ -6826,6 +6825,18 @@ dependencies = [ "syn 2.0.28", ] +[[package]] +name = "num_enum_derive" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56ea360eafe1022f7cc56cd7b869ed57330fb2453d0c7831d99b74c65d2f5597" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.28", +] + [[package]] name = "number_prefix" version = "0.4.0" @@ -7675,9 +7686,9 @@ checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777" [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] name = "pin-utils" @@ -8453,7 +8464,7 @@ dependencies = [ "mime", "once_cell", "percent-encoding", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.13", "rustls 0.21.6", "rustls-pemfile", "serde", @@ -8765,7 +8776,7 @@ dependencies = [ "log", "md-5 0.9.1", "percent-encoding", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.13", "rusoto_credential", "rustc_version", "serde", @@ -10272,6 +10283,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "socket2" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877" +dependencies = [ + "libc", + "windows-sys 0.48.0", +] + [[package]] name = "soketto" version = "0.7.1" @@ -11595,26 +11616,6 @@ dependencies = [ "sp-core-hashing 8.0.0", ] -[[package]] -name = "svm-rs" -version = "0.2.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a04fc4f5cd35c700153b233f5575ccb3237e0f941fa5049d9e98254d10bf2fe" -dependencies = [ - "fs2", - "hex", - "home", - "once_cell", - "reqwest", - "semver", - "serde", - "serde_json", - "sha2 0.10.6", - "thiserror", - "url", - "zip", -] - [[package]] name = "svm-rs" version = "0.3.0" @@ -11645,7 +11646,7 @@ dependencies = [ "hex", "semver", "serde_json", - "svm-rs 0.3.0", + "svm-rs", ] [[package]] @@ -11723,9 +11724,9 @@ checksum = "9410d0f6853b1d94f0e519fb95df60f29d2c1eff2d921ffdf01a4c8a3b54f12d" [[package]] name = "tempfile" -version = "3.7.1" +version = "3.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc02fddf48964c42031a0b3fe0428320ecf3a73c401040fc0096f97794310651" +checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" dependencies = [ "cfg-if 1.0.0", "fastrand 2.0.0", @@ -12059,20 +12060,19 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.29.1" +version = "1.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" +checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" dependencies = [ - "autocfg", "backtrace", "bytes", "libc", "mio", "num_cpus", "parking_lot 0.12.1", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.13", "signal-hook-registry", - "socket2", + "socket2 0.5.3", "tokio-macros", "windows-sys 0.48.0", ] @@ -12083,7 +12083,7 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" dependencies = [ - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.13", "tokio", ] @@ -12137,7 +12137,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d660770404473ccd7bc9f8b28494a811bc18542b915c0855c51e8f419d5223ce" dependencies = [ "futures-core", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.13", "tokio", "tokio-util", ] @@ -12167,7 +12167,7 @@ dependencies = [ "futures-core", "futures-io", "futures-sink", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.13", "tokio", "tracing", ] @@ -12278,7 +12278,7 @@ dependencies = [ "futures-util", "indexmap 1.9.2", "pin-project", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.13", "rand 0.8.5", "slab", "tokio", @@ -12301,7 +12301,7 @@ dependencies = [ "http", "http-body", "http-range-header", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.13", "tower", "tower-layer", "tower-service", @@ -12327,7 +12327,7 @@ checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ "cfg-if 1.0.0", "log", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.13", "tracing-attributes", "tracing-core", ] @@ -12505,7 +12505,7 @@ dependencies = [ "lazy_static", "rand 0.8.5", "smallvec 1.10.0", - "socket2", + "socket2 0.4.9", "thiserror", "tinyvec", "tokio", @@ -13408,7 +13408,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f08dfd7a6e3987e255c4dbe710dde5d94d0f0574f8a21afa95d171376c143106" dependencies = [ "log", - "socket2", + "socket2 0.4.9", "thiserror", "tokio", "webrtc-util", diff --git a/hyperspace/core/src/chain.rs b/hyperspace/core/src/chain.rs index 2c0a6737e..2ae86d789 100644 --- a/hyperspace/core/src/chain.rs +++ b/hyperspace/core/src/chain.rs @@ -24,7 +24,9 @@ use async_trait::async_trait; #[cfg(feature = "cosmos")] use cosmos::client::{CosmosClient, CosmosClientConfig}; #[cfg(feature = "ethereum")] -use ethereum::{client::EthereumClient as EthereumClient, config::Config as EthereumClientConfig}; +use ethereum::client::EthereumClient; +#[cfg(feature = "ethereum")] +use ethereum::config::Config as EthereumClientConfig; use futures::Stream; #[cfg(any(test, feature = "testing"))] use ibc::applications::transfer::msgs::transfer::MsgTransfer; diff --git a/hyperspace/core/src/macros.rs b/hyperspace/core/src/macros.rs index 8ef627984..f5aec6651 100644 --- a/hyperspace/core/src/macros.rs +++ b/hyperspace/core/src/macros.rs @@ -414,6 +414,7 @@ macro_rules! chains { async fn query_received_packets( &self, + at: Height, channel_id: ChannelId, port_id: PortId, seqs: Vec, diff --git a/hyperspace/cosmos/src/provider.rs b/hyperspace/cosmos/src/provider.rs index 179b35cc6..04c456e5e 100644 --- a/hyperspace/cosmos/src/provider.rs +++ b/hyperspace/cosmos/src/provider.rs @@ -715,6 +715,7 @@ where async fn query_received_packets( &self, + at: Height, channel_id: ChannelId, port_id: PortId, seqs: Vec, diff --git a/hyperspace/ethereum/src/chain.rs b/hyperspace/ethereum/src/chain.rs index 34eaa73d4..445619e78 100644 --- a/hyperspace/ethereum/src/chain.rs +++ b/hyperspace/ethereum/src/chain.rs @@ -2,12 +2,11 @@ use std::time::Duration; use ethers::providers::Middleware; use futures::{Stream, StreamExt}; -use ibc::core::ics02_client::events::UpdateClient; -use ibc::Height; +use ibc::{core::ics02_client::events::UpdateClient, Height}; use pallet_ibc::light_clients::AnyClientMessage; -use primitives::{Chain, CommonClientState, LightClientSync, MisbehaviourHandler}; +use primitives::{Chain, CommonClientState, MisbehaviourHandler}; -use crate::{client::EthereumClient, ibc_provider::BlockHeight}; +use crate::client::EthereumClient; #[async_trait::async_trait] impl MisbehaviourHandler for EthereumClient { @@ -37,7 +36,8 @@ impl Chain for EthereumClient { &self, msg: Vec, ) -> Result { - // TODO: estimate gas for the tx. Convert any to another type (see `wrap_any_msg_into_wasm` for an example) + // TODO: estimate gas for the tx. Convert any to another type (see `wrap_any_msg_into_wasm` + // for an example) Ok(1) } @@ -71,7 +71,10 @@ impl Chain for EthereumClient { todo!("submit to ethereum") } - async fn query_client_message(&self, update: UpdateClient) -> Result { + async fn query_client_message( + &self, + update: UpdateClient, + ) -> Result { todo!("used for misbehaviour; skip for now") } @@ -79,7 +82,6 @@ impl Chain for EthereumClient { block_height } - async fn handle_error(&mut self, error: &anyhow::Error) -> Result<(), anyhow::Error> { tracing::error!(?error, "handle-error"); Ok(()) diff --git a/hyperspace/ethereum/src/client.rs b/hyperspace/ethereum/src/client.rs index 9bfef3410..3a06b8ec4 100644 --- a/hyperspace/ethereum/src/client.rs +++ b/hyperspace/ethereum/src/client.rs @@ -1,18 +1,19 @@ +use crate::{ + config::Config, + utils::{DeployYuiIbc, ProviderImpl}, +}; use async_trait::async_trait; use ethers::{ - abi::{AbiEncode, Address, ParamType, ParseError, Token}, - prelude::signer::SignerMiddlewareError, - providers::{Http, Middleware, Provider, ProviderError, ProviderExt, Ws}, - signers::{coins_bip39::English, LocalWallet, MnemonicBuilder, Signer}, - types::{ - Block, BlockId, BlockNumber, EIP1186ProofResponse, Filter, Log, NameOrAddress, H160, H256, - U256, + abi::{AbiEncode, Address, ParamType, Token}, + prelude::{ + coins_bip39::English, signer::SignerMiddlewareError, BlockId, BlockNumber, + EIP1186ProofResponse, Filter, LocalWallet, Log, MnemonicBuilder, NameOrAddress, H256, }, + providers::{Http, Middleware, Provider, ProviderError, ProviderExt, Ws}, + signers::Signer, + types::U256, utils::keccak256, }; -use once_cell::sync::{Lazy, OnceCell}; -use std::{future::Future, ops::Add, pin::Pin, str::FromStr, sync::Arc}; - use futures::{Stream, TryFutureExt}; use ibc::{ applications::transfer::{msgs::transfer::MsgTransfer, PrefixedCoin}, @@ -20,11 +21,11 @@ use ibc::{ Height, }; use ibc_primitives::Timeout; +use once_cell::sync::Lazy; use primitives::CommonClientState; +use std::{future::Future, ops::Add, pin::Pin, str::FromStr, sync::Arc}; use thiserror::Error; -use crate::config::Config; - pub(crate) type EthRpcClient = ethers::prelude::SignerMiddleware< ethers::providers::Provider, ethers::signers::Wallet, @@ -47,6 +48,7 @@ pub struct EthereumClient { pub(crate) config: Config, /// Common relayer data pub common_state: CommonClientState, + pub yui: DeployYuiIbc, ProviderImpl>, } pub type MiddlewareErrorType = SignerMiddlewareError< @@ -89,7 +91,10 @@ pub struct AckPacket { } impl EthereumClient { - pub async fn new(mut config: Config) -> Result { + pub async fn new( + mut config: Config, + yui: DeployYuiIbc, ProviderImpl>, + ) -> Result { let client = Provider::::try_from(config.http_rpc_url.to_string()) .map_err(|_| ClientError::UriParseError(config.http_rpc_url.clone()))?; @@ -125,6 +130,7 @@ impl EthereumClient { ws_uri: config.ws_rpc_url.clone(), config, common_state: Default::default(), + yui, }) } @@ -137,24 +143,23 @@ impl EthereumClient { pub async fn generated_channel_identifiers( &self, from_block: BlockNumber, - ) -> Result, ClientError> { + ) -> Result, ClientError> { let filter = Filter::new() - .from_block(from_block) + .from_block(BlockNumber::Earliest) + // .from_block(from_block) .to_block(BlockNumber::Latest) .address(self.config.ibc_handler_address) - .event("GeneratedChannelIdentifier(string)"); + .event("OpenInitChannel(string,string)"); let logs = self.http_rpc.get_logs(&filter).await.unwrap(); let v = logs .into_iter() .map(|log| { - ethers::abi::decode(&[ParamType::String], &log.data.0) - .unwrap() - .into_iter() - .next() - .unwrap() - .to_string() + let toks = + ethers::abi::decode(&[ParamType::String, ParamType::String], &log.data.0) + .unwrap(); + (toks[0].to_string(), toks[1].to_string()) }) .collect(); @@ -424,25 +429,21 @@ impl EthereumClient { pub fn query_client_impl_address( &self, client_id: ClientId, - at: ibc::Height, - ) -> impl Future, bool), ClientError>> { + at: Height, + ) -> impl Future, bool), ClientError>> + '_ { let fut = self.eth_query_proof( client_id.as_str(), Some(at.revision_height), CLIENT_IMPLS_STORAGE_INDEX, ); - let contract = crate::contract::light_client_contract( - self.config.ibc_handler_address.clone(), - Arc::clone(&self.http_rpc), - ); - async move { let proof = fut.await?; if let Some(storage_proof) = proof.storage_proof.first() { if !storage_proof.value.is_zero() { - let binding = contract + let binding = self + .yui .method("getClientState", (client_id.as_str().to_owned(),)) .expect("contract is missing getClientState"); @@ -467,14 +468,10 @@ impl EthereumClient { port_id: String, channel_id: String, sequence: u64, - ) -> impl Future> { - let client = self.http_rpc.clone(); - let address = self.config.ibc_handler_address.clone(); - - let contract = crate::contract::ibc_handler(address, Arc::clone(&client)); - + ) -> impl Future> + '_ { async move { - let binding = contract + let binding = self + .yui .method("hasPacketReceipt", (port_id, channel_id, sequence)) .expect("contract is missing hasPacketReceipt"); @@ -496,14 +493,10 @@ impl EthereumClient { port_id: String, channel_id: String, sequence: u64, - ) -> impl Future> { - let client = self.http_rpc.clone(); - let address = self.config.ibc_handler_address.clone(); - - let contract = crate::contract::ibc_handler(address, Arc::clone(&client)); - + ) -> impl Future> + '_ { async move { - let binding = contract + let binding = self + .yui .method("hasAcknowledgement", (port_id, channel_id, sequence)) .expect("contract is missing hasAcknowledgement"); diff --git a/hyperspace/ethereum/src/ibc_provider.rs b/hyperspace/ethereum/src/ibc_provider.rs index 24c52728b..889edd725 100644 --- a/hyperspace/ethereum/src/ibc_provider.rs +++ b/hyperspace/ethereum/src/ibc_provider.rs @@ -1,14 +1,10 @@ use ethers::{ - abi::{ - encode, encode_packed, ethabi, Abi, AbiEncode, Detokenize, InvalidOutputType, ParamType, - Token, Tokenizable, Topic, - }, + abi::{encode, AbiEncode, Detokenize, ParamType, Token, Tokenizable}, contract::abigen, - middleware::contract::Contract, + prelude::Topic, providers::Middleware, types::{ - BlockId, BlockNumber, EIP1186ProofResponse, Filter, StorageProof, ValueOrArray, H256, I256, - U256, + BlockId, BlockNumber, EIP1186ProofResponse, Filter, StorageProof, ValueOrArray, H256, U256, }, utils::keccak256, }; @@ -22,7 +18,7 @@ use ibc::{ ics23_commitment::commitment::CommitmentPrefix, ics24_host::{ identifier::{ChannelId, ClientId, ConnectionId, PortId}, - path::{AcksPath, CommitmentsPath, ReceiptsPath, SeqRecvsPath}, + path::{AcksPath, CommitmentsPath, ReceiptsPath}, Path, }, }, @@ -39,8 +35,7 @@ use ibc_proto::{ }, client::v1::{QueryClientStateResponse, QueryConsensusStateResponse}, connection::v1::{ - ConnectionEnd, Counterparty as ConnectionCounterparty, IdentifiedConnection, - QueryConnectionResponse, Version, + Counterparty as ConnectionCounterparty, IdentifiedConnection, QueryConnectionResponse, }, }, }; @@ -50,21 +45,25 @@ use std::{ collections::HashSet, future::Future, pin::Pin, str::FromStr, sync::Arc, time::Duration, }; +use crate::client::{ + ClientError, EthereumClient, COMMITMENTS_STORAGE_INDEX, CONNECTIONS_STORAGE_INDEX, +}; use futures::{FutureExt, Stream, StreamExt}; use ibc::{ applications::transfer::PrefixedCoin, core::ics04_channel::channel::{Order, State}, events::IbcEvent, }; -use ibc_proto::{google::protobuf::Any, ibc::core::channel::v1::Channel}; +use ibc_proto::{ + google::protobuf::Any, + ibc::core::{ + channel::v1::Channel, + commitment::v1::MerklePrefix, + connection::v1::{ConnectionEnd, Version}, + }, +}; use ibc_rpc::{IbcApiClient, PacketInfo}; use pallet_ibc::light_clients::{AnyClientState, AnyConsensusState}; -use thiserror::Error; - -use crate::client::{ - ClientError, EthereumClient, CHANNELS_STORAGE_INDEX, CLIENT_IMPLS_STORAGE_INDEX, - COMMITMENTS_STORAGE_INDEX, CONNECTIONS_STORAGE_INDEX, -}; abigen!( IbcHandlerAbi, @@ -124,6 +123,73 @@ abigen!( "name": "SendPacket", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "sequence", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "string", + "name": "source_port", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "source_channel", + "type": "string" + }, + { + "indexed": true, + "internalType": "string", + "name": "destination_port", + "type": "string" + }, + { + "indexed": true, + "internalType": "string", + "name": "destination_channel", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "revision_number", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "revision_height", + "type": "uint64" + } + ], + "indexed": false, + "internalType": "struct HeightData", + "name": "timeout_height", + "type": "tuple" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "timeout_timestamp", + "type": "uint64" + } + ], + "name": "RecvPacket", + "type": "event" + }, { "inputs": [ { @@ -178,7 +244,7 @@ abigen!( "type": "tuple" } ], - "internalType": "struct IBCMsgs.MsgChannelOpenInit", + "internalType": "struct IBCMsgsMsgChannelOpenInit", "name": "msg_", "type": "tuple" } @@ -193,6 +259,87 @@ abigen!( ], "stateMutability": "nonpayable", "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "connectionId", + "type": "string" + }, + { + "components": [ + { + "internalType": "string", + "name": "client_id", + "type": "string" + }, + { + "components": [ + { + "internalType": "string", + "name": "identifier", + "type": "string" + }, + { + "internalType": "string[]", + "name": "features", + "type": "string[]" + } + ], + "internalType": "struct VersionData[]", + "name": "versions", + "type": "tuple[]" + }, + { + "internalType": "enum ConnectionEndState", + "name": "state", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "string", + "name": "client_id", + "type": "string" + }, + { + "internalType": "string", + "name": "connection_id", + "type": "string" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "key_prefix", + "type": "bytes" + } + ], + "internalType": "struct MerklePrefixData", + "name": "prefix", + "type": "tuple" + } + ], + "internalType": "struct CounterpartyData", + "name": "counterparty", + "type": "tuple" + }, + { + "internalType": "uint64", + "name": "delay_period", + "type": "uint64" + } + ], + "internalType": "struct ConnectionEndData", + "name": "connection", + "type": "tuple" + } + ], + "name": "setConnection", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" } ]"# ); @@ -216,7 +363,7 @@ impl From for ibc_proto::ibc::core::client::v1::Height { } #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)] -pub struct BlockHeight(pub(crate) ethers::types::BlockNumber); +pub struct BlockHeight(pub(crate) BlockNumber); #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum FinalityEvent { @@ -261,9 +408,7 @@ impl IbcProvider for EthereumClient { Ok(vec![]) } - async fn ibc_events( - &self, - ) -> Pin + Send + 'static>> { + async fn ibc_events(&self) -> Pin + Send + 'static>> { fn decode_string(bytes: &[u8]) -> String { ethers::abi::decode(&[ParamType::String], &bytes) .unwrap() @@ -273,9 +418,9 @@ impl IbcProvider for EthereumClient { .to_string() } - fn decode_client_id_log(log: ethers::types::Log) -> ibc::events::IbcEvent { + fn decode_client_id_log(log: ethers::types::Log) -> IbcEvent { let client_id = decode_string(&log.data.0); - ibc::events::IbcEvent::CreateClient(CreateClient(Attributes { + IbcEvent::CreateClient(CreateClient(Attributes { height: Height::default(), client_id: ClientId::from_str(&client_id).unwrap(), client_type: "00-uninitialized".to_owned(), @@ -367,18 +512,12 @@ impl IbcProvider for EthereumClient { client_id: ClientId, consensus_height: Height, ) -> Result { - let contract = crate::contract::ibc_handler( - self.config.ibc_handler_address.clone(), - Arc::clone(&self.http_rpc), - ); - println!("the address again: {:?}, {client_id}", self.config.ibc_handler_address); - - let binding = contract + let binding = self + .yui .method( "getConsensusState", ( Token::String(client_id.as_str().to_owned()), - // Token::Uint(consensus_height.revision_height.into()), Token::Tuple(vec![ Token::Uint(consensus_height.revision_number.into()), Token::Uint(consensus_height.revision_height.into()), @@ -408,13 +547,9 @@ impl IbcProvider for EthereumClient { at: Height, client_id: ClientId, ) -> Result { - let contract = crate::contract::ibc_handler( - self.config.ibc_handler_address.clone(), - Arc::clone(&self.http_rpc), - ); - - let (client_state, _): (Vec, bool) = contract - .method("getClientState", (client_id.as_str().to_owned(),)) + let (client_state, _): (Vec, bool) = self + .yui + .method("getClientState", (client_id.to_string(),)) .expect("contract is missing getClientState") .block(BlockId::Number(BlockNumber::Number(at.revision_height.into()))) .call() @@ -433,64 +568,45 @@ impl IbcProvider for EthereumClient { at: Height, connection_id: ConnectionId, ) -> Result { - let fut = self.eth_query_proof( - connection_id.as_str(), - Some(at.revision_height), - CONNECTIONS_STORAGE_INDEX, - ); - - query_proof_then(fut, move |storage_proof| async move { - if !storage_proof.value.is_zero() { - let contract = crate::contract::ibc_handler( - self.config.ibc_handler_address.clone(), - Arc::clone(&self.http_rpc), - ); - - /* - let binding = contract - .method("getConnectionEnd", (connection_id.as_str().to_owned(),)) - .expect("contract is missing getConnectionEnd"); - - let connection_end: crate::contract::ConnectionEnd = binding - .block(BlockId::Number(BlockNumber::Number(at.revision_height.into()))) - .call() - .await - .unwrap(); - - let proof_height = Some(at.into()); - let proof = storage_proof.proof.first().map(|b| b.to_vec()).unwrap_or_default(); - - Ok(QueryConnectionResponse { - connection: Some(ConnectionEnd { - state: connection_end.state as i32, - client_id: connection_end.client_id, - counterparty: Some(ConnectionCounterparty { - client_id: connection_end.counterparty.client_id, - connection_id: connection_end.counterparty.connection_id, - prefix: Some(ibc_proto::ibc::core::commitment::v1::MerklePrefix { - key_prefix: connection_end.counterparty.prefix, - }), - }), - versions: connection_end - .versions - .into_iter() - .map(|v| ibc_proto::ibc::core::connection::v1::Version { - identifier: v.identifier, - features: v.features, - }) - .collect(), - delay_period: connection_end.delay_period, - }), - proof, - proof_height, - }) - */ - todo!() + let (connection_end, exists): (ConnectionEndData, bool) = self + .yui + .method("getConnection", (connection_id.to_string(),)) + .expect("contract is missing getConnectionEnd") + .block(BlockId::Number(BlockNumber::Number(at.revision_height.into()))) + .call() + .await + .map_err(|err| todo!("query_connection_end: error: {err:?}")) + .unwrap(); + + let connection = if exists { + let prefix = if connection_end.counterparty.prefix.key_prefix.0.is_empty() { + None } else { - todo!("error: client address is zero") - } - }) - .await + Some(MerklePrefix { + key_prefix: connection_end.counterparty.prefix.key_prefix.to_vec(), + }) + }; + + Some(ConnectionEnd { + client_id: connection_end.client_id, + versions: connection_end + .versions + .into_iter() + .map(|v| Version { identifier: v.identifier, features: v.features }) + .collect(), + state: connection_end.state as _, + counterparty: Some(ConnectionCounterparty { + client_id: connection_end.counterparty.client_id, + connection_id: connection_end.counterparty.connection_id, + prefix, + }), + delay_period: connection_end.delay_period, + }) + } else { + None + }; + + Ok(QueryConnectionResponse { connection, proof: Vec::new(), proof_height: Some(at.into()) }) } async fn query_channel_end( @@ -499,27 +615,19 @@ impl IbcProvider for EthereumClient { channel_id: ChannelId, port_id: PortId, ) -> Result { - let contract = crate::contract::ibc_handler( - self.config.ibc_handler_address.clone(), - Arc::clone(&self.http_rpc), - ); - - // channels[portId][channelId] - let binding = contract - .method::<_, (ChannelData, bool)>( + let binding = self + .yui + .method::<_, ChannelData>( "getChannel", - (channel_id.to_string(), port_id.as_str().to_owned()), + (port_id.as_str().to_owned(), channel_id.to_string()), ) .expect("contract is missing getChannel"); - let (channel_data, exists) = binding + let channel_data = binding .block(BlockId::Number(BlockNumber::Number(at.revision_height.into()))) .call() .await .unwrap(); - if !exists { - todo!("error: channel does not exist") - } let state = State::from_i32(channel_data.state as _).expect("invalid channel state"); let counterparty = match state { @@ -627,12 +735,8 @@ impl IbcProvider for EthereumClient { port_id: &PortId, channel_id: &ChannelId, ) -> Result { - let contract = crate::contract::ibc_handler( - self.config.ibc_handler_address.clone(), - Arc::clone(&self.http_rpc), - ); - - let binding = contract + let binding = self + .yui .method::<_, u64>( "getNextSequenceRecv", (channel_id.to_string(), port_id.as_str().to_owned()), @@ -685,15 +789,21 @@ impl IbcProvider for EthereumClient { } async fn latest_height_and_timestamp(&self) -> Result<(Height, Timestamp), Self::Error> { - let latest_block = self - .http_rpc - .get_block_number() - .await - .map_err(|err| ClientError::MiddlewareError(err))?; + // TODO: fix latest_height_and_timestamp in basic builds + let block_number =// if dbg!(cfg!(feature = "test")) { + BlockNumber::from( + self.http_rpc + .get_block_number() + .await + .map_err(|err| ClientError::MiddlewareError(err))?, + ); + // } else { + // BlockNumber::Finalized + // }; let block = self .http_rpc - .get_block(latest_block) + .get_block(BlockId::Number(block_number)) .await .map_err(|err| ClientError::MiddlewareError(err))? .ok_or_else(|| ClientError::MiddlewareError(todo!()))?; @@ -701,7 +811,7 @@ impl IbcProvider for EthereumClient { let nanoseconds = Duration::from_secs(block.timestamp.as_u64()).as_nanos() as u64; let timestamp = Timestamp::from_nanoseconds(nanoseconds).expect("timestamp error"); - Ok((Height::new(0, latest_block.as_u64()), timestamp)) + Ok((Height::new(0, block.number.expect("expected block number").as_u64()), timestamp)) } async fn query_packet_commitments( @@ -710,13 +820,10 @@ impl IbcProvider for EthereumClient { channel_id: ChannelId, port_id: PortId, ) -> Result, Self::Error> { - let contract = crate::contract::ibc_handler( - self.config.ibc_handler_address.clone(), - Arc::clone(&self.http_rpc), - ); let start_seq = 0u64; let end_seq = 255u64; - let binding = contract + let binding = self + .yui .method( "hasCommitments", (port_id.as_str().to_owned(), channel_id.to_string(), start_seq, end_seq), @@ -751,14 +858,10 @@ impl IbcProvider for EthereumClient { channel_id: ChannelId, port_id: PortId, ) -> Result, Self::Error> { - let contract = crate::contract::ibc_handler( - self.config.ibc_handler_address.clone(), - Arc::clone(&self.http_rpc), - ); - let start_seq = 0u64; let end_seq = 255u64; - let binding = contract + let binding = self + .yui .method( "hasAcknowledgements", (port_id.as_str().to_owned(), channel_id.to_string(), start_seq, end_seq), @@ -850,20 +953,13 @@ impl IbcProvider for EthereumClient { channel_id: ChannelId, port_id: PortId, seqs: Vec, - ) -> Result, Self::Error> { - let contract = crate::contract::ibc_handler( - self.config.ibc_handler_address.clone(), - Arc::clone(&self.http_rpc), - ); - - // hash.0. - let event_filter = contract - .event_for_name::( - "SendPacket", - // "SendPacket(uint64,string,string,(uint64,uint64),uint64,bytes)", - ) + ) -> Result, Self::Error> { + let source_port = port_id.to_string(); + let source_channel = channel_id.to_string(); + let event_filter = self + .yui + .event_for_name::("SendPacket") .expect("contract is missing SendPacket event") - .address(ValueOrArray::Value(self.config.ibc_handler_address.clone())) .from_block(BlockNumber::Earliest) // TODO: use contract creation height .to_block(BlockNumber::Latest) .topic1(ValueOrArray::Array( @@ -876,17 +972,28 @@ impl IbcProvider for EthereumClient { )) .topic2({ let hash = H256::from_slice(&encode(&[Token::FixedBytes( - port_id.to_string().into_bytes(), + keccak256(source_port.clone().into_bytes()).to_vec(), )])); ValueOrArray::Value(hash) }) .topic3({ let hash = H256::from_slice(&encode(&[Token::FixedBytes( - channel_id.to_string().into_bytes(), + keccak256(source_channel.clone().into_bytes()).to_vec(), )])); ValueOrArray::Value(hash) }); + for i in 0..4 { + let Some(topic) = &event_filter.filter.topics[i] else { continue }; + let data = match topic { + Topic::Value(v) => v.iter().map(|v| &v.0[..]).collect::>(), + Topic::Array(vs) => vs.iter().flatten().map(|v| &v.0[..]).collect(), + }; + println!( + "Looking for topic{i}: {}", + data.into_iter().map(hex::encode).collect::>().join(", ") + ); + } let events = event_filter.query().await.unwrap(); let channel = self.query_channel_end(at, channel_id, port_id).await?; @@ -894,10 +1001,10 @@ impl IbcProvider for EthereumClient { let counterparty = channel.counterparty.expect("counterparty is none"); Ok(events .into_iter() - .map(|value| PacketInfo { + .map(move |value| PacketInfo { height: None, - source_port: String::from_utf8_lossy(&value.source_port.0).to_string(), - source_channel: String::from_utf8_lossy(&value.source_channel.0).to_string(), + source_port: source_port.clone(), + source_channel: source_channel.clone(), destination_port: counterparty.port_id.clone(), destination_channel: counterparty.channel_id.clone(), sequence: value.sequence, @@ -915,15 +1022,67 @@ impl IbcProvider for EthereumClient { async fn query_received_packets( &self, + at: Height, channel_id: ChannelId, port_id: PortId, seqs: Vec, ) -> Result, Self::Error> { - todo!() + let destination_port = port_id.to_string(); + let destination_channel = channel_id.to_string(); + let event_filter = self + .yui + .event_for_name::("RecvPacket") + .expect("contract is missing RecvPacket event") + .from_block(BlockNumber::Earliest) // TODO: use contract creation height + .to_block(BlockNumber::Latest) + .topic1(ValueOrArray::Array( + seqs.into_iter() + .map(|seq| { + let bytes = encode(&[Token::Uint(seq.into())]); + H256::from_slice(bytes.as_slice()) + }) + .collect(), + )) + .topic2({ + let hash = H256::from_slice(&encode(&[Token::FixedBytes( + keccak256(destination_port.clone().into_bytes()).to_vec(), + )])); + ValueOrArray::Value(hash) + }) + .topic3({ + let hash = H256::from_slice(&encode(&[Token::FixedBytes( + keccak256(destination_channel.clone().into_bytes()).to_vec(), + )])); + ValueOrArray::Value(hash) + }); + + let events = event_filter.query().await.unwrap(); + let channel = self.query_channel_end(at, channel_id, port_id).await?; + + let channel = channel.channel.expect("channel is none"); + Ok(events + .into_iter() + .map(move |value| PacketInfo { + height: None, + source_port: value.source_port.clone(), + source_channel: value.source_channel.clone(), + destination_port: destination_port.clone(), + destination_channel: destination_channel.clone(), + sequence: value.sequence, + timeout_height: value.timeout_height.into(), + timeout_timestamp: value.timeout_timestamp, + data: value.data.to_vec(), + channel_order: Order::from_i32(channel.ordering) + .map_err(|_| Self::Error::Other("invalid channel order".to_owned())) + .unwrap() + .to_string(), + ack: None, + }) + .collect()) } - fn expected_block_time(&self) -> std::time::Duration { - todo!() + fn expected_block_time(&self) -> Duration { + Duration::from_secs(14) } async fn query_client_update_time_and_height( @@ -991,8 +1150,10 @@ impl IbcProvider for EthereumClient { async fn query_channels(&self) -> Result, Self::Error> { let ids = self.generated_channel_identifiers(0.into()).await?; - - todo!("query_channels") + dbg!(&ids); + ids.into_iter() + .map(|id| Ok((id.1.parse().unwrap(), id.0.parse().unwrap()))) + .collect() } async fn query_connection_using_client( @@ -1008,7 +1169,6 @@ impl IbcProvider for EthereumClient { latest_height: u64, latest_client_height_on_counterparty: u64, ) -> Result { - // not implemented for the moment. Ok(false) } @@ -1040,7 +1200,7 @@ impl IbcProvider for EthereumClient { } async fn upload_wasm(&self, wasm: Vec) -> Result, Self::Error> { - todo!() + unimplemented!("upload_wasm") } } diff --git a/hyperspace/ethereum/src/lib.rs b/hyperspace/ethereum/src/lib.rs index 722c17d9e..71f4fdfa7 100644 --- a/hyperspace/ethereum/src/lib.rs +++ b/hyperspace/ethereum/src/lib.rs @@ -10,3 +10,4 @@ pub mod chain; pub mod ibc_provider; pub mod key_provider; pub mod light_client_sync; +pub mod utils; diff --git a/hyperspace/ethereum/src/light_client_sync.rs b/hyperspace/ethereum/src/light_client_sync.rs index b4a36f877..dcb84eba3 100644 --- a/hyperspace/ethereum/src/light_client_sync.rs +++ b/hyperspace/ethereum/src/light_client_sync.rs @@ -11,7 +11,10 @@ impl LightClientSync for EthereumClient { Ok(true) } - async fn fetch_mandatory_updates(&self, counterparty: &C) -> Result<(Vec, Vec), Error> { + async fn fetch_mandatory_updates( + &self, + _counterparty: &C, + ) -> Result<(Vec, Vec), Error> { todo!() } } diff --git a/hyperspace/ethereum/src/utils.rs b/hyperspace/ethereum/src/utils.rs new file mode 100644 index 000000000..64a88ecca --- /dev/null +++ b/hyperspace/ethereum/src/utils.rs @@ -0,0 +1,328 @@ +use crate::contract::UnwrapContractError; +use ethers::{ + abi::{AbiError, Address, Detokenize, EventExt, Token, Tokenize}, + contract::{ContractInstance, FunctionCall}, + prelude::*, +}; +use ethers_solc::artifacts::{Storage, StorageLayout, StorageType}; +use ibc::core::ics04_channel::packet::Packet; + +pub type ProviderImpl = ethers::prelude::SignerMiddleware, LocalWallet>; + +#[repr(u32)] +#[derive(Clone, Copy, Debug)] +pub enum FacetCutAction { + Add = 0, + Replace = 1, + Remove = 2, +} + +#[derive(Clone, Debug)] +pub struct FacetCut { + pub address: Address, + pub action: FacetCutAction, + pub selectors: Vec<(String, [u8; 4])>, +} + +impl FacetCut { + pub fn into_token(self) -> Token { + Token::Tuple(vec![ + Token::Address(self.address), + Token::Uint((FacetCutAction::Add as u32).into()), + Token::Array( + self.selectors.into_iter().map(|(_, x)| Token::FixedBytes(x.to_vec())).collect(), + ), + ]) + } +} + +#[derive(Debug)] +pub struct DeployYuiIbc { + // pub ibc_client: ContractInstance, + // pub ibc_connection: ContractInstance, + // pub ibc_channel_handshake: ContractInstance, + // pub ibc_packet: ContractInstance, + // pub ibc_handler: ContractInstance, + pub facet_cuts: Vec, + pub deployed_facets: Vec>, + pub diamond: ContractInstance, + pub storage_layout: StorageLayout, +} + +impl DeployYuiIbc +where + B: Clone + std::borrow::Borrow, + M: Middleware, +{ + pub async fn bind_port(&self, port_id: &str, address: Address) { + let bind_port = self + .method::<_, ()>("bindPort", (Token::String(port_id.into()), Token::Address(address))) + .unwrap(); + let () = bind_port.call().await.unwrap_contract_error(); + let tx_recp = bind_port.send().await.unwrap_contract_error().await.unwrap().unwrap(); + assert_eq!(tx_recp.status, Some(1.into())); + } + + pub async fn connection_open_init(&self, client_id: &str) -> String { + let connection_open_init = self + .method::<_, String>( + "connectionOpenInit", + (Token::Tuple(vec![ + Token::String(client_id.into()), + Token::Tuple(vec![ + Token::String(client_id.into()), + Token::String("port-0".into()), + Token::Tuple(vec![Token::Bytes(vec![])]), + ]), + Token::Uint(0.into()), + ]),), + ) + .unwrap(); + let connection_id = connection_open_init.call().await.unwrap_contract_error(); + let tx_recp = connection_open_init + .send() + .await + .unwrap_contract_error() + .await + .unwrap() + .unwrap(); + assert_eq!(tx_recp.status, Some(1.into())); + connection_id + } + + pub async fn connection_open_ack(&self, connection_id: &str, client_state_bytes: Vec) { + let connection_open_ack = self + .method::<_, ()>( + "connectionOpenAck", + (Token::Tuple(vec![ + Token::String(connection_id.to_string()), + Token::Bytes(client_state_bytes), // clientStateBytes + Token::Tuple(vec![ + Token::String("counterparty-version".into()), + Token::Array(vec![]), + ]), // Version.Data + Token::String("counterparty-connection-id".into()), // counterpartyConnectionID + Token::Bytes(vec![]), // proofTry + Token::Bytes(vec![]), // proofClient + Token::Bytes(vec![]), // proofConsensus + Token::Tuple(vec![Token::Uint(0.into()), Token::Uint(1.into())]), // proofHeight + Token::Tuple(vec![Token::Uint(0.into()), Token::Uint(1.into())]), // consesusHeight + ]),), + ) + .unwrap(); + + let () = connection_open_ack.call().await.unwrap_contract_error(); + let tx_recp = + connection_open_ack.send().await.unwrap_contract_error().await.unwrap().unwrap(); + + dbg!(&tx_recp.block_number); + + assert_eq!(tx_recp.status, Some(1.into())); + } + + pub async fn channel_open_init(&self, port_id: &str, connection_id: &str) -> String { + let fut = self + .method::<_, String>( + "channelOpenInit", + (Token::Tuple(vec![ + Token::String(port_id.into()), + Token::Tuple(vec![ + // Channel.Data + Token::Uint(1.into()), // State, Init + Token::Uint(1.into()), // Ordering + Token::Tuple(vec![ + Token::String("port-0".into()), + Token::String("channel-0".into()), + ]), // counterparty + Token::Array(vec![Token::String(connection_id.into())]), // connectionHops + Token::String("1".into()), // version + ]), + ]),), + ) + .unwrap(); + + let channel_id = fut.call().await.unwrap_contract_error(); + let tx = fut.send().await.unwrap_contract_error().await.unwrap().unwrap(); + assert_eq!(tx.status, Some(1.into())); + channel_id + } + + pub async fn channel_open_ack(&self, channel_id: &str, port_id: &str) { + let fut = self + .method::<_, ()>( + "channelOpenAck", + (Token::Tuple(vec![ + Token::String(port_id.into()), // port-id + Token::String(channel_id.into()), // channel-id + Token::String("1".into()), // counterparty-version + Token::String("channel-0".into()), // counterparty-channel-id + Token::Bytes(vec![]), // proof-try + Token::Tuple(vec![ + // proof-height + Token::Uint(0.into()), + Token::Uint(1.into()), + ]), + ]),), + ) + .unwrap(); + + let () = fut.call().await.unwrap_contract_error(); + let tx = fut.send().await.unwrap_contract_error().await.unwrap().unwrap(); + assert_eq!(tx.status, Some(1.into())); + } + + pub async fn recv_packet(&self, packet: Packet) -> TransactionReceipt { + let fut = self + .method::<_, ()>( + "recvPacket", + (Token::Tuple(vec![ + Token::Tuple(vec![ + Token::Uint(packet.sequence.0.into()), // sequence + Token::String(packet.source_port.to_string()), // port-id + Token::String(packet.source_channel.to_string()), // channel-id + Token::String(packet.destination_port.to_string()), // port-id + Token::String(packet.destination_channel.to_string()), // channel-id + Token::Bytes(packet.data), // data + Token::Tuple(vec![ + // timeout-height + Token::Uint(packet.timeout_height.revision_number.into()), + Token::Uint(packet.timeout_height.revision_height.into()), + ]), + Token::Uint( + packet + .timeout_timestamp + .into_tm_time() + .map(|x| x.unix_timestamp_nanos() as u64) + .unwrap_or(0u64) + .into(), + ), /* timeout-timestamp */ + ]), + Token::Bytes(vec![]), /* proof */ + Token::Tuple(vec![ + // proof-height + Token::Uint(0.into()), + Token::Uint(1.into()), + ]), + ]),), + ) + .unwrap(); + + let () = fut.call().await.unwrap_contract_error(); + // let trace = self + // .ibc_handler + // .client() + // .borrow() + // .debug_trace_call(fut.tx.clone(), None, GethDebugTracingCallOptions::default()) + // .await + // .unwrap(); + // std::fs::write("trace.txt", format!("{:#?}", trace)).unwrap(); + // println!("trace: {:?}", trace); + let tx = fut.send().await.unwrap_contract_error().await.unwrap().unwrap(); + // dbg!(tx.logs); + let status = tx.status.expect("status not found"); + + if status == 0.into() { + panic!("status is 0"); + } + tx + } + + pub fn method( + &self, + name: &str, + args: T, + ) -> Result, AbiError> { + let mut contract: Option<&ContractInstance> = None; + + let lookup_contracts = self.deployed_facets.iter().chain(std::iter::once(&self.diamond)); + + for lookup_contract in lookup_contracts { + if lookup_contract.abi().function(name).is_ok() { + if contract.is_some() { + panic!("ambiguous method name: {}", name); + } + contract = Some(lookup_contract); + } + } + let contract = contract.take().ok_or_else(|| AbiError::WrongSelector)?; + + let mut f = contract.method(name, args); + + if let Ok(f) = &mut f { + f.tx.set_to(self.diamond.address()); + } + + f + } + + pub fn event_for_name(&self, name: &str) -> Result, AbiError> { + let mut contract: Option<&ContractInstance> = None; + let lookup_contracts = self.deployed_facets.iter().chain(std::iter::once(&self.diamond)); + + for lookup_contract in lookup_contracts { + if lookup_contract.abi().event(name).is_ok() { + if contract.is_some() { + panic!("ambiguous event name: {}", name); + } + contract = Some(lookup_contract); + } + } + + let contract = contract.take().ok_or_else(|| AbiError::WrongSelector)?; + let mut event = contract.abi().event(name).expect("we've just found the event"); + let filter = contract + .event_with_filter(Filter::new().event(&event.abi_signature())) + .address(self.diamond.address().into()); + + Ok(filter) + } + + pub async fn register_client(&self, kind: &str, address: Address) { + let method = self + .method::<_, ()>( + "registerClient", + (Token::String(kind.into()), Token::Address(address)), + ) + .unwrap(); + + let _ = method.call().await.unwrap_contract_error(); + + let receipt = method.send().await.unwrap().await.unwrap().unwrap(); + assert_eq!(receipt.status, Some(1.into())); + } + + pub async fn create_client(&self, msg: Token) -> String { + let method = self.method::<_, String>("createClient", (msg,)).unwrap(); + + let client_id = method.call().await.unwrap_contract_error(); + + let receipt = method.send().await.unwrap().await.unwrap().unwrap(); + assert_eq!(receipt.status, Some(1.into())); + + println!("{:?}", receipt.block_number); + + client_id + } + + pub fn find_storage(&self, name: &str) -> &Storage { + self.storage_layout.storage.iter().find(|x| x.contract == name).unwrap() + } +} + +impl Clone for DeployYuiIbc +where + B: Clone + std::borrow::Borrow, +{ + fn clone(&self) -> Self { + Self { + // ibc_client: self.ibc_client.clone(), + // ibc_connection: self.ibc_connection.clone(), + // ibc_channel_handshake: self.ibc_channel_handshake.clone(), + // ibc_packet: self.ibc_packet.clone(), + facet_cuts: self.facet_cuts.clone(), + deployed_facets: self.deployed_facets.clone(), + diamond: self.diamond.clone(), + storage_layout: self.storage_layout.clone(), + } + } +} diff --git a/hyperspace/ethereum/tests/sanity_checks.rs b/hyperspace/ethereum/tests/sanity_checks.rs index a28c86c31..5953a6b62 100644 --- a/hyperspace/ethereum/tests/sanity_checks.rs +++ b/hyperspace/ethereum/tests/sanity_checks.rs @@ -1,23 +1,26 @@ -use std::{future::Future, ops::Deref, path::PathBuf, str::FromStr, sync::Arc, time::Duration}; +use std::{future::Future, ops::Deref, path::PathBuf, str::FromStr, sync::Arc}; use crate::utils::USE_GETH; use ethers::{ abi::{encode_packed, Token}, - contract::MultiAbigen, core::k256::sha2::{Digest, Sha256}, - prelude::{ContractInstance, LocalWallet, TransactionReceipt}, - types::{H256, U256}, - utils::{keccak256, Anvil, AnvilInstance}, + prelude::{ContractInstance, TransactionReceipt}, + types::U256, + utils::{keccak256, AnvilInstance}, }; use ethers_solc::{ProjectCompileOutput, ProjectPathsConfig}; use hyperspace_ethereum::{ config::Config, - contract::{ibc_handler, UnwrapContractError}, + contract::UnwrapContractError, + utils::{DeployYuiIbc, ProviderImpl}, }; use ibc::{ core::{ ics02_client::height::Height, - ics04_channel::packet::{Packet, Sequence}, + ics04_channel::{ + channel::Order, + packet::{Packet, Sequence}, + }, ics24_host::identifier::{ChannelId, PortId}, }, timestamp::Timestamp, @@ -26,12 +29,13 @@ use ibc_rpc::PacketInfo; use primitives::IbcProvider; use prost::Message; use tracing::log; +use tracing_subscriber::{filter, layer::SubscriberExt, util::SubscriberInitExt, Layer}; mod utils; -async fn hyperspace_ethereum_client_fixture( +async fn hyperspace_ethereum_client_fixture( anvil: ðers::utils::AnvilInstance, - utils::DeployYuiIbc { facet_cuts, deployed_facets, diamond }: &utils::DeployYuiIbc, M>, + yui_ibc: DeployYuiIbc, ProviderImpl>, ) -> hyperspace_ethereum::client::EthereumClient { let endpoint = if USE_GETH { "http://localhost:6001".to_string() } else { anvil.endpoint() }; let wallet_path = if USE_GETH { @@ -41,29 +45,27 @@ async fn hyperspace_ethereum_client_fixture( }; let wallet = if !USE_GETH { Some(anvil.endpoint().parse().unwrap()) } else { None }; - hyperspace_ethereum::client::EthereumClient::new(Config { - http_rpc_url: endpoint.parse().unwrap(), - ws_rpc_url: Default::default(), - ibc_handler_address: diamond.address(), - mnemonic: None, - max_block_weight: 1, - private_key: wallet, - private_key_path: wallet_path, - name: "mock-ethereum-client".into(), - client_id: None, - connection_id: None, - channel_whitelist: vec![], - commitment_prefix: "".into(), - }) + hyperspace_ethereum::client::EthereumClient::new( + Config { + http_rpc_url: endpoint.parse().unwrap(), + ws_rpc_url: Default::default(), + ibc_handler_address: yui_ibc.diamond.address(), + mnemonic: None, + max_block_weight: 1, + private_key: wallet, + private_key_path: wallet_path, + name: "mock-ethereum-client".into(), + client_id: None, + connection_id: None, + channel_whitelist: vec![], + commitment_prefix: "".into(), + }, + yui_ibc, + ) .await .unwrap() } -pub type ProviderImpl = ethers::prelude::SignerMiddleware< - ethers::providers::Provider, - ethers::signers::LocalWallet, ->; - #[allow(dead_code)] struct DeployYuiIbcMockClient { pub path: PathBuf, @@ -73,7 +75,7 @@ struct DeployYuiIbcMockClient { pub client: Arc, pub ibc_mock_client: ContractInstance, ProviderImpl>, pub ibc_mock_module: Option, ProviderImpl>>, - pub yui_ibc: utils::DeployYuiIbc, ProviderImpl>, + pub yui_ibc: DeployYuiIbc, ProviderImpl>, } impl DeployYuiIbcMockClient { @@ -234,22 +236,17 @@ async fn test_deploy_yui_ibc_and_mock_client() { async fn test_hyperspace_ethereum_client() { let DeployYuiIbcMockClient { anvil, yui_ibc, .. } = deploy_yui_ibc_and_mock_client_fixture().await; - let _hyperspace = hyperspace_ethereum_client_fixture(&anvil, &yui_ibc).await; + let _hyperspace = hyperspace_ethereum_client_fixture(&anvil, yui_ibc.clone()).await; } #[tokio::test] async fn test_ibc_client() { let deploy = deploy_yui_ibc_and_mock_client_fixture().await; - let hyperspace = hyperspace_ethereum_client_fixture(&deploy.anvil, &deploy.yui_ibc).await; + let hyperspace = + hyperspace_ethereum_client_fixture(&deploy.anvil, deploy.yui_ibc.clone()).await; let client_id = deploy_mock_client_fixture(&deploy).await; - - let r = hyperspace - .query_client_state( - ibc::Height { revision_number: 0, revision_height: 1 }, - client_id.parse().unwrap(), - ) - .await - .unwrap(); + let height = hyperspace.latest_height_and_timestamp().await.unwrap().0; + let r = hyperspace.query_client_state(height, client_id.parse().unwrap()).await.unwrap(); assert_eq!( r.client_state, @@ -267,7 +264,7 @@ async fn test_ibc_client() { let r = hyperspace .query_client_consensus( - ibc::Height { revision_number: 0, revision_height: 1 }, + height, client_id.parse().unwrap(), ibc::Height { revision_number: 0, revision_height: 1 }, ) @@ -285,8 +282,15 @@ async fn test_ibc_client() { #[tokio::test] async fn test_ibc_connection() { + let stdout_log = tracing_subscriber::fmt::layer().pretty(); + tracing_subscriber::registry() + .with(stdout_log.with_filter(filter::LevelFilter::INFO).with_filter(filter::filter_fn( + |metadata| metadata.file().map(|x| x.contains("ethers")).unwrap_or_default(), + ))) + .init(); let deploy = deploy_yui_ibc_and_mock_client_fixture().await; - let hyperspace = hyperspace_ethereum_client_fixture(&deploy.anvil, &deploy.yui_ibc).await; + let hyperspace = + hyperspace_ethereum_client_fixture(&deploy.anvil, deploy.yui_ibc.clone()).await; let client_id = deploy_mock_client_fixture(&deploy).await; let connection_id = deploy.yui_ibc.connection_open_init(&client_id).await; @@ -294,24 +298,11 @@ async fn test_ibc_connection() { .yui_ibc .connection_open_ack(&connection_id, utils::mock::client_state_bytes()) .await; - - // hyperspace.query_connection_channels(at, connection_id) - // let channels = hyperspace - // .query_connection_channels( - // ibc::Height { revision_number: 0, revision_height: 1 }, - // &connection_id.parse().unwrap(), - // ) - // .await - // .unwrap(); - // - // assert!(channels.channels.is_empty()); + let height = hyperspace.latest_height_and_timestamp().await.unwrap().0; // hyperspace.query_connection_end(at, connection_id) let connection_end = hyperspace - .query_connection_end( - ibc::Height { revision_number: 0, revision_height: 1 }, - connection_id.parse().unwrap(), - ) + .query_connection_end(dbg!(height), connection_id.parse().unwrap()) .await .unwrap(); @@ -321,16 +312,14 @@ async fn test_ibc_connection() { client_id: client_id.parse().unwrap(), counterparty: Some(ibc_proto::ibc::core::connection::v1::Counterparty { client_id: client_id.parse().unwrap(), - connection_id: connection_id.parse().unwrap(), - prefix: Some(ibc_proto::ibc::core::commitment::v1::MerklePrefix { - key_prefix: vec![], - }), + connection_id: "counterparty-connection-id".parse().unwrap(), + prefix: None, }), - state: ibc_proto::ibc::core::connection::v1::State::Init as i32, + state: ibc_proto::ibc::core::connection::v1::State::Open as i32, delay_period: 0, versions: vec![ibc_proto::ibc::core::connection::v1::Version { - identifier: "1".into(), - features: vec![], + identifier: "counterparty-version".into(), + features: vec!["ORDER_ORDERED".to_string(), "ORDER_UNORDERED".to_string()], }], }) ); @@ -339,7 +328,8 @@ async fn test_ibc_connection() { #[tokio::test] async fn test_ibc_channel() { let deploy = deploy_yui_ibc_and_mock_client_fixture().await; - let hyperspace = hyperspace_ethereum_client_fixture(&deploy.anvil, &deploy.yui_ibc).await; + let hyperspace = + hyperspace_ethereum_client_fixture(&deploy.anvil, deploy.yui_ibc.clone()).await; let client_id = deploy_mock_client_fixture(&deploy).await; let mock_module = deploy_mock_module_fixture(&deploy).await; @@ -349,42 +339,54 @@ async fn test_ibc_channel() { let channel_id = deploy.yui_ibc.channel_open_init("port-0", &connection_id).await; deploy.yui_ibc.channel_open_ack(&channel_id, "port-0").await; - // hyperspace.query_channels(at, channel_id) let channels = hyperspace.query_channels().await.unwrap(); - assert!(!channels.is_empty()); assert_eq!(channels[0].0, channel_id.parse().unwrap()); - // hyperspace.query_channel_end(at, channel_id) + let height = hyperspace.latest_height_and_timestamp().await.unwrap().0; + let channel_end = hyperspace - .query_channel_end( - ibc::Height { revision_number: 0, revision_height: 1 }, - channel_id.parse().unwrap(), - "port-0".parse().unwrap(), - ) + .query_channel_end(height, channel_id.parse().unwrap(), "port-0".parse().unwrap()) .await .unwrap(); - assert_eq!( - channel_end.channel, - Some(ibc_proto::ibc::core::channel::v1::Channel { - state: ibc_proto::ibc::core::channel::v1::State::Init as i32, - ordering: ibc_proto::ibc::core::channel::v1::Order::Unordered as i32, - counterparty: Some(ibc_proto::ibc::core::channel::v1::Counterparty { - port_id: "port-0".into(), - channel_id: channel_id.parse().unwrap(), - }), - connection_hops: vec![connection_id.parse().unwrap()], - version: "1".into(), - }) - ); + let expected_channel = ibc_proto::ibc::core::channel::v1::Channel { + state: ibc_proto::ibc::core::channel::v1::State::Open as i32, + ordering: ibc_proto::ibc::core::channel::v1::Order::Unordered as i32, + counterparty: Some(ibc_proto::ibc::core::channel::v1::Counterparty { + port_id: "port-0".into(), + channel_id: channel_id.parse().unwrap(), + }), + connection_hops: vec![connection_id.parse().unwrap()], + version: "1".into(), + }; + assert_eq!(channel_end.channel, Some(expected_channel.clone())); + + // TODO: only used in integration tests. Should we really test that? + // let channels = hyperspace + // .query_connection_channels(height, &connection_id.parse().unwrap()) + // .await + // .unwrap(); + // assert_eq!( + // channels, + // vec![ibc_proto::ibc::core::channel::v1::IdentifiedChannel { + // state: expected_channel.state, + // ordering: expected_channel.ordering, + // counterparty: expected_channel.counterparty, + // connection_hops: expected_channel.connection_hops, + // version: expected_channel.version, + // port_id: "port-0".into(), + // channel_id, + // }] + // ); } #[tokio::test] async fn test_ibc_packet() { let _ = env_logger::try_init(); let mut deploy = deploy_yui_ibc_and_mock_client_fixture().await; - let hyperspace = hyperspace_ethereum_client_fixture(&deploy.anvil, &deploy.yui_ibc).await; + let hyperspace = + hyperspace_ethereum_client_fixture(&deploy.anvil, deploy.yui_ibc.clone()).await; let client_id = deploy_mock_client_fixture(&deploy).await; let mock_module = deploy_mock_module_fixture(&deploy).await; @@ -406,6 +408,37 @@ async fn test_ibc_packet() { .await; let height = tx.block_number.unwrap().as_u64(); + tx.logs.iter().for_each(|log| { + println!("send_packet log: {:#?}", log); + }); + + let send_packet = hyperspace + .query_send_packets( + ibc::Height { revision_number: 0, revision_height: height }, + ChannelId::from_str("channel-0").unwrap(), + PortId::from_str("port-0").unwrap(), + vec![1], + ) + .await + .unwrap() + .pop() + .unwrap(); + + let info = PacketInfo { + height: None, + sequence: 1, + source_port: "port-0".to_string(), + source_channel: "channel-0".to_string(), + destination_port: "port-0".to_string(), + destination_channel: "channel-0".to_string(), + channel_order: Order::Unordered.to_string(), + data: "hello_send".as_bytes().to_vec(), + timeout_height: Height::new(0, 1000000).into(), + timeout_timestamp: 0, + ack: None, + }; + assert_eq!(send_packet, info); + // query_packet_commitment let commitment = hyperspace .query_packet_commitment( @@ -459,10 +492,8 @@ async fn test_ibc_packet() { timeout_timestamp: Timestamp::default(), }) .await; - - // query_packet_acknowledgement - let height = tx.block_number.unwrap().as_u64(); + let ack = hyperspace .query_packet_acknowledgement( ibc::Height { revision_number: 0, revision_height: height }, @@ -476,6 +507,32 @@ async fn test_ibc_packet() { println!("{}", hex::encode(&ack.acknowledgement)); assert_eq!(ack.acknowledgement, ack_hash.to_vec()); + let received_packets = hyperspace + .query_received_packets( + ibc::Height { revision_number: 0, revision_height: height }, + ChannelId::from_str("channel-0").unwrap(), + PortId::from_str("port-0").unwrap(), + vec![sequence.0], + ) + .await + .unwrap(); + assert_eq!( + received_packets, + vec![PacketInfo { + height: None, + sequence: sequence.0, + source_port: "port-0".to_string(), + source_channel: "channel-0".to_string(), + destination_port: "port-0".to_string(), + destination_channel: "channel-0".to_string(), + channel_order: Order::Unordered.to_string(), + data: "hello_recv".as_bytes().to_vec(), + timeout_height: Height::new(0, 1000000).into(), + timeout_timestamp: 0, + ack: None, + }] + ); + // TODO: query_packet_receipt let receipt = hyperspace .query_packet_receipt( @@ -523,35 +580,6 @@ async fn test_ibc_packet() { .await .unwrap(); assert_eq!(unreceived, vec![1, 2]); - - let send_packet = hyperspace - .query_send_packets( - ibc::Height { revision_number: 0, revision_height: height }, - ChannelId::from_str("channel-0").unwrap(), - PortId::from_str("port-0").unwrap(), - vec![1], - ) - .await - .unwrap() - .pop() - .unwrap(); - - assert_eq!( - dbg!(send_packet), - PacketInfo { - height: None, - sequence: 1, - source_port: "port-0".to_string(), - source_channel: "channel-0".to_string(), - destination_port: "port-0".to_string(), - destination_channel: "channel-0".to_string(), - channel_order: "0".to_string(), - data: "hello_send".as_bytes().to_vec(), - timeout_height: Height::new(0, 1000000).into(), - timeout_timestamp: 0, - ack: None, - } - ); } fn u64_to_token(x: u64) -> Token { diff --git a/hyperspace/ethereum/tests/utils.rs b/hyperspace/ethereum/tests/utils.rs index 0bf449a93..a42e98537 100644 --- a/hyperspace/ethereum/tests/utils.rs +++ b/hyperspace/ethereum/tests/utils.rs @@ -3,6 +3,8 @@ use cast::hashbrown::HashSet; use std::{ collections::HashMap, + fs::File, + iter::once, path::{Path, PathBuf}, sync::Arc, time::Duration, @@ -21,13 +23,16 @@ use ethers::{ use ethers_solc::{ artifacts::{ output_selection::OutputSelection, DebuggingSettings, Libraries, Optimizer, - OptimizerDetails, RevertStrings, Settings, SettingsMetadata, + OptimizerDetails, RevertStrings, Settings, SettingsMetadata, StorageLayout, }, Artifact, ConfigurableContractArtifact, EvmVersion, Project, ProjectCompileOutput, ProjectPathsConfig, SolcConfig, }; use futures::SinkExt; -use hyperspace_ethereum::contract::UnwrapContractError; +use hyperspace_ethereum::{ + contract::UnwrapContractError, + utils::{DeployYuiIbc, FacetCut, FacetCutAction}, +}; use ibc::{ core::{ ics04_channel::packet::Packet, @@ -80,6 +85,14 @@ pub fn spawn_anvil() -> (AnvilInstance, Arc, Loc #[track_caller] pub fn compile_solc(project_paths: ProjectPathsConfig) -> ProjectCompileOutput { // custom solc config to solve Yul-relatated compilation errors + let mut selection = OutputSelection::default_output_selection(); + selection + .0 + .get_mut("*") + .unwrap() + .get_mut("*") + .unwrap() + .push("storageLayout".to_string()); let solc_config = SolcConfig { settings: Settings { stop_after: None, @@ -101,7 +114,7 @@ pub fn compile_solc(project_paths: ProjectPathsConfig) -> ProjectCompileOutput { }, model_checker: None, metadata: None, - output_selection: OutputSelection::default_output_selection(), + output_selection: selection, evm_version: Some(EvmVersion::Paris), via_ir: Some(false), // debug: Some(DebuggingSettings { @@ -113,14 +126,18 @@ pub fn compile_solc(project_paths: ProjectPathsConfig) -> ProjectCompileOutput { }, }; - let project = Project::builder() + let mut project = Project::builder() .paths(project_paths) .ephemeral() - .no_artifacts() .solc_config(solc_config) .build() .expect("project build failed"); + // TODO: figure out how to enable it in the config + // project.artifacts.additional_values.storage_layout = true; + project.artifacts.additional_files.abi = true; + // project.solc.args.push("--storage-layout".to_string()); + let project_output = project.compile().expect("compilation failed"); if project_output.has_compiler_errors() { @@ -219,291 +236,6 @@ pub mod mock { } } -#[derive(Debug)] -pub struct DeployYuiIbc { - // pub ibc_client: ContractInstance, - // pub ibc_connection: ContractInstance, - // pub ibc_channel_handshake: ContractInstance, - // pub ibc_packet: ContractInstance, - // pub ibc_handler: ContractInstance, - pub facet_cuts: Vec, - pub deployed_facets: Vec>, - pub diamond: ContractInstance, -} - -impl DeployYuiIbc -where - B: Clone + std::borrow::Borrow, - M: Middleware, -{ - pub async fn bind_port(&self, port_id: &str, address: Address) { - let bind_port = self - .method::<_, ()>("bindPort", (Token::String(port_id.into()), Token::Address(address))) - .unwrap(); - let () = bind_port.call().await.unwrap_contract_error(); - let tx_recp = bind_port.send().await.unwrap_contract_error().await.unwrap().unwrap(); - assert_eq!(tx_recp.status, Some(1.into())); - } - - pub async fn connection_open_init(&self, client_id: &str) -> String { - let connection_open_init = self - .method::<_, String>( - "connectionOpenInit", - (Token::Tuple(vec![ - Token::String(client_id.into()), - Token::Tuple(vec![ - Token::String(client_id.into()), - Token::String("port-0".into()), - Token::Tuple(vec![Token::Bytes(vec![])]), - ]), - Token::Uint(0.into()), - ]),), - ) - .unwrap(); - let connection_id = connection_open_init.call().await.unwrap_contract_error(); - let tx_recp = connection_open_init - .send() - .await - .unwrap_contract_error() - .await - .unwrap() - .unwrap(); - assert_eq!(tx_recp.status, Some(1.into())); - connection_id - } - - pub async fn connection_open_ack(&self, connection_id: &str, client_state_bytes: Vec) { - let connection_open_ack = self - .method::<_, ()>( - "connectionOpenAck", - (Token::Tuple(vec![ - Token::String(connection_id.to_string()), - Token::Bytes(client_state_bytes), // clientStateBytes - Token::Tuple(vec![ - Token::String("counterparty-version".into()), - Token::Array(vec![]), - ]), // Version.Data - Token::String("counterparty-connection-id".into()), // counterpartyConnectionID - Token::Bytes(vec![]), // proofTry - Token::Bytes(vec![]), // proofClient - Token::Bytes(vec![]), // proofConsensus - Token::Tuple(vec![Token::Uint(0.into()), Token::Uint(1.into())]), // proofHeight - Token::Tuple(vec![Token::Uint(0.into()), Token::Uint(1.into())]), // consesusHeight - ]),), - ) - .unwrap(); - - let () = connection_open_ack.call().await.unwrap_contract_error(); - let tx_recp = - connection_open_ack.send().await.unwrap_contract_error().await.unwrap().unwrap(); - assert_eq!(tx_recp.status, Some(1.into())); - } - - pub async fn channel_open_init(&self, port_id: &str, connection_id: &str) -> String { - let fut = self - .method::<_, String>( - "channelOpenInit", - (Token::Tuple(vec![ - Token::String(port_id.into()), - Token::Tuple(vec![ - // Channel.Data - Token::Uint(1.into()), // State, Init - Token::Uint(1.into()), // Ordering - Token::Tuple(vec![ - Token::String("port-0".into()), - Token::String("channel-0".into()), - ]), // counterparty - Token::Array(vec![Token::String(connection_id.into())]), // connectionHops - Token::String("1".into()), // version - ]), - ]),), - ) - .unwrap(); - - let channel_id = fut.call().await.unwrap_contract_error(); - let tx = fut.send().await.unwrap_contract_error().await.unwrap().unwrap(); - assert_eq!(tx.status, Some(1.into())); - channel_id - } - - pub async fn channel_open_ack(&self, channel_id: &str, port_id: &str) { - let fut = self - .method::<_, ()>( - "channelOpenAck", - (Token::Tuple(vec![ - Token::String(port_id.into()), // port-id - Token::String(channel_id.into()), // channel-id - Token::String("1".into()), // counterparty-version - Token::String("channel-0".into()), // counterparty-channel-id - Token::Bytes(vec![]), // proof-try - Token::Tuple(vec![ - // proof-height - Token::Uint(0.into()), - Token::Uint(1.into()), - ]), - ]),), - ) - .unwrap(); - - let () = fut.call().await.unwrap_contract_error(); - let tx = fut.send().await.unwrap_contract_error().await.unwrap().unwrap(); - assert_eq!(tx.status, Some(1.into())); - } - - pub async fn recv_packet(&self, packet: Packet) -> TransactionReceipt { - let fut = self - .method::<_, ()>( - "recvPacket", - (Token::Tuple(vec![ - Token::Tuple(vec![ - Token::Uint(packet.sequence.0.into()), // sequence - Token::String(packet.source_port.to_string()), // port-id - Token::String(packet.source_channel.to_string()), // channel-id - Token::String(packet.destination_port.to_string()), // port-id - Token::String(packet.destination_channel.to_string()), // channel-id - Token::Bytes(packet.data), // data - Token::Tuple(vec![ - // timeout-height - Token::Uint(packet.timeout_height.revision_number.into()), - Token::Uint(packet.timeout_height.revision_height.into()), - ]), - Token::Uint( - packet - .timeout_timestamp - .into_tm_time() - .map(|x| x.unix_timestamp_nanos() as u64) - .unwrap_or(0u64) - .into(), - ), /* timeout-timestamp */ - ]), - Token::Bytes(vec![]), /* proof */ - Token::Tuple(vec![ - // proof-height - Token::Uint(0.into()), - Token::Uint(1.into()), - ]), - ]),), - ) - .unwrap(); - - let () = fut.call().await.unwrap_contract_error(); - // let trace = self - // .ibc_handler - // .client() - // .borrow() - // .debug_trace_call(fut.tx.clone(), None, GethDebugTracingCallOptions::default()) - // .await - // .unwrap(); - // std::fs::write("trace.txt", format!("{:#?}", trace)).unwrap(); - // println!("trace: {:?}", trace); - let tx = fut.send().await.unwrap_contract_error().await.unwrap().unwrap(); - // dbg!(tx.logs); - let status = tx.status.expect("status not found"); - - if status == 0.into() { - panic!("status is 0"); - } - tx - } - - pub fn method( - &self, - name: &str, - args: T, - ) -> Result, AbiError> { - let mut contract: Option<&ContractInstance> = None; - - let lookup_contracts = self.deployed_facets.iter().chain(std::iter::once(&self.diamond)); - - for lookup_contract in lookup_contracts { - if lookup_contract.abi().function(name).is_ok() { - if contract.is_some() { - panic!("ambiguous method name: {}", name); - } - contract = Some(lookup_contract); - } - } - let contract = contract.take().ok_or_else(|| AbiError::WrongSelector)?; - - let mut f = contract.method(name, args); - - if let Ok(f) = &mut f { - f.tx.set_to(self.diamond.address()); - } - - f - } - - pub async fn register_client(&self, kind: &str, address: Address) { - let method = self - .method::<_, ()>( - "registerClient", - (Token::String(kind.into()), Token::Address(address)), - ) - .unwrap(); - - let _ = method.call().await.unwrap_contract_error(); - - let receipt = method.send().await.unwrap().await.unwrap().unwrap(); - assert_eq!(receipt.status, Some(1.into())); - } - - pub async fn create_client(&self, msg: Token) -> String { - let method = self.method::<_, String>("createClient", (msg,)).unwrap(); - - let client_id = method.call().await.unwrap_contract_error(); - - let receipt = method.send().await.unwrap().await.unwrap().unwrap(); - assert_eq!(receipt.status, Some(1.into())); - - client_id - } -} - -impl Clone for DeployYuiIbc -where - B: Clone + std::borrow::Borrow, -{ - fn clone(&self) -> Self { - Self { - // ibc_client: self.ibc_client.clone(), - // ibc_connection: self.ibc_connection.clone(), - // ibc_channel_handshake: self.ibc_channel_handshake.clone(), - // ibc_packet: self.ibc_packet.clone(), - facet_cuts: self.facet_cuts.clone(), - deployed_facets: self.deployed_facets.clone(), - diamond: self.diamond.clone(), - } - } -} - -#[repr(u32)] -#[derive(Clone, Copy, Debug)] -pub enum FacetCutAction { - Add = 0, - Replace = 1, - Remove = 2, -} - -#[derive(Clone, Debug)] -pub struct FacetCut { - address: Address, - action: FacetCutAction, - selectors: Vec<(String, [u8; 4])>, -} - -impl FacetCut { - pub fn into_token(self) -> Token { - Token::Tuple(vec![ - Token::Address(self.address), - Token::Uint((FacetCutAction::Add as u32).into()), - Token::Array( - self.selectors.into_iter().map(|(_, x)| Token::FixedBytes(x.to_vec())).collect(), - ), - ]) - } -} - fn get_selectors(contract: &ContractInstance, M>) -> Vec<(String, [u8; 4])> where M: Middleware, @@ -611,5 +343,38 @@ where .await .unwrap(); - DeployYuiIbc { diamond, facet_cuts, deployed_facets } + // std::fs::ReadDir::new(). + let predefined_layout = serde_json::from_reader::<_, StorageLayout>( + File::open("/Users/vmark/work/centauri-private/hyperspace/ethereum/src/storage_layout/ibc_storage.json").unwrap(), + ) + .expect("failed to read predefined storage layout"); + + let storage_layout = project_output + .compiled_artifacts() + .iter() + .chain(diamond_project_output.compiled_artifacts()) + .flat_map(|(_, artifact)| { + artifact.into_iter().flat_map(|(an, artifact)| { + println!("artifact name {an}"); + artifact + }) + }) + .filter_map(|ar| ar.artifact.storage_layout.clone()) + .chain(once(predefined_layout)) + .fold(StorageLayout { storage: vec![], types: Default::default() }, |mut acc, layout| { + // let mut len0 = acc.storage.len(); + // let mut len1 = layout.storage.len(); + acc.storage.extend(layout.storage); + // assert_eq!(acc.storage.len(), len0 + len1, "duplicated storage"); + + let len0 = acc.types.len(); + let len1 = layout.types.len(); + acc.types.extend(layout.types); + assert_eq!(acc.types.len(), len0 + len1, "duplicated type"); + acc + }); + + // dbg!(&storage_layout); + + DeployYuiIbc { diamond, facet_cuts, deployed_facets, storage_layout } } diff --git a/hyperspace/parachain/src/provider.rs b/hyperspace/parachain/src/provider.rs index 20e2ad6f1..c23c71d45 100644 --- a/hyperspace/parachain/src/provider.rs +++ b/hyperspace/parachain/src/provider.rs @@ -491,6 +491,7 @@ where async fn query_received_packets( &self, + at: Height, channel_id: ChannelId, port_id: PortId, seqs: Vec, diff --git a/hyperspace/primitives/src/lib.rs b/hyperspace/primitives/src/lib.rs index 34bae1e33..2ecf1f950 100644 --- a/hyperspace/primitives/src/lib.rs +++ b/hyperspace/primitives/src/lib.rs @@ -362,6 +362,7 @@ pub trait IbcProvider { /// emitted. async fn query_received_packets( &self, + at: Height, channel_id: ChannelId, port_id: PortId, seqs: Vec, From 25640c5c8278e7d9a31849edf0077f539b0dfa62 Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Thu, 31 Aug 2023 17:54:16 -0300 Subject: [PATCH 08/43] Improve ICS Ethereum light client integration Refactored the light-clients/icsxx-ethereum and hyperspace/ethereum modules to improve ICS Ethereum light client integration. The integration tests are updated to accommodate these changes. Also, a new module 'verify' was added to the project to streamline verifying processes. The hyperspace module's dependencies and Cargo.toml file also saw updates. These changes were necessary to refine the function and increase efficiency in the codebase, making it easier to manage and navigate through. Finally, an empty file named jwt.rs got added to manage Json Web Tokens but awaits population. --- Cargo.lock | 640 +++++++++++++++++- Cargo.toml | 4 +- hyperspace/ethereum/Cargo.toml | 10 + hyperspace/ethereum/src/chain.rs | 4 +- hyperspace/ethereum/src/client.rs | 27 +- hyperspace/ethereum/src/events.rs | 98 +++ hyperspace/ethereum/src/ibc_provider.rs | 605 ++++++----------- hyperspace/ethereum/src/jwt.rs | 101 +++ hyperspace/ethereum/src/lib.rs | 3 + hyperspace/ethereum/src/prove.rs | 236 +++++++ hyperspace/ethereum/src/utils.rs | 6 +- hyperspace/ethereum/tests/sanity_checks.rs | 26 +- light-clients/icsxx-ethereum/Cargo.toml | 15 +- .../icsxx-ethereum/src/client_def.rs | 17 +- .../icsxx-ethereum/src/client_state.rs | 4 +- light-clients/icsxx-ethereum/src/lib.rs | 1 + light-clients/icsxx-ethereum/src/tests.rs | 1 + light-clients/icsxx-ethereum/src/verify.rs | 1 + 18 files changed, 1343 insertions(+), 456 deletions(-) create mode 100644 hyperspace/ethereum/src/events.rs create mode 100644 hyperspace/ethereum/src/jwt.rs create mode 100644 hyperspace/ethereum/src/prove.rs create mode 100644 light-clients/icsxx-ethereum/src/verify.rs diff --git a/Cargo.lock b/Cargo.lock index e0c832a75..0285e1cc5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12,6 +12,27 @@ dependencies = [ "regex", ] +[[package]] +name = "actix-macros" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" +dependencies = [ + "quote", + "syn 2.0.28", +] + +[[package]] +name = "actix-rt" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28f32d40287d3f402ae0028a9d54bef51af15c8769492826a69d28f81893151d" +dependencies = [ + "actix-macros", + "futures-core", + "tokio", +] + [[package]] name = "addr2line" version = "0.17.0" @@ -188,6 +209,11 @@ dependencies = [ "memchr", ] +[[package]] +name = "amcl" +version = "0.3.0" +source = "git+https://github.com/sigp/milagro_bls#d3fc0a40cfe8b72ccda46ba050ee6786a59ce753" + [[package]] name = "android_system_properties" version = "0.1.5" @@ -258,6 +284,15 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" +[[package]] +name = "arrayvec" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" +dependencies = [ + "nodrop", +] + [[package]] name = "arrayvec" version = "0.5.2" @@ -270,6 +305,12 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" +[[package]] +name = "as-any" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3419eecc9f5967e6f0f29a0c3fefe22bda6ea34b15798f3c452cb81f2c3fa7" + [[package]] name = "ascii-canvas" version = "3.0.0" @@ -575,6 +616,15 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" +[[package]] +name = "base2" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0d6cf42565b8bd996c9f583069619124475caa645d598d75918923b240409be" +dependencies = [ + "int", +] + [[package]] name = "base58" version = "0.2.0" @@ -849,6 +899,16 @@ dependencies = [ "digest 0.10.6", ] +[[package]] +name = "blake2-rfc" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" +dependencies = [ + "arrayvec 0.4.12", + "constant_time_eq 0.1.5", +] + [[package]] name = "blake2b_simd" version = "1.0.1" @@ -915,6 +975,12 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" +[[package]] +name = "bnum" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "845141a4fade3f790628b7daaaa298a25b204fb28907eb54febe5142db6ce653" + [[package]] name = "bounded-collections" version = "0.1.6" @@ -1504,6 +1570,28 @@ dependencies = [ "memchr", ] +[[package]] +name = "cosmwasm-crypto" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "871ce1d5a4b00ed1741f84b377eec19fadd81a904a227bc1e268d76539d26f5e" +dependencies = [ + "digest 0.10.6", + "ed25519-zebra", + "k256 0.11.6", + "rand_core 0.6.4", + "thiserror", +] + +[[package]] +name = "cosmwasm-derive" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ce8b44b45a7c8c6d6f770cd0a51458c2445c7c15b6115e1d215fa35c77b305c" +dependencies = [ + "syn 1.0.109", +] + [[package]] name = "cosmwasm-schema" version = "1.3.1" @@ -1528,6 +1616,36 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "cosmwasm-std" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da78abcf059181e8cb01e95e5003cf64fe95dde6c72b3fe37e5cabc75cdba32a" +dependencies = [ + "base64 0.13.1", + "bnum", + "cosmwasm-crypto", + "cosmwasm-derive", + "derivative", + "forward_ref", + "hex", + "schemars", + "serde", + "serde-json-wasm", + "sha2 0.10.6", + "thiserror", +] + +[[package]] +name = "cosmwasm-storage" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b52be0d56b78f502f3acb75e40908a0d04d9f265b6beb0f86b36ec2ece048748" +dependencies = [ + "cosmwasm-std", + "serde", +] + [[package]] name = "cpp_demangle" version = "0.3.5" @@ -1915,6 +2033,64 @@ dependencies = [ "zeroize", ] +[[package]] +name = "cw-multi-test" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8e81b4a7821d5eeba0d23f737c16027b39a600742ca8c32eb980895ffd270f4" +dependencies = [ + "anyhow", + "cosmwasm-std", + "cosmwasm-storage", + "cw-storage-plus", + "cw-utils", + "derivative", + "itertools", + "prost 0.9.0", + "schemars", + "serde", + "thiserror", +] + +[[package]] +name = "cw-storage-plus" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc6cf70ef7686e2da9ad7b067c5942cd3e88dd9453f7af42f54557f8af300fb0" +dependencies = [ + "cosmwasm-std", + "schemars", + "serde", +] + +[[package]] +name = "cw-utils" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ae0b69fa7679de78825b4edeeec045066aa2b2c4b6e063d80042e565bb4da5c" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw2", + "schemars", + "semver", + "serde", + "thiserror", +] + +[[package]] +name = "cw2" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5abb8ecea72e09afff830252963cb60faf945ce6cef2c20a43814516082653da" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus", + "schemars", + "serde", +] + [[package]] name = "cxx" version = "1.0.89" @@ -2455,6 +2631,25 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "enr" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26fa0a0be8915790626d5759eb51fe47435a8eac92c2f212bd2da9aa7f30ea56" +dependencies = [ + "base64 0.13.1", + "bs58", + "bytes", + "hex", + "k256 0.11.6", + "log", + "rand 0.8.5", + "rlp", + "serde", + "sha3", + "zeroize", +] + [[package]] name = "enr" version = "0.8.1" @@ -2585,6 +2780,16 @@ dependencies = [ "libc", ] +[[package]] +name = "error-chain" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc" +dependencies = [ + "backtrace", + "version_check", +] + [[package]] name = "eth-keystore" version = "0.5.0" @@ -2639,6 +2844,31 @@ dependencies = [ "tiny-keccak", ] +[[package]] +name = "ethereum-consensus" +version = "0.1.1" +source = "git+https://github.com/polytope-labs/ethereum-consensus?branch=main#48335b5c8074d63553ee4681993e294eba947f88" +dependencies = [ + "async-stream", + "bs58", + "enr 0.6.2", + "error-chain", + "hashbrown 0.13.2", + "hex", + "integer-sqrt", + "milagro_bls", + "multiaddr 0.14.0", + "multihash", + "rand 0.8.5", + "serde", + "serde_json", + "serde_yaml", + "sha2 0.9.9", + "ssz-rs", + "tokio", + "tokio-stream", +] + [[package]] name = "ethereum-types" version = "0.14.1" @@ -3323,6 +3553,21 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "forge-fmt" version = "0.2.0" @@ -3355,6 +3600,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "forward_ref" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8cbd1169bd7b4a0a20d92b9af7a7e0422888bd38a6f5ec29c1fd8c1558a272e" + [[package]] name = "foundry-abi" version = "0.1.0" @@ -4466,6 +4717,19 @@ dependencies = [ "tokio-io-timeout", ] +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper", + "native-tls", + "tokio", + "tokio-native-tls", +] + [[package]] name = "hyperspace" version = "0.1.0" @@ -4510,7 +4774,7 @@ dependencies = [ "pallet-ibc-ping", "parity-scale-codec", "prometheus", - "prost", + "prost 0.11.6", "rand 0.8.5", "scale-decode", "scale-encode", @@ -4556,7 +4820,7 @@ dependencies = [ "log", "pallet-ibc", "parity-scale-codec", - "prost", + "prost 0.11.6", "quick_cache", "rand 0.8.5", "ripemd", @@ -4587,7 +4851,9 @@ dependencies = [ "cast", "elliptic-curve 0.13.5", "env_logger 0.10.0", + "ethereum-consensus", "ethers 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ethers-providers 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "ethers-solc 2.0.9", "futures", "git2", @@ -4599,11 +4865,17 @@ dependencies = [ "ibc-proto", "ibc-rpc", "ics07-tendermint", + "icsxx-ethereum", + "jsonwebtoken", "once_cell", "pallet-ibc", - "prost", + "prost 0.11.6", "serde", "serde_json", + "ssz-rs", + "sync-committee-primitives", + "sync-committee-prover", + "sync-committee-verifier", "thiserror", "tokio", "toml 0.7.6", @@ -4667,7 +4939,7 @@ dependencies = [ "pallet-transaction-payment-rpc-runtime-api", "parity-scale-codec", "polkadot-core-primitives", - "prost", + "prost 0.11.6", "rand 0.8.5", "rs_merkle", "sc-finality-grandpa-rpc", @@ -4748,13 +5020,13 @@ dependencies = [ "hex", "ibc-derive", "ibc-proto", - "ics23", + "ics23 0.10.0", "log", "modelator", "num-traits", "parity-scale-codec", "primitive-types", - "prost", + "prost 0.11.6", "safe-regex", "scale-info", "serde", @@ -4815,7 +5087,7 @@ version = "0.18.0" dependencies = [ "base64 0.13.1", "bytes", - "prost", + "prost 0.11.6", "schemars", "serde", "tendermint-proto", @@ -4870,10 +5142,10 @@ dependencies = [ "ibc", "ibc-derive", "ibc-proto", - "ics23", + "ics23 0.10.0", "log", "modelator", - "prost", + "prost 0.11.6", "serde", "serde_json", "sha2 0.10.6", @@ -4897,7 +5169,7 @@ dependencies = [ "hex", "ibc", "ibc-proto", - "prost", + "prost 0.11.6", "serde", "tendermint-proto", ] @@ -4925,7 +5197,7 @@ dependencies = [ "light-client-common", "log", "parity-scale-codec", - "prost", + "prost 0.11.6", "prost-build", "prost-types", "sc-finality-grandpa-rpc", @@ -4960,7 +5232,7 @@ dependencies = [ "ibc-proto", "light-client-common", "parity-scale-codec", - "prost", + "prost 0.11.6", "prost-build", "prost-types", "serde", @@ -4978,6 +5250,17 @@ dependencies = [ "tokio", ] +[[package]] +name = "ics23" +version = "0.8.1" +source = "git+https://github.com/confio/ics23?rev=a4daeb4c24ce1be827829c0841446abc690c4f11#a4daeb4c24ce1be827829c0841446abc690c4f11" +dependencies = [ + "anyhow", + "bytes", + "hex", + "prost 0.11.6", +] + [[package]] name = "ics23" version = "0.10.0" @@ -4986,12 +5269,80 @@ dependencies = [ "anyhow", "bytes", "hex", - "prost", + "prost 0.11.6", "ripemd", "sha2 0.10.6", "sha3", ] +[[package]] +name = "icsxx-ethereum" +version = "0.1.0" +dependencies = [ + "actix-rt", + "anyhow", + "derive_more", + "env_logger 0.9.3", + "ethereum-consensus", + "futures", + "hex", + "ibc", + "ibc-derive", + "ibc-proto", + "jsonrpsee-ws-client", + "light-client-common", + "log", + "prost 0.11.6", + "prost-build", + "prost-types", + "serde", + "serde_json", + "ssz-rs", + "sync-committee-primitives", + "sync-committee-prover", + "sync-committee-verifier", + "tendermint", + "tendermint-proto", + "tokio", +] + +[[package]] +name = "icsxx-ethereum-cw" +version = "0.1.0" +dependencies = [ + "blake2-rfc", + "byteorder", + "cosmwasm-schema", + "cosmwasm-std", + "cosmwasm-storage", + "cw-multi-test", + "cw-storage-plus", + "cw2", + "derive_more", + "digest 0.10.6", + "ed25519-zebra", + "hex", + "hyperspace-primitives", + "ibc", + "ibc-derive", + "ibc-proto", + "ics08-wasm", + "ics23 0.8.1", + "icsxx-ethereum", + "pallet-ibc", + "prost 0.11.6", + "schemars", + "serde", + "serde-json-wasm", + "serde_json", + "sha2 0.10.6", + "sha3", + "sp-std 5.0.0", + "tendermint-proto", + "thiserror", + "twox-hash", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -5146,6 +5497,15 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "int" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d64bb35c7fc709fa8934dd85f3d0c0e418a3b067e62e6c6041dd19519c0899b" +dependencies = [ + "num-traits", +] + [[package]] name = "integer-sqrt" version = "0.1.5" @@ -5582,7 +5942,7 @@ dependencies = [ "libp2p-webrtc", "libp2p-websocket", "libp2p-yamux", - "multiaddr", + "multiaddr 0.16.0", "parking_lot 0.12.1", "pin-project", "smallvec 1.10.0", @@ -5603,13 +5963,13 @@ dependencies = [ "futures-timer", "instant", "log", - "multiaddr", + "multiaddr 0.16.0", "multihash", "multistream-select", "once_cell", "parking_lot 0.12.1", "pin-project", - "prost", + "prost 0.11.6", "prost-build", "rand 0.8.5", "rw-stream-sink", @@ -5649,7 +6009,7 @@ dependencies = [ "libp2p-swarm", "log", "lru", - "prost", + "prost 0.11.6", "prost-build", "prost-codec", "smallvec 1.10.0", @@ -5674,7 +6034,7 @@ dependencies = [ "libp2p-core", "libp2p-swarm", "log", - "prost", + "prost 0.11.6", "prost-build", "rand 0.8.5", "sha2 0.10.6", @@ -5749,7 +6109,7 @@ dependencies = [ "libp2p-core", "log", "once_cell", - "prost", + "prost 0.11.6", "prost-build", "rand 0.8.5", "sha2 0.10.6", @@ -5913,7 +6273,7 @@ dependencies = [ "libp2p-noise", "log", "multihash", - "prost", + "prost 0.11.6", "prost-build", "prost-codec", "rand 0.8.5", @@ -6319,6 +6679,18 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39617bc909d64b068dcffd0e3e31679195b5576d0c83fadc52690268cc2b2b55" +[[package]] +name = "milagro_bls" +version = "1.5.1" +source = "git+https://github.com/sigp/milagro_bls#d3fc0a40cfe8b72ccda46ba050ee6786a59ce753" +dependencies = [ + "amcl", + "hex", + "lazy_static", + "rand 0.8.5", + "zeroize", +] + [[package]] name = "mime" version = "0.3.16" @@ -6439,6 +6811,24 @@ dependencies = [ "ureq", ] +[[package]] +name = "multiaddr" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c580bfdd8803cce319b047d239559a22f809094aaea4ac13902a1fdcfcd4261" +dependencies = [ + "arrayref", + "bs58", + "byteorder", + "data-encoding", + "multihash", + "percent-encoding", + "serde", + "static_assertions", + "unsigned-varint", + "url", +] + [[package]] name = "multiaddr" version = "0.16.0" @@ -6542,6 +6932,24 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "native-tls" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + [[package]] name = "netlink-packet-core" version = "0.4.2" @@ -6925,6 +7333,32 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "openssl" +version = "0.10.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c" +dependencies = [ + "bitflags 2.3.3", + "cfg-if 1.0.0", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] + [[package]] name = "openssl-probe" version = "0.1.5" @@ -6933,9 +7367,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.91" +version = "0.9.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "866b5f16f90776b9bb8dc1e1802ac6f0513de3a7a7465867bfbc563dc737faac" +checksum = "db7e971c2c2bba161b2d2fdf37080177eff520b3bc044787c7f1f5f9e78d869b" dependencies = [ "cc", "libc", @@ -7177,7 +7611,7 @@ dependencies = [ "ics08-wasm", "ics10-grandpa", "ics11-beefy", - "ics23", + "ics23 0.10.0", "light-client-common", "log", "orml-tokens", @@ -7190,7 +7624,7 @@ dependencies = [ "pallet-timestamp", "parachain-info", "parity-scale-codec", - "prost", + "prost 0.11.6", "scale-info", "serde", "serde_json", @@ -8022,6 +8456,16 @@ dependencies = [ "unarray", ] +[[package]] +name = "prost" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001" +dependencies = [ + "bytes", + "prost-derive 0.9.0", +] + [[package]] name = "prost" version = "0.11.6" @@ -8029,7 +8473,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21dc42e00223fc37204bd4aa177e69420c604ca4a183209a8f9de30c6d934698" dependencies = [ "bytes", - "prost-derive", + "prost-derive 0.11.6", ] [[package]] @@ -8046,7 +8490,7 @@ dependencies = [ "multimap", "petgraph", "prettyplease 0.1.23", - "prost", + "prost 0.11.6", "prost-types", "regex", "syn 1.0.109", @@ -8062,11 +8506,24 @@ checksum = "0dc34979ff898b6e141106178981ce2596c387ea6e62533facfc61a37fc879c0" dependencies = [ "asynchronous-codec", "bytes", - "prost", + "prost 0.11.6", "thiserror", "unsigned-varint", ] +[[package]] +name = "prost-derive" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9cc1a3263e07e0bf68e96268f37665207b49560d98739662cdfaae215c720fe" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "prost-derive" version = "0.11.6" @@ -8087,7 +8544,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a5e0526209433e96d83d750dd81a99118edbc55739e7e61a46764fd2ad537788" dependencies = [ "bytes", - "prost", + "prost 0.11.6", ] [[package]] @@ -8458,10 +8915,12 @@ dependencies = [ "http-body", "hyper", "hyper-rustls 0.24.1", + "hyper-tls", "ipnet", "js-sys", "log", "mime", + "native-tls", "once_cell", "percent-encoding", "pin-project-lite 0.2.13", @@ -8471,6 +8930,7 @@ dependencies = [ "serde_json", "serde_urlencoded", "tokio", + "tokio-native-tls", "tokio-rustls 0.24.1", "tower-service", "url", @@ -9936,6 +10396,15 @@ dependencies = [ "smallvec 0.6.14", ] +[[package]] +name = "serde-json-wasm" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16a62a1fad1e1828b24acac8f2b468971dade7b8c3c2e672bcadefefb1f8c137" +dependencies = [ + "serde", +] + [[package]] name = "serde_bytes" version = "0.11.9" @@ -10031,6 +10500,18 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_yaml" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" +dependencies = [ + "indexmap 1.9.2", + "ryu", + "serde", + "yaml-rust", +] + [[package]] name = "sha-1" version = "0.9.8" @@ -10201,9 +10682,9 @@ name = "simple-iavl" version = "0.1.0" dependencies = [ "bytes", - "ics23", + "ics23 0.10.0", "proptest", - "rand 0.7.3", + "rand 0.8.5", "sha2 0.10.6", "tendermint", ] @@ -11356,6 +11837,31 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "ssz-rs" +version = "0.8.0" +source = "git+https://github.com/polytope-labs/ssz-rs?branch=main#be360ab4849fefc82cfb9f3f5d6a09352ddd6eee" +dependencies = [ + "as-any", + "bitvec 1.0.1", + "hex", + "itertools", + "num-bigint", + "serde", + "sha2 0.9.9", + "ssz-rs-derive", +] + +[[package]] +name = "ssz-rs-derive" +version = "0.8.0" +source = "git+https://github.com/polytope-labs/ssz-rs?branch=main#be360ab4849fefc82cfb9f3f5d6a09352ddd6eee" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -11671,6 +12177,49 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sync-committee-primitives" +version = "0.1.0" +source = "git+https://github.com/polytope-labs/sync-committee-rs.git?rev=c5afca4fbb92cb60dde29c3a89454c288b022d97#c5afca4fbb92cb60dde29c3a89454c288b022d97" +dependencies = [ + "ethereum-consensus", + "hex-literal 0.4.1", + "parity-scale-codec", + "ssz-rs", +] + +[[package]] +name = "sync-committee-prover" +version = "0.1.0" +source = "git+https://github.com/polytope-labs/sync-committee-rs.git?rev=c5afca4fbb92cb60dde29c3a89454c288b022d97#c5afca4fbb92cb60dde29c3a89454c288b022d97" +dependencies = [ + "actix-rt", + "anyhow", + "async-stream", + "base2", + "env_logger 0.10.0", + "ethereum-consensus", + "reqwest", + "serde", + "serde_json", + "ssz-rs", + "sync-committee-primitives", + "sync-committee-verifier", + "tokio", + "tokio-stream", +] + +[[package]] +name = "sync-committee-verifier" +version = "0.1.0" +source = "git+https://github.com/polytope-labs/sync-committee-rs.git?rev=c5afca4fbb92cb60dde29c3a89454c288b022d97#c5afca4fbb92cb60dde29c3a89454c288b022d97" +dependencies = [ + "ethereum-consensus", + "log", + "ssz-rs", + "sync-committee-primitives", +] + [[package]] name = "sync_wrapper" version = "0.1.2" @@ -11749,7 +12298,7 @@ dependencies = [ "k256 0.11.6", "num-traits", "once_cell", - "prost", + "prost 0.11.6", "prost-types", "ripemd", "serde", @@ -11820,7 +12369,7 @@ dependencies = [ "flex-error", "num-derive", "num-traits", - "prost", + "prost 0.11.6", "prost-types", "serde", "serde_bytes", @@ -12098,6 +12647,16 @@ dependencies = [ "syn 2.0.28", ] +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + [[package]] name = "tokio-rustls" version = "0.22.0" @@ -12253,8 +12812,8 @@ dependencies = [ "hyper-timeout", "percent-encoding", "pin-project", - "prost", - "prost-derive", + "prost 0.11.6", + "prost-derive 0.11.6", "rustls-native-certs 0.6.2", "rustls-pemfile", "tokio", @@ -12612,9 +13171,9 @@ version = "1.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "digest 0.10.6", - "rand 0.7.3", + "rand 0.8.5", "static_assertions", ] @@ -13887,6 +14446,15 @@ version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47430998a7b5d499ccee752b41567bc3afc57e1327dc855b1a2aa44ce29b5fa1" +[[package]] +name = "yaml-rust" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" +dependencies = [ + "linked-hash-map", +] + [[package]] name = "yamux" version = "0.10.2" diff --git a/Cargo.toml b/Cargo.toml index 8ee076d45..2c741f495 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,8 +32,8 @@ members = [ # "light-clients/ics10-grandpa-cw", "light-clients/ics11-beefy", # "light-clients/ics13-near", -# "light-clients/icsxx-ethereum", -# "light-clients/icsxx-ethereum-cw", + "light-clients/icsxx-ethereum", + "light-clients/icsxx-ethereum-cw", # "light-clients/ics11-beefy", # "light-clients/ics13-near", diff --git a/hyperspace/ethereum/Cargo.toml b/hyperspace/ethereum/Cargo.toml index 6bee6645c..d6ab14647 100644 --- a/hyperspace/ethereum/Cargo.toml +++ b/hyperspace/ethereum/Cargo.toml @@ -15,8 +15,16 @@ ibc-primitives = { path = "../../contracts/pallet-ibc/primitives" } ibc-proto = { path = "../../ibc/proto" } ibc-rpc = { path = "../../contracts/pallet-ibc/rpc" } ics07-tendermint = { path = "../../light-clients/ics07-tendermint" } +icsxx-ethereum = { path = "../../light-clients/icsxx-ethereum" } pallet-ibc = { path = "../../contracts/pallet-ibc" } +sync-committee-primitives = { git = "https://github.com/polytope-labs/sync-committee-rs.git", rev = "c5afca4fbb92cb60dde29c3a89454c288b022d97", features = ["testing"] } +sync-committee-verifier = { git = "https://github.com/polytope-labs/sync-committee-rs.git", rev = "c5afca4fbb92cb60dde29c3a89454c288b022d97", features = ["testing"] } +sync-committee-prover = { git = "https://github.com/polytope-labs/sync-committee-rs.git", rev = "c5afca4fbb92cb60dde29c3a89454c288b022d97" } +#light-client-common = { path = "../common" } +ethereum-consensus = { git = "https://github.com/polytope-labs/ethereum-consensus", branch = "main" } +ssz-rs = { git = "https://github.com/polytope-labs/ssz-rs", branch = "main" } + cast = { git = "https://github.com/foundry-rs/foundry", version = "0.2.0" } anyhow = "1.0.65" @@ -25,6 +33,8 @@ async-trait = "0.1.53" elliptic-curve = { features = ["pem"], version = "0.13.5" } ethers = { version = "2.0.2", features = ["ws"] } ethers-solc = "2.0.8" +ethers-providers = "2.0.8" +jsonwebtoken = "8.3.0" futures = "0.3.28" hex = "0.4.3" http = "0.2.9" diff --git a/hyperspace/ethereum/src/chain.rs b/hyperspace/ethereum/src/chain.rs index 445619e78..205bfeae6 100644 --- a/hyperspace/ethereum/src/chain.rs +++ b/hyperspace/ethereum/src/chain.rs @@ -55,9 +55,7 @@ impl Chain for EthereumClient { let mut stream = ws.subscribe_blocks().await.expect("fuck"); while let Some(block) = stream.next().await { - if let Some(hash) = block.hash.clone() { - yield Self::FinalityEvent::Ethereum { hash }; - } + yield block } }; diff --git a/hyperspace/ethereum/src/client.rs b/hyperspace/ethereum/src/client.rs index 3a06b8ec4..8ea7d2e98 100644 --- a/hyperspace/ethereum/src/client.rs +++ b/hyperspace/ethereum/src/client.rs @@ -6,7 +6,7 @@ use async_trait::async_trait; use ethers::{ abi::{AbiEncode, Address, ParamType, Token}, prelude::{ - coins_bip39::English, signer::SignerMiddlewareError, BlockId, BlockNumber, + coins_bip39::English, signer::SignerMiddlewareError, Authorization, BlockId, BlockNumber, EIP1186ProofResponse, Filter, LocalWallet, Log, MnemonicBuilder, NameOrAddress, H256, }, providers::{Http, Middleware, Provider, ProviderError, ProviderExt, Ws}, @@ -14,10 +14,15 @@ use ethers::{ types::U256, utils::keccak256, }; +// use ethers_providers:: +use crate::jwt::{JwtAuth, JwtKey}; use futures::{Stream, TryFutureExt}; use ibc::{ applications::transfer::{msgs::transfer::MsgTransfer, PrefixedCoin}, - core::ics24_host::identifier::{ChannelId, ClientId, PortId}, + core::ics24_host::{ + error::ValidationError, + identifier::{ChannelId, ClientId, PortId}, + }, Height, }; use ibc_primitives::Timeout; @@ -72,6 +77,12 @@ pub enum ClientError { Other(String), } +impl From for ClientError { + fn from(value: ValidationError) -> Self { + Self::Other(value.to_string()) + } +} + impl From for ClientError { fn from(value: String) -> Self { Self::Other(value) @@ -135,7 +146,17 @@ impl EthereumClient { } pub async fn websocket_provider(&self) -> Result, ClientError> { - Provider::::connect(self.ws_uri.to_string()) + let secret = std::fs::read_to_string( + "/Users/vmark/.lighthouse/local-testnet/geth_datadir1/geth/jwtsecret", + ) + .unwrap(); + println!("secret = {secret}"); + let secret = JwtKey::from_slice(&hex::decode(&secret[2..]).unwrap()).expect("oops"); + let jwt_auth = JwtAuth::new(secret, None, None); + let token = jwt_auth.generate_token().unwrap(); + + let auth = Authorization::bearer(dbg!(token)); + Provider::::connect_with_auth(self.ws_uri.to_string(), auth) .await .map_err(|e| ClientError::ProviderError(self.ws_uri.clone(), ProviderError::from(e))) } diff --git a/hyperspace/ethereum/src/events.rs b/hyperspace/ethereum/src/events.rs new file mode 100644 index 000000000..015bb5052 --- /dev/null +++ b/hyperspace/ethereum/src/events.rs @@ -0,0 +1,98 @@ +use crate::{ + client::{ClientError, EthereumClient}, + ibc_provider::{CreateClientFilter, UpdateClientFilter}, +}; +use async_trait::async_trait; +use ethers::prelude::Log; +use ibc::{ + core::ics02_client::events::{Attributes as ClientAttributes, CreateClient, UpdateClient}, + events::IbcEvent, + Height, +}; + +#[async_trait] +pub trait TryFromEvent +where + Self: Sized, +{ + async fn try_from_event( + client: &EthereumClient, + event: T, + log: Log, + height: Height, + ) -> Result; +} + +/* + NewBlock(NewBlock), + + CreateClient(ClientEvents::CreateClient), + UpdateClient(ClientEvents::UpdateClient), + UpgradeClient(ClientEvents::UpgradeClient), + ClientMisbehaviour(ClientEvents::ClientMisbehaviour), + PushWasmCode(ClientEvents::PushWasmCode), + + OpenInitConnection(ConnectionEvents::OpenInit), + OpenTryConnection(ConnectionEvents::OpenTry), + OpenAckConnection(ConnectionEvents::OpenAck), + OpenConfirmConnection(ConnectionEvents::OpenConfirm), + + OpenInitChannel(ChannelEvents::OpenInit), + OpenTryChannel(ChannelEvents::OpenTry), + OpenAckChannel(ChannelEvents::OpenAck), + OpenConfirmChannel(ChannelEvents::OpenConfirm), + CloseInitChannel(ChannelEvents::CloseInit), + CloseConfirmChannel(ChannelEvents::CloseConfirm), + + SendPacket(ChannelEvents::SendPacket), + ReceivePacket(ChannelEvents::ReceivePacket), + WriteAcknowledgement(ChannelEvents::WriteAcknowledgement), + AcknowledgePacket(ChannelEvents::AcknowledgePacket), + TimeoutPacket(ChannelEvents::TimeoutPacket), + TimeoutOnClosePacket(ChannelEvents::TimeoutOnClosePacket), + + AppModule(ModuleEvent), + + Empty(String), // Special event, signifying empty response + ChainError(String), // Special event, signifying an error on CheckTx or DeliverTx + +*/ + +#[async_trait] +impl TryFromEvent for IbcEvent { + async fn try_from_event( + client: &EthereumClient, + event: CreateClientFilter, + log: Log, + height: Height, + ) -> Result { + let CreateClientFilter { client_id, client_type } = event; + Ok(IbcEvent::CreateClient(CreateClient(ClientAttributes { + height, + client_id: client_id.parse()?, + client_type, + consensus_height: Default::default(), // TODO: consensus height? + }))) + } +} + +#[async_trait] +impl TryFromEvent for IbcEvent { + async fn try_from_event( + client: &EthereumClient, + event: UpdateClientFilter, + log: Log, + height: Height, + ) -> Result { + let UpdateClientFilter { client_id, header } = event; + Ok(IbcEvent::UpdateClient(UpdateClient { + common: ClientAttributes { + height, + client_id: client_id.parse()?, + client_type: Default::default(), // TODO: client type? + consensus_height: Default::default(), // TODO: consensus height? + }, + header: Some(header.to_vec()), // TODO: header query + })) + } +} diff --git a/hyperspace/ethereum/src/ibc_provider.rs b/hyperspace/ethereum/src/ibc_provider.rs index 889edd725..abacc74da 100644 --- a/hyperspace/ethereum/src/ibc_provider.rs +++ b/hyperspace/ethereum/src/ibc_provider.rs @@ -1,7 +1,7 @@ use ethers::{ - abi::{encode, AbiEncode, Detokenize, ParamType, Token, Tokenizable}, - contract::abigen, - prelude::Topic, + abi::{encode, AbiEncode, Detokenize, ParamType, RawLog, Token, Tokenizable}, + contract::{abigen, EthEvent}, + prelude::{Block, Topic}, providers::Middleware, types::{ BlockId, BlockNumber, EIP1186ProofResponse, Filter, StorageProof, ValueOrArray, H256, U256, @@ -42,17 +42,27 @@ use ibc_proto::{ use primitives::{IbcProvider, UpdateType}; use prost::Message; use std::{ - collections::HashSet, future::Future, pin::Pin, str::FromStr, sync::Arc, time::Duration, + collections::{HashMap, HashSet}, + future::Future, + pin::Pin, + str::FromStr, + sync::Arc, + time::Duration, }; -use crate::client::{ - ClientError, EthereumClient, COMMITMENTS_STORAGE_INDEX, CONNECTIONS_STORAGE_INDEX, +use crate::{ + client::{ClientError, EthereumClient, COMMITMENTS_STORAGE_INDEX, CONNECTIONS_STORAGE_INDEX}, + events::TryFromEvent, }; use futures::{FutureExt, Stream, StreamExt}; use ibc::{ applications::transfer::PrefixedCoin, - core::ics04_channel::channel::{Order, State}, + core::ics04_channel::{ + channel::{Order, State}, + events::SendPacket, + }, events::IbcEvent, + protobuf::Protobuf, }; use ibc_proto::{ google::protobuf::Any, @@ -63,285 +73,21 @@ use ibc_proto::{ }, }; use ibc_rpc::{IbcApiClient, PacketInfo}; -use pallet_ibc::light_clients::{AnyClientState, AnyConsensusState}; +use icsxx_ethereum::client_state::ClientState; +use pallet_ibc::light_clients::{AnyClientState, AnyConsensusState, HostFunctionsManager}; abigen!( - IbcHandlerAbi, - r#"[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "sequence", - "type": "uint64" - }, - { - "indexed": true, - "internalType": "string", - "name": "sourcePort", - "type": "string" - }, - { - "indexed": true, - "internalType": "string", - "name": "sourceChannel", - "type": "string" - }, - { - "components": [ - { - "internalType": "uint64", - "name": "revision_number", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "revision_height", - "type": "uint64" - } - ], - "indexed": false, - "internalType": "struct HeightData", - "name": "timeoutHeight", - "type": "tuple" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "timeoutTimestamp", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "SendPacket", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "sequence", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "string", - "name": "source_port", - "type": "string" - }, - { - "indexed": false, - "internalType": "string", - "name": "source_channel", - "type": "string" - }, - { - "indexed": true, - "internalType": "string", - "name": "destination_port", - "type": "string" - }, - { - "indexed": true, - "internalType": "string", - "name": "destination_channel", - "type": "string" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "uint64", - "name": "revision_number", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "revision_height", - "type": "uint64" - } - ], - "indexed": false, - "internalType": "struct HeightData", - "name": "timeout_height", - "type": "tuple" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "timeout_timestamp", - "type": "uint64" - } - ], - "name": "RecvPacket", - "type": "event" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "string", - "name": "portId", - "type": "string" - }, - { - "components": [ - { - "internalType": "enum ChannelState", - "name": "state", - "type": "uint8" - }, - { - "internalType": "enum ChannelOrder", - "name": "ordering", - "type": "uint8" - }, - { - "components": [ - { - "internalType": "string", - "name": "port_id", - "type": "string" - }, - { - "internalType": "string", - "name": "channel_id", - "type": "string" - } - ], - "internalType": "struct ChannelCounterpartyData", - "name": "counterparty", - "type": "tuple" - }, - { - "internalType": "string[]", - "name": "connection_hops", - "type": "string[]" - }, - { - "internalType": "string", - "name": "version", - "type": "string" - } - ], - "internalType": "struct ChannelData", - "name": "channel", - "type": "tuple" - } - ], - "internalType": "struct IBCMsgsMsgChannelOpenInit", - "name": "msg_", - "type": "tuple" - } - ], - "name": "channelOpenInit", - "outputs": [ - { - "internalType": "string", - "name": "channelId", - "type": "string" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "connectionId", - "type": "string" - }, - { - "components": [ - { - "internalType": "string", - "name": "client_id", - "type": "string" - }, - { - "components": [ - { - "internalType": "string", - "name": "identifier", - "type": "string" - }, - { - "internalType": "string[]", - "name": "features", - "type": "string[]" - } - ], - "internalType": "struct VersionData[]", - "name": "versions", - "type": "tuple[]" - }, - { - "internalType": "enum ConnectionEndState", - "name": "state", - "type": "uint8" - }, - { - "components": [ - { - "internalType": "string", - "name": "client_id", - "type": "string" - }, - { - "internalType": "string", - "name": "connection_id", - "type": "string" - }, - { - "components": [ - { - "internalType": "bytes", - "name": "key_prefix", - "type": "bytes" - } - ], - "internalType": "struct MerklePrefixData", - "name": "prefix", - "type": "tuple" - } - ], - "internalType": "struct CounterpartyData", - "name": "counterparty", - "type": "tuple" - }, - { - "internalType": "uint64", - "name": "delay_period", - "type": "uint64" - } - ], - "internalType": "struct ConnectionEndData", - "name": "connection", - "type": "tuple" - } - ], - "name": "setConnection", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ]"# + IbcClientAbi, + "/Users/vmark/work/centauri-private/hyperspace/ethereum/src/abi/ibc-client-abi.json"; + + IbcConnectionAbi, + "/Users/vmark/work/centauri-private/hyperspace/ethereum/src/abi/ibc-connection-abi.json"; + + IbcChannelAbi, + "/Users/vmark/work/centauri-private/hyperspace/ethereum/src/abi/ibc-channel-abi.json"; + + IbcPacketAbi, + "/Users/vmark/work/centauri-private/hyperspace/ethereum/src/abi/ibc-packet-abi.json"; ); impl From for Height { @@ -385,9 +131,11 @@ where } } +const NUMBER_OF_BLOCKS_TO_PROCESS_PER_ITER: u64 = 100; + #[async_trait::async_trait] impl IbcProvider for EthereumClient { - type FinalityEvent = FinalityEvent; + type FinalityEvent = Block; type TransactionId = (); @@ -403,106 +151,101 @@ impl IbcProvider for EthereumClient { where T: primitives::Chain, { - tracing::debug!(?finality_event, "querying latest ibc events"); - tracing::warn!("TODO: implement query_latest_ibc_events"); - Ok(vec![]) + let client_id = self.client_id(); + let latest_cp_height = counterparty.latest_height_and_timestamp().await?.0; + let latest_cp_client_state = + counterparty.query_client_state(latest_cp_height, client_id.clone()).await?; + let client_state_response = latest_cp_client_state.client_state.ok_or_else(|| { + ClientError::Other("counterparty returned empty client state".to_string()) + })?; + let client_state = ClientState::::decode_vec( + &client_state_response.value, + ) + .map_err(|_| ClientError::Other("failed to decode client state response".to_string()))?; + let latest_cp_client_height = client_state.latest_height().revision_height; + let latest_height = self.latest_height_and_timestamp().await?.0; + let latest_revision = latest_height.revision_number; + + // tracing::debug!(?finality_event, "querying latest ibc events"); + // tracing::warn!("TODO: implement query_latest_ibc_events"); + let from = latest_cp_client_height; + let to = finality_event + .number + .unwrap() + .as_u64() + .min(latest_cp_client_height + NUMBER_OF_BLOCKS_TO_PROCESS_PER_ITER); + println!("Getting blocks {}..{}", from, to); + let filter = + Filter::new().from_block(from).to_block(to).address(self.yui.diamond.address()); + let client = self.clone(); + let logs = self.http_rpc.get_logs(&filter).await.unwrap(); + let mut events = vec![]; + + // for log in logs { + // let raw_log = RawLog::from(log.clone()); + // let height = Height::new(0, log.block_number.unwrap().as_u64()); + // let topic0 = log.topics[0]; + // + // let mut maybe_ibc_event = if topic0 == CreateClientFilter::signature() { + // let event = CreateClientFilter::decode_log(&raw_log).expect("decode event"); + // IbcEvent::try_from_event(&client, event, log, height).await + // } else { + // eprintln!("unknown event: {}", log.log_type.unwrap_or(format!("{topic0:?}"))); + // continue + // }; + // + // match maybe_ibc_event { + // Ok(ev) => todo!(), + // Err(err) => { + // eprintln!("failed to decode event: {err}"); + // None + // }, + // } + // } + + Ok(events) } async fn ibc_events(&self) -> Pin + Send + 'static>> { - fn decode_string(bytes: &[u8]) -> String { - ethers::abi::decode(&[ParamType::String], &bytes) - .unwrap() - .into_iter() - .next() - .unwrap() - .to_string() - } - - fn decode_client_id_log(log: ethers::types::Log) -> IbcEvent { - let client_id = decode_string(&log.data.0); - IbcEvent::CreateClient(CreateClient(Attributes { - height: Height::default(), - client_id: ClientId::from_str(&client_id).unwrap(), - client_type: "00-uninitialized".to_owned(), - consensus_height: Height::default(), - })) - } + let ibc_address = self.config.ibc_handler_address; + let client = self.clone(); - let ibc_handler_address = self.config.ibc_handler_address; - - match self.websocket_provider().await { - Ok(ws) => async_stream::stream! { - let channel_id_stream = ws - .subscribe_logs( - &Filter::new() - .from_block(BlockNumber::Latest) - .address(ibc_handler_address) - .event("GeneratedChannelIdentifier(string)"), - ) - .await - .expect("failed to subscribe to GeneratedChannelIdentifier event") - .map(decode_client_id_log); - - let client_id_stream = ws - .subscribe_logs( - &Filter::new() - .from_block(BlockNumber::Latest) - .address(ibc_handler_address) - .event("GeneratedClientIdentifier(string)"), - ) - .await - .expect("failed to subscribe to GeneratedClientId event") - .map(decode_client_id_log); - - let connection_id_stream = ws - .subscribe_logs( - &Filter::new() - .from_block(BlockNumber::Latest) - .address(ibc_handler_address) - .event("GeneratedConnectionIdentifier(string)"), - ) - .await - .expect("failed to subscribe to GeneratedConnectionIdentifier event") - .map(decode_client_id_log); - - let recv_packet_stream = ws - .subscribe_logs( - &Filter::new() - .from_block(BlockNumber::Latest) - .address(ibc_handler_address) - .event("RecvPacket((uint64,string,string,string,string,bytes,(uint64,uint64),uint64))"), - ) - .await - .expect("failed to subscribe to RecvPacket event") - .map(decode_client_id_log); - - let send_packet_stream = ws - .subscribe_logs( - &Filter::new() - .from_block(BlockNumber::Latest) - .address(ibc_handler_address) - .event("SendPacket(uint64,string,string,(uint64,uint64),uint64,bytes)"), - ) - .await - .expect("failed to subscribe to SendPacket event") - .map(decode_client_id_log); - - let inner = futures::stream::select_all([ - channel_id_stream, - client_id_stream, - connection_id_stream, - recv_packet_stream, - send_packet_stream - ]); - futures::pin_mut!(inner); - - while let Some(ev) = inner.next().await { - yield ev + let ws = self.websocket_provider().await.unwrap(); + (async_stream::stream! { + let mut events_stream = ws.subscribe_logs( + &Filter::new().from_block(BlockNumber::Latest).address(ibc_address), + ) + .await + .unwrap() + .filter_map(|log| async { + let raw_log = RawLog::from(log.clone()); + let height = Height::new(0, log.block_number.unwrap().as_u64()); + let topic0 = log.topics[0]; + + let mut maybe_ibc_event = if topic0 == CreateClientFilter::signature() { + let event = CreateClientFilter::decode_log(&raw_log).expect("decode event"); + IbcEvent::try_from_event(&client, event, log, height).await + } else { + eprintln!( + "unknown event: {}", + log.log_type.unwrap_or(format!("{topic0:?}")) + ); + return None + }; + + match maybe_ibc_event { + Ok(ev) => Some(ev), + Err(err) => { + eprintln!("failed to decode event: {err}"); + None + }, } + }).boxed(); + + while let Some(ev) = events_stream.next().await { + yield ev } - .left_stream(), - Err(_) => futures::stream::empty().right_stream(), - } + }) .boxed() } @@ -1036,7 +779,8 @@ impl IbcProvider for EthereumClient { .from_block(BlockNumber::Earliest) // TODO: use contract creation height .to_block(BlockNumber::Latest) .topic1(ValueOrArray::Array( - seqs.into_iter() + seqs.clone() + .into_iter() .map(|seq| { let bytes = encode(&[Token::Uint(seq.into())]); H256::from_slice(bytes.as_slice()) @@ -1044,22 +788,53 @@ impl IbcProvider for EthereumClient { .collect(), )) .topic2({ - let hash = H256::from_slice(&encode(&[Token::FixedBytes( + ValueOrArray::Value(H256::from_slice(&encode(&[Token::FixedBytes( keccak256(destination_port.clone().into_bytes()).to_vec(), - )])); - ValueOrArray::Value(hash) + )]))) }) .topic3({ - let hash = H256::from_slice(&encode(&[Token::FixedBytes( + ValueOrArray::Value(H256::from_slice(&encode(&[Token::FixedBytes( keccak256(destination_channel.clone().into_bytes()).to_vec(), - )])); - ValueOrArray::Value(hash) + )]))) }); let events = event_filter.query().await.unwrap(); let channel = self.query_channel_end(at, channel_id, port_id).await?; - let channel = channel.channel.expect("channel is none"); + + let acks_filter = self + .yui + .event_for_name::("WriteAcknowledgement") + .expect("contract is missing WriteAcknowledgement event") + .from_block(BlockNumber::Earliest) // TODO: use contract creation height + .to_block(BlockNumber::Latest) + .topic3(ValueOrArray::Array( + seqs.into_iter() + .map(|seq| { + let bytes = encode(&[Token::Uint(seq.into())]); + H256::from_slice(bytes.as_slice()) + }) + .collect(), + )) + .topic1({ + ValueOrArray::Value(H256::from_slice(&encode(&[Token::FixedBytes( + keccak256(destination_port.clone().into_bytes()).to_vec(), + )]))) + }) + .topic2({ + ValueOrArray::Value(H256::from_slice(&encode(&[Token::FixedBytes( + keccak256(destination_channel.clone().into_bytes()).to_vec(), + )]))) + }); + + let mut acks_map = acks_filter + .query() + .await + .unwrap() + .into_iter() + .map(|ack| (ack.sequence, ack.acknowledgement.to_vec())) + .collect::>(); + Ok(events .into_iter() .map(move |value| PacketInfo { @@ -1076,7 +851,7 @@ impl IbcProvider for EthereumClient { .map_err(|_| Self::Error::Other("invalid channel order".to_owned())) .unwrap() .to_string(), - ack: None, + ack: acks_map.get(&value.sequence).cloned(), }) .collect()) } @@ -1090,14 +865,51 @@ impl IbcProvider for EthereumClient { client_id: ClientId, client_height: Height, ) -> Result<(Height, Timestamp), Self::Error> { - todo!(); + let event_filter = self + .yui + .event_for_name::("UpdateClientHeight") + .expect("contract is missing UpdateClientHeight event") + .from_block(BlockNumber::Earliest) // TODO: use contract creation height + .to_block(BlockNumber::Latest) + .topic1({ + ValueOrArray::Value(H256::from_slice(&encode(&[Token::FixedBytes( + keccak256(client_id.to_string()).to_vec(), + )]))) + }) + .topic2({ + let height_bytes = encode(&[Token::Tuple(vec![ + Token::Uint(client_height.revision_number.into()), + Token::Uint(client_height.revision_height.into()), + ])]); + ValueOrArray::Value(H256::from_slice(&encode(&[Token::FixedBytes( + keccak256(&height_bytes).to_vec(), + )]))) + }); + + let log = self + .yui + .diamond + .client() + .get_logs(&event_filter.filter) + .await + .unwrap() + .pop() + .unwrap(); + + let height = Height::new(0, log.block_number.expect("block number is none").as_u64()); + + let timestamp = + Timestamp::from_nanoseconds(self.query_timestamp_at(height.revision_height).await?) + .unwrap(); + + Ok((height, timestamp)) } async fn query_host_consensus_state_proof( &self, - client_state: &AnyClientState, + _client_state: &AnyClientState, ) -> Result>, Self::Error> { - todo!() + Ok(Some(vec![])) } async fn query_ibc_balance( @@ -1137,11 +949,18 @@ impl IbcProvider for EthereumClient { } fn client_type(&self) -> ClientType { - todo!() + "xx-ethereum".to_string() } async fn query_timestamp_at(&self, block_number: u64) -> Result { - todo!() + let block = self + .http_rpc + .get_block(BlockId::Number(BlockNumber::Number(block_number.into()))) + .await + .map_err(|err| ClientError::MiddlewareError(err))? + .ok_or_else(|| ClientError::MiddlewareError(todo!()))?; + + Ok(Duration::from_secs(block.timestamp.as_u64()).as_nanos() as u64) } async fn query_clients(&self) -> Result, Self::Error> { diff --git a/hyperspace/ethereum/src/jwt.rs b/hyperspace/ethereum/src/jwt.rs new file mode 100644 index 000000000..515d340e3 --- /dev/null +++ b/hyperspace/ethereum/src/jwt.rs @@ -0,0 +1,101 @@ +use jsonwebtoken::{encode, get_current_timestamp, Algorithm, EncodingKey, Header}; +use serde::{Deserialize, Serialize}; + +/// Default algorithm used for JWT token signing. +const DEFAULT_ALGORITHM: Algorithm = Algorithm::HS256; + +/// JWT secret length in bytes. +pub const JWT_SECRET_LENGTH: usize = 32; + +/// Generates a bearer token from a JWT secret +pub struct JwtKey([u8; JWT_SECRET_LENGTH]); + +impl JwtKey { + /// Wrap given slice in `Self`. Returns an error if slice.len() != `JWT_SECRET_LENGTH`. + pub fn from_slice(key: &[u8]) -> Result { + if key.len() != JWT_SECRET_LENGTH { + return Err(format!( + "Invalid key length. Expected {} got {}", + JWT_SECRET_LENGTH, + key.len() + )) + } + let mut res = [0; JWT_SECRET_LENGTH]; + res.copy_from_slice(key); + Ok(Self(res)) + } + + /// Decode the given string from hex (no 0x prefix), and attempt to create a key from it. + pub fn from_hex(hex: &str) -> Result { + let bytes = hex::decode(hex).map_err(|e| format!("Invalid hex: {}", e))?; + Self::from_slice(&bytes) + } + + /// Returns a reference to the underlying byte array. + pub fn as_bytes(&self) -> &[u8; JWT_SECRET_LENGTH] { + &self.0 + } + + /// Consumes the key, returning its underlying byte array. + pub fn into_bytes(self) -> [u8; JWT_SECRET_LENGTH] { + self.0 + } +} + +/// Contains the JWT secret and claims parameters. +pub struct JwtAuth { + key: EncodingKey, + id: Option, + clv: Option, +} + +impl JwtAuth { + /// Create a new [JwtAuth] from a secret key, and optional `id` and `clv` claims. + pub fn new(secret: JwtKey, id: Option, clv: Option) -> Self { + Self { key: EncodingKey::from_secret(secret.as_bytes()), id, clv } + } + + /// Generate a JWT token with `claims.iat` set to current time. + pub fn generate_token(&self) -> Result { + let claims = self.generate_claims_at_timestamp(); + self.generate_token_with_claims(&claims) + } + + /// Generate a JWT token with the given claims. + fn generate_token_with_claims(&self, claims: &Claims) -> Result { + let header = Header::new(DEFAULT_ALGORITHM); + Ok(encode(&header, claims, &self.key)?) + } + + /// Generate a `Claims` struct with `iat` set to current time + fn generate_claims_at_timestamp(&self) -> Claims { + Claims { iat: get_current_timestamp(), id: self.id.clone(), clv: self.clv.clone() } + } + + /// Validate a JWT token given the secret key and return the originally signed `TokenData`. + pub fn validate_token( + token: &str, + secret: &JwtKey, + ) -> Result, anyhow::Error> { + let mut validation = jsonwebtoken::Validation::new(DEFAULT_ALGORITHM); + validation.validate_exp = false; + validation.required_spec_claims.remove("exp"); + + Ok(jsonwebtoken::decode::( + token, + &jsonwebtoken::DecodingKey::from_secret(secret.as_bytes()), + &validation, + )?) + } +} + +/// Claims struct as defined in +#[derive(Debug, Serialize, Deserialize, PartialEq)] +pub struct Claims { + /// issued-at claim. Represented as seconds passed since UNIX_EPOCH. + iat: u64, + /// Optional unique identifier for the CL node. + id: Option, + /// Optional client version for the CL node. + clv: Option, +} diff --git a/hyperspace/ethereum/src/lib.rs b/hyperspace/ethereum/src/lib.rs index 71f4fdfa7..92b9b3800 100644 --- a/hyperspace/ethereum/src/lib.rs +++ b/hyperspace/ethereum/src/lib.rs @@ -7,7 +7,10 @@ pub mod client; pub mod contract; pub mod chain; +pub mod events; pub mod ibc_provider; +pub mod jwt; pub mod key_provider; pub mod light_client_sync; +pub mod prove; pub mod utils; diff --git a/hyperspace/ethereum/src/prove.rs b/hyperspace/ethereum/src/prove.rs new file mode 100644 index 000000000..63e6f7cc0 --- /dev/null +++ b/hyperspace/ethereum/src/prove.rs @@ -0,0 +1,236 @@ +// use base2::Base2; +use crate::client::{ClientError, EthereumClient}; +use ethereum_consensus::{ + altair::mainnet::SYNC_COMMITTEE_SIZE, + bellatrix::compute_domain, + phase0::mainnet::SLOTS_PER_EPOCH, + primitives::{Bytes32, Root}, + signing::compute_signing_root, + state_transition::Context, +}; +use ethers::prelude::{EthCall, H256}; +use ssz_rs::{ + calculate_multi_merkle_root, is_valid_merkle_branch, GeneralizedIndex, Merkleized, Node, +}; +use std::time::Duration; +use sync_committee_primitives::{ + types::{ + AncestorBlock, FinalityProof, LightClientState, LightClientUpdate, SyncCommitteeUpdate, + DOMAIN_SYNC_COMMITTEE, GENESIS_VALIDATORS_ROOT, + }, + util::{compute_fork_version, compute_sync_committee_period_at_slot}, +}; +use sync_committee_prover::{ + prove_block_roots_proof, prove_execution_payload, prove_finalized_header, + prove_sync_committee_update, SyncCommitteeProver, +}; +use sync_committee_verifier::{verify_sync_committee_attestation, SignatureVerifier}; +use tokio::time; +// use tokio_stream::{wrappers::IntervalStream, StreamExt}; + +pub async fn prove( + client: &EthereumClient, + block_hash: H256, +) -> Result, ClientError> { + let sync_committee_prover = SyncCommitteeProver::new(client.config.http_rpc_url.to_string()); + + let block_id = format!("{block_hash:?}"); + // let block_id = "head"; + + let block_header = sync_committee_prover.fetch_header(&block_id).await.unwrap(); + + let state = sync_committee_prover + .fetch_beacon_state(&block_header.slot.to_string()) + .await + .unwrap(); + + let mut client_state = LightClientState { + finalized_header: block_header.clone(), + latest_finalized_epoch: 0, + current_sync_committee: state.current_sync_committee, + next_sync_committee: state.next_sync_committee, + }; + + let finality_checkpoint = sync_committee_prover.fetch_finalized_checkpoint().await.unwrap(); + if finality_checkpoint.finalized.root == Node::default() || + finality_checkpoint.finalized.epoch <= client_state.latest_finalized_epoch || + finality_checkpoint.finalized.root == + client_state.finalized_header.clone().hash_tree_root().unwrap() + { + panic!("No new finalized checkpoint found") + } + + println!("A new epoch has been finalized {}", finality_checkpoint.finalized.epoch); + + let block_id = { + let mut block_id = hex::encode(finality_checkpoint.finalized.root.as_bytes()); + block_id.insert_str(0, "0x"); + block_id + }; + + let finalized_header = sync_committee_prover.fetch_header(&block_id).await.unwrap(); + let finalized_state = sync_committee_prover + .fetch_beacon_state(finalized_header.slot.to_string().as_str()) + .await + .unwrap(); + let execution_payload_proof = prove_execution_payload(finalized_state.clone()).unwrap(); + + let mut attested_epoch = finality_checkpoint.finalized.epoch + 2; + // Get attested header and the signature slot + + let mut attested_slot = attested_epoch * SLOTS_PER_EPOCH; + // Due to the fact that all slots in an epoch can be missed we are going to try and fetch + // the attested block from four possible epochs. + let mut attested_epoch_loop_count = 0; + let (attested_block_header, signature_block) = loop { + if attested_epoch_loop_count == 4 { + panic!("Could not fetch any block from the attested epoch after going through four epochs, your Eth devnet is fucked") + } + // If we have maxed out the slots in the current epoch and still didn't find any block, + // we move to the next epoch + if (attested_epoch * SLOTS_PER_EPOCH).saturating_add(SLOTS_PER_EPOCH - 1) == attested_slot { + // No block was found in attested epoch we move to the next possible attested epoch + println!( + "No slots found in epoch {attested_epoch} Moving to the next possible epoch {}", + attested_epoch + 1 + ); + std::thread::sleep(Duration::from_secs(24)); + attested_epoch += 1; + attested_slot = attested_epoch * SLOTS_PER_EPOCH; + attested_epoch_loop_count += 1; + } + + if let Ok(header) = + sync_committee_prover.fetch_header(attested_slot.to_string().as_str()).await + { + let mut signature_slot = header.slot + 1; + let mut loop_count = 0; + let signature_block = loop { + if loop_count == 2 { + break None + } + if (attested_epoch * SLOTS_PER_EPOCH).saturating_add(SLOTS_PER_EPOCH - 1) == + signature_slot + { + println!("Waiting for signature block for attested header"); + std::thread::sleep(Duration::from_secs(24)); + signature_slot = header.slot + 1; + loop_count += 1; + } + if let Ok(signature_block) = + sync_committee_prover.fetch_block(signature_slot.to_string().as_str()).await + { + break Some(signature_block) + } + signature_slot += 1; + }; + // If the next block does not have sufficient sync committee participants + if let Some(signature_block) = signature_block { + if signature_block + .body + .sync_aggregate + .sync_committee_bits + .as_bitslice() + .count_ones() < (2 * (SYNC_COMMITTEE_SIZE)) / 3 + { + attested_slot += 1; + println!("Signature block does not have sufficient sync committee participants -> participants {}", signature_block.body.sync_aggregate.sync_committee_bits.as_bitslice().count_ones()); + continue + } + break (header, signature_block) + } else { + println!("No signature block found in {attested_epoch} Moving to the next possible epoch {}", attested_epoch + 1); + std::thread::sleep(Duration::from_secs(24)); + attested_epoch += 1; + attested_slot = attested_epoch * SLOTS_PER_EPOCH; + attested_epoch_loop_count += 1; + continue + } + } + attested_slot += 1 + }; + + let attested_state = sync_committee_prover + .fetch_beacon_state(attested_block_header.slot.to_string().as_str()) + .await + .unwrap(); + + let finalized_hash_tree_root = finalized_header.clone().hash_tree_root().unwrap(); + println!("{:?}, {}", attested_state.finalized_checkpoint, attested_state.slot); + println!("{:?}, {}", finalized_hash_tree_root, finalized_header.slot); + + assert_eq!(finalized_hash_tree_root, attested_state.finalized_checkpoint.root); + + let finality_proof = FinalityProof { + epoch: finality_checkpoint.finalized.epoch, + finality_branch: prove_finalized_header(attested_state.clone()).unwrap(), + }; + + let state_period = compute_sync_committee_period_at_slot(finalized_header.slot); + + let update_attested_period = compute_sync_committee_period_at_slot(attested_block_header.slot); + + let sync_committee_update = if state_period == update_attested_period { + let sync_committee_proof = prove_sync_committee_update(attested_state.clone()).unwrap(); + + let sync_committee_proof = sync_committee_proof + .into_iter() + .map(|node| Bytes32::try_from(node.as_bytes()).expect("Node is always 32 byte slice")) + .collect::>(); + + Some(SyncCommitteeUpdate { + next_sync_committee: attested_state.next_sync_committee, + next_sync_committee_branch: sync_committee_proof, + }) + } else { + None + }; + + let mut i = finalized_header.slot - 1; + let mut ancestor_blocks = vec![]; + while ancestor_blocks.len() < 5 { + if (finalized_header.slot - i) > 100 { + break + } + if let Ok(ancestor_header) = + sync_committee_prover.fetch_header(i.to_string().as_str()).await + { + let ancestry_proof = + prove_block_roots_proof(finalized_state.clone(), ancestor_header.clone()).unwrap(); + let header_state = + sync_committee_prover.fetch_beacon_state(i.to_string().as_str()).await.unwrap(); + let execution_payload_proof = prove_execution_payload(header_state).unwrap(); + ancestor_blocks.push(AncestorBlock { + header: ancestor_header, + execution_payload: execution_payload_proof, + ancestry_proof, + }) + } + i -= 1; + } + + println!("\nAncestor blocks count: \n {:?} \n", ancestor_blocks.len()); + + // construct light client + let light_client_update = LightClientUpdate { + attested_header: attested_block_header, + sync_committee_update, + finalized_header, + execution_payload: execution_payload_proof, + finality_proof, + sync_aggregate: signature_block.body.sync_aggregate, + signature_slot: signature_block.slot, + ancestor_blocks: vec![], // TODO: add ancestor blocks? + }; + + // client_state = verify_sync_committee_attestation::( + // client_state.clone(), + // light_client_update, + // ) + // .unwrap(); + // println!( + // "Sucessfully verified Ethereum block at slot {:?}", + // client_state.finalized_header.slot + // ); + Ok(light_client_update) +} diff --git a/hyperspace/ethereum/src/utils.rs b/hyperspace/ethereum/src/utils.rs index 64a88ecca..ad3721d80 100644 --- a/hyperspace/ethereum/src/utils.rs +++ b/hyperspace/ethereum/src/utils.rs @@ -2,9 +2,11 @@ use crate::contract::UnwrapContractError; use ethers::{ abi::{AbiError, Address, Detokenize, EventExt, Token, Tokenize}, contract::{ContractInstance, FunctionCall}, - prelude::*, + prelude::{ + EthEvent, Event, Filter, Http, LocalWallet, Middleware, Provider, TransactionReceipt, + }, }; -use ethers_solc::artifacts::{Storage, StorageLayout, StorageType}; +use ethers_solc::artifacts::{Storage, StorageLayout}; use ibc::core::ics04_channel::packet::Packet; pub type ProviderImpl = ethers::prelude::SignerMiddleware, LocalWallet>; diff --git a/hyperspace/ethereum/tests/sanity_checks.rs b/hyperspace/ethereum/tests/sanity_checks.rs index 5953a6b62..879bfdf76 100644 --- a/hyperspace/ethereum/tests/sanity_checks.rs +++ b/hyperspace/ethereum/tests/sanity_checks.rs @@ -1,4 +1,4 @@ -use std::{future::Future, ops::Deref, path::PathBuf, str::FromStr, sync::Arc}; +use std::{future::Future, ops::Deref, path::PathBuf, str::FromStr, sync::Arc, time::Duration}; use crate::utils::USE_GETH; use ethers::{ @@ -9,6 +9,7 @@ use ethers::{ utils::{keccak256, AnvilInstance}, }; use ethers_solc::{ProjectCompileOutput, ProjectPathsConfig}; +use futures::{stream::StreamExt, TryStreamExt}; use hyperspace_ethereum::{ config::Config, contract::UnwrapContractError, @@ -23,11 +24,13 @@ use ibc::{ }, ics24_host::identifier::{ChannelId, PortId}, }, + events::IbcEvent, timestamp::Timestamp, }; use ibc_rpc::PacketInfo; use primitives::IbcProvider; use prost::Message; +use tokio::time::timeout; use tracing::log; use tracing_subscriber::{filter, layer::SubscriberExt, util::SubscriberInitExt, Layer}; @@ -48,7 +51,7 @@ async fn hyperspace_ethereum_client_fixture( hyperspace_ethereum::client::EthereumClient::new( Config { http_rpc_url: endpoint.parse().unwrap(), - ws_rpc_url: Default::default(), + ws_rpc_url: "ws://localhost:5001".parse().unwrap(), ibc_handler_address: yui_ibc.diamond.address(), mnemonic: None, max_block_weight: 1, @@ -244,6 +247,7 @@ async fn test_ibc_client() { let deploy = deploy_yui_ibc_and_mock_client_fixture().await; let hyperspace = hyperspace_ethereum_client_fixture(&deploy.anvil, deploy.yui_ibc.clone()).await; + let events = hyperspace.ibc_events().await; let client_id = deploy_mock_client_fixture(&deploy).await; let height = hyperspace.latest_height_and_timestamp().await.unwrap().0; let r = hyperspace.query_client_state(height, client_id.parse().unwrap()).await.unwrap(); @@ -278,6 +282,19 @@ async fn test_ibc_client() { value: utils::mock::ConsensusState { timestamp: 1 }.encode_to_vec(), }) ); + + let (_host_height, _host_timestamp) = hyperspace + .query_client_update_time_and_height( + client_id.parse().unwrap(), + ibc::Height { revision_number: 0, revision_height: 1 }, + ) + .await + .unwrap(); + + let events = timeout(Duration::from_secs(5), events.take(1).collect::>()) + .await + .unwrap(); + dbg!(events); } #[tokio::test] @@ -387,6 +404,8 @@ async fn test_ibc_packet() { let mut deploy = deploy_yui_ibc_and_mock_client_fixture().await; let hyperspace = hyperspace_ethereum_client_fixture(&deploy.anvil, deploy.yui_ibc.clone()).await; + let events = hyperspace.ibc_events().await; + let client_id = deploy_mock_client_fixture(&deploy).await; let mock_module = deploy_mock_module_fixture(&deploy).await; @@ -580,6 +599,9 @@ async fn test_ibc_packet() { .await .unwrap(); assert_eq!(unreceived, vec![1, 2]); + + let events = events.collect::>().await; + dbg!(events); } fn u64_to_token(x: u64) -> Token { diff --git a/light-clients/icsxx-ethereum/Cargo.toml b/light-clients/icsxx-ethereum/Cargo.toml index 4ebe42587..4a371abbb 100644 --- a/light-clients/icsxx-ethereum/Cargo.toml +++ b/light-clients/icsxx-ethereum/Cargo.toml @@ -13,11 +13,9 @@ ibc = { path = "../../ibc/modules", default-features = false } ibc-proto = { path = "../../ibc/proto", default-features = false } # local deps -sync-committee-verifier = { git = "https://github.com/polytope-labs/sync-committee-rs.git", rev = "4e45ae9797198a617abfcbff098253cedc8a1f2e", default-features = false } -sync-committee-primitives = { git = "https://github.com/polytope-labs/sync-committee-rs.git", rev = "4e45ae9797198a617abfcbff098253cedc8a1f2e", default-features = false } +sync-committee-verifier = { git = "https://github.com/polytope-labs/sync-committee-rs.git", rev = "c5afca4fbb92cb60dde29c3a89454c288b022d97", default-features = false } +sync-committee-primitives = { git = "https://github.com/polytope-labs/sync-committee-rs.git", rev = "c5afca4fbb92cb60dde29c3a89454c288b022d97", default-features = false } light-client-common = { path = "../common", default-features = false } -#ethereum-consensus = { git = "https://github.com/polytope-labs/ethereum-consensus", rev = "48335b5c8074d63553ee4681993e294eba947f88", default-features = false } -#ssz-rs = { git = "https://github.com/polytope-labs/ssz-rs", rev = "96f9a89ccc56ab2abb4c3a83eaedb415034ada49", default-features = false } ethereum-consensus = { git = "https://github.com/polytope-labs/ethereum-consensus", branch = "main", default-features = false } ssz-rs = { git = "https://github.com/polytope-labs/ssz-rs", branch = "main" , default-features = false } @@ -45,12 +43,11 @@ tokio = { version = "1.21.1", features = ["macros"] } json = { package = "serde_json", version = "1.0.85" } jsonrpsee-ws-client = "0.16.2" actix-rt = "2.3.0" -sync-committee-primitives = { git = "https://github.com/polytope-labs/sync-committee-rs.git", rev = "4e45ae9797198a617abfcbff098253cedc8a1f2e", features = ["testing"] } -sync-committee-verifier = { git = "https://github.com/polytope-labs/sync-committee-rs.git", rev = "4e45ae9797198a617abfcbff098253cedc8a1f2e", features = ["testing"] } -sync-committee-prover = { git = "https://github.com/polytope-labs/sync-committee-rs.git", rev = "4e45ae9797198a617abfcbff098253cedc8a1f2e" } +sync-committee-primitives = { git = "https://github.com/polytope-labs/sync-committee-rs.git", rev = "c5afca4fbb92cb60dde29c3a89454c288b022d97", features = ["testing"] } +sync-committee-verifier = { git = "https://github.com/polytope-labs/sync-committee-rs.git", rev = "c5afca4fbb92cb60dde29c3a89454c288b022d97", features = ["testing"] } +sync-committee-prover = { git = "https://github.com/polytope-labs/sync-committee-rs.git", rev = "c5afca4fbb92cb60dde29c3a89454c288b022d97" } [features] -#default = ["std"] default = ["std"] std = [ "ibc/std", @@ -63,6 +60,8 @@ std = [ "sync-committee-verifier/std", "sync-committee-primitives/std", "ethereum-consensus/std", + "ethereum-consensus/async", + "ethereum-consensus/async-stream", "ssz-rs/std", "tendermint/std", ] diff --git a/light-clients/icsxx-ethereum/src/client_def.rs b/light-clients/icsxx-ethereum/src/client_def.rs index 012898572..23eb05531 100644 --- a/light-clients/icsxx-ethereum/src/client_def.rs +++ b/light-clients/icsxx-ethereum/src/client_def.rs @@ -48,7 +48,7 @@ use ibc::{ use light_client_common::{ state_machine, verify_delay_passed, verify_membership, verify_non_membership, }; -use sync_committee_verifier::{verify_sync_committee_attestation, LightClientState}; +use sync_committee_verifier::{verify_sync_committee_attestation, BlsVerify, LightClientState}; use tendermint_proto::Protobuf; const CLIENT_STATE_UPGRADE_PATH: &[u8] = b"client-state-upgrade-path"; @@ -59,7 +59,7 @@ pub struct EthereumClient(PhantomData); impl ClientDef for EthereumClient where - H: Clone + Eq + Send + Sync + Debug + Default, + H: Clone + Eq + Send + Sync + Debug + Default + BlsVerify, { type ClientMessage = ClientMessage; type ClientState = ClientState; @@ -74,7 +74,7 @@ where ) -> Result<(), Ics02Error> { match client_message { ClientMessage::Header(header) => { - let _ = verify_sync_committee_attestation(client_state.inner, header) + let _ = verify_sync_committee_attestation::(client_state.inner, header) .map_err(|e| Ics02Error::implementation_specific(e.to_string()))?; }, ClientMessage::Misbehaviour(Misbehaviour { never }) => match never {}, @@ -130,7 +130,7 @@ where css.push((height, cs)); let cs = client_state.inner; - let new_client_state = verify_sync_committee_attestation(cs, header) + let new_client_state = verify_sync_committee_attestation::(cs, header) .map_err(|e| Ics02Error::implementation_specific(e.to_string()))?; client_state.inner = new_client_state; Ok((client_state, ConsensusUpdateResult::Batch(css))) @@ -171,7 +171,14 @@ where unimplemented!() } - fn check_substitute_and_update_state(&self, ctx: &Ctx, subject_client_id: ClientId, substitute_client_id: ClientId, old_client_state: Self::ClientState, substitute_client_state: Self::ClientState) -> Result<(Self::ClientState, ConsensusUpdateResult), Ics02Error> { + fn check_substitute_and_update_state( + &self, + ctx: &Ctx, + subject_client_id: ClientId, + substitute_client_id: ClientId, + old_client_state: Self::ClientState, + substitute_client_state: Self::ClientState, + ) -> Result<(Self::ClientState, ConsensusUpdateResult), Ics02Error> { todo!("check_substitute_and_update_state") } diff --git a/light-clients/icsxx-ethereum/src/client_state.rs b/light-clients/icsxx-ethereum/src/client_state.rs index b557faf5c..c2e02bdc8 100644 --- a/light-clients/icsxx-ethereum/src/client_state.rs +++ b/light-clients/icsxx-ethereum/src/client_state.rs @@ -29,7 +29,7 @@ use ibc::{ use ibc_proto::google::protobuf::Any; use light_client_common::{HostFunctions, RelayChain}; use serde::{Deserialize, Serialize}; -use sync_committee_verifier::LightClientState; +use sync_committee_verifier::{BlsVerify, LightClientState}; use tendermint_proto::Protobuf; /// Protobuf type url for GRANDPA ClientState @@ -125,7 +125,7 @@ impl ClientState { impl ibc::core::ics02_client::client_state::ClientState for ClientState where - H: Send + Sync + Clone + Debug + Default + Eq, + H: Send + Sync + Clone + Debug + Default + Eq + BlsVerify, { type UpgradeOptions = UpgradeOptions; type ClientDef = EthereumClient; diff --git a/light-clients/icsxx-ethereum/src/lib.rs b/light-clients/icsxx-ethereum/src/lib.rs index bdc30e474..7eb9061bb 100644 --- a/light-clients/icsxx-ethereum/src/lib.rs +++ b/light-clients/icsxx-ethereum/src/lib.rs @@ -26,6 +26,7 @@ pub mod client_state; pub mod consensus_state; pub mod error; pub mod proto; +pub mod verify; // #[cfg(test)] // mod mock; diff --git a/light-clients/icsxx-ethereum/src/tests.rs b/light-clients/icsxx-ethereum/src/tests.rs index 518203419..15b71f77b 100644 --- a/light-clients/icsxx-ethereum/src/tests.rs +++ b/light-clients/icsxx-ethereum/src/tests.rs @@ -34,6 +34,7 @@ async fn test_prover() { .fetch_beacon_state(&block_header.slot.to_string()) .await .unwrap(); + // sync_committee_prover. // println!("state: {:?}", state); // println!("state: {:?}", state.validators); } diff --git a/light-clients/icsxx-ethereum/src/verify.rs b/light-clients/icsxx-ethereum/src/verify.rs new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/light-clients/icsxx-ethereum/src/verify.rs @@ -0,0 +1 @@ + From b30d183530dfbeed3e011715d1e608fa9b2797dc Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Mon, 4 Sep 2023 12:55:45 -0300 Subject: [PATCH 09/43] fix contract compilation --- Cargo.lock | 6 ++- light-clients/common/src/state_machine.rs | 20 +++++-- light-clients/icsxx-ethereum-cw/Cargo.toml | 6 +++ light-clients/icsxx-ethereum-cw/src/client.rs | 9 ++-- .../icsxx-ethereum-cw/src/context.rs | 3 +- .../icsxx-ethereum-cw/src/contract.rs | 11 ++++ light-clients/icsxx-ethereum-cw/src/error.rs | 6 +-- .../src/ics23/consensus_states.rs | 11 ++++ light-clients/icsxx-ethereum/Cargo.toml | 4 +- .../icsxx-ethereum/src/client_def.rs | 53 +++++++++++++++++-- .../icsxx-ethereum/src/client_state.rs | 1 - .../icsxx-ethereum/src/consensus_state.rs | 1 - 12 files changed, 109 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0285e1cc5..0d1d0be57 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5290,7 +5290,6 @@ dependencies = [ "ibc-derive", "ibc-proto", "jsonrpsee-ws-client", - "light-client-common", "log", "prost 0.11.6", "prost-build", @@ -5321,6 +5320,7 @@ dependencies = [ "derive_more", "digest 0.10.6", "ed25519-zebra", + "ethereum-consensus", "hex", "hyperspace-primitives", "ibc", @@ -5337,7 +5337,11 @@ dependencies = [ "serde_json", "sha2 0.10.6", "sha3", + "sp-io 7.0.0", "sp-std 5.0.0", + "ssz-rs", + "sync-committee-primitives", + "sync-committee-verifier", "tendermint-proto", "thiserror", "twox-hash", diff --git a/light-clients/common/src/state_machine.rs b/light-clients/common/src/state_machine.rs index 2b693dab6..8924bf782 100644 --- a/light-clients/common/src/state_machine.rs +++ b/light-clients/common/src/state_machine.rs @@ -15,7 +15,12 @@ //! State verification functions -use alloc::{ collections::BTreeMap, string::String, vec::Vec}; +use alloc::{ + collections::BTreeMap, + format, + string::{String, ToString}, + vec::Vec, +}; use codec::Decode; use core::fmt::Debug; use hash_db::{HashDB, Hasher, EMPTY_PREFIX}; @@ -49,7 +54,8 @@ where let memory_db = proof.into_memory_db::(); let trie = TrieDBBuilder::>::new(&memory_db, &root).build(); let child_root = trie - .get(child_info.prefixed_storage_key().as_slice()).map_err(|e| Error::Trie(format!("{e}")))? + .get(child_info.prefixed_storage_key().as_slice()) + .map_err(|e| Error::Trie(format!("{e}")))? .map(|r| { let mut hash = H::Out::default(); @@ -63,7 +69,10 @@ where let child_trie = TrieDBBuilder::>::new(&child_db, &child_root).build(); for (key, value) in items { - let recovered = child_trie.get(&key).map_err(|e| Error::Trie(format!("{e}")))?.and_then(|val| Decode::decode(&mut &val[..]).ok()); + let recovered = child_trie + .get(&key) + .map_err(|e| Error::Trie(format!("{e}")))? + .and_then(|val| Decode::decode(&mut &val[..]).ok()); if recovered != value { Err(Error::ValueMismatch { @@ -99,7 +108,10 @@ where let mut result = BTreeMap::new(); for key in keys.into_iter() { - let value = trie.get(key.as_ref()).map_err(|e| Error::Trie(format!("{e}")))?.and_then(|val| Decode::decode(&mut &val[..]).ok()); + let value = trie + .get(key.as_ref()) + .map_err(|e| Error::Trie(format!("{e}")))? + .and_then(|val| Decode::decode(&mut &val[..]).ok()); result.insert(key.as_ref().to_vec(), value); } diff --git a/light-clients/icsxx-ethereum-cw/Cargo.toml b/light-clients/icsxx-ethereum-cw/Cargo.toml index 2010af6ad..d0356fb17 100644 --- a/light-clients/icsxx-ethereum-cw/Cargo.toml +++ b/light-clients/icsxx-ethereum-cw/Cargo.toml @@ -60,6 +60,12 @@ digest = { version = "0.10.3", default-features = false } hex = "0.4.3" tendermint-proto = { git = "https://github.com/informalsystems/tendermint-rs", rev = "e81f7bf23d63ffbcd242381d1ce5e35da3515ff1", default-features = false } sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39", default-features = false } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39", default-features = false, features = ["disable_panic_handler", "disable_oom", "disable_allocator"] } + +ethereum-consensus = { git = "https://github.com/polytope-labs/ethereum-consensus", branch = "main", default-features = false } +sync-committee-verifier = { git = "https://github.com/polytope-labs/sync-committee-rs.git", rev = "c5afca4fbb92cb60dde29c3a89454c288b022d97", default-features = false } +sync-committee-primitives = { git = "https://github.com/polytope-labs/sync-committee-rs.git", rev = "c5afca4fbb92cb60dde29c3a89454c288b022d97", default-features = false } +ssz-rs = { git = "https://github.com/polytope-labs/ssz-rs", branch = "main" , default-features = false } [dev-dependencies] cw-multi-test = "0.15.1" diff --git a/light-clients/icsxx-ethereum-cw/src/client.rs b/light-clients/icsxx-ethereum-cw/src/client.rs index 57962b491..91c10a505 100644 --- a/light-clients/icsxx-ethereum-cw/src/client.rs +++ b/light-clients/icsxx-ethereum-cw/src/client.rs @@ -29,10 +29,11 @@ use icsxx_ethereum::{ }; use prost::Message; use std::str::FromStr; +use sync_committee_verifier::BlsVerify; impl<'a, H> ClientTypes for Context<'a, H> where - H: Clone + Eq + Send + Sync + Debug + Default + 'static, + H: Clone + Eq + Send + Sync + Debug + Default + BlsVerify + 'static, { type AnyClientMessage = ClientMessage; type AnyClientState = ClientState; @@ -42,7 +43,7 @@ where impl<'a, H> ClientReader for Context<'a, H> where - H: Clone + Eq + Send + Sync + Debug + Default + 'static, + H: Clone + Eq + Send + Sync + Debug + Default + BlsVerify + 'static, { fn client_type(&self, client_id: &ClientId) -> Result { log!(self, "in client : [client_type] >> client_id = {:?}", client_id); @@ -199,7 +200,7 @@ where impl<'a, H> ClientKeeper for Context<'a, H> where - H: Clone + Eq + Send + Sync + Debug + Default + 'static, + H: Clone + Eq + Send + Sync + Debug + Default + BlsVerify + 'static, { fn store_client_type( &mut self, @@ -232,9 +233,7 @@ where let wasm_consensus_state = ics08_wasm::consensus_state::ConsensusState { data: consensus_state.to_any().encode_to_vec(), - code_id: code_id(self.deps.storage), timestamp: consensus_state.timestamp().nanoseconds(), - root: CommitmentRoot::from_bytes(&vec![1; 32]), inner: Box::new(FakeInner), }; let vec1 = wasm_consensus_state.to_any().encode_to_vec(); diff --git a/light-clients/icsxx-ethereum-cw/src/context.rs b/light-clients/icsxx-ethereum-cw/src/context.rs index afa39fb02..dae50c378 100644 --- a/light-clients/icsxx-ethereum-cw/src/context.rs +++ b/light-clients/icsxx-ethereum-cw/src/context.rs @@ -1,6 +1,7 @@ use cosmwasm_std::{DepsMut, Env, Storage}; use ibc::core::ics26_routing::context::ReaderContext; use std::{fmt, fmt::Debug, marker::PhantomData}; +use sync_committee_verifier::BlsVerify; pub struct Context<'a, H> { pub deps: DepsMut<'a>, @@ -47,6 +48,6 @@ impl<'a, H> Context<'a, H> { } impl<'a, H> ReaderContext for Context<'a, H> where - H: Clone + Eq + Send + Sync + Debug + Default + 'static + H: Clone + Eq + Send + Sync + Debug + Default + BlsVerify + 'static { } diff --git a/light-clients/icsxx-ethereum-cw/src/contract.rs b/light-clients/icsxx-ethereum-cw/src/contract.rs index 8e94f5a98..4fca9f2ed 100644 --- a/light-clients/icsxx-ethereum-cw/src/contract.rs +++ b/light-clients/icsxx-ethereum-cw/src/contract.rs @@ -34,6 +34,7 @@ use icsxx_ethereum::{ }; use prost::Message; use std::{collections::BTreeSet, str::FromStr}; +use sync_committee_verifier::BlsVerify; /* // version info for migration info const CONTRACT_NAME: &str = "crates.io:ics10-grandpa-cw"; @@ -233,3 +234,13 @@ pub fn query(_deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { pub fn code_id(store: &dyn Storage) -> Vec { CODE_ID.load(store).expect("code id must be set") } + +impl BlsVerify for HostFunctions { + fn verify( + public_keys: &[ðereum_consensus::crypto::PublicKey], + msg: &[u8], + signature: ðereum_consensus::crypto::Signature, + ) -> Result<(), sync_committee_verifier::error::Error> { + todo!() + } +} diff --git a/light-clients/icsxx-ethereum-cw/src/error.rs b/light-clients/icsxx-ethereum-cw/src/error.rs index 192de7d13..6a15b87ab 100644 --- a/light-clients/icsxx-ethereum-cw/src/error.rs +++ b/light-clients/icsxx-ethereum-cw/src/error.rs @@ -1,6 +1,6 @@ use cosmwasm_std::StdError; use derive_more::{Display, From}; -use icsxx_ethereum::error::Error as GrandpaError; +use icsxx_ethereum::error::Error as EthereumError; use std::error::Error; // use thiserror::Error; @@ -35,8 +35,8 @@ pub enum ContractError { impl Error for ContractError {} -impl From for ContractError { - fn from(e: GrandpaError) -> Self { +impl From for ContractError { + fn from(e: EthereumError) -> Self { ContractError::Client(e.to_string()) } } diff --git a/light-clients/icsxx-ethereum-cw/src/ics23/consensus_states.rs b/light-clients/icsxx-ethereum-cw/src/ics23/consensus_states.rs index b53992e7a..891257a79 100644 --- a/light-clients/icsxx-ethereum-cw/src/ics23/consensus_states.rs +++ b/light-clients/icsxx-ethereum-cw/src/ics23/consensus_states.rs @@ -217,6 +217,17 @@ impl ClientDef for FakeInner { unimplemented!() } + fn check_substitute_and_update_state( + &self, + ctx: &Ctx, + subject_client_id: ClientId, + substitute_client_id: ClientId, + old_client_state: Self::ClientState, + substitute_client_state: Self::ClientState, + ) -> Result<(Self::ClientState, ConsensusUpdateResult), Error> { + unimplemented!() + } + fn verify_client_consensus_state( &self, _ctx: &Ctx, diff --git a/light-clients/icsxx-ethereum/Cargo.toml b/light-clients/icsxx-ethereum/Cargo.toml index 4a371abbb..639e5c7d1 100644 --- a/light-clients/icsxx-ethereum/Cargo.toml +++ b/light-clients/icsxx-ethereum/Cargo.toml @@ -13,10 +13,9 @@ ibc = { path = "../../ibc/modules", default-features = false } ibc-proto = { path = "../../ibc/proto", default-features = false } # local deps +ethereum-consensus = { git = "https://github.com/polytope-labs/ethereum-consensus", branch = "main", default-features = false } sync-committee-verifier = { git = "https://github.com/polytope-labs/sync-committee-rs.git", rev = "c5afca4fbb92cb60dde29c3a89454c288b022d97", default-features = false } sync-committee-primitives = { git = "https://github.com/polytope-labs/sync-committee-rs.git", rev = "c5afca4fbb92cb60dde29c3a89454c288b022d97", default-features = false } -light-client-common = { path = "../common", default-features = false } -ethereum-consensus = { git = "https://github.com/polytope-labs/ethereum-consensus", branch = "main", default-features = false } ssz-rs = { git = "https://github.com/polytope-labs/ssz-rs", branch = "main" , default-features = false } # crates.io @@ -52,7 +51,6 @@ default = ["std"] std = [ "ibc/std", "ibc-proto/std", - "light-client-common/std", "prost/std", "prost-types/std", "anyhow/std", diff --git a/light-clients/icsxx-ethereum/src/client_def.rs b/light-clients/icsxx-ethereum/src/client_def.rs index 23eb05531..934ac14fb 100644 --- a/light-clients/icsxx-ethereum/src/client_def.rs +++ b/light-clients/icsxx-ethereum/src/client_def.rs @@ -20,7 +20,9 @@ use ibc::core::ics02_client::{ use crate::client_message::{ClientMessage, Misbehaviour}; use alloc::{format, string::ToString, vec, vec::Vec}; +use anyhow::anyhow; use core::{fmt::Debug, marker::PhantomData}; +use ethereum_consensus::crypto::{PublicKey, Signature}; use ibc::{ core::{ ics02_client::{ @@ -45,12 +47,47 @@ use ibc::{ }, Height, }; -use light_client_common::{ - state_machine, verify_delay_passed, verify_membership, verify_non_membership, -}; use sync_committee_verifier::{verify_sync_committee_attestation, BlsVerify, LightClientState}; use tendermint_proto::Protobuf; +// TODO: move this function in a separate crate and remove the one from `light_client_common` crate +/// This will verify that the connection delay has elapsed for a given [`ibc::Height`] +pub fn verify_delay_passed( + ctx: &C, + height: Height, + connection_end: &ConnectionEnd, +) -> Result<(), anyhow::Error> +where + H: Clone, + C: ReaderContext, +{ + let current_time = ctx.host_timestamp(); + let current_height = ctx.host_height(); + + let client_id = connection_end.client_id(); + let processed_time = ctx.client_update_time(client_id, height).map_err(anyhow::Error::msg)?; + let processed_height = + ctx.client_update_height(client_id, height).map_err(anyhow::Error::msg)?; + + let delay_period_time = connection_end.delay_period(); + let delay_period_blocks = ctx.block_delay(delay_period_time); + + let earliest_time = + (processed_time + delay_period_time).map_err(|_| anyhow!("Timestamp overflowed!"))?; + if !(current_time == earliest_time || current_time.after(&earliest_time)) { + return Err(anyhow!( + "Not enough time elapsed current time: {current_time}, earliest time: {earliest_time}" + )) + } + + let earliest_height = processed_height.add(delay_period_blocks); + if current_height < earliest_height { + return Err(anyhow!("Not enough blocks elapsed, current height: {current_height}, earliest height: {earliest_height}")); + } + + Ok(()) +} + const CLIENT_STATE_UPGRADE_PATH: &[u8] = b"client-state-upgrade-path"; const CONSENSUS_STATE_UPGRADE_PATH: &[u8] = b"consensus-state-upgrade-path"; @@ -384,3 +421,13 @@ where Ok(()) } } + +impl BlsVerify for EthereumClient { + fn verify( + public_keys: &[&PublicKey], + msg: &[u8], + signature: &Signature, + ) -> Result<(), sync_committee_verifier::error::Error> { + todo!() + } +} diff --git a/light-clients/icsxx-ethereum/src/client_state.rs b/light-clients/icsxx-ethereum/src/client_state.rs index c2e02bdc8..4309de6c8 100644 --- a/light-clients/icsxx-ethereum/src/client_state.rs +++ b/light-clients/icsxx-ethereum/src/client_state.rs @@ -27,7 +27,6 @@ use ibc::{ Height, }; use ibc_proto::google::protobuf::Any; -use light_client_common::{HostFunctions, RelayChain}; use serde::{Deserialize, Serialize}; use sync_committee_verifier::{BlsVerify, LightClientState}; use tendermint_proto::Protobuf; diff --git a/light-clients/icsxx-ethereum/src/consensus_state.rs b/light-clients/icsxx-ethereum/src/consensus_state.rs index a43ef23a3..1cd522382 100644 --- a/light-clients/icsxx-ethereum/src/consensus_state.rs +++ b/light-clients/icsxx-ethereum/src/consensus_state.rs @@ -20,7 +20,6 @@ use core::{convert::Infallible, fmt::Debug}; use ethereum_consensus::primitives::Hash32; use ibc::{core::ics23_commitment::commitment::CommitmentRoot, timestamp::Timestamp, Height}; use ibc_proto::google::protobuf::Any; -use light_client_common::{decode_timestamp_extrinsic, state_machine}; use serde::{Deserialize, Serialize}; use tendermint::time::Time; use tendermint_proto::{google::protobuf as tpb, Protobuf}; From 335f1eff8372cb01381d39a18d366da340dc397b Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Tue, 5 Sep 2023 14:33:16 -0300 Subject: [PATCH 10/43] Add Ethereum-Cosmos tests and correctly decode light client state New test file `ethereum_cosmos.rs` was added under `hyperspace/testsuite/tests` to test integration of Ethereum and Cosmos. Fixed light client state decoding in Ethereum `ibc_provider.rs`. Update client event creation was included along with a create client event handler. Further, additional log filtering for key Ethereum events useful for the IBC (Inter-Blockchain Communication) was added. Additionally, couple of methods were moved out of the `#[cfg(test)]` normalization blocks, making them available outside of testing. Some TODO comments were also addressed, that mainly handled function implementations and debugging of values. The integration tests include behaviors such as setting up clients, connection and channel setup, tests with different packet timeouts and connection delays. --- Cargo.lock | 42 +++ Cargo.toml | 2 +- contracts/pallet-ibc/Cargo.toml | 5 +- contracts/pallet-ibc/src/lib.rs | 8 + contracts/pallet-ibc/src/light_clients.rs | 61 +++- hyperspace/core/src/chain.rs | 2 +- hyperspace/core/src/command.rs | 5 +- hyperspace/core/src/macros.rs | 8 +- hyperspace/core/src/packets.rs | 9 +- hyperspace/cosmos/src/provider.rs | 1 - hyperspace/ethereum/Cargo.toml | 1 + hyperspace/ethereum/src/client.rs | 10 +- hyperspace/ethereum/src/config.rs | 15 +- hyperspace/ethereum/src/config/test.rs | 7 +- hyperspace/ethereum/src/events.rs | 61 +++- hyperspace/ethereum/src/ibc_provider.rs | 81 ++++- hyperspace/ethereum/src/key_provider.rs | 4 +- hyperspace/ethereum/src/lib.rs | 2 + hyperspace/ethereum/src/mock/mod.rs | 2 + hyperspace/ethereum/src/prove.rs | 2 +- hyperspace/ethereum/tests/sanity_checks.rs | 8 +- hyperspace/parachain/src/provider.rs | 1 - hyperspace/primitives/src/lib.rs | 1 - hyperspace/testsuite/Cargo.toml | 6 +- hyperspace/testsuite/tests/ethereum_cosmos.rs | 294 ++++++++++++++++++ .../src/prost/ibc.lightclients.wasm.v1.rs | 2 +- .../icsxx-ethereum/src/client_state.rs | 2 +- light-clients/icsxx-ethereum/src/lib.rs | 5 + 28 files changed, 601 insertions(+), 46 deletions(-) create mode 100644 hyperspace/ethereum/src/mock/mod.rs create mode 100644 hyperspace/testsuite/tests/ethereum_cosmos.rs diff --git a/Cargo.lock b/Cargo.lock index 0d1d0be57..15b15722d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4876,6 +4876,7 @@ dependencies = [ "sync-committee-primitives", "sync-committee-prover", "sync-committee-verifier", + "tendermint", "thiserror", "tokio", "toml 0.7.6", @@ -4985,6 +4986,46 @@ dependencies = [ "tokio", ] +[[package]] +name = "hyperspace-testsuite" +version = "0.1.0" +dependencies = [ + "anyhow", + "async-trait", + "finality-grandpa", + "futures", + "grandpa-light-client-primitives", + "grandpa-light-client-verifier", + "hex", + "hyperspace-core", + "hyperspace-cosmos", + "hyperspace-ethereum", + "hyperspace-parachain", + "hyperspace-primitives", + "ibc", + "ibc-proto", + "ics10-grandpa", + "light-client-common", + "log", + "pallet-ibc", + "pallet-ibc-ping", + "parity-scale-codec", + "polkadot-core-primitives", + "rand 0.8.5", + "serde_json", + "sp-core 7.0.0", + "sp-finality-grandpa", + "sp-keyring", + "sp-keystore 0.13.0", + "sp-runtime 7.0.0", + "sp-state-machine 0.13.0", + "sp-trie 7.0.0", + "subxt", + "tendermint-proto", + "tokio", + "toml 0.7.6", +] + [[package]] name = "iana-time-zone" version = "0.1.53" @@ -7616,6 +7657,7 @@ dependencies = [ "ics10-grandpa", "ics11-beefy", "ics23 0.10.0", + "icsxx-ethereum", "light-client-common", "log", "orml-tokens", diff --git a/Cargo.toml b/Cargo.toml index 2c741f495..fff532928 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,7 +43,7 @@ members = [ "hyperspace/primitives", # "hyperspace/parachain", # "hyperspace/cosmos", - # "hyperspace/testsuite", + "hyperspace/testsuite", # "hyperspace/metrics", "hyperspace/ethereum", diff --git a/contracts/pallet-ibc/Cargo.toml b/contracts/pallet-ibc/Cargo.toml index 41b47e980..e832df0d6 100644 --- a/contracts/pallet-ibc/Cargo.toml +++ b/contracts/pallet-ibc/Cargo.toml @@ -42,6 +42,7 @@ ics08-wasm = { path = "../../light-clients/ics08-wasm", default-features = false ics10-grandpa = { path = "../../light-clients/ics10-grandpa", default-features = false } ics11-beefy = { path = "../../light-clients/ics11-beefy", default-features = false } ics07-tendermint = { path = "../../light-clients/ics07-tendermint", default-features = false } +icsxx-ethereum = { path = "../../light-clients/icsxx-ethereum", default-features = false, optional = true } hex = { version = "0.4.3", default-features = false } # local deps ibc-primitives = { path = "primitives", default-features = false } @@ -105,7 +106,7 @@ path = "../../ibc/modules" features = ["mocks"] [features] -default = ["std"] +default = ["std", "ethereum"] testing = [] std = [ "codec/std", @@ -162,3 +163,5 @@ runtime-benchmarks = [ ] try-runtime = ["frame-support/try-runtime"] + +ethereum = ["icsxx-ethereum"] \ No newline at end of file diff --git a/contracts/pallet-ibc/src/lib.rs b/contracts/pallet-ibc/src/lib.rs index 55a93be68..96c93b710 100644 --- a/contracts/pallet-ibc/src/lib.rs +++ b/contracts/pallet-ibc/src/lib.rs @@ -1105,6 +1105,14 @@ pub mod pallet { .map_err(|_| Error::::ClientFreezeFailed)?, ) }, + #[cfg(feature = "ethereum")] + AnyClientState::Ethereum(msg) => { + let latest_height = msg.latest_height(); + AnyClientState::wrap( + &msg.with_frozen_height(Height::new(latest_height.revision_number, height)) + .map_err(|_| Error::::ClientFreezeFailed)?, + ) + }, AnyClientState::Wasm(_) => return Err(Error::::ClientFreezeFailed.into()), #[cfg(test)] AnyClientState::Mock(mut ms) => { diff --git a/contracts/pallet-ibc/src/light_clients.rs b/contracts/pallet-ibc/src/light_clients.rs index 66f97d4ea..24fe08455 100644 --- a/contracts/pallet-ibc/src/light_clients.rs +++ b/contracts/pallet-ibc/src/light_clients.rs @@ -44,6 +44,15 @@ use ics11_beefy::{ client_message::BEEFY_CLIENT_MESSAGE_TYPE_URL, client_state::BEEFY_CLIENT_STATE_TYPE_URL, consensus_state::BEEFY_CONSENSUS_STATE_TYPE_URL, }; +use icsxx_ethereum::{ + client_message::{ + ETHEREUM_CLIENT_MESSAGE_TYPE_URL, ETHEREUM_HEADER_TYPE_URL, ETHEREUM_MISBEHAVIOUR_TYPE_URL, + }, + client_state::ETHEREUM_CLIENT_STATE_TYPE_URL, + consensus_state::ETHEREUM_CONSENSUS_STATE_TYPE_URL, +}; +#[cfg(feature = "ethereum")] +use icsxx_ethereum::{BlsVerify, EthereumError, EthereumPublicKey, EthereumSignature}; use prost::Message; use sp_core::{crypto::ByteArray, ed25519, H256}; use sp_runtime::{ @@ -212,11 +221,24 @@ impl beefy_client_primitives::HostFunctions for HostFunctionsManager { } } +#[cfg(feature = "ethereum")] +impl BlsVerify for HostFunctionsManager { + fn verify( + _public_keys: &[&EthereumPublicKey], + _msg: &[u8], + _signature: &EthereumSignature, + ) -> Result<(), EthereumError> { + unimplemented!() + } +} + #[derive(Clone, Debug, PartialEq, Eq, ClientDef)] pub enum AnyClient { Grandpa(ics10_grandpa::client_def::GrandpaClient), Beefy(ics11_beefy::client_def::BeefyClient), Tendermint(ics07_tendermint::client_def::TendermintClient), + #[cfg(feature = "ethereum")] + Ethereum(icsxx_ethereum::client_def::EthereumClient), Wasm(ics08_wasm::client_def::WasmClient), #[cfg(test)] Mock(ibc::mock::client_def::MockClient), @@ -227,6 +249,8 @@ pub enum AnyUpgradeOptions { Grandpa(ics10_grandpa::client_state::UpgradeOptions), Beefy(ics11_beefy::client_state::UpgradeOptions), Tendermint(ics07_tendermint::client_state::UpgradeOptions), + #[cfg(feature = "ethereum")] + Ethereum(icsxx_ethereum::client_state::UpgradeOptions), Wasm(Box), #[cfg(test)] Mock(()), @@ -240,6 +264,9 @@ pub enum AnyClientState { Beefy(ics11_beefy::client_state::ClientState), #[ibc(proto_url = "TENDERMINT_CLIENT_STATE_TYPE_URL")] Tendermint(ics07_tendermint::client_state::ClientState), + #[cfg(feature = "ethereum")] + #[ibc(proto_url = "ETHEREUM_CLIENT_STATE_TYPE_URL")] + Ethereum(icsxx_ethereum::client_state::ClientState), #[ibc(proto_url = "WASM_CLIENT_STATE_TYPE_URL")] Wasm(ics08_wasm::client_state::ClientState), #[cfg(test)] @@ -300,6 +327,9 @@ pub enum AnyConsensusState { Beefy(ics11_beefy::consensus_state::ConsensusState), #[ibc(proto_url = "TENDERMINT_CONSENSUS_STATE_TYPE_URL")] Tendermint(ics07_tendermint::consensus_state::ConsensusState), + #[cfg(feature = "ethereum")] + #[ibc(proto_url = "ETHEREUM_CONSENSUS_STATE_TYPE_URL")] + Ethereum(icsxx_ethereum::consensus_state::ConsensusState), #[ibc(proto_url = "WASM_CONSENSUS_STATE_TYPE_URL")] Wasm(ics08_wasm::consensus_state::ConsensusState), #[cfg(test)] @@ -326,6 +356,9 @@ pub enum AnyClientMessage { Beefy(ics11_beefy::client_message::ClientMessage), #[ibc(proto_url = "TENDERMINT_CLIENT_MESSAGE_TYPE_URL")] Tendermint(ics07_tendermint::client_message::ClientMessage), + #[cfg(feature = "ethereum")] + #[ibc(proto_url = "ETHEREUM_CLIENT_MESSAGE_TYPE_URL")] + Ethereum(icsxx_ethereum::client_message::ClientMessage), #[ibc(proto_url = "WASM_CLIENT_MESSAGE_TYPE_URL")] Wasm(ics08_wasm::client_message::ClientMessage), #[cfg(test)] @@ -354,6 +387,11 @@ impl AnyClientMessage { h.inner.maybe_header_height(), ics08_wasm::client_message::ClientMessage::Misbehaviour(_) => None, }, + #[cfg(feature = "ethereum")] + Self::Ethereum(m) => match m { + icsxx_ethereum::client_message::ClientMessage::Header(h) => None, + icsxx_ethereum::client_message::ClientMessage::Misbehaviour(_) => None, + }, #[cfg(test)] Self::Mock(inner) => match inner { ibc::mock::header::MockClientMessage::Header(h) => Some(h.height()), @@ -442,6 +480,23 @@ impl TryFrom for AnyClientMessage { ics07_tendermint::client_message::Misbehaviour::decode_vec(&value.value) .map_err(ics02_client::error::Error::decode_raw_header)?, ))), + #[cfg(feature = "ethereum")] + ETHEREUM_CLIENT_MESSAGE_TYPE_URL => Ok(Self::Ethereum( + icsxx_ethereum::client_message::ClientMessage::decode_vec(&value.value) + .map_err(ics02_client::error::Error::decode_raw_header)?, + )), + #[cfg(feature = "ethereum")] + ETHEREUM_HEADER_TYPE_URL => + Ok(Self::Ethereum(icsxx_ethereum::client_message::ClientMessage::Header( + icsxx_ethereum::client_message::Header::decode_vec(&value.value) + .map_err(ics02_client::error::Error::decode_raw_header)?, + ))), + #[cfg(feature = "ethereum")] + ETHEREUM_MISBEHAVIOUR_TYPE_URL => + Ok(Self::Ethereum(icsxx_ethereum::client_message::ClientMessage::Misbehaviour( + icsxx_ethereum::client_message::Misbehaviour::decode_vec(&value.value) + .map_err(ics02_client::error::Error::decode_raw_header)?, + ))), WASM_CLIENT_MESSAGE_TYPE_URL => Ok(Self::Wasm( ics08_wasm::client_message::ClientMessage::decode_vec(&value.value) .map_err(ics02_client::error::Error::decode_raw_header)?, @@ -492,7 +547,11 @@ impl From for Any { type_url: TENDERMINT_CLIENT_MESSAGE_TYPE_URL.to_string(), value: msg.encode_vec().expect("encode_vec failed"), }, - + #[cfg(feature = "ethereum")] + AnyClientMessage::Ethereum(msg) => Any { + type_url: ETHEREUM_CLIENT_MESSAGE_TYPE_URL.to_string(), + value: msg.encode_vec().expect("encode_vec failed"), + }, #[cfg(test)] AnyClientMessage::Mock(_msg) => panic!("MockHeader can't be serialized"), } diff --git a/hyperspace/core/src/chain.rs b/hyperspace/core/src/chain.rs index 2ae86d789..1c7d0e276 100644 --- a/hyperspace/core/src/chain.rs +++ b/hyperspace/core/src/chain.rs @@ -26,7 +26,7 @@ use cosmos::client::{CosmosClient, CosmosClientConfig}; #[cfg(feature = "ethereum")] use ethereum::client::EthereumClient; #[cfg(feature = "ethereum")] -use ethereum::config::Config as EthereumClientConfig; +use ethereum::config::EthereumClientConfig; use futures::Stream; #[cfg(any(test, feature = "testing"))] use ibc::applications::transfer::msgs::transfer::MsgTransfer; diff --git a/hyperspace/core/src/command.rs b/hyperspace/core/src/command.rs index 9fa551ae9..bcd1cca34 100644 --- a/hyperspace/core/src/command.rs +++ b/hyperspace/core/src/command.rs @@ -191,7 +191,10 @@ impl Cmd { } pub async fn create_connection(&self) -> Result { - let delay_period_seconds: NonZeroU64 = self.delay_period_seconds.into().into(); + let delay_period_seconds: NonZeroU64 = self + .delay_period + .expect("delay_period should be provided when creating a connection") + .into(); let delay = Duration::from_secs(delay_period_seconds.into()); let mut config = self.parse_config().await?; let mut chain_a = config.chain_a.clone().into_client().await?; diff --git a/hyperspace/core/src/macros.rs b/hyperspace/core/src/macros.rs index f5aec6651..ebcb7e4dc 100644 --- a/hyperspace/core/src/macros.rs +++ b/hyperspace/core/src/macros.rs @@ -404,11 +404,11 @@ macro_rules! chains { $( $(#[$($meta)*])* Self::$name(chain) => chain - .query_send_packets(channel_id, port_id, seqs) + .query_send_packets(at, channel_id, port_id, seqs) .await .map_err(AnyError::$name), )* - Self::Wasm(c) => c.inner.query_send_packets(channel_id, port_id, seqs).await, + Self::Wasm(c) => c.inner.query_send_packets(at, channel_id, port_id, seqs).await, } } @@ -423,11 +423,11 @@ macro_rules! chains { $( $(#[$($meta)*])* Self::$name(chain) => chain - .query_received_packets(channel_id, port_id, seqs) + .query_received_packets(at, channel_id, port_id, seqs) .await .map_err(AnyError::$name), )* - Self::Wasm(c) => c.inner.query_received_packets(channel_id, port_id, seqs).await, + Self::Wasm(c) => c.inner.query_received_packets(at, channel_id, port_id, seqs).await, } } diff --git a/hyperspace/core/src/packets.rs b/hyperspace/core/src/packets.rs index 0b3d745cd..967435881 100644 --- a/hyperspace/core/src/packets.rs +++ b/hyperspace/core/src/packets.rs @@ -195,7 +195,9 @@ pub async fn query_ready_and_timed_out_packets( log::debug!(target: "hyperspace", "Found {} undelivered packets for {:?}/{:?} for {seqs:?}", seqs.len(), channel_id, port_id.clone()); - let mut send_packets = source.query_send_packets(channel_id, port_id.clone(), seqs).await?; + let mut send_packets = source + .query_send_packets(source_height, channel_id, port_id.clone(), seqs) + .await?; log::trace!(target: "hyperspace", "SendPackets count before deduplication: {}", send_packets.len()); send_packets.sort(); send_packets.dedup(); @@ -392,8 +394,9 @@ pub async fn query_ready_and_timed_out_packets( .take(max_packets_to_process) .collect::>(); - let acknowledgements = - source.query_received_packets(channel_id, port_id.clone(), acks).await?; + let acknowledgements = source + .query_received_packets(source_height, channel_id, port_id.clone(), acks) + .await?; log::trace!(target: "hyperspace", "Got acknowledgements for channel {:?}: {:?}", channel_id, acknowledgements); let mut acknowledgements_join_set: JoinSet> = JoinSet::new(); sink.on_undelivered_sequences(!acknowledgements.is_empty(), UndeliveredType::Acks) diff --git a/hyperspace/cosmos/src/provider.rs b/hyperspace/cosmos/src/provider.rs index 04c456e5e..f0b5eef82 100644 --- a/hyperspace/cosmos/src/provider.rs +++ b/hyperspace/cosmos/src/provider.rs @@ -616,7 +616,6 @@ where self.channel_whitelist.lock().unwrap().clone() } - #[cfg(test)] async fn query_connection_channels( &self, _at: Height, diff --git a/hyperspace/ethereum/Cargo.toml b/hyperspace/ethereum/Cargo.toml index d6ab14647..7dbf6e4e2 100644 --- a/hyperspace/ethereum/Cargo.toml +++ b/hyperspace/ethereum/Cargo.toml @@ -26,6 +26,7 @@ ethereum-consensus = { git = "https://github.com/polytope-labs/ethereum-consensu ssz-rs = { git = "https://github.com/polytope-labs/ssz-rs", branch = "main" } cast = { git = "https://github.com/foundry-rs/foundry", version = "0.2.0" } +tendermint = { git = "https://github.com/informalsystems/tendermint-rs", rev = "e81f7bf23d63ffbcd242381d1ce5e35da3515ff1", default-features = false } anyhow = "1.0.65" async-stream = "0.3.5" diff --git a/hyperspace/ethereum/src/client.rs b/hyperspace/ethereum/src/client.rs index 8ea7d2e98..b7fb6db11 100644 --- a/hyperspace/ethereum/src/client.rs +++ b/hyperspace/ethereum/src/client.rs @@ -1,5 +1,5 @@ use crate::{ - config::Config, + config::EthereumClientConfig, utils::{DeployYuiIbc, ProviderImpl}, }; use async_trait::async_trait; @@ -50,7 +50,7 @@ pub const CHANNELS_STORAGE_INDEX: u32 = 5; pub struct EthereumClient { pub http_rpc: Arc, pub(crate) ws_uri: http::Uri, - pub(crate) config: Config, + pub(crate) config: EthereumClientConfig, /// Common relayer data pub common_state: CommonClientState, pub yui: DeployYuiIbc, ProviderImpl>, @@ -102,10 +102,7 @@ pub struct AckPacket { } impl EthereumClient { - pub async fn new( - mut config: Config, - yui: DeployYuiIbc, ProviderImpl>, - ) -> Result { + pub async fn new(mut config: EthereumClientConfig) -> Result { let client = Provider::::try_from(config.http_rpc_url.to_string()) .map_err(|_| ClientError::UriParseError(config.http_rpc_url.clone()))?; @@ -136,6 +133,7 @@ impl EthereumClient { let client = ethers::middleware::SignerMiddleware::new(client, wallet); + let yui = config.yui.take().unwrap(); Ok(Self { http_rpc: Arc::new(client), ws_uri: config.ws_rpc_url.clone(), diff --git a/hyperspace/ethereum/src/config.rs b/hyperspace/ethereum/src/config.rs index 3142a4d18..39388cdd6 100644 --- a/hyperspace/ethereum/src/config.rs +++ b/hyperspace/ethereum/src/config.rs @@ -1,6 +1,7 @@ use ethers::signers::LocalWallet; -use std::str::FromStr; +use std::{str::FromStr, sync::Arc}; +use crate::utils::{DeployYuiIbc, ProviderImpl}; use ethers::types::Address; use ibc::core::ics24_host::identifier::{ChannelId, ClientId, ConnectionId, PortId}; use serde::{de::Visitor, Deserialize, Deserializer, Serialize, Serializer}; @@ -61,13 +62,16 @@ where } #[derive(Debug, Clone, Deserialize, Serialize)] -pub struct Config { +pub struct EthereumClientConfig { /// HTTP URL for RPC #[serde(deserialize_with = "uri_de", serialize_with = "uri_se")] pub http_rpc_url: http::uri::Uri, /// Websocket URL for RPC #[serde(deserialize_with = "uri_de", serialize_with = "uri_se")] pub ws_rpc_url: http::uri::Uri, + /// HTTP URL for RPC (Beacon node) + #[serde(deserialize_with = "uri_de", serialize_with = "uri_se")] + pub beacon_rpc_url: http::uri::Uri, /// address of the OwnableIBCHandler contract. #[serde(deserialize_with = "address_de")] pub ibc_handler_address: Address, @@ -100,9 +104,14 @@ pub struct Config { pub channel_whitelist: Vec<(ChannelId, PortId)>, /// Commitment prefix pub commitment_prefix: String, + /// All the client states and headers will be wrapped in WASM ones using the WASM code ID. + #[serde(default)] + pub wasm_code_id: Option, + #[serde(skip)] + pub yui: Option, ProviderImpl>>, } -impl Config { +impl EthereumClientConfig { /// ICS-23 compatible commitment prefix #[track_caller] pub fn commitment_prefix(&self) -> Vec { diff --git a/hyperspace/ethereum/src/config/test.rs b/hyperspace/ethereum/src/config/test.rs index 2e498dc32..772af1d24 100644 --- a/hyperspace/ethereum/src/config/test.rs +++ b/hyperspace/ethereum/src/config/test.rs @@ -2,7 +2,7 @@ const CONFIG: &'static str = include_str!("test_config.toml"); #[test] fn parse_config() { - let config: super::Config = toml::from_str(&CONFIG).expect("parsing error"); + let config: super::EthereumClientConfig = toml::from_str(&CONFIG).expect("parsing error"); assert_eq!(config.name, "mainnet"); assert!(config.http_rpc_url.host().is_some()); assert_eq!(config.http_rpc_url.host(), Some("localhost")); @@ -14,5 +14,8 @@ fn parse_config() { assert_eq!(config.ws_rpc_url.scheme_str(), Some("ws")); assert_eq!(config.mnemonic, Some("1337".into())); assert_eq!(config.channel_whitelist, &[]); - assert_eq!(config.ibc_handler_address, "0xdc64a140aa3e981100a9beca4e685f962f0cf6c9".parse().unwrap()); + assert_eq!( + config.ibc_handler_address, + "0xdc64a140aa3e981100a9beca4e685f962f0cf6c9".parse().unwrap() + ); } diff --git a/hyperspace/ethereum/src/events.rs b/hyperspace/ethereum/src/events.rs index 015bb5052..725b7b822 100644 --- a/hyperspace/ethereum/src/events.rs +++ b/hyperspace/ethereum/src/events.rs @@ -1,14 +1,23 @@ use crate::{ client::{ClientError, EthereumClient}, - ibc_provider::{CreateClientFilter, UpdateClientFilter}, + ibc_provider::{ + CloseConfirmChannelFilter, CreateClientFilter, OpenConfirmChannelFilter, + OpenConfirmConnectionFilter, UpdateClientFilter, + }, }; use async_trait::async_trait; use ethers::prelude::Log; use ibc::{ - core::ics02_client::events::{Attributes as ClientAttributes, CreateClient, UpdateClient}, + core::{ + ics02_client::events::{Attributes as ClientAttributes, CreateClient, UpdateClient}, + ics03_connection::events::{Attributes, OpenConfirm as ConnectionOpenConfirm}, + ics04_channel::events::{CloseConfirm, OpenConfirm as ChannelOpenConfirm}, + ics24_host::identifier::{ChannelId, ConnectionId, PortId}, + }, events::IbcEvent, Height, }; +use primitives::IbcProvider; #[async_trait] pub trait TryFromEvent @@ -55,7 +64,6 @@ where Empty(String), // Special event, signifying empty response ChainError(String), // Special event, signifying an error on CheckTx or DeliverTx - */ #[async_trait] @@ -96,3 +104,50 @@ impl TryFromEvent for IbcEvent { })) } } + +#[async_trait] +impl TryFromEvent for IbcEvent { + async fn try_from_event( + client: &EthereumClient, + event: OpenConfirmConnectionFilter, + _log: Log, + height: Height, + ) -> Result { + let OpenConfirmConnectionFilter { connection_id } = event; + let connection_id: ConnectionId = connection_id.parse()?; + let resp = client.query_connection_end(height, connection_id.clone()).await?; + let counterparty = resp.connection.unwrap().counterparty.unwrap(); + Ok(IbcEvent::OpenConfirmConnection(ConnectionOpenConfirm(Attributes { + height, + connection_id: Some(connection_id), + client_id: client.client_id(), + counterparty_connection_id: Some(counterparty.connection_id.parse()?), + counterparty_client_id: counterparty.client_id.parse()?, + }))) + } +} + +#[async_trait] +impl TryFromEvent for IbcEvent { + async fn try_from_event( + client: &EthereumClient, + event: OpenConfirmChannelFilter, + _log: Log, + height: Height, + ) -> Result { + let OpenConfirmChannelFilter { port_id, channel_id } = event; + let port_id: PortId = port_id.parse()?; + let channel_id: ChannelId = channel_id.parse()?; + let resp = client.query_channel_end(height, channel_id, port_id.clone()).await?; + let channel = resp.channel.unwrap(); + let counterparty = channel.counterparty.unwrap(); + Ok(IbcEvent::OpenConfirmChannel(ChannelOpenConfirm { + height, + channel_id: Some(channel_id), + connection_id: channel.connection_hops[0].parse()?, + counterparty_port_id: counterparty.port_id.parse()?, + port_id, + counterparty_channel_id: Some(counterparty.port_id.parse()?), + })) + } +} diff --git a/hyperspace/ethereum/src/ibc_provider.rs b/hyperspace/ethereum/src/ibc_provider.rs index abacc74da..53fd354fc 100644 --- a/hyperspace/ethereum/src/ibc_provider.rs +++ b/hyperspace/ethereum/src/ibc_provider.rs @@ -53,13 +53,17 @@ use std::{ use crate::{ client::{ClientError, EthereumClient, COMMITMENTS_STORAGE_INDEX, CONNECTIONS_STORAGE_INDEX}, events::TryFromEvent, + prove::prove, }; use futures::{FutureExt, Stream, StreamExt}; use ibc::{ applications::transfer::PrefixedCoin, - core::ics04_channel::{ - channel::{Order, State}, - events::SendPacket, + core::{ + ics04_channel::{ + channel::{Order, State}, + events::SendPacket, + }, + ics23_commitment::commitment::CommitmentRoot, }, events::IbcEvent, protobuf::Protobuf, @@ -73,8 +77,10 @@ use ibc_proto::{ }, }; use ibc_rpc::{IbcApiClient, PacketInfo}; -use icsxx_ethereum::client_state::ClientState; +use icsxx_ethereum::{client_state::ClientState, consensus_state::ConsensusState}; use pallet_ibc::light_clients::{AnyClientState, AnyConsensusState, HostFunctionsManager}; +use sync_committee_primitives::types::LightClientState; +use sync_committee_prover::SyncCommitteeProver; abigen!( IbcClientAbi, @@ -181,6 +187,14 @@ impl IbcProvider for EthereumClient { let logs = self.http_rpc.get_logs(&filter).await.unwrap(); let mut events = vec![]; + let update = prove(self, finality_event.hash.unwrap()).await?; + + println!( + "proven: state root = {}, body root = {}, slot = {}", + update.finalized_header.state_root, + update.finalized_header.body_root, + update.finalized_header.slot + ); // for log in logs { // let raw_log = RawLog::from(log.clone()); // let height = Height::new(0, log.block_number.unwrap().as_u64()); @@ -206,6 +220,7 @@ impl IbcProvider for EthereumClient { Ok(events) } + // TODO: this function is mostly used in tests and in 'fishing' mode. async fn ibc_events(&self) -> Pin + Send + 'static>> { let ibc_address = self.config.ibc_handler_address; let client = self.clone(); @@ -274,7 +289,7 @@ impl IbcProvider for EthereumClient { .call() .await .map_err(|err| { - eprintln!("{err}"); + eprintln!("error: {err}"); err }) .unwrap(); @@ -681,7 +696,6 @@ impl IbcProvider for EthereumClient { self.config.channel_whitelist.clone().into_iter().collect() } - #[cfg(test)] async fn query_connection_channels( &self, at: Height, @@ -963,8 +977,9 @@ impl IbcProvider for EthereumClient { Ok(Duration::from_secs(block.timestamp.as_u64()).as_nanos() as u64) } + // TODO async fn query_clients(&self) -> Result, Self::Error> { - todo!() + Ok(vec![]) } async fn query_channels(&self) -> Result, Self::Error> { @@ -994,7 +1009,57 @@ impl IbcProvider for EthereumClient { async fn initialize_client_state( &self, ) -> Result<(AnyClientState, AnyConsensusState), Self::Error> { - todo!() + let mut string = self.config.beacon_rpc_url.to_string(); + string.pop(); + let sync_committee_prover = SyncCommitteeProver::new(string); + let block_id = "finalized"; + let block_header = sync_committee_prover.fetch_header(&block_id).await.unwrap(); + + let state = sync_committee_prover + .fetch_beacon_state(&block_header.slot.to_string()) + .await + .unwrap(); + + // TODO: query `at` block + let finality_checkpoint = sync_committee_prover.fetch_finalized_checkpoint().await.unwrap(); + let client_state = LightClientState { + finalized_header: block_header.clone(), + latest_finalized_epoch: finality_checkpoint.finalized.epoch, // TODO: ???? + current_sync_committee: state.current_sync_committee, + next_sync_committee: state.next_sync_committee, + }; + + let block = self + .http_rpc + .get_block(BlockId::Number(BlockNumber::Number(dbg!(block_header.slot).into()))) + .await + .unwrap() + .unwrap(); + + dbg!(&block.state_root); + dbg!(&block.hash.unwrap()); + dbg!(&state.state_roots.iter().take(10).collect::>()); + dbg!(&state.block_roots.iter().take(10).collect::>()); + dbg!(&block_header.state_root); + dbg!(&block_header.body_root); + + let client_state = AnyClientState::Ethereum(ClientState { + inner: client_state, + frozen_height: None, + latest_height: block_header.slot as _, + _phantom: Default::default(), + }); + + let consensus_state = AnyConsensusState::Ethereum(ConsensusState { + timestamp: tendermint::time::Time::from_unix_timestamp( + block.timestamp.as_u64() as i64, + 0, + ) + .unwrap(), + root: CommitmentRoot { bytes: block.state_root.0.to_vec() }, + }); + + Ok((client_state, consensus_state)) } async fn query_client_id_from_tx_hash( diff --git a/hyperspace/ethereum/src/key_provider.rs b/hyperspace/ethereum/src/key_provider.rs index 9f334c5ff..e9b558c61 100644 --- a/hyperspace/ethereum/src/key_provider.rs +++ b/hyperspace/ethereum/src/key_provider.rs @@ -1,9 +1,11 @@ use primitives::KeyProvider; +use std::str::FromStr; use crate::client::EthereumClient; impl KeyProvider for EthereumClient { fn account_id(&self) -> pallet_ibc::Signer { - todo!("return public key in string") + // TODO: + pallet_ibc::Signer::from_str(&self.config.name).unwrap() } } diff --git a/hyperspace/ethereum/src/lib.rs b/hyperspace/ethereum/src/lib.rs index 92b9b3800..3e7fd84d9 100644 --- a/hyperspace/ethereum/src/lib.rs +++ b/hyperspace/ethereum/src/lib.rs @@ -14,3 +14,5 @@ pub mod key_provider; pub mod light_client_sync; pub mod prove; pub mod utils; + +pub mod mock; diff --git a/hyperspace/ethereum/src/mock/mod.rs b/hyperspace/ethereum/src/mock/mod.rs new file mode 100644 index 000000000..9d020727b --- /dev/null +++ b/hyperspace/ethereum/src/mock/mod.rs @@ -0,0 +1,2 @@ +pub mod sanity_checks; +pub mod utils; diff --git a/hyperspace/ethereum/src/prove.rs b/hyperspace/ethereum/src/prove.rs index 63e6f7cc0..93ed21e7b 100644 --- a/hyperspace/ethereum/src/prove.rs +++ b/hyperspace/ethereum/src/prove.rs @@ -131,7 +131,7 @@ pub async fn prove( .sync_aggregate .sync_committee_bits .as_bitslice() - .count_ones() < (2 * (SYNC_COMMITTEE_SIZE)) / 3 + .count_ones() < (2 * SYNC_COMMITTEE_SIZE) / 3 { attested_slot += 1; println!("Signature block does not have sufficient sync committee participants -> participants {}", signature_block.body.sync_aggregate.sync_committee_bits.as_bitslice().count_ones()); diff --git a/hyperspace/ethereum/tests/sanity_checks.rs b/hyperspace/ethereum/tests/sanity_checks.rs index 879bfdf76..6504697ea 100644 --- a/hyperspace/ethereum/tests/sanity_checks.rs +++ b/hyperspace/ethereum/tests/sanity_checks.rs @@ -9,9 +9,9 @@ use ethers::{ utils::{keccak256, AnvilInstance}, }; use ethers_solc::{ProjectCompileOutput, ProjectPathsConfig}; -use futures::{stream::StreamExt, TryStreamExt}; +use futures::{stream::StreamExt, Stream, TryStreamExt}; use hyperspace_ethereum::{ - config::Config, + config::EthereumClientConfig, contract::UnwrapContractError, utils::{DeployYuiIbc, ProviderImpl}, }; @@ -28,7 +28,7 @@ use ibc::{ timestamp::Timestamp, }; use ibc_rpc::PacketInfo; -use primitives::IbcProvider; +use primitives::{Chain, IbcProvider}; use prost::Message; use tokio::time::timeout; use tracing::log; @@ -49,7 +49,7 @@ async fn hyperspace_ethereum_client_fixture( let wallet = if !USE_GETH { Some(anvil.endpoint().parse().unwrap()) } else { None }; hyperspace_ethereum::client::EthereumClient::new( - Config { + EthereumClientConfig { http_rpc_url: endpoint.parse().unwrap(), ws_rpc_url: "ws://localhost:5001".parse().unwrap(), ibc_handler_address: yui_ibc.diamond.address(), diff --git a/hyperspace/parachain/src/provider.rs b/hyperspace/parachain/src/provider.rs index c23c71d45..f71667944 100644 --- a/hyperspace/parachain/src/provider.rs +++ b/hyperspace/parachain/src/provider.rs @@ -452,7 +452,6 @@ where self.channel_whitelist.lock().unwrap().iter().cloned().collect() } - #[cfg(test)] async fn query_connection_channels( &self, at: Height, diff --git a/hyperspace/primitives/src/lib.rs b/hyperspace/primitives/src/lib.rs index 2ecf1f950..992df271e 100644 --- a/hyperspace/primitives/src/lib.rs +++ b/hyperspace/primitives/src/lib.rs @@ -340,7 +340,6 @@ pub trait IbcProvider { fn channel_whitelist(&self) -> HashSet<(ChannelId, PortId)>; /// Query all channels for a connection - #[cfg(test)] async fn query_connection_channels( &self, at: Height, diff --git a/hyperspace/testsuite/Cargo.toml b/hyperspace/testsuite/Cargo.toml index 7e6b521d8..ec997316d 100644 --- a/hyperspace/testsuite/Cargo.toml +++ b/hyperspace/testsuite/Cargo.toml @@ -48,9 +48,10 @@ toml = "0.7.4" [dev-dependencies] subxt = { git = "https://github.com/paritytech/subxt", rev = "2a4da618a033bb82f768e4ef67b093b371f8b492", features = ["substrate-compat"] } -hyperspace-core = { path = "../core", features = ["testing", "build-metadata-from-ws"] } +hyperspace-core = { path = "../core", features = ["testing"] } hyperspace-parachain = { path = "../parachain", features = ["testing"] } hyperspace-cosmos = { path = "../cosmos", features = [] } +hyperspace-ethereum = { path = "../ethereum", features = [] } # We need this so the tests run sequentially [[test]] @@ -58,3 +59,6 @@ name = "parachain_parachain" [[test]] name = "parachain_cosmos" + +[[test]] +name = "ethereum_cosmos" diff --git a/hyperspace/testsuite/tests/ethereum_cosmos.rs b/hyperspace/testsuite/tests/ethereum_cosmos.rs new file mode 100644 index 000000000..f0c13f3ef --- /dev/null +++ b/hyperspace/testsuite/tests/ethereum_cosmos.rs @@ -0,0 +1,294 @@ +// Copyright 2022 ComposableFi +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use core::time::Duration; +use futures::StreamExt; +use hyperspace_core::{ + chain::{AnyAssetId, AnyChain, AnyConfig}, + logging, + substrate::DefaultConfig, +}; +use hyperspace_cosmos::client::{CosmosClient, CosmosClientConfig}; +use hyperspace_ethereum::{ + config::EthereumClientConfig, + mock::sanity_checks::{ + deploy_yui_ibc_and_mock_client_fixture, hyperspace_ethereum_client_fixture, + DeployYuiIbcMockClient, + }, +}; +use hyperspace_parachain::{finality_protocol::FinalityProtocol, ParachainClientConfig}; +use hyperspace_primitives::{utils::create_clients, CommonClientConfig, IbcProvider}; +use hyperspace_testsuite::{ + ibc_channel_close, ibc_messaging_packet_height_timeout_with_connection_delay, + ibc_messaging_packet_timeout_on_channel_close, + ibc_messaging_packet_timestamp_timeout_with_connection_delay, + ibc_messaging_with_connection_delay, misbehaviour::ibc_messaging_submit_misbehaviour, + setup_connection_and_channel, +}; +use ibc::core::ics24_host::identifier::PortId; +use sp_core::hashing::sha2_256; + +#[derive(Debug, Clone)] +pub struct Args { + pub chain_a: String, + pub chain_b: String, + pub connection_prefix_a: String, + pub connection_prefix_b: String, + pub cosmos_grpc: String, + pub cosmos_ws: String, + pub ethereum_rpc: String, + pub wasm_path: String, +} + +impl Default for Args { + fn default() -> Self { + let eth = std::env::var("ETHEREUM_HOST").unwrap_or_else(|_| "127.0.0.1".to_string()); + let cosmos = std::env::var("COSMOS_HOST").unwrap_or_else(|_| "127.0.0.1".to_string()); + let wasm_path = std::env::var("WASM_PATH").unwrap_or_else(|_| { + "../../target/wasm32-unknown-unknown/release/icsxx_ethereum_cw.wasm".to_string() + }); + + Args { + chain_a: format!("ws://{eth}:5001"), + chain_b: format!("http://{cosmos}:26657"), + connection_prefix_a: "ibc/".to_string(), + connection_prefix_b: "ibc".to_string(), + cosmos_grpc: format!("http://{cosmos}:9090"), + cosmos_ws: format!("ws://{cosmos}:26657/websocket"), + ethereum_rpc: format!("http://{eth}:6001"), + wasm_path, + } + } +} + +async fn setup_clients() -> (AnyChain, AnyChain) { + log::info!(target: "hyperspace", "=========================== Starting Test ==========================="); + let args = Args::default(); + + // Create client configurations + // let config_a = EthereumClientConfig { + // http_rpc_url: Default::default(), + // ws_rpc_url: Default::default(), + // ibc_handler_address: Default::default(), + // name: "ethereum".to_string(), + // // para_id: args.para_id, + // // parachain_rpc_url: args.chain_a, + // // relay_chain_rpc_url: args.relay_chain.clone(), + // client_id: None, + // connection_id: None, + // commitment_prefix: args.connection_prefix_a.as_bytes().to_vec().into(), + // // ss58_version: 42, + // channel_whitelist: vec![], + // // finality_protocol: FinalityProtocol::Grandpa, + // private_key: None, + // // key_type: "sr25519".to_string(), + // // wasm_code_id: None, + // private_key_path: Some( + // "../ethereum/keys/0x73db010c3275eb7a92e5c38770316248f4c644ee".to_string(), + // ), + // mnemonic: None, + // max_block_weight: 1, + // }; + + let DeployYuiIbcMockClient { anvil, yui_ibc, .. } = + deploy_yui_ibc_and_mock_client_fixture().await; + let config_a = hyperspace_ethereum_client_fixture(&anvil, yui_ibc).await; + + let mut config_b = CosmosClientConfig { + name: "centauri".to_string(), + rpc_url: args.chain_b.clone().parse().unwrap(), + grpc_url: args.cosmos_grpc.clone().parse().unwrap(), + websocket_url: args.cosmos_ws.clone().parse().unwrap(), + chain_id: "centauri-testnet-1".to_string(), + client_id: None, + connection_id: None, + account_prefix: "centauri".to_string(), + fee_denom: "stake".to_string(), + fee_amount: "4000".to_string(), + gas_limit: (i64::MAX - 1) as u64, + store_prefix: args.connection_prefix_b, + max_tx_size: 200000, + mnemonic: // 26657 + "sense state fringe stool behind explain area quit ugly affair develop thumb clinic weasel choice atom gesture spare sea renew penalty second upon peace" + .to_string(), + wasm_code_id: None, + channel_whitelist: vec![], + common: CommonClientConfig { + skip_optional_client_updates: true, + max_packets_to_process: 200, + }, + }; + + let chain_b = CosmosClient::::new(config_b.clone()).await.unwrap(); + + let wasm_data = tokio::fs::read(&args.wasm_path).await.expect("Failed to read wasm file"); + let code_id = match chain_b.upload_wasm(wasm_data.clone()).await { + Ok(code_id) => code_id, + Err(e) => { + let e_str = format!("{e:?}"); + if !e_str.contains("wasm code already exists") { + panic!("Failed to upload wasm: {e_str}"); + } + sha2_256(&wasm_data).to_vec() + }, + }; + let code_id_str = hex::encode(code_id); + config_b.wasm_code_id = Some(code_id_str); + + let mut chain_a_wrapped = AnyConfig::Ethereum(config_a).into_client().await.unwrap(); + let mut chain_b_wrapped = AnyConfig::Cosmos(config_b).into_client().await.unwrap(); + + let clients_on_a = chain_a_wrapped.query_clients().await.unwrap(); + let clients_on_b = chain_b_wrapped.query_clients().await.unwrap(); + + if !clients_on_a.is_empty() && !clients_on_b.is_empty() { + chain_a_wrapped.set_client_id(clients_on_b[0].clone()); + chain_b_wrapped.set_client_id(clients_on_a[0].clone()); + return (chain_a_wrapped, chain_b_wrapped) + } + + let (client_b, client_a) = + create_clients(&mut chain_b_wrapped, &mut chain_a_wrapped).await.unwrap(); + chain_a_wrapped.set_client_id(client_a); + chain_b_wrapped.set_client_id(client_b); + (chain_a_wrapped, chain_b_wrapped) +} + +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +#[ignore] +async fn ethereum_to_cosmos_ibc_messaging_full_integration_test() { + logging::setup_logging(); + + let asset_id_a = AnyAssetId::Ethereum(()); + let asset_id_b = AnyAssetId::Cosmos( + "ibc/47B97D8FF01DA03FCB2F4B1FFEC931645F254E21EF465FA95CBA6888CB964DC4".to_string(), + ); + let (mut chain_a, mut chain_b) = setup_clients().await; + // let (handle, channel_a, channel_b, connection_id_a, connection_id_b) = + // setup_connection_and_channel(&mut chain_a, &mut chain_b, Duration::from_secs(60 * 2)).await; + // handle.abort(); + // + // // Set connections and channel whitelist + // chain_a.set_connection_id(connection_id_a); + // chain_b.set_connection_id(connection_id_b); + // + // chain_a.set_channel_whitelist(vec![(channel_a, PortId::transfer())].into_iter().collect()); + // chain_b.set_channel_whitelist(vec![(channel_b, PortId::transfer())].into_iter().collect()); + // + // // Run tests sequentially + // + // // no timeouts + connection delay + // + // ibc_messaging_with_connection_delay( + // &mut chain_a, + // &mut chain_b, + // asset_id_a.clone(), + // asset_id_b.clone(), + // channel_a, + // channel_b, + // ) + // .await; + // + // // timeouts + connection delay + // ibc_messaging_packet_height_timeout_with_connection_delay( + // &mut chain_a, + // &mut chain_b, + // asset_id_a.clone(), + // channel_a, + // channel_b, + // ) + // .await; + // ibc_messaging_packet_timestamp_timeout_with_connection_delay( + // &mut chain_a, + // &mut chain_b, + // asset_id_a.clone(), + // channel_a, + // channel_b, + // ) + // .await; + // + // // channel closing semantics + // ibc_messaging_packet_timeout_on_channel_close( + // &mut chain_a, + // &mut chain_b, + // asset_id_a.clone(), + // channel_a, + // ) + // .await; + // ibc_channel_close(&mut chain_a, &mut chain_b).await; + + // TODO: tendermint misbehaviour? + // ibc_messaging_submit_misbehaviour(&mut chain_a, &mut chain_b).await; +} + +#[tokio::test] +#[ignore] +async fn cosmos_to_ethereum_ibc_messaging_full_integration_test() { + logging::setup_logging(); + + let (chain_a, chain_b) = setup_clients().await; + let (mut chain_b, mut chain_a) = (chain_a, chain_b); + + let (handle, channel_a, channel_b, connection_id_a, connection_id_b) = + setup_connection_and_channel(&mut chain_a, &mut chain_b, Duration::from_secs(60 * 2)).await; + handle.abort(); + + // Set connections and channel whitelist + chain_a.set_connection_id(connection_id_a); + chain_b.set_connection_id(connection_id_b); + + chain_a.set_channel_whitelist(vec![(channel_a, PortId::transfer())].into_iter().collect()); + chain_b.set_channel_whitelist(vec![(channel_b, PortId::transfer())].into_iter().collect()); + + let asset_id_a = AnyAssetId::Cosmos("stake".to_string()); + let asset_id_b = AnyAssetId::Parachain(2); + + // Run tests sequentially + + // no timeouts + connection delay + ibc_messaging_with_connection_delay( + &mut chain_a, + &mut chain_b, + asset_id_a.clone(), + asset_id_b.clone(), + channel_a, + channel_b, + ) + .await; + + // timeouts + connection delay + ibc_messaging_packet_height_timeout_with_connection_delay( + &mut chain_a, + &mut chain_b, + asset_id_a.clone(), + channel_a, + channel_b, + ) + .await; + ibc_messaging_packet_timestamp_timeout_with_connection_delay( + &mut chain_a, + &mut chain_b, + asset_id_a.clone(), + channel_a, + channel_b, + ) + .await; + + // channel closing semantics (doesn't work on cosmos) + // ibc_messaging_packet_timeout_on_channel_close(&mut chain_a, &mut chain_b, asset_id_a.clone()) + // .await; + // ibc_channel_close(&mut chain_a, &mut chain_b).await; + + ibc_messaging_submit_misbehaviour(&mut chain_a, &mut chain_b).await; +} diff --git a/ibc/proto/src/prost/ibc.lightclients.wasm.v1.rs b/ibc/proto/src/prost/ibc.lightclients.wasm.v1.rs index 69b4ef2a0..b3deba754 100644 --- a/ibc/proto/src/prost/ibc.lightclients.wasm.v1.rs +++ b/ibc/proto/src/prost/ibc.lightclients.wasm.v1.rs @@ -4,7 +4,7 @@ pub struct MsgPushNewWasmCode { #[prost(string, tag = "1")] pub signer: ::prost::alloc::string::String, - #[prost(bytes = "vec", tag = "3")] + #[prost(bytes = "vec", tag = "2")] pub code: ::prost::alloc::vec::Vec, } /// Response in case of successful handling diff --git a/light-clients/icsxx-ethereum/src/client_state.rs b/light-clients/icsxx-ethereum/src/client_state.rs index 4309de6c8..cb15d0eba 100644 --- a/light-clients/icsxx-ethereum/src/client_state.rs +++ b/light-clients/icsxx-ethereum/src/client_state.rs @@ -39,7 +39,7 @@ pub struct ClientState { pub inner: LightClientState, pub frozen_height: Option, pub latest_height: u32, - _phantom: PhantomData, + pub _phantom: PhantomData, } impl Protobuf for ClientState {} diff --git a/light-clients/icsxx-ethereum/src/lib.rs b/light-clients/icsxx-ethereum/src/lib.rs index 7eb9061bb..69b519457 100644 --- a/light-clients/icsxx-ethereum/src/lib.rs +++ b/light-clients/icsxx-ethereum/src/lib.rs @@ -34,4 +34,9 @@ pub mod verify; #[cfg(test)] mod tests; +pub use ethereum_consensus::crypto::{ + PublicKey as EthereumPublicKey, Signature as EthereumSignature, +}; +pub use sync_committee_verifier::{error::Error as EthereumError, BlsVerify}; + pub trait HostFunctions: Sized + Send + Sync {} From 530800682a202152e308e8e302d69a8a42364f6e Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Tue, 5 Sep 2023 17:36:38 -0300 Subject: [PATCH 11/43] fix some of the tests --- Cargo.lock | 43 ++++++++++- hyperspace/ethereum/Cargo.toml | 1 + .../ethereum/integration-tests/src/utils.rs | 33 +++++++-- hyperspace/ethereum/src/client.rs | 13 ++-- hyperspace/ethereum/src/ibc_provider.rs | 10 ++- hyperspace/ethereum/src/utils.rs | 2 + hyperspace/ethereum/tests/sanity_checks.rs | 71 ++++++++++++------- hyperspace/ethereum/tests/utils.rs | 30 +++----- 8 files changed, 133 insertions(+), 70 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 15b15722d..05ba36d7c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4849,6 +4849,7 @@ dependencies = [ "async-stream", "async-trait", "cast", + "ecdsa 0.16.7", "elliptic-curve 0.13.5", "env_logger 0.10.0", "ethereum-consensus", @@ -4859,6 +4860,7 @@ dependencies = [ "git2", "hex", "http", + "hyperspace-cosmos", "hyperspace-primitives", "ibc", "ibc-primitives", @@ -4879,6 +4881,43 @@ dependencies = [ "tendermint", "thiserror", "tokio", + "tokio-stream", + "toml 0.7.6", + "tracing", + "tracing-subscriber 0.3.17", +] + +[[package]] +name = "hyperspace-integration-tests" +version = "0.1.0" +dependencies = [ + "anyhow", + "async-stream", + "async-trait", + "cast", + "elliptic-curve 0.13.5", + "env_logger 0.10.0", + "ethers 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ethers-solc 2.0.9", + "futures", + "git2", + "hex", + "http", + "hyperspace-core", + "hyperspace-cosmos", + "hyperspace-ethereum", + "hyperspace-primitives", + "ibc", + "ibc-primitives", + "ibc-proto", + "ibc-rpc", + "ics07-tendermint", + "pallet-ibc", + "prost 0.11.6", + "serde", + "serde_json", + "thiserror", + "tokio", "toml 0.7.6", "tracing", "tracing-subscriber 0.3.17", @@ -12737,9 +12776,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.11" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d660770404473ccd7bc9f8b28494a811bc18542b915c0855c51e8f419d5223ce" +checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" dependencies = [ "futures-core", "pin-project-lite 0.2.13", diff --git a/hyperspace/ethereum/Cargo.toml b/hyperspace/ethereum/Cargo.toml index f05ed44c9..1eb42e4f2 100644 --- a/hyperspace/ethereum/Cargo.toml +++ b/hyperspace/ethereum/Cargo.toml @@ -45,6 +45,7 @@ serde = { version = "1.0.137", features = ["derive"] } serde_json = "1.0.74" thiserror = "1.0.31" tokio = { version = "1.19.2", features = ["full"] } +tokio-stream = "0.1.14" tracing = "0.1.36" tracing-subscriber = "0.3.17" env_logger = "0.10.0" diff --git a/hyperspace/ethereum/integration-tests/src/utils.rs b/hyperspace/ethereum/integration-tests/src/utils.rs index 0c2c67c4d..33ec909d4 100644 --- a/hyperspace/ethereum/integration-tests/src/utils.rs +++ b/hyperspace/ethereum/integration-tests/src/utils.rs @@ -25,7 +25,7 @@ use ethers_solc::{ Artifact, ConfigurableContractArtifact, EvmVersion, Project, ProjectCompileOutput, ProjectPathsConfig, SolcConfig, }; -use hyperspace_ethereum::{contract::UnwrapContractError, client::EthRpcClient, config::Config}; +use hyperspace_ethereum::{client::EthRpcClient, config::Config, contract::UnwrapContractError}; use ibc::{ core::{ ics04_channel::packet::Packet, @@ -43,7 +43,7 @@ pub async fn hyperspace_ethereum_client_fixture( ibc_channel_handshake, ibc_packet, ibc_handler, - tendermint_client + tendermint_client, }: &DeployYuiIbc, M>, client: Option>, ) -> hyperspace_ethereum::client::EthereumClient { @@ -59,7 +59,19 @@ pub async fn hyperspace_ethereum_client_fixture( dbg!(anvil.chain_id()); dbg!("hyperspace_ethereum_client_fixture"); - let wallet = if !USE_GETH { Some(anvil.keys()[0].clone().to_sec1_pem(pem::LineEnding::CR).unwrap().as_str().to_owned().to_string()) } else { None }; + let wallet = if !USE_GETH { + Some( + anvil.keys()[0] + .clone() + .to_sec1_pem(pem::LineEnding::CR) + .unwrap() + .as_str() + .to_owned() + .to_string(), + ) + } else { + None + }; let mut ret = hyperspace_ethereum::client::EthereumClient::new(Config { http_rpc_url: endpoint.parse().unwrap(), @@ -69,7 +81,7 @@ pub async fn hyperspace_ethereum_client_fixture( ibc_client_address: ibc_client.address(), ibc_connection_address: ibc_connection.address(), ibc_channel_handshake_address: ibc_channel_handshake.address(), - tendermint_client_address: tendermint_client.address(), + // tendermint_client_address: tendermint_client.address(), mnemonic: None, max_block_weight: 1, private_key: wallet, @@ -82,7 +94,7 @@ pub async fn hyperspace_ethereum_client_fixture( }) .await .unwrap(); - if let Some(client) = client{ + if let Some(client) = client { ret.http_rpc = client; } ret @@ -498,7 +510,7 @@ where ibc_channel_handshake: self.ibc_channel_handshake.clone(), ibc_packet: self.ibc_packet.clone(), ibc_handler: self.ibc_handler.clone(), - tendermint_client: self.tendermint_client.clone(), + // tendermint_client: self.tendermint_client.clone(), } } } @@ -566,5 +578,12 @@ where println!("IBC Handler address: {:?}", ibc_handler.address()); - DeployYuiIbc { ibc_client, ibc_connection, ibc_channel_handshake, ibc_packet, ibc_handler, tendermint_client } + DeployYuiIbc { + ibc_client, + ibc_connection, + ibc_channel_handshake, + ibc_packet, + ibc_handler, + tendermint_client, + } } diff --git a/hyperspace/ethereum/src/client.rs b/hyperspace/ethereum/src/client.rs index 3013c941c..25b670fb1 100644 --- a/hyperspace/ethereum/src/client.rs +++ b/hyperspace/ethereum/src/client.rs @@ -32,9 +32,7 @@ use primitives::CommonClientState; use std::{future::Future, ops::Add, pin::Pin, str::FromStr, sync::Arc}; use thiserror::Error; -use crate::config::Config; - -pub(crate) type EthRpcClient = ethers::prelude::SignerMiddleware< +pub type EthRpcClient = ethers::prelude::SignerMiddleware< ethers::providers::Provider, ethers::signers::Wallet, >; @@ -147,11 +145,12 @@ impl EthereumClient { prev_state: Arc::new(std::sync::Mutex::new((vec![], vec![]))), }) } - + // cauce pub async fn websocket_provider(&self) -> Result, ClientError> { - let secret = std::fs::read_to_string( - "/Users/vmark/.lighthouse/local-testnet/geth_datadir1/geth/jwtsecret", - ) + let secret = std::fs::read_to_string(format!( + "{}/.lighthouse/local-testnet/geth_datadir1/geth/jwtsecret", + env!("HOME"), + )) .unwrap(); println!("secret = {secret}"); let secret = JwtKey::from_slice(&hex::decode(&secret[2..]).unwrap()).expect("oops"); diff --git a/hyperspace/ethereum/src/ibc_provider.rs b/hyperspace/ethereum/src/ibc_provider.rs index a2643aa34..b797ef09c 100644 --- a/hyperspace/ethereum/src/ibc_provider.rs +++ b/hyperspace/ethereum/src/ibc_provider.rs @@ -1,14 +1,15 @@ use ethers::{ abi::{ encode, encode_packed, ethabi, Abi, AbiEncode, Detokenize, InvalidOutputType, ParamType, - RawLog, Token, Tokenizable, Topic, + RawLog, Token, Tokenizable, }, contract::{abigen, EthEvent}, middleware::contract::Contract, prelude::Block, providers::Middleware, types::{ - BlockId, BlockNumber, EIP1186ProofResponse, Filter, StorageProof, ValueOrArray, H256, U256, + BlockId, BlockNumber, EIP1186ProofResponse, Filter, StorageProof, Topic, ValueOrArray, + H256, U256, }, utils::keccak256, }; @@ -390,14 +391,11 @@ impl IbcProvider for EthereumClient { ) .expect("contract is missing getChannel"); - let (channel_data, exists) = binding + let channel_data = binding .block(BlockId::Number(BlockNumber::Number(at.revision_height.into()))) .call() .await .unwrap(); - if !exists { - todo!("error: channel does not exist") - } let state = State::from_i32(channel_data.state as _).expect("invalid channel state"); let counterparty = match state { diff --git a/hyperspace/ethereum/src/utils.rs b/hyperspace/ethereum/src/utils.rs index ad3721d80..ee0aaee68 100644 --- a/hyperspace/ethereum/src/utils.rs +++ b/hyperspace/ethereum/src/utils.rs @@ -49,6 +49,7 @@ pub struct DeployYuiIbc { pub deployed_facets: Vec>, pub diamond: ContractInstance, pub storage_layout: StorageLayout, + pub tendermint: ContractInstance, } impl DeployYuiIbc @@ -325,6 +326,7 @@ where deployed_facets: self.deployed_facets.clone(), diamond: self.diamond.clone(), storage_layout: self.storage_layout.clone(), + tendermint: self.tendermint.clone(), } } } diff --git a/hyperspace/ethereum/tests/sanity_checks.rs b/hyperspace/ethereum/tests/sanity_checks.rs index 0aa45c7cb..56aa2962f 100644 --- a/hyperspace/ethereum/tests/sanity_checks.rs +++ b/hyperspace/ethereum/tests/sanity_checks.rs @@ -14,13 +14,15 @@ use ethers::{ types::U256, utils::{keccak256, AnvilInstance}, }; -use ethers_solc::{ProjectCompileOutput, ProjectPathsConfig}; -use futures::{stream::StreamExt, Stream, TryStreamExt}; +use ethers_solc::{Artifact, ProjectCompileOutput, ProjectPathsConfig}; +use futures::{Stream, TryStreamExt}; use hyperspace_cosmos::client::{CosmosClient, CosmosClientConfig}; use hyperspace_ethereum::{ + client::EthRpcClient, config::EthereumClientConfig, - contract::UnwrapContractError, + contract::{DiamandHandler, IbcHandler, UnwrapContractError}, utils::{DeployYuiIbc, ProviderImpl}, + yui_types::IntoToken, }; use ibc::{ core::{ @@ -55,13 +57,23 @@ use ibc::{ ics24_host::identifier::{ChainId, ChannelId, ConnectionId, PortId}, }, events::IbcEvent, + proofs::{ConsensusProof, Proofs}, + protobuf::Protobuf, + signer::Signer, timestamp::Timestamp, tx_msg::Msg, }; +use ibc_proto::google::protobuf::Any; use ibc_rpc::PacketInfo; -use primitives::{Chain, IbcProvider}; +use ics07_tendermint::client_state::ClientState; +use pallet_ibc::light_clients::{AnyClientState, AnyConsensusState, HostFunctionsManager}; +use primitives::{mock::LocalClientTypes, Chain, IbcProvider}; use prost::Message; -use tokio::time::timeout; +use tokio::{ + task::LocalSet, + time::{sleep, timeout, Interval}, +}; +use tokio_stream::{Elapsed, StreamExt as _}; use tracing::log; use tracing_subscriber::{filter, layer::SubscriberExt, util::SubscriberInitExt, Layer}; @@ -99,11 +111,12 @@ async fn hyperspace_ethereum_client_fixture( None }; - let mut ret = hyperspace_ethereum::client::EthereumClient::new(Config { + let mut ret = hyperspace_ethereum::client::EthereumClient::new(EthereumClientConfig { http_rpc_url: endpoint.parse().unwrap(), ws_rpc_url: "ws://localhost:5001".parse().unwrap(), + beacon_rpc_url: Default::default(), ibc_handler_address: yui_ibc.diamond.address(), - tendermint_client_address: tendermint_client.address(), + tendermint_client_address: yui_ibc.tendermint.address(), mnemonic: None, max_block_weight: 1, private_key: wallet, @@ -115,22 +128,21 @@ async fn hyperspace_ethereum_client_fixture( connection_id: None, channel_whitelist: vec![], commitment_prefix: "".into(), + wasm_code_id: None, + yui: Some(yui_ibc), client_type: "07-tendermint".into(), diamond_handler: diamond_hanlder, }) .await .unwrap(); + if let Some(client) = client { ret.http_rpc = client; } + ret } -pub type ProviderImpl = ethers::prelude::SignerMiddleware< - ethers::providers::Provider, - ethers::signers::LocalWallet, ->; - #[allow(dead_code)] struct DeployYuiIbcMockClient { pub path: PathBuf, @@ -192,7 +204,7 @@ impl DeployYuiIbcMockClient { async fn deploy_yui_ibc_and_mock_client_fixture() -> DeployYuiIbcMockClient { let path = utils::yui_ibc_solidity_path(); - let project_output: ProjectCompileOutput = utils::compile_yui(&path, "contracts/core"); + let project_output = utils::compile_yui(&path, "contracts/core"); let diamond_project_output = utils::compile_yui(&path, "contracts/diamond"); let (anvil, client) = utils::spawn_anvil(); log::warn!("{}", anvil.endpoint()); @@ -320,7 +332,7 @@ async fn test_deploy_yui_ibc_and_create_eth_client() { //create ethereum hyperspace client let mut hyperspace = hyperspace_ethereum_client_fixture( &anvil, - &yui_ibc, + yui_ibc.clone(), Some(client.clone()), Some(diamond.clone()), ) @@ -353,7 +365,7 @@ async fn test_deploy_yui_ibc_and_create_eth_client() { //replace the tendermint client address in hyperspace config with a real one hyperspace.config.ibc_handler_address = yui_ibc.diamond.address(); hyperspace.config.tendermint_client_address = tendermint_light_client.address(); - yui_ibc.tendermint_client = tendermint_light_client; + // yui_ibc.tendermint_client = tendermint_light_client; /* ______________________________________________________________________________ */ /* ______________________________________________________________________________ */ @@ -465,7 +477,7 @@ async fn test_deploy_yui_ibc_and_create_eth_client() { Height::new(1, 1), ) .unwrap(); - // + let msg = MsgConnectionOpenAck:: { connection_id: ConnectionId::new(0), counterparty_connection_id: ConnectionId::new(0), @@ -717,7 +729,6 @@ async fn test_hyperspace_ethereum_client() { } #[tokio::test] -#[ignore] async fn test_ibc_client() { let deploy = deploy_yui_ibc_and_mock_client_fixture().await; let hyperspace = @@ -766,14 +777,16 @@ async fn test_ibc_client() { .await .unwrap(); - let events = timeout(Duration::from_secs(5), events.take(1).collect::>()) - .await - .unwrap(); + let events = events + .timeout(Duration::from_secs(5)) + .take_while(|x| x.is_ok()) + .filter_map(|x| x.ok()) + .collect::>() + .await; dbg!(events); } #[tokio::test] -#[ignore] async fn test_ibc_connection() { let stdout_log = tracing_subscriber::fmt::layer().pretty(); tracing_subscriber::registry() @@ -819,7 +832,6 @@ async fn test_ibc_connection() { } #[tokio::test] -#[ignore] async fn test_ibc_channel() { let deploy = deploy_yui_ibc_and_mock_client_fixture().await; let hyperspace = @@ -876,12 +888,12 @@ async fn test_ibc_channel() { } #[tokio::test] -#[ignore] async fn test_ibc_packet() { let _ = env_logger::try_init(); let mut deploy = deploy_yui_ibc_and_mock_client_fixture().await; let hyperspace = hyperspace_ethereum_client_fixture(&deploy.anvil, deploy.yui_ibc.clone(), None, None).await; + let events = hyperspace.ibc_events().await; let client_id = deploy_mock_client_fixture(&deploy).await; let mock_module = deploy_mock_module_fixture(&deploy).await; @@ -982,7 +994,7 @@ async fn test_ibc_packet() { source_channel: ChannelId::from_str("channel-0").unwrap(), destination_port: PortId::from_str("port-0").unwrap(), destination_channel: ChannelId::from_str("channel-0").unwrap(), - data, + data: data.clone(), timeout_height: Height::new(0, 1000000), timeout_timestamp: Timestamp::default(), }) @@ -1024,7 +1036,7 @@ async fn test_ibc_packet() { data: "hello_recv".as_bytes().to_vec(), timeout_height: Height::new(0, 1000000).into(), timeout_timestamp: 0, - ack: None, + ack: Some(data.clone()), }] ); @@ -1076,7 +1088,14 @@ async fn test_ibc_packet() { .unwrap(); assert_eq!(unreceived, vec![1, 2]); - let events = events.collect::>().await; + log::warn!("waiting for events"); + + let events = events + .timeout(Duration::from_secs(5)) + .take_while(|x| x.is_ok()) + .filter_map(|x| x.ok()) + .collect::>() + .await; dbg!(events); } diff --git a/hyperspace/ethereum/tests/utils.rs b/hyperspace/ethereum/tests/utils.rs index 230e9e063..cd1c23b60 100644 --- a/hyperspace/ethereum/tests/utils.rs +++ b/hyperspace/ethereum/tests/utils.rs @@ -43,7 +43,7 @@ use ibc::{ }; use tracing::log; -pub const USE_GETH: bool = false; +pub const USE_GETH: bool = true; #[track_caller] pub fn yui_ibc_solidity_path() -> PathBuf { @@ -236,26 +236,6 @@ pub mod mock { } } -#[derive(Debug)] -pub struct DeployYuiIbc { - pub facet_cuts: Vec, - pub deployed_facets: Vec>, - pub diamond: ContractInstance, - pub tendermint_client: ContractInstance, -} - -impl FacetCut { - pub fn into_token(self) -> Token { - Token::Tuple(vec![ - Token::Address(self.address), - Token::Uint((FacetCutAction::Add as u32).into()), - Token::Array( - self.selectors.into_iter().map(|(_, x)| Token::FixedBytes(x.to_vec())).collect(), - ), - ]) - } -} - fn get_selectors(contract: &ContractInstance, M>) -> Vec<(String, [u8; 4])> where M: Middleware, @@ -396,5 +376,11 @@ where let tendermint_client = diamond.clone(); - DeployYuiIbc { diamond, facet_cuts, deployed_facets, storage_layout, tendermint_client } + DeployYuiIbc { + diamond, + facet_cuts, + deployed_facets, + storage_layout, + tendermint: tendermint_client, + } } From 37f403296fe0b86edf10b81769c2e8776ae6e023 Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Tue, 5 Sep 2023 18:49:33 -0300 Subject: [PATCH 12/43] add mock --- hyperspace/ethereum/src/mock/sanity_checks.rs | 617 ++++++++++++++++++ hyperspace/ethereum/src/mock/utils.rs | 389 +++++++++++ 2 files changed, 1006 insertions(+) create mode 100644 hyperspace/ethereum/src/mock/sanity_checks.rs create mode 100644 hyperspace/ethereum/src/mock/utils.rs diff --git a/hyperspace/ethereum/src/mock/sanity_checks.rs b/hyperspace/ethereum/src/mock/sanity_checks.rs new file mode 100644 index 000000000..beaf1c838 --- /dev/null +++ b/hyperspace/ethereum/src/mock/sanity_checks.rs @@ -0,0 +1,617 @@ +use std::{future::Future, ops::Deref, path::PathBuf, str::FromStr, sync::Arc, time::Duration}; + +use super::{utils, utils::USE_GETH}; +use crate::{ + config::EthereumClientConfig, + contract::UnwrapContractError, + utils::{DeployYuiIbc, ProviderImpl}, +}; +use ethers::{ + abi::{encode_packed, Token}, + core::k256::sha2::{Digest, Sha256}, + prelude::{ContractInstance, TransactionReceipt}, + types::U256, + utils::{keccak256, AnvilInstance}, +}; +use ethers_solc::{ProjectCompileOutput, ProjectPathsConfig}; +use futures::{stream::StreamExt, Stream, TryStreamExt}; +use ibc::{ + core::{ + ics02_client::height::Height, + ics03_connection::msgs::conn_open_ack::MsgConnectionOpenAck, + ics04_channel::{ + channel::Order, + packet::{Packet, Sequence}, + }, + ics24_host::identifier::{ChannelId, PortId}, + }, + events::IbcEvent, + timestamp::Timestamp, +}; +use ibc_rpc::PacketInfo; +use primitives::{mock::LocalClientTypes, Chain, IbcProvider}; +use prost::Message; +use tokio::time::timeout; +use tracing::log; +use tracing_subscriber::{filter, layer::SubscriberExt, util::SubscriberInitExt, Layer}; + +pub async fn hyperspace_ethereum_client_fixture( + anvil: &AnvilInstance, + yui_ibc: DeployYuiIbc, ProviderImpl>, +) -> EthereumClientConfig { + // ) -> crate::client::EthereumClient { + let endpoint = if USE_GETH { "http://localhost:6001".to_string() } else { anvil.endpoint() }; + let wallet_path = if USE_GETH { + Some("keys/0x73db010c3275eb7a92e5c38770316248f4c644ee".to_string()) + } else { + None + }; + let wallet = if !USE_GETH { Some(anvil.endpoint().parse().unwrap()) } else { None }; + + // crate::client::EthereumClient::new( + EthereumClientConfig { + http_rpc_url: endpoint.parse().unwrap(), + ws_rpc_url: "ws://localhost:5001".parse().unwrap(), + beacon_rpc_url: "http://localhost:8001".parse().unwrap(), + ibc_handler_address: yui_ibc.diamond.address(), + tendermint_client_address: Default::default(), + mnemonic: None, + max_block_weight: 1, + private_key: wallet, + private_key_path: wallet_path, + name: "mock-ethereum-client".into(), + client_id: None, + connection_id: None, + channel_whitelist: vec![], + commitment_prefix: "".into(), + wasm_code_id: None, + yui: Some(yui_ibc), + client_type: "".to_string(), + } + // ) + // .await + // .unwrap() +} + +#[allow(dead_code)] +pub struct DeployYuiIbcMockClient { + pub path: PathBuf, + pub project_output: ProjectCompileOutput, + // pub project_output: ethers::solc::ProjectCompileOutput, + pub anvil: AnvilInstance, + pub client: Arc, + pub ibc_mock_client: ContractInstance, ProviderImpl>, + pub ibc_mock_module: Option, ProviderImpl>>, + pub yui_ibc: DeployYuiIbc, ProviderImpl>, +} + +impl DeployYuiIbcMockClient { + pub async fn send_mock_packet( + &self, + source_port: PortId, + source_channel: ChannelId, + timeout_height: Height, + data: Vec, + ) -> TransactionReceipt { + let fut = self + .mock_module_ref() + .method::<_, ()>( + "sendMockPacket", + ( + Token::Bytes(data), // data + Token::String(source_port.to_string()), // port-id + Token::String(source_channel.to_string()), // channel-id + // timeout-height + Token::Uint(timeout_height.revision_height.into()), + ), + ) + .unwrap(); + + let () = fut.call().await.unwrap_contract_error(); + // let trace = self + // .ibc_handler + // .client() + // .borrow() + // .debug_trace_call(fut.tx.clone(), None, GethDebugTracingCallOptions::default()) + // .await + // .unwrap(); + // std::fs::write("trace.txt", format!("{:#?}", trace)).unwrap(); + // println!("trace: {:?}", trace); + let tx = fut.send().await.unwrap_contract_error().await.unwrap().unwrap(); + // dbg!(tx.logs); + let status = tx.status.expect("status not found"); + + if status == 0.into() { + panic!("status is 0"); + } + tx + } + + fn mock_module_ref(&self) -> &ContractInstance, ProviderImpl> { + self.ibc_mock_module.as_ref().expect("no mock module set") + } +} + +pub async fn deploy_yui_ibc_and_mock_client_fixture() -> DeployYuiIbcMockClient { + let path = utils::yui_ibc_solidity_path(); + let project_output = utils::compile_yui(&path, "contracts/core"); + let diamond_project_output = utils::compile_yui(&path, "contracts/diamond"); + let (anvil, client) = utils::spawn_anvil(); + log::warn!("{}", anvil.endpoint()); + let yui_ibc = + utils::deploy_yui_ibc(&project_output, &diamond_project_output, client.clone()).await; + + let ibc_mock_client = utils::compile_solc({ + let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + + ProjectPathsConfig::builder() + .root(manifest_dir.join("tests/contracts")) + .sources(manifest_dir.join("tests/contracts/clients")) + .build() + .unwrap() + }); + + let ibc_mock_client = utils::deploy_contract( + ibc_mock_client.find_first("MockClient").unwrap(), + (Token::Address(yui_ibc.diamond.address()),), + client.clone(), + ) + .await; + + println!("Mock client address: {:?}", ibc_mock_client.address()); + + // todo: some interactions between the mock client and the ibc handler to verify behaviour. + + DeployYuiIbcMockClient { + path, + project_output, + anvil, + client, + yui_ibc, + ibc_mock_client, + ibc_mock_module: None, + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +struct ClientId(pub String); + +impl Deref for ClientId { + type Target = String; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl ClientId { + pub async fn open_connection(&self, deploy: &DeployYuiIbcMockClient) -> String { + let connection_id = deploy.yui_ibc.connection_open_init_mock(&self.0).await; + let () = deploy + .yui_ibc + .connection_open_ack_mock(&connection_id, utils::mock::client_state_bytes()) + .await; + connection_id + } +} + +async fn deploy_mock_client_fixture(deploy: &DeployYuiIbcMockClient) -> ClientId { + deploy + .yui_ibc + .register_client("mock-client", deploy.ibc_mock_client.address()) + .await; + + let string = deploy + .yui_ibc + .create_client(utils::mock::create_client_msg("mock-client")) + .await; + println!("client id: {}", string); + println!("Diamond contract addr: {:?}", deploy.yui_ibc.diamond.address()); + ClientId(string) +} + +#[track_caller] +fn deploy_mock_module_fixture( + deploy: &DeployYuiIbcMockClient, +) -> impl Future, ProviderImpl>> + '_ { + async move { + let clients = utils::compile_solc({ + let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + + ProjectPathsConfig::builder() + .root(manifest_dir.join("tests/contracts")) + .sources(manifest_dir.join("tests/contracts/clients")) + .build() + .unwrap() + }); + + let contract = clients.find_first("MockModule").expect("no MockModule in project output"); + let constructor_args = (Token::Address(deploy.yui_ibc.diamond.address()),); + let contract = + utils::deploy_contract(contract, constructor_args, deploy.client.clone()).await; + println!("Mock module address: {:?}", contract.address()); + contract + } +} + +#[tokio::test] +async fn test_deploy_yui_ibc_and_mock_client() { + deploy_yui_ibc_and_mock_client_fixture().await; +} + +#[tokio::test] +async fn test_hyperspace_ethereum_client() { + let DeployYuiIbcMockClient { anvil, yui_ibc, .. } = + deploy_yui_ibc_and_mock_client_fixture().await; + let _hyperspace = hyperspace_ethereum_client_fixture(&anvil, yui_ibc.clone()).await; +} + +#[tokio::test] +async fn test_ibc_client() { + let deploy = deploy_yui_ibc_and_mock_client_fixture().await; + let hyperspace = + hyperspace_ethereum_client_fixture(&deploy.anvil, deploy.yui_ibc.clone()).await; + let events = hyperspace.ibc_events().await; + let client_id = deploy_mock_client_fixture(&deploy).await; + let height = hyperspace.latest_height_and_timestamp().await.unwrap().0; + let r = hyperspace.query_client_state(height, client_id.parse().unwrap()).await.unwrap(); + + assert_eq!( + r.client_state, + Some(ibc_proto::google::protobuf::Any { + type_url: "/ibc.lightclients.mock.v1.ClientState".into(), + value: utils::mock::ClientState { + height: ibc_proto::ibc::core::client::v1::Height { + revision_number: 0, + revision_height: 1, + }, + } + .encode_to_vec(), + }) + ); + + let r = hyperspace + .query_client_consensus( + height, + client_id.parse().unwrap(), + ibc::Height { revision_number: 0, revision_height: 1 }, + ) + .await + .unwrap(); + + assert_eq!( + r.consensus_state, + Some(ibc_proto::google::protobuf::Any { + type_url: "/ibc.lightclients.mock.v1.ConsensusState".into(), + value: utils::mock::ConsensusState { timestamp: 1 }.encode_to_vec(), + }) + ); + + let (_host_height, _host_timestamp) = hyperspace + .query_client_update_time_and_height( + client_id.parse().unwrap(), + ibc::Height { revision_number: 0, revision_height: 1 }, + ) + .await + .unwrap(); + + let events = timeout(Duration::from_secs(5), events.take(1).collect::>()) + .await + .unwrap(); + dbg!(events); +} + +#[tokio::test] +async fn test_ibc_connection() { + let stdout_log = tracing_subscriber::fmt::layer().pretty(); + tracing_subscriber::registry() + .with(stdout_log.with_filter(filter::LevelFilter::INFO).with_filter(filter::filter_fn( + |metadata| metadata.file().map(|x| x.contains("ethers")).unwrap_or_default(), + ))) + .init(); + let deploy = deploy_yui_ibc_and_mock_client_fixture().await; + let hyperspace = + hyperspace_ethereum_client_fixture(&deploy.anvil, deploy.yui_ibc.clone()).await; + let client_id = deploy_mock_client_fixture(&deploy).await; + + let connection_id = deploy.yui_ibc.connection_open_init_mock(&client_id).await; + let () = deploy + .yui_ibc + .connection_open_ack_mock(&connection_id, utils::mock::client_state_bytes()) + .await; + let height = hyperspace.latest_height_and_timestamp().await.unwrap().0; + + // hyperspace.query_connection_end(at, connection_id) + let connection_end = hyperspace + .query_connection_end(dbg!(height), connection_id.parse().unwrap()) + .await + .unwrap(); + + assert_eq!( + connection_end.connection, + Some(ibc_proto::ibc::core::connection::v1::ConnectionEnd { + client_id: client_id.parse().unwrap(), + counterparty: Some(ibc_proto::ibc::core::connection::v1::Counterparty { + client_id: client_id.parse().unwrap(), + connection_id: "counterparty-connection-id".parse().unwrap(), + prefix: None, + }), + state: ibc_proto::ibc::core::connection::v1::State::Open as i32, + delay_period: 0, + versions: vec![ibc_proto::ibc::core::connection::v1::Version { + identifier: "counterparty-version".into(), + features: vec!["ORDER_ORDERED".to_string(), "ORDER_UNORDERED".to_string()], + }], + }) + ); +} + +#[tokio::test] +async fn test_ibc_channel() { + let deploy = deploy_yui_ibc_and_mock_client_fixture().await; + let hyperspace = + hyperspace_ethereum_client_fixture(&deploy.anvil, deploy.yui_ibc.clone()).await; + let client_id = deploy_mock_client_fixture(&deploy).await; + + let mock_module = deploy_mock_module_fixture(&deploy).await; + deploy.yui_ibc.bind_port("port-0", mock_module.address()).await; + + let connection_id = client_id.open_connection(&deploy).await; + let channel_id = deploy.yui_ibc.channel_open_init("port-0", &connection_id).await; + deploy.yui_ibc.channel_open_ack(&channel_id, "port-0").await; + + let channels = hyperspace.query_channels().await.unwrap(); + assert!(!channels.is_empty()); + assert_eq!(channels[0].0, channel_id.parse().unwrap()); + + let height = hyperspace.latest_height_and_timestamp().await.unwrap().0; + + let channel_end = hyperspace + .query_channel_end(height, channel_id.parse().unwrap(), "port-0".parse().unwrap()) + .await + .unwrap(); + + let expected_channel = ibc_proto::ibc::core::channel::v1::Channel { + state: ibc_proto::ibc::core::channel::v1::State::Open as i32, + ordering: ibc_proto::ibc::core::channel::v1::Order::Unordered as i32, + counterparty: Some(ibc_proto::ibc::core::channel::v1::Counterparty { + port_id: "port-0".into(), + channel_id: channel_id.parse().unwrap(), + }), + connection_hops: vec![connection_id.parse().unwrap()], + version: "1".into(), + }; + assert_eq!(channel_end.channel, Some(expected_channel.clone())); + + // TODO: only used in integration tests. Should we really test that? + // let channels = hyperspace + // .query_connection_channels(height, &connection_id.parse().unwrap()) + // .await + // .unwrap(); + // assert_eq!( + // channels, + // vec![ibc_proto::ibc::core::channel::v1::IdentifiedChannel { + // state: expected_channel.state, + // ordering: expected_channel.ordering, + // counterparty: expected_channel.counterparty, + // connection_hops: expected_channel.connection_hops, + // version: expected_channel.version, + // port_id: "port-0".into(), + // channel_id, + // }] + // ); +} + +#[tokio::test] +async fn test_ibc_packet() { + let _ = env_logger::try_init(); + let mut deploy = deploy_yui_ibc_and_mock_client_fixture().await; + let hyperspace = + hyperspace_ethereum_client_fixture(&deploy.anvil, deploy.yui_ibc.clone()).await; + let events = hyperspace.ibc_events().await; + + let client_id = deploy_mock_client_fixture(&deploy).await; + + let mock_module = deploy_mock_module_fixture(&deploy).await; + deploy.yui_ibc.bind_port("port-0", mock_module.address()).await; + deploy.ibc_mock_module = Some(mock_module); + + let connection_id = client_id.open_connection(&deploy).await; + let channel_id = deploy.yui_ibc.channel_open_init("port-0", &connection_id).await; + deploy.yui_ibc.channel_open_ack(&channel_id, "port-0").await; + + let data = "hello_send".as_bytes().to_vec(); + let tx = deploy + .send_mock_packet( + PortId::from_str("port-0").unwrap(), + ChannelId::from_str("channel-0").unwrap(), + Height::new(0, 1000000), + data.clone(), + ) + .await; + let height = tx.block_number.unwrap().as_u64(); + + tx.logs.iter().for_each(|log| { + println!("send_packet log: {:#?}", log); + }); + + let send_packet = hyperspace + .query_send_packets( + ibc::Height { revision_number: 0, revision_height: height }, + ChannelId::from_str("channel-0").unwrap(), + PortId::from_str("port-0").unwrap(), + vec![1], + ) + .await + .unwrap() + .pop() + .unwrap(); + + let info = PacketInfo { + height: None, + sequence: 1, + source_port: "port-0".to_string(), + source_channel: "channel-0".to_string(), + destination_port: "port-0".to_string(), + destination_channel: "channel-0".to_string(), + channel_order: Order::Unordered.to_string(), + data: "hello_send".as_bytes().to_vec(), + timeout_height: Height::new(0, 1000000).into(), + timeout_timestamp: 0, + ack: None, + }; + assert_eq!(send_packet, info); + + // query_packet_commitment + let commitment = hyperspace + .query_packet_commitment( + ibc::Height { revision_number: 0, revision_height: height }, + &PortId::from_str("port-0").unwrap(), + &ChannelId::from_str("channel-0").unwrap(), + 1, + ) + .await + .unwrap(); + + assert_eq!( + commitment.commitment, + keccak256(&Sha256::digest( + &encode_packed(&[ + u64_to_token(0), + u64_to_token(0), + u64_to_token(1000000), + Token::Bytes(Sha256::digest(&data).to_vec()) + ]) + .unwrap() + )) + .to_vec() + ); + + // query_packet_commitments + let commitments = hyperspace + .query_packet_commitments( + ibc::Height { revision_number: 0, revision_height: height }, + ChannelId::from_str("channel-0").unwrap(), + PortId::from_str("port-0").unwrap(), + ) + .await + .unwrap(); + + assert_eq!(commitments, vec![1]); + + let sequence = Sequence(0); + let data = "hello_recv".as_bytes().to_vec(); + let ack_hash = keccak256(&Sha256::digest(&data)); + let tx = deploy + .yui_ibc + .recv_packet(Packet { + sequence, + source_port: PortId::from_str("port-0").unwrap(), + source_channel: ChannelId::from_str("channel-0").unwrap(), + destination_port: PortId::from_str("port-0").unwrap(), + destination_channel: ChannelId::from_str("channel-0").unwrap(), + data, + timeout_height: Height::new(0, 1000000), + timeout_timestamp: Timestamp::default(), + }) + .await; + let height = tx.block_number.unwrap().as_u64(); + + let ack = hyperspace + .query_packet_acknowledgement( + ibc::Height { revision_number: 0, revision_height: height }, + &PortId::from_str("port-0").unwrap(), + &ChannelId::from_str("channel-0").unwrap(), + sequence.0, // sequence + ) + .await + .unwrap(); + + println!("{}", hex::encode(&ack.acknowledgement)); + assert_eq!(ack.acknowledgement, ack_hash.to_vec()); + + let received_packets = hyperspace + .query_received_packets( + ibc::Height { revision_number: 0, revision_height: height }, + ChannelId::from_str("channel-0").unwrap(), + PortId::from_str("port-0").unwrap(), + vec![sequence.0], + ) + .await + .unwrap(); + assert_eq!( + received_packets, + vec![PacketInfo { + height: None, + sequence: sequence.0, + source_port: "port-0".to_string(), + source_channel: "channel-0".to_string(), + destination_port: "port-0".to_string(), + destination_channel: "channel-0".to_string(), + channel_order: Order::Unordered.to_string(), + data: "hello_recv".as_bytes().to_vec(), + timeout_height: Height::new(0, 1000000).into(), + timeout_timestamp: 0, + ack: None, + }] + ); + + // TODO: query_packet_receipt + let receipt = hyperspace + .query_packet_receipt( + ibc::Height { revision_number: 0, revision_height: height }, + &PortId::from_str("port-0").unwrap(), + &ChannelId::from_str("channel-0").unwrap(), + 0, // sequence + ) + .await + .unwrap(); + assert!(receipt.received); + + // query_packet_acknowledgements + let acks = hyperspace + .query_packet_acknowledgements( + ibc::Height { revision_number: 0, revision_height: height }, + ChannelId::from_str("channel-0").unwrap(), + PortId::from_str("port-0").unwrap(), + ) + .await + .unwrap(); + + assert_eq!(acks, vec![0]); + + // query_unreceived_packets + let unreceived = hyperspace + .query_unreceived_packets( + ibc::Height { revision_number: 0, revision_height: height }, + ChannelId::from_str("channel-0").unwrap(), + PortId::from_str("port-0").unwrap(), + vec![0, 1, 2], + ) + .await + .unwrap(); + assert_eq!(unreceived, vec![1, 2]); + + // query_unreceived_acknowledgements + let unreceived = hyperspace + .query_unreceived_acknowledgements( + ibc::Height { revision_number: 0, revision_height: height }, + ChannelId::from_str("channel-0").unwrap(), + PortId::from_str("port-0").unwrap(), + vec![0, 1, 2], + ) + .await + .unwrap(); + assert_eq!(unreceived, vec![1, 2]); + + let events = events.collect::>().await; + dbg!(events); +} + +fn u64_to_token(x: u64) -> Token { + let n = U256::from(x); + let mut buf = [0; 32]; + n.to_big_endian(&mut buf); + let start = (32 - u64::BITS / 8) as usize; + Token::Bytes(buf[start..32].to_vec()) +} diff --git a/hyperspace/ethereum/src/mock/utils.rs b/hyperspace/ethereum/src/mock/utils.rs new file mode 100644 index 000000000..38ea53352 --- /dev/null +++ b/hyperspace/ethereum/src/mock/utils.rs @@ -0,0 +1,389 @@ +#![allow(dead_code)] + +use cast::hashbrown::HashSet; +use std::{ + collections::HashMap, + fs::File, + iter::once, + path::{Path, PathBuf}, + sync::Arc, + time::Duration, +}; + +use crate::{ + contract::UnwrapContractError, + utils::{DeployYuiIbc, FacetCut, FacetCutAction}, +}; +use ethers::{ + abi::{Detokenize, Token, Tokenize}, + contract::ContractFactory, + core::{rand::rngs::ThreadRng, utils::Anvil}, + middleware::SignerMiddleware, + prelude::{ContractInstance, *}, + providers::{Http, Middleware, Provider}, + signers::{LocalWallet, Signer}, + utils::AnvilInstance, +}; +use ethers_solc::{ + artifacts::{ + output_selection::OutputSelection, DebuggingSettings, Libraries, Optimizer, + OptimizerDetails, RevertStrings, Settings, SettingsMetadata, StorageLayout, + }, + Artifact, ConfigurableContractArtifact, EvmVersion, Project, ProjectCompileOutput, + ProjectPathsConfig, SolcConfig, +}; +use futures::SinkExt; +use ibc::{ + core::{ + ics04_channel::packet::Packet, + ics24_host::identifier::{ChannelId, PortId}, + }, + timestamp::Timestamp, + Height, +}; +use tracing::log; + +pub const USE_GETH: bool = true; + +#[track_caller] +pub fn yui_ibc_solidity_path() -> PathBuf { + let base = env!("CARGO_MANIFEST_DIR"); + let default = PathBuf::from(base).join("yui-ibc-solidity"); + + if let Ok(path) = std::env::var("YUI_IBC_SOLIDITY_PATH") { + path.into() + } else { + default + } +} + +#[track_caller] +pub fn spawn_anvil() -> (AnvilInstance, Arc, LocalWallet>>) { + let anvil = Anvil::new().spawn(); + println!("{:?}", std::env::current_dir().unwrap()); + let wallet: LocalWallet = if USE_GETH { + LocalWallet::decrypt_keystore( + "keys/0x73db010c3275eb7a92e5c38770316248f4c644ee", + option_env!("KEY_PASS").expect("KEY_PASS not set"), + ) + .unwrap() + .into() + } else { + anvil.keys()[0].clone().into() + }; + + let endpoint = if USE_GETH { "http://localhost:6001".to_string() } else { anvil.endpoint() }; + let provider = Provider::::try_from(endpoint) + .unwrap() + .interval(Duration::from_millis(10u64)); + let chain_id = if USE_GETH { 4242u64 } else { anvil.chain_id() }; + let client = SignerMiddleware::new(provider, wallet.with_chain_id(chain_id)); + let client = Arc::new(client); + + (anvil, client) +} + +#[track_caller] +pub fn compile_solc(project_paths: ProjectPathsConfig) -> ProjectCompileOutput { + // custom solc config to solve Yul-relatated compilation errors + let mut selection = OutputSelection::default_output_selection(); + // selection + // .0 + // .get_mut("*") + // .unwrap() + // .get_mut("*") + // .unwrap() + // .push("storageLayout".to_string()); + let solc_config = SolcConfig { + settings: Settings { + stop_after: None, + remappings: vec![], + optimizer: Optimizer { + enabled: Some(true), + runs: Some(5), + details: Some(OptimizerDetails { + peephole: Some(true), + inliner: Some(true), + jumpdest_remover: Some(true), + order_literals: Some(true), + deduplicate: Some(true), + cse: Some(true), + constant_optimizer: Some(true), + yul: Some(false), + yul_details: None, + }), + }, + model_checker: None, + metadata: None, + output_selection: selection, + evm_version: Some(EvmVersion::Paris), + via_ir: Some(false), + // debug: Some(DebuggingSettings { + // revert_strings: Some(RevertStrings::Debug), + // debug_info: vec!["location".to_string()], + // }), + debug: None, + libraries: Libraries { libs: Default::default() }, + }, + }; + + let mut project = Project::builder() + .paths(project_paths) + .ephemeral() + .no_artifacts() + .solc_config(solc_config) + .build() + .expect("project build failed"); + + // TODO: figure out how to enable it in the config + // project.artifacts.additional_values.storage_layout = true; + // project.artifacts.additional_files.abi = true; + // project.solc.args.push("--storage-layout".to_string()); + + let project_output = project.compile().expect("compilation failed"); + + if project_output.has_compiler_errors() { + for err in project_output.output().errors { + eprintln!("error: {}", err); + } + panic!("compiler errors"); + } + + return project_output +} + +/// Uses solc to compile the yui-ibc-solidity contracts. +/// +/// first argument is the path to the yui-ibc-solidity repo. +/// the second argument is the path to the solidity sources, relative to the first argument. +/// +/// so if you have the yui-ibc-solidity as the path to yui then sources should be "contracts/core" +/// for IBCHandler or "contracts/clients" for the clients. +#[track_caller] +pub fn compile_yui(path_to_yui: &Path, sources: &str) -> ProjectCompileOutput { + assert!( + path_to_yui.exists(), + "path to yui-ibc-solidity does not exist: {}", + path_to_yui.display() + ); + + let project_paths = ProjectPathsConfig::builder() + .root(&path_to_yui) + .sources(path_to_yui.join(sources)) + .build() + .unwrap(); + + compile_solc(project_paths) +} + +#[allow(dead_code)] +pub async fn deploy_contract( + contract: &ConfigurableContractArtifact, + constructor_args: T, + client: Arc, +) -> ContractInstance, M> +where + M: Middleware, + T: abi::Tokenize, +{ + let (abi, bytecode, _) = contract.clone().into_parts(); + let mut factory = ContractFactory::new(abi.unwrap(), bytecode.unwrap(), client.clone()); + factory.deploy(constructor_args).unwrap().send().await.unwrap() +} + +pub mod mock { + use ethers::abi::Token; + use prost::Message; + + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct ClientState { + #[prost(message, required, tag = "1")] + pub height: ibc_proto::ibc::core::client::v1::Height, + } + + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct ConsensusState { + #[prost(uint64, tag = "1")] + pub timestamp: u64, + } + + pub fn create_client_msg(kind: &str) -> Token { + let client_state_bytes = client_state_bytes(); + + let consensus_state_bytes = ibc_proto::google::protobuf::Any { + type_url: "/ibc.lightclients.mock.v1.ConsensusState".into(), + value: ConsensusState { timestamp: 1 }.encode_to_vec(), + } + .encode_to_vec(); + + Token::Tuple(vec![ + Token::String(kind.into()), + Token::Bytes(client_state_bytes), + Token::Bytes(consensus_state_bytes), + ]) + } + + pub fn client_state_bytes() -> Vec { + ibc_proto::google::protobuf::Any { + type_url: "/ibc.lightclients.mock.v1.ClientState".into(), + value: ClientState { + height: ibc_proto::ibc::core::client::v1::Height { + revision_number: 0, + revision_height: 1, + }, + } + .encode_to_vec(), + } + .encode_to_vec() + } +} + +fn get_selectors(contract: &ContractInstance, M>) -> Vec<(String, [u8; 4])> +where + M: Middleware, +{ + let signatures = contract.abi().functions.keys().cloned().collect::>(); + signatures + .into_iter() + .filter(|val| val != "init(bytes)") + .map(|val| (val.clone(), contract.abi().function(&val).unwrap().short_signature())) + .collect() +} + +pub async fn deploy_yui_ibc( + project_output: &ProjectCompileOutput, + diamond_project_output: &ProjectCompileOutput, + client: Arc, +) -> DeployYuiIbc, M> +where + M: Middleware, +{ + let facet_names = [ + "IBCClient", + "IBCConnection", + "IBCChannelHandshake", + "IBCPacket", + "IBCQuerier", + "DiamondCutFacet", + "DiamondLoupeFacet", + "OwnershipFacet", + ]; + + project_output.artifacts().for_each(|(name, artifact)| { + let size = artifact.bytecode.as_ref().unwrap().object.as_bytes().unwrap().len(); + let max = 24 * 1024; + if size > max { + panic!("{} size is too big: {}/{}", name, size, max); + } + log::info!("{} size: {}/{}", name, size, max); + }); + diamond_project_output.artifacts().for_each(|(name, artifact)| { + let size = artifact.bytecode.as_ref().unwrap().object.as_bytes().unwrap().len(); + let max = 24 * 1024; + if size > max { + panic!("{} size is too big: {}/{}", name, size, max); + } + log::info!("{} size: {}/{}", name, size, max); + }); + + let acc = client.default_sender().unwrap(); + + println!("Sender account: {acc:?}"); + + let contract = diamond_project_output.find_first("DiamondInit").unwrap(); + let (abi, bytecode, _) = contract.clone().into_parts(); + let factory = ContractFactory::new(abi.unwrap(), bytecode.unwrap(), client.clone()); + let diamond_init = factory.deploy(()).unwrap().send().await.unwrap(); + println!("Diamond init address: {:?}", diamond_init.address()); + + let mut sigs = HashMap::<[u8; 4], (String, String)>::new(); + let mut facet_cuts = vec![]; + let mut deployed_facets = vec![]; + for facet_name in facet_names { + let contract = project_output + .find_first(facet_name) + .or_else(|| diamond_project_output.find_first(facet_name)) + .unwrap(); + let (abi, bytecode, _) = contract.clone().into_parts(); + let factory = ContractFactory::new(abi.unwrap(), bytecode.unwrap(), client.clone()); + let facet = factory.deploy(()).unwrap().send().await.unwrap(); + let facet_address = facet.address(); + println!("Deployed {facet_name} on {facet_address:?}"); + deployed_facets.push(facet.clone()); + let selectors = get_selectors(&facet); + + for (name, selector) in &selectors { + if sigs.contains_key(selector) { + let (contract_name, fn_name) = &sigs[selector]; + panic!( + "duplicate selector: {}:{} and {}:{}", + contract_name, fn_name, facet_name, name + ); + } + sigs.insert(*selector, (facet_name.to_owned(), name.clone())); + } + + let facet_cut = FacetCut { address: facet_address, action: FacetCutAction::Add, selectors }; + facet_cuts.push(facet_cut); + } + let init_calldata = diamond_init.method::<_, ()>("init", ()).unwrap().calldata().unwrap(); + + let contract = diamond_project_output.find_first("Diamond").unwrap(); + let (abi, bytecode, _) = contract.clone().into_parts(); + let factory = ContractFactory::new(abi.unwrap(), bytecode.unwrap(), client.clone()); + let diamond = factory + .deploy(Token::Tuple(vec![ + Token::Array(facet_cuts.clone().into_iter().map(|x| x.into_token()).collect()), + Token::Tuple(vec![ + Token::Address(acc), + Token::Address(diamond_init.address()), + Token::Bytes(init_calldata.0.into()), + ]), + ])) + .unwrap() + .send() + .await + .unwrap(); + + // std::fs::ReadDir::new(). + let predefined_layout = serde_json::from_reader::<_, StorageLayout>( + File::open("/Users/vmark/work/centauri-private/hyperspace/ethereum/src/storage_layout/ibc_storage.json").unwrap(), + ) + .expect("failed to read predefined storage layout"); + + let storage_layout = project_output + .compiled_artifacts() + .iter() + .chain(diamond_project_output.compiled_artifacts()) + .flat_map(|(_, artifact)| { + artifact.into_iter().flat_map(|(an, artifact)| { + println!("artifact name {an}"); + artifact + }) + }) + .filter_map(|ar| ar.artifact.storage_layout.clone()) + .chain(once(predefined_layout)) + .fold(StorageLayout { storage: vec![], types: Default::default() }, |mut acc, layout| { + // let mut len0 = acc.storage.len(); + // let mut len1 = layout.storage.len(); + acc.storage.extend(layout.storage); + // assert_eq!(acc.storage.len(), len0 + len1, "duplicated storage"); + + let len0 = acc.types.len(); + let len1 = layout.types.len(); + acc.types.extend(layout.types); + assert_eq!(acc.types.len(), len0 + len1, "duplicated type"); + acc + }); + + // dbg!(&storage_layout); + let tendermint_client = diamond.clone(); + + DeployYuiIbc { + diamond, + facet_cuts, + deployed_facets, + storage_layout, + tendermint: tendermint_client, + } +} From 6fdf52aa8d624df2d9141a7e4a54f985d78b417c Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Tue, 5 Sep 2023 19:31:32 -0300 Subject: [PATCH 13/43] restructure modules --- Cargo.lock | 36 - Cargo.toml | 1 - hyperspace/cosmos/src/provider.rs | 1 - hyperspace/ethereum/composable-centauri | 1 - .../ethereum/integration-tests/Cargo.toml | 49 - .../ethereum/integration-tests/src/main.rs | 96 -- .../ethereum/integration-tests/src/utils.rs | 589 -------- .../ethereum/src/abi/ibc-channel-abi.json | 490 ++++++ .../ethereum/src/abi/ibc-client-abi.json | 182 +++ .../ethereum/src/abi/ibc-connection-abi.json | 531 +++++++ hyperspace/ethereum/src/abi/ibc-host-abi.json | 1334 +++++++++++++++++ .../ethereum/src/abi/ibc-packet-abi.json | 571 +++++++ hyperspace/ethereum/src/bin/launch-yui-ibc.rs | 3 +- hyperspace/ethereum/src/chain.rs | 105 +- hyperspace/ethereum/src/client.rs | 24 +- hyperspace/ethereum/src/config.rs | 4 - hyperspace/ethereum/src/contract.rs | 175 +-- hyperspace/ethereum/src/ibc_provider.rs | 12 +- hyperspace/ethereum/src/mock/mod.rs | 1 - hyperspace/ethereum/src/mock/sanity_checks.rs | 617 -------- hyperspace/ethereum/src/utils.rs | 127 +- hyperspace/ethereum/tests/sanity_checks.rs | 101 +- hyperspace/ethereum/tests/utils.rs | 386 ----- hyperspace/parachain/src/provider.rs | 1 - hyperspace/primitives/src/lib.rs | 1 - hyperspace/testsuite/tests/ethereum_cosmos.rs | 26 + 26 files changed, 3353 insertions(+), 2111 deletions(-) delete mode 160000 hyperspace/ethereum/composable-centauri delete mode 100644 hyperspace/ethereum/integration-tests/Cargo.toml delete mode 100644 hyperspace/ethereum/integration-tests/src/main.rs delete mode 100644 hyperspace/ethereum/integration-tests/src/utils.rs create mode 100644 hyperspace/ethereum/src/abi/ibc-channel-abi.json create mode 100644 hyperspace/ethereum/src/abi/ibc-client-abi.json create mode 100644 hyperspace/ethereum/src/abi/ibc-connection-abi.json create mode 100644 hyperspace/ethereum/src/abi/ibc-host-abi.json create mode 100644 hyperspace/ethereum/src/abi/ibc-packet-abi.json delete mode 100644 hyperspace/ethereum/src/mock/sanity_checks.rs delete mode 100644 hyperspace/ethereum/tests/utils.rs diff --git a/Cargo.lock b/Cargo.lock index 05ba36d7c..c4e75ed30 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4887,42 +4887,6 @@ dependencies = [ "tracing-subscriber 0.3.17", ] -[[package]] -name = "hyperspace-integration-tests" -version = "0.1.0" -dependencies = [ - "anyhow", - "async-stream", - "async-trait", - "cast", - "elliptic-curve 0.13.5", - "env_logger 0.10.0", - "ethers 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "ethers-solc 2.0.9", - "futures", - "git2", - "hex", - "http", - "hyperspace-core", - "hyperspace-cosmos", - "hyperspace-ethereum", - "hyperspace-primitives", - "ibc", - "ibc-primitives", - "ibc-proto", - "ibc-rpc", - "ics07-tendermint", - "pallet-ibc", - "prost 0.11.6", - "serde", - "serde_json", - "thiserror", - "tokio", - "toml 0.7.6", - "tracing", - "tracing-subscriber 0.3.17", -] - [[package]] name = "hyperspace-metrics" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 1fc80ae0d..fbe996abc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,7 +44,6 @@ members = [ "hyperspace/testsuite", # "hyperspace/metrics", "hyperspace/ethereum", - "hyperspace/ethereum/integration-tests", # utilities # "utils/subxt/codegen", diff --git a/hyperspace/cosmos/src/provider.rs b/hyperspace/cosmos/src/provider.rs index 04c456e5e..f0b5eef82 100644 --- a/hyperspace/cosmos/src/provider.rs +++ b/hyperspace/cosmos/src/provider.rs @@ -616,7 +616,6 @@ where self.channel_whitelist.lock().unwrap().clone() } - #[cfg(test)] async fn query_connection_channels( &self, _at: Height, diff --git a/hyperspace/ethereum/composable-centauri b/hyperspace/ethereum/composable-centauri deleted file mode 160000 index c1c3bb815..000000000 --- a/hyperspace/ethereum/composable-centauri +++ /dev/null @@ -1 +0,0 @@ -Subproject commit c1c3bb81598b4c9b01c75c20952723ac2129f3ca diff --git a/hyperspace/ethereum/integration-tests/Cargo.toml b/hyperspace/ethereum/integration-tests/Cargo.toml deleted file mode 100644 index 8f592a8c9..000000000 --- a/hyperspace/ethereum/integration-tests/Cargo.toml +++ /dev/null @@ -1,49 +0,0 @@ -[package] -name = "hyperspace-integration-tests" -version = "0.1.0" -edition = "2021" -authors = ["Composable Developers"] - -[[bin]] -name = "hyperspace-integration-tests" -path = "src/main.rs" - -[dependencies] -primitives = { path = "../../primitives", package = "hyperspace-primitives", features = [ - "testing", -] } - -# composable -ibc = { path = "../../../ibc/modules", features = [] } -ibc-primitives = { path = "../../../contracts/pallet-ibc/primitives" } -ibc-proto = { path = "../../../ibc/proto" } -ibc-rpc = { path = "../../../contracts/pallet-ibc/rpc" } -ics07-tendermint = { path = "../../../light-clients/ics07-tendermint" } -pallet-ibc = { path = "../../../contracts/pallet-ibc" } -hyperspace-cosmos = { path = "../../cosmos" } -hyperspace-ethereum = { path = "../../ethereum" } -hyperspace-core = { path = "../../core", features = ["testing"] } - -cast = { git = "https://github.com/foundry-rs/foundry", version = "0.2.0" } - -anyhow = "1.0.65" -async-stream = "0.3.5" -async-trait = "0.1.53" -elliptic-curve = { features = ["pem"], version = "0.13.5" } -ethers = { version = "2.0.2", features = ["ws"] } -ethers-solc = "2.0.8" -futures = "0.3.28" -hex = "0.4.3" -http = "0.2.9" -prost = "0.11" -serde = { version = "1.0.137", features = ["derive"] } -serde_json = "1.0.74" -thiserror = "1.0.31" -tokio = { version = "1.19.2", features = ["full"] } -tracing = "0.1.36" -tracing-subscriber = "0.3.17" -env_logger = "0.10.0" - -[dev-dependencies] -toml = "0.7.3" -git2 = "0.17.1" \ No newline at end of file diff --git a/hyperspace/ethereum/integration-tests/src/main.rs b/hyperspace/ethereum/integration-tests/src/main.rs deleted file mode 100644 index c0cecc8b5..000000000 --- a/hyperspace/ethereum/integration-tests/src/main.rs +++ /dev/null @@ -1,96 +0,0 @@ -mod utils; -use ethers::{prelude::ContractFactory, abi::Token}; -use ethers_solc::Artifact; -use futures::StreamExt; -use hyperspace_core::substrate::DefaultConfig; -use hyperspace_cosmos::client::{CosmosClientConfig, CosmosClient}; -use ibc::core::ics24_host::identifier::{ConnectionId, ChannelId, PortId}; -use primitives::{CommonClientConfig, Chain, IbcProvider}; -#[tokio::main] -async fn main() { - -} - -#[derive(Debug, Clone)] -pub struct Args { - pub chain_a: String, - pub chain_b: String, - pub relay_chain: String, - pub para_id: u32, - pub connection_prefix_a: String, - pub connection_prefix_b: String, - pub cosmos_grpc: String, - pub cosmos_ws: String, - pub wasm_path: String, -} - -impl Default for Args { - fn default() -> Self { - let relay = std::env::var("RELAY_HOST").unwrap_or_else(|_| "127.0.0.1".to_string()); - let para = std::env::var("PARA_HOST").unwrap_or_else(|_| "127.0.0.1".to_string()); - let cosmos = std::env::var("COSMOS_HOST").unwrap_or_else(|_| "127.0.0.1".to_string()); - let wasm_path = std::env::var("WASM_PATH").unwrap_or_else(|_| { - "../../target/wasm32-unknown-unknown/release/ics10_grandpa_cw.wasm".to_string() - }); - - Args { - chain_a: format!("ws://{para}:9188"), - chain_b: format!("http://{cosmos}:26657"), - relay_chain: format!("ws://{relay}:9944"), - para_id: 2000, - connection_prefix_a: "ibc/".to_string(), - connection_prefix_b: "ibc".to_string(), - cosmos_grpc: format!("http://{cosmos}:9090"), - cosmos_ws: format!("ws://{cosmos}:26657/websocket"), - wasm_path, - } - } -} - - -#[tokio::test] -async fn test_deploy_yui_ibc_and_create_eth_client() { - - let c = hyperspace_core::command::Cmd{ config_a: "../../config-a.toml".to_string(), config_b: "../../config-b.toml".to_string(), config_core: "../../config-core.toml".to_string(), port_id: None, delay_period: None, order: None, version: None, out_config_a: None, out_config_b: None }; - let config = c.parse_config().await.unwrap(); - let mut chain_a = config.chain_b.into_client().await.unwrap(); - let mut f = chain_a.finality_notifications().await.unwrap(); - let n = f.next().await.unwrap(); - - - - - let path = utils::yui_ibc_solidity_path(); - let project_output = utils::compile_yui(&path, "contracts/core"); - let project_output1 = utils::compile_yui(&path, "contracts/clients"); - - let (anvil, client) = utils::spawn_anvil(); - - let yui_ibc = utils::deploy_yui_ibc(&project_output, client.clone()).await; - - let mut hyperspace = utils::hyperspace_ethereum_client_fixture(&anvil, &yui_ibc, Some(client.clone())).await; - - let result = chain_a.query_latest_ibc_events(n, &mut hyperspace).await.unwrap(); - - let upd = project_output1.find_first("DelegateTendermintUpdate").unwrap(); - let (abi, bytecode, _) = upd.clone().into_parts(); - let factory = ContractFactory::new(abi.unwrap(), bytecode.unwrap(), client.clone()); - let update_client_delegate_contract = factory.deploy(()).unwrap().send().await.unwrap(); - - let contract = project_output1.find_first("TendermintLightClientSimple").unwrap(); - // dbg!(&contract); - let r = contract.clone(); - let (abi, bytecode, _) = r.into_parts(); - - let factory = ContractFactory::new(abi.unwrap(), bytecode.unwrap(), client.clone()); - let tendermint_light_client = factory.deploy( - (Token::Address(yui_ibc.ibc_handler.address()), Token::Address(update_client_delegate_contract.address())) - ).unwrap().send().await.unwrap(); - - //replace the tendermint client address in hyperspace config with a real one - hyperspace.config.tendermint_client_address = tendermint_light_client.address(); - - let result = hyperspace.submit(vec![]).await.unwrap(); - - //call submit to create a new client -} \ No newline at end of file diff --git a/hyperspace/ethereum/integration-tests/src/utils.rs b/hyperspace/ethereum/integration-tests/src/utils.rs deleted file mode 100644 index 33ec909d4..000000000 --- a/hyperspace/ethereum/integration-tests/src/utils.rs +++ /dev/null @@ -1,589 +0,0 @@ -#![allow(dead_code)] - -use std::{ - path::{Path, PathBuf}, - sync::Arc, - time::Duration, -}; - -use elliptic_curve::pkcs8::der::pem; -use ethers::{ - abi::Token, - contract::ContractFactory, - core::{rand::rngs::ThreadRng, utils::Anvil}, - middleware::SignerMiddleware, - prelude::{ContractInstance, *}, - providers::{Http, Middleware, Provider}, - signers::{LocalWallet, Signer}, - utils::AnvilInstance, -}; -use ethers_solc::{ - artifacts::{ - output_selection::OutputSelection, DebuggingSettings, Libraries, Optimizer, - OptimizerDetails, RevertStrings, Settings, SettingsMetadata, - }, - Artifact, ConfigurableContractArtifact, EvmVersion, Project, ProjectCompileOutput, - ProjectPathsConfig, SolcConfig, -}; -use hyperspace_ethereum::{client::EthRpcClient, config::Config, contract::UnwrapContractError}; -use ibc::{ - core::{ - ics04_channel::packet::Packet, - ics24_host::identifier::{ChannelId, PortId}, - }, - timestamp::Timestamp, - Height, -}; - -pub async fn hyperspace_ethereum_client_fixture( - anvil: ðers::utils::AnvilInstance, - DeployYuiIbc { - ibc_client, - ibc_connection, - ibc_channel_handshake, - ibc_packet, - ibc_handler, - tendermint_client, - }: &DeployYuiIbc, M>, - client: Option>, -) -> hyperspace_ethereum::client::EthereumClient { - let endpoint = if USE_GETH { "http://localhost:6001".to_string() } else { anvil.endpoint() }; - let wallet_path = if USE_GETH { - Some("keys/0x73db010c3275eb7a92e5c38770316248f4c644ee".to_string()) - } else { - None - }; - - dbg!("hyperspace_ethereum_client_fixture"); - dbg!(anvil.endpoint()); - dbg!(anvil.chain_id()); - dbg!("hyperspace_ethereum_client_fixture"); - - let wallet = if !USE_GETH { - Some( - anvil.keys()[0] - .clone() - .to_sec1_pem(pem::LineEnding::CR) - .unwrap() - .as_str() - .to_owned() - .to_string(), - ) - } else { - None - }; - - let mut ret = hyperspace_ethereum::client::EthereumClient::new(Config { - http_rpc_url: endpoint.parse().unwrap(), - ws_rpc_url: Default::default(), - ibc_handler_address: ibc_handler.address(), - ibc_packet_address: ibc_packet.address(), - ibc_client_address: ibc_client.address(), - ibc_connection_address: ibc_connection.address(), - ibc_channel_handshake_address: ibc_channel_handshake.address(), - // tendermint_client_address: tendermint_client.address(), - mnemonic: None, - max_block_weight: 1, - private_key: wallet, - private_key_path: wallet_path, - name: "mock-ethereum-client".into(), - client_id: None, - connection_id: None, - channel_whitelist: vec![], - commitment_prefix: "".into(), - }) - .await - .unwrap(); - if let Some(client) = client { - ret.http_rpc = client; - } - ret -} - -pub const USE_GETH: bool = false; - -#[track_caller] -pub fn yui_ibc_solidity_path() -> PathBuf { - let mut base = env!("CARGO_MANIFEST_DIR").to_string(); - base = base.replace("/integration-tests", ""); - let default = PathBuf::from(base).join("yui-ibc-solidity"); - - if let Ok(path) = std::env::var("YUI_IBC_SOLIDITY_PATH") { - path.into() - } else { - default - } -} - -#[track_caller] -pub fn spawn_anvil() -> (AnvilInstance, Arc, LocalWallet>>) { - let anvil = Anvil::new().spawn(); - let wallet: LocalWallet = if USE_GETH { - LocalWallet::decrypt_keystore( - "keys/0x73db010c3275eb7a92e5c38770316248f4c644ee", - option_env!("KEY_PASS").expect("KEY_PASS not set"), - ) - .unwrap() - .into() - } else { - anvil.keys()[0].clone().into() - }; - - let endpoint = if USE_GETH { "http://localhost:6001".to_string() } else { anvil.endpoint() }; - let provider = Provider::::try_from(endpoint) - .unwrap() - .interval(Duration::from_millis(10u64)); - let chain_id = if USE_GETH { 4242u64 } else { anvil.chain_id() }; - let client = SignerMiddleware::new(provider, wallet.with_chain_id(chain_id)); - let client = Arc::new(client); - - (anvil, client) -} - -#[track_caller] -pub fn compile_solc(project_paths: ProjectPathsConfig) -> ProjectCompileOutput { - // custom solc config to solve Yul-relatated compilation errors - let solc_config = SolcConfig { - settings: Settings { - stop_after: None, - remappings: vec![], - optimizer: Optimizer { - enabled: Some(false), - runs: Some(256), - details: Some(OptimizerDetails { - peephole: Some(true), - inliner: Some(true), - jumpdest_remover: Some(true), - order_literals: Some(true), - deduplicate: Some(true), - cse: Some(true), - constant_optimizer: Some(true), - yul: Some(false), - yul_details: None, - }), - }, - model_checker: None, - metadata: None, - output_selection: OutputSelection::default_output_selection(), - evm_version: Some(EvmVersion::Paris), - via_ir: Some(false), - debug: Some(DebuggingSettings { - revert_strings: Some(RevertStrings::Debug), - debug_info: vec!["location".to_string()], - }), - libraries: Libraries { libs: Default::default() }, - }, - }; - - let project = Project::builder() - .paths(project_paths) - .ephemeral() - .no_artifacts() - .solc_config(solc_config) - .build() - .expect("project build failed"); - - let project_output = project.compile().expect("compilation failed"); - - if project_output.has_compiler_errors() { - for err in project_output.output().errors { - eprintln!("{}", err); - } - panic!("compiler errors"); - } - - return project_output -} - -/// Uses solc to compile the yui-ibc-solidity contracts. -/// -/// first argument is the path to the yui-ibc-solidity repo. -/// the second argument is the path to the solidity sources, relative to the first argument. -/// -/// so if you have the yui-ibc-solidity as the path to yui then sources should be "contracts/core" -/// for IBCHandler or "contracts/clients" for the clients. -#[track_caller] -pub fn compile_yui(path_to_yui: &Path, sources: &str) -> ProjectCompileOutput { - assert!( - path_to_yui.exists(), - "path to yui-ibc-solidity does not exist: {}", - path_to_yui.display() - ); - - let project_paths = ProjectPathsConfig::builder() - .root(&path_to_yui) - .sources(path_to_yui.join(sources)) - .build() - .unwrap(); - - compile_solc(project_paths) -} - -#[allow(dead_code)] -pub async fn deploy_contract( - contract: &ConfigurableContractArtifact, - constructor_args: T, - client: Arc, -) -> ContractInstance, M> -where - M: Middleware, - T: abi::Tokenize, -{ - let (abi, bytecode, _) = contract.clone().into_parts(); - let mut factory = ContractFactory::new(abi.unwrap(), bytecode.unwrap(), client.clone()); - factory.deploy(constructor_args).unwrap().send().await.unwrap() -} - -pub mod mock { - use ethers::abi::Token; - use prost::Message; - - #[derive(Clone, PartialEq, ::prost::Message)] - pub struct ClientState { - #[prost(message, required, tag = "1")] - pub height: ibc_proto::ibc::core::client::v1::Height, - } - - #[derive(Clone, PartialEq, ::prost::Message)] - pub struct ConsensusState { - #[prost(uint64, tag = "1")] - pub timestamp: u64, - } - - pub fn create_client_msg(kind: &str) -> Token { - let client_state_bytes = client_state_bytes(); - - let consensus_state_bytes = ibc_proto::google::protobuf::Any { - type_url: "/ibc.lightclients.mock.v1.ConsensusState".into(), - value: ConsensusState { timestamp: 1 }.encode_to_vec(), - } - .encode_to_vec(); - - Token::Tuple(vec![ - Token::String(kind.into()), - Token::Bytes(client_state_bytes), - Token::Bytes(consensus_state_bytes), - ]) - } - - pub fn client_state_bytes() -> Vec { - ibc_proto::google::protobuf::Any { - type_url: "/ibc.lightclients.mock.v1.ClientState".into(), - value: ClientState { - height: ibc_proto::ibc::core::client::v1::Height { - revision_number: 0, - revision_height: 1, - }, - } - .encode_to_vec(), - } - .encode_to_vec() - } -} - -#[derive(Debug)] -pub struct DeployYuiIbc { - pub ibc_client: ContractInstance, - pub ibc_connection: ContractInstance, - pub ibc_channel_handshake: ContractInstance, - pub ibc_packet: ContractInstance, - pub ibc_handler: ContractInstance, - pub tendermint_client: ContractInstance, -} - -impl DeployYuiIbc -where - B: Clone + std::borrow::Borrow, - M: Middleware, -{ - pub async fn bind_port(&self, port_id: &str, address: Address) { - let bind_port = self - .ibc_handler - .method::<_, ()>("bindPort", (Token::String(port_id.into()), Token::Address(address))) - .unwrap(); - let () = bind_port.call().await.unwrap_contract_error(); - let tx_recp = bind_port.send().await.unwrap_contract_error().await.unwrap().unwrap(); - assert_eq!(tx_recp.status, Some(1.into())); - } - - pub async fn connection_open_init(&self, client_id: &str) -> String { - let connection_open_init = self - .ibc_handler - .method::<_, String>( - "connectionOpenInit", - (Token::Tuple(vec![ - Token::String(client_id.into()), - Token::Tuple(vec![ - Token::String(client_id.into()), - Token::String("port-0".into()), - Token::Tuple(vec![Token::Bytes(vec![])]), - ]), - Token::Uint(0.into()), - ]),), - ) - .unwrap(); - let connection_id = connection_open_init.call().await.unwrap_contract_error(); - let tx_recp = connection_open_init - .send() - .await - .unwrap_contract_error() - .await - .unwrap() - .unwrap(); - assert_eq!(tx_recp.status, Some(1.into())); - connection_id - } - - pub async fn connection_open_ack(&self, connection_id: &str, client_state_bytes: Vec) { - let connection_open_ack = self - .ibc_handler - .method::<_, ()>( - "connectionOpenAck", - (Token::Tuple(vec![ - Token::String(connection_id.to_string()), - Token::Bytes(client_state_bytes), // clientStateBytes - Token::Tuple(vec![ - Token::String("counterparty-version".into()), - Token::Array(vec![]), - ]), // Version.Data - Token::String("counterparty-connection-id".into()), // counterpartyConnectionID - Token::Bytes(vec![]), // proofTry - Token::Bytes(vec![]), // proofClient - Token::Bytes(vec![]), // proofConsensus - Token::Tuple(vec![Token::Uint(0.into()), Token::Uint(1.into())]), // proofHeight - Token::Tuple(vec![Token::Uint(0.into()), Token::Uint(1.into())]), // consesusHeight - ]),), - ) - .unwrap(); - - let () = connection_open_ack.call().await.unwrap_contract_error(); - let tx_recp = - connection_open_ack.send().await.unwrap_contract_error().await.unwrap().unwrap(); - assert_eq!(tx_recp.status, Some(1.into())); - } - - pub async fn channel_open_init(&self, port_id: &str, connection_id: &str) -> String { - let fut = self - .ibc_handler - .method::<_, String>( - "channelOpenInit", - (Token::Tuple(vec![ - Token::String(port_id.into()), - Token::Tuple(vec![ - // Channel.Data - Token::Uint(1.into()), // State, Init - Token::Uint(1.into()), // Ordering - Token::Tuple(vec![ - Token::String("port-0".into()), - Token::String("channel-0".into()), - ]), // counterparty - Token::Array(vec![Token::String(connection_id.into())]), // connectionHops - Token::String("1".into()), // version - ]), - ]),), - ) - .unwrap(); - - let channel_id = fut.call().await.unwrap_contract_error(); - let tx = fut.send().await.unwrap_contract_error().await.unwrap().unwrap(); - assert_eq!(tx.status, Some(1.into())); - channel_id - } - - pub async fn channel_open_ack(&self, channel_id: &str, port_id: &str) { - let fut = self - .ibc_handler - .method::<_, ()>( - "channelOpenAck", - (Token::Tuple(vec![ - Token::String(port_id.into()), // port-id - Token::String(channel_id.into()), // channel-id - Token::String("1".into()), // counterparty-version - Token::String("channel-0".into()), // counterparty-channel-id - Token::Bytes(vec![]), // proof-try - Token::Tuple(vec![ - // proof-height - Token::Uint(0.into()), - Token::Uint(1.into()), - ]), - ]),), - ) - .unwrap(); - - let () = fut.call().await.unwrap_contract_error(); - let tx = fut.send().await.unwrap_contract_error().await.unwrap().unwrap(); - assert_eq!(tx.status, Some(1.into())); - } - - pub async fn recv_packet(&self, packet: Packet) -> TransactionReceipt { - let fut = self - .ibc_handler - .method::<_, ()>( - "recvPacket", - (Token::Tuple(vec![ - Token::Tuple(vec![ - Token::Uint(packet.sequence.0.into()), // sequence - Token::String(packet.source_port.to_string()), // port-id - Token::String(packet.source_channel.to_string()), // channel-id - Token::String(packet.destination_port.to_string()), // port-id - Token::String(packet.destination_channel.to_string()), // channel-id - Token::Bytes(packet.data), // data - Token::Tuple(vec![ - // timeout-height - Token::Uint(packet.timeout_height.revision_number.into()), - Token::Uint(packet.timeout_height.revision_height.into()), - ]), - Token::Uint( - packet - .timeout_timestamp - .into_tm_time() - .map(|x| x.unix_timestamp_nanos() as u64) - .unwrap_or(0u64) - .into(), - ), /* timeout-timestamp */ - ]), - Token::Bytes(vec![]), /* proof */ - Token::Tuple(vec![ - // proof-height - Token::Uint(0.into()), - Token::Uint(1.into()), - ]), - ]),), - ) - .unwrap(); - - let () = fut.call().await.unwrap_contract_error(); - // let trace = self - // .ibc_handler - // .client() - // .borrow() - // .debug_trace_call(fut.tx.clone(), None, GethDebugTracingCallOptions::default()) - // .await - // .unwrap(); - // std::fs::write("trace.txt", format!("{:#?}", trace)).unwrap(); - // println!("trace: {:?}", trace); - let tx = fut.send().await.unwrap_contract_error().await.unwrap().unwrap(); - // dbg!(tx.logs); - let status = tx.status.expect("status not found"); - - if status == 0.into() { - panic!("status is 0"); - } - tx - } - - pub async fn register_client(&self, kind: &str, address: Address) { - let method = self - .ibc_handler - .method::<_, ()>( - "registerClient", - (Token::String(kind.into()), Token::Address(address)), - ) - .unwrap(); - - let _ = method.call().await.unwrap_contract_error(); - - let receipt = method.send().await.unwrap().await.unwrap().unwrap(); - assert_eq!(receipt.status, Some(1.into())); - } - - pub async fn create_client(&self, msg: Token) -> String { - let method = self.ibc_handler.method::<_, String>("createClient", (msg,)).unwrap(); - - let client_id = method.call().await.unwrap_contract_error(); - - let receipt = method.send().await.unwrap().await.unwrap().unwrap(); - assert_eq!(receipt.status, Some(1.into())); - - client_id - } -} - -impl Clone for DeployYuiIbc -where - B: Clone + std::borrow::Borrow, -{ - fn clone(&self) -> Self { - Self { - ibc_client: self.ibc_client.clone(), - ibc_connection: self.ibc_connection.clone(), - ibc_channel_handshake: self.ibc_channel_handshake.clone(), - ibc_packet: self.ibc_packet.clone(), - ibc_handler: self.ibc_handler.clone(), - // tendermint_client: self.tendermint_client.clone(), - } - } -} - -pub async fn deploy_yui_ibc( - project_output: &ProjectCompileOutput, - client: Arc, -) -> DeployYuiIbc, M> -where - M: Middleware, -{ - let contract = project_output.find_first("OwnableIBCHandler").unwrap(); - let (abi, bytecode, _) = contract.clone().into_parts(); - let handler_bytecode = bytecode.unwrap(); - let handler_abi = abi.unwrap(); - dbg!(&handler_bytecode.len() / 1); - - if handler_bytecode.len() > dbg!(24 * 1024) { - panic!("handler bytecode too large"); - } - - let contract = project_output.find_first("IBCClient").unwrap(); - let (abi, bytecode, _) = contract.clone().into_parts(); - let factory = ContractFactory::new(abi.unwrap(), bytecode.unwrap(), client.clone()); - let deployer1 = factory.deploy(()).unwrap(); - let acc = deployer1.client().default_sender().unwrap(); - dbg!(client.get_balance(acc, None).await.unwrap()); - let ibc_client = deployer1.send().await.unwrap(); - - let contract = project_output.find_first("IBCConnection").unwrap(); - let (abi, bytecode, _) = contract.clone().into_parts(); - let factory = ContractFactory::new(abi.unwrap(), bytecode.unwrap(), client.clone()); - let ibc_connection = factory.deploy(()).unwrap().send().await.unwrap(); - - let contract = project_output.find_first("IBCChannelHandshake").unwrap(); - let (abi, bytecode, _) = contract.clone().into_parts(); - let factory = ContractFactory::new(abi.unwrap(), bytecode.unwrap(), client.clone()); - let ibc_channel_handshake = factory.deploy(()).unwrap().send().await.unwrap(); - - let contract = project_output.find_first("IBCPacket").unwrap(); - let (abi, bytecode, _) = contract.clone().into_parts(); - let factory = ContractFactory::new(abi.unwrap(), bytecode.unwrap(), client.clone()); - let ibc_packet = factory.deploy(()).unwrap().send().await.unwrap(); - - //TODO deploy tendermint client as well - //TODO - let contract = project_output.find_first("IBCPacket").unwrap(); - let (abi, bytecode, _) = contract.clone().into_parts(); - let factory = ContractFactory::new(abi.unwrap(), bytecode.unwrap(), client.clone()); - let tendermint_client = factory.deploy(()).unwrap().send().await.unwrap(); - - let factory = ContractFactory::new(handler_abi, handler_bytecode, client.clone()); - let mut deployer = factory - .deploy(( - Token::Address(ibc_client.address()), - Token::Address(ibc_connection.address()), - Token::Address(ibc_channel_handshake.address()), - Token::Address(ibc_packet.address()), - )) - .unwrap(); - // let estimated_gas = client.estimate_gas(&deployer.tx, None).await.unwrap(); - // dbg!(estimated_gas); - dbg!(client.get_balance(acc, None).await.unwrap()); - let ibc_handler = deployer.clone().send().await.expect("failed to deploy OwnableIBCHandler"); - - println!("IBC Handler address: {:?}", ibc_handler.address()); - - DeployYuiIbc { - ibc_client, - ibc_connection, - ibc_channel_handshake, - ibc_packet, - ibc_handler, - tendermint_client, - } -} diff --git a/hyperspace/ethereum/src/abi/ibc-channel-abi.json b/hyperspace/ethereum/src/abi/ibc-channel-abi.json new file mode 100644 index 000000000..6b21f77b0 --- /dev/null +++ b/hyperspace/ethereum/src/abi/ibc-channel-abi.json @@ -0,0 +1,490 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "channelId", + "type": "string" + } + ], + "name": "CloseConfirmChannel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "channelId", + "type": "string" + } + ], + "name": "CloseInitChannel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "", + "type": "string" + } + ], + "name": "GeneratedChannelIdentifier", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "channelId", + "type": "string" + } + ], + "name": "OpenAckChannel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "channelId", + "type": "string" + } + ], + "name": "OpenConfirmChannel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "channelId", + "type": "string" + } + ], + "name": "OpenInitChannel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "channelId", + "type": "string" + } + ], + "name": "OpenTryChannel", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "internalType": "address", + "name": "moduleAddress", + "type": "address" + } + ], + "name": "bindPort", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "internalType": "string", + "name": "channelId", + "type": "string" + }, + { + "internalType": "bytes", + "name": "proofInit", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "revision_number", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "revision_height", + "type": "uint64" + } + ], + "internalType": "struct HeightData", + "name": "proofHeight", + "type": "tuple" + } + ], + "internalType": "struct IBCMsgsMsgChannelCloseConfirm", + "name": "msg_", + "type": "tuple" + } + ], + "name": "channelCloseConfirm", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "internalType": "string", + "name": "channelId", + "type": "string" + } + ], + "internalType": "struct IBCMsgsMsgChannelCloseInit", + "name": "msg_", + "type": "tuple" + } + ], + "name": "channelCloseInit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "internalType": "string", + "name": "channelId", + "type": "string" + }, + { + "internalType": "string", + "name": "counterpartyVersion", + "type": "string" + }, + { + "internalType": "string", + "name": "counterpartyChannelId", + "type": "string" + }, + { + "internalType": "bytes", + "name": "proofTry", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "revision_number", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "revision_height", + "type": "uint64" + } + ], + "internalType": "struct HeightData", + "name": "proofHeight", + "type": "tuple" + } + ], + "internalType": "struct IBCMsgsMsgChannelOpenAck", + "name": "msg_", + "type": "tuple" + } + ], + "name": "channelOpenAck", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "internalType": "string", + "name": "channelId", + "type": "string" + }, + { + "internalType": "bytes", + "name": "proofAck", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "revision_number", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "revision_height", + "type": "uint64" + } + ], + "internalType": "struct HeightData", + "name": "proofHeight", + "type": "tuple" + } + ], + "internalType": "struct IBCMsgsMsgChannelOpenConfirm", + "name": "msg_", + "type": "tuple" + } + ], + "name": "channelOpenConfirm", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "components": [ + { + "internalType": "enum ChannelState", + "name": "state", + "type": "uint8" + }, + { + "internalType": "enum ChannelOrder", + "name": "ordering", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "string", + "name": "port_id", + "type": "string" + }, + { + "internalType": "string", + "name": "channel_id", + "type": "string" + } + ], + "internalType": "struct ChannelCounterpartyData", + "name": "counterparty", + "type": "tuple" + }, + { + "internalType": "string[]", + "name": "connection_hops", + "type": "string[]" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + } + ], + "internalType": "struct ChannelData", + "name": "channel", + "type": "tuple" + } + ], + "internalType": "struct IBCMsgsMsgChannelOpenInit", + "name": "msg_", + "type": "tuple" + } + ], + "name": "channelOpenInit", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "components": [ + { + "internalType": "enum ChannelState", + "name": "state", + "type": "uint8" + }, + { + "internalType": "enum ChannelOrder", + "name": "ordering", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "string", + "name": "port_id", + "type": "string" + }, + { + "internalType": "string", + "name": "channel_id", + "type": "string" + } + ], + "internalType": "struct ChannelCounterpartyData", + "name": "counterparty", + "type": "tuple" + }, + { + "internalType": "string[]", + "name": "connection_hops", + "type": "string[]" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + } + ], + "internalType": "struct ChannelData", + "name": "channel", + "type": "tuple" + }, + { + "internalType": "string", + "name": "counterpartyVersion", + "type": "string" + }, + { + "internalType": "bytes", + "name": "proofInit", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "revision_number", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "revision_height", + "type": "uint64" + } + ], + "internalType": "struct HeightData", + "name": "proofHeight", + "type": "tuple" + } + ], + "internalType": "struct IBCMsgsMsgChannelOpenTry", + "name": "msg_", + "type": "tuple" + } + ], + "name": "channelOpenTry", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/hyperspace/ethereum/src/abi/ibc-client-abi.json b/hyperspace/ethereum/src/abi/ibc-client-abi.json new file mode 100644 index 000000000..c2bb7f4c5 --- /dev/null +++ b/hyperspace/ethereum/src/abi/ibc-client-abi.json @@ -0,0 +1,182 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "clientId", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "clientType", + "type": "string" + } + ], + "name": "CreateClient", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "", + "type": "string" + } + ], + "name": "GeneratedClientIdentifier", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "clientType", + "type": "string" + }, + { + "indexed": false, + "internalType": "address", + "name": "client", + "type": "address" + } + ], + "name": "RegisterClient", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "clientId", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "header", + "type": "bytes32" + } + ], + "name": "UpdateClient", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "clientId", + "type": "string" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "revision_number", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "revision_height", + "type": "uint64" + } + ], + "indexed": false, + "internalType": "struct HeightData", + "name": "client_height", + "type": "tuple" + } + ], + "name": "UpdateClientHeight", + "type": "event" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "string", + "name": "clientType", + "type": "string" + }, + { + "internalType": "bytes", + "name": "clientStateBytes", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "consensusStateBytes", + "type": "bytes" + } + ], + "internalType": "struct IBCMsgsMsgCreateClient", + "name": "msg_", + "type": "tuple" + } + ], + "name": "createClient", + "outputs": [ + { + "internalType": "string", + "name": "clientId", + "type": "string" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "clientType", + "type": "string" + }, + { + "internalType": "contract ILightClient", + "name": "client", + "type": "address" + } + ], + "name": "registerClient", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "string", + "name": "clientId", + "type": "string" + }, + { + "internalType": "bytes", + "name": "clientMessage", + "type": "bytes" + } + ], + "internalType": "struct IBCMsgsMsgUpdateClient", + "name": "msg_", + "type": "tuple" + } + ], + "name": "updateClient", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/hyperspace/ethereum/src/abi/ibc-connection-abi.json b/hyperspace/ethereum/src/abi/ibc-connection-abi.json new file mode 100644 index 000000000..70fa13023 --- /dev/null +++ b/hyperspace/ethereum/src/abi/ibc-connection-abi.json @@ -0,0 +1,531 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "", + "type": "string" + } + ], + "name": "GeneratedConnectionIdentifier", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "connectionId", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "counterpartyConnectionId", + "type": "string" + } + ], + "name": "OpenAckConnection", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "connectionId", + "type": "string" + } + ], + "name": "OpenConfirmConnection", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "connectionId", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "clientId", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "counterpartyConnectionId", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "counterpartyClientId", + "type": "string" + } + ], + "name": "OpenInitConnection", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "connectionId", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "clientId", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "counterpartyConnectionId", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "counterpartyClientId", + "type": "string" + } + ], + "name": "OpenTryConnection", + "type": "event" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "string", + "name": "client_id", + "type": "string" + }, + { + "components": [ + { + "internalType": "string", + "name": "identifier", + "type": "string" + }, + { + "internalType": "string[]", + "name": "features", + "type": "string[]" + } + ], + "internalType": "struct VersionData[]", + "name": "versions", + "type": "tuple[]" + }, + { + "internalType": "enum ConnectionEndState", + "name": "state", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "string", + "name": "client_id", + "type": "string" + }, + { + "internalType": "string", + "name": "connection_id", + "type": "string" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "key_prefix", + "type": "bytes" + } + ], + "internalType": "struct MerklePrefixData", + "name": "prefix", + "type": "tuple" + } + ], + "internalType": "struct CounterpartyData", + "name": "counterparty", + "type": "tuple" + }, + { + "internalType": "uint64", + "name": "delay_period", + "type": "uint64" + } + ], + "internalType": "struct ConnectionEndData", + "name": "a", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "revision_number", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "revision_height", + "type": "uint64" + } + ], + "internalType": "struct HeightData", + "name": "b", + "type": "tuple" + } + ], + "name": "_expose_data_types", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "string", + "name": "connectionId", + "type": "string" + }, + { + "internalType": "bytes", + "name": "clientStateBytes", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "string", + "name": "identifier", + "type": "string" + }, + { + "internalType": "string[]", + "name": "features", + "type": "string[]" + } + ], + "internalType": "struct VersionData", + "name": "version", + "type": "tuple" + }, + { + "internalType": "string", + "name": "counterpartyConnectionID", + "type": "string" + }, + { + "internalType": "bytes", + "name": "proofTry", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "proofClient", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "proofConsensus", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "revision_number", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "revision_height", + "type": "uint64" + } + ], + "internalType": "struct HeightData", + "name": "proofHeight", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "revision_number", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "revision_height", + "type": "uint64" + } + ], + "internalType": "struct HeightData", + "name": "consensusHeight", + "type": "tuple" + } + ], + "internalType": "struct IBCMsgsMsgConnectionOpenAck", + "name": "msg_", + "type": "tuple" + } + ], + "name": "connectionOpenAck", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "string", + "name": "connectionId", + "type": "string" + }, + { + "internalType": "bytes", + "name": "proofAck", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "revision_number", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "revision_height", + "type": "uint64" + } + ], + "internalType": "struct HeightData", + "name": "proofHeight", + "type": "tuple" + } + ], + "internalType": "struct IBCMsgsMsgConnectionOpenConfirm", + "name": "msg_", + "type": "tuple" + } + ], + "name": "connectionOpenConfirm", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "string", + "name": "clientId", + "type": "string" + }, + { + "components": [ + { + "internalType": "string", + "name": "client_id", + "type": "string" + }, + { + "internalType": "string", + "name": "connection_id", + "type": "string" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "key_prefix", + "type": "bytes" + } + ], + "internalType": "struct MerklePrefixData", + "name": "prefix", + "type": "tuple" + } + ], + "internalType": "struct CounterpartyData", + "name": "counterparty", + "type": "tuple" + }, + { + "internalType": "uint64", + "name": "delayPeriod", + "type": "uint64" + } + ], + "internalType": "struct IBCMsgsMsgConnectionOpenInit", + "name": "msg_", + "type": "tuple" + } + ], + "name": "connectionOpenInit", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "string", + "name": "client_id", + "type": "string" + }, + { + "internalType": "string", + "name": "connection_id", + "type": "string" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "key_prefix", + "type": "bytes" + } + ], + "internalType": "struct MerklePrefixData", + "name": "prefix", + "type": "tuple" + } + ], + "internalType": "struct CounterpartyData", + "name": "counterparty", + "type": "tuple" + }, + { + "internalType": "uint64", + "name": "delayPeriod", + "type": "uint64" + }, + { + "internalType": "string", + "name": "clientId", + "type": "string" + }, + { + "internalType": "bytes", + "name": "clientStateBytes", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "string", + "name": "identifier", + "type": "string" + }, + { + "internalType": "string[]", + "name": "features", + "type": "string[]" + } + ], + "internalType": "struct VersionData[]", + "name": "counterpartyVersions", + "type": "tuple[]" + }, + { + "internalType": "bytes", + "name": "proofInit", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "proofClient", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "proofConsensus", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "revision_number", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "revision_height", + "type": "uint64" + } + ], + "internalType": "struct HeightData", + "name": "proofHeight", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "revision_number", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "revision_height", + "type": "uint64" + } + ], + "internalType": "struct HeightData", + "name": "consensusHeight", + "type": "tuple" + } + ], + "internalType": "struct IBCMsgsMsgConnectionOpenTry", + "name": "msg_", + "type": "tuple" + } + ], + "name": "connectionOpenTry", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/hyperspace/ethereum/src/abi/ibc-host-abi.json b/hyperspace/ethereum/src/abi/ibc-host-abi.json new file mode 100644 index 000000000..c0541973d --- /dev/null +++ b/hyperspace/ethereum/src/abi/ibc-host-abi.json @@ -0,0 +1,1334 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "", + "type": "string" + } + ], + "name": "GeneratedChannelIdentifier", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "", + "type": "string" + } + ], + "name": "GeneratedClientIdentifier", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "", + "type": "string" + } + ], + "name": "GeneratedConnectionIdentifier", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + }, + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "authenticateCapability", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + }, + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "claimCapability", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "internalType": "string", + "name": "channelId", + "type": "string" + }, + { + "internalType": "uint64", + "name": "sequence", + "type": "uint64" + } + ], + "name": "deletePacketCommitment", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "generateChannelIdentifier", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "clientType", + "type": "string" + } + ], + "name": "generateClientIdentifier", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "generateConnectionIdentifier", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "internalType": "string", + "name": "channelId", + "type": "string" + } + ], + "name": "getChannel", + "outputs": [ + { + "components": [ + { + "internalType": "enum Channel.State", + "name": "state", + "type": "uint8" + }, + { + "internalType": "enum Channel.Order", + "name": "ordering", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "string", + "name": "port_id", + "type": "string" + }, + { + "internalType": "string", + "name": "channel_id", + "type": "string" + } + ], + "internalType": "struct ChannelCounterparty.Data", + "name": "counterparty", + "type": "tuple" + }, + { + "internalType": "string[]", + "name": "connection_hops", + "type": "string[]" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + } + ], + "internalType": "struct Channel.Data", + "name": "channel", + "type": "tuple" + }, + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "clientType", + "type": "string" + } + ], + "name": "getClientImpl", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "clientId", + "type": "string" + } + ], + "name": "getClientState", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + }, + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "clientId", + "type": "string" + } + ], + "name": "getClientType", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "connectionId", + "type": "string" + } + ], + "name": "getConnection", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "client_id", + "type": "string" + }, + { + "components": [ + { + "internalType": "string", + "name": "identifier", + "type": "string" + }, + { + "internalType": "string[]", + "name": "features", + "type": "string[]" + } + ], + "internalType": "struct Version.Data[]", + "name": "versions", + "type": "tuple[]" + }, + { + "internalType": "enum ConnectionEnd.State", + "name": "state", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "string", + "name": "client_id", + "type": "string" + }, + { + "internalType": "string", + "name": "connection_id", + "type": "string" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "key_prefix", + "type": "bytes" + } + ], + "internalType": "struct MerklePrefix.Data", + "name": "prefix", + "type": "tuple" + } + ], + "internalType": "struct Counterparty.Data", + "name": "counterparty", + "type": "tuple" + }, + { + "internalType": "uint64", + "name": "delay_period", + "type": "uint64" + } + ], + "internalType": "struct ConnectionEnd.Data", + "name": "connection", + "type": "tuple" + }, + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "clientId", + "type": "string" + }, + { + "internalType": "uint64", + "name": "height", + "type": "uint64" + } + ], + "name": "getConsensusState", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + }, + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getExpectedTimePerBlock", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + } + ], + "name": "getModuleOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "internalType": "string", + "name": "channelId", + "type": "string" + } + ], + "name": "getNextSequenceAck", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "internalType": "string", + "name": "channelId", + "type": "string" + } + ], + "name": "getNextSequenceRecv", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "internalType": "string", + "name": "channelId", + "type": "string" + } + ], + "name": "getNextSequenceSend", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "internalType": "string", + "name": "channelId", + "type": "string" + }, + { + "internalType": "uint64", + "name": "sequence", + "type": "uint64" + } + ], + "name": "getPacketAcknowledgementCommitment", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "internalType": "string", + "name": "channelId", + "type": "string" + }, + { + "internalType": "uint64", + "name": "sequence", + "type": "uint64" + } + ], + "name": "getPacketCommitment", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "clientId", + "type": "string" + }, + { + "internalType": "uint64", + "name": "height", + "type": "uint64" + } + ], + "name": "getProcessedHeight", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "clientId", + "type": "string" + }, + { + "internalType": "uint64", + "name": "height", + "type": "uint64" + } + ], + "name": "getProcessedTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "internalType": "string", + "name": "channelId", + "type": "string" + }, + { + "internalType": "uint64", + "name": "sequence", + "type": "uint64" + } + ], + "name": "hasAcknowledgement", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "internalType": "string", + "name": "channelId", + "type": "string" + }, + { + "internalType": "uint64", + "name": "fromSequence", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "toSequence", + "type": "uint64" + } + ], + "name": "hasAcknowledgements", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "internalType": "string", + "name": "channelId", + "type": "string" + }, + { + "internalType": "uint64", + "name": "sequence", + "type": "uint64" + } + ], + "name": "hasPacketReceipt", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "acknowledgement", + "type": "bytes" + } + ], + "name": "makePacketAcknowledgementCommitment", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint64", + "name": "sequence", + "type": "uint64" + }, + { + "internalType": "string", + "name": "source_port", + "type": "string" + }, + { + "internalType": "string", + "name": "source_channel", + "type": "string" + }, + { + "internalType": "string", + "name": "destination_port", + "type": "string" + }, + { + "internalType": "string", + "name": "destination_channel", + "type": "string" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "revision_number", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "revision_height", + "type": "uint64" + } + ], + "internalType": "struct Height.Data", + "name": "timeout_height", + "type": "tuple" + }, + { + "internalType": "uint64", + "name": "timeout_timestamp", + "type": "uint64" + } + ], + "internalType": "struct Packet.Data", + "name": "packet", + "type": "tuple" + } + ], + "name": "makePacketCommitment", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "onlyIBCModule", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "setAboba", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "internalType": "string", + "name": "channelId", + "type": "string" + }, + { + "components": [ + { + "internalType": "enum Channel.State", + "name": "state", + "type": "uint8" + }, + { + "internalType": "enum Channel.Order", + "name": "ordering", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "string", + "name": "port_id", + "type": "string" + }, + { + "internalType": "string", + "name": "channel_id", + "type": "string" + } + ], + "internalType": "struct ChannelCounterparty.Data", + "name": "counterparty", + "type": "tuple" + }, + { + "internalType": "string[]", + "name": "connection_hops", + "type": "string[]" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + } + ], + "internalType": "struct Channel.Data", + "name": "channel", + "type": "tuple" + } + ], + "name": "setChannel", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "clientType", + "type": "string" + }, + { + "internalType": "address", + "name": "clientImpl", + "type": "address" + } + ], + "name": "setClientImpl", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "clientId", + "type": "string" + }, + { + "internalType": "bytes", + "name": "clientStateBytes", + "type": "bytes" + } + ], + "name": "setClientState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "clientId", + "type": "string" + }, + { + "internalType": "string", + "name": "clientType", + "type": "string" + } + ], + "name": "setClientType", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "connectionId", + "type": "string" + }, + { + "components": [ + { + "internalType": "string", + "name": "client_id", + "type": "string" + }, + { + "components": [ + { + "internalType": "string", + "name": "identifier", + "type": "string" + }, + { + "internalType": "string[]", + "name": "features", + "type": "string[]" + } + ], + "internalType": "struct Version.Data[]", + "name": "versions", + "type": "tuple[]" + }, + { + "internalType": "enum ConnectionEnd.State", + "name": "state", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "string", + "name": "client_id", + "type": "string" + }, + { + "internalType": "string", + "name": "connection_id", + "type": "string" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "key_prefix", + "type": "bytes" + } + ], + "internalType": "struct MerklePrefix.Data", + "name": "prefix", + "type": "tuple" + } + ], + "internalType": "struct Counterparty.Data", + "name": "counterparty", + "type": "tuple" + }, + { + "internalType": "uint64", + "name": "delay_period", + "type": "uint64" + } + ], + "internalType": "struct ConnectionEnd.Data", + "name": "connection", + "type": "tuple" + } + ], + "name": "setConnection", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "clientId", + "type": "string" + }, + { + "internalType": "uint64", + "name": "height", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "consensusStateBytes", + "type": "bytes" + } + ], + "name": "setConsensusState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "expectedTimePerBlock_", + "type": "uint64" + } + ], + "name": "setExpectedTimePerBlock", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "ibcModule_", + "type": "address" + } + ], + "name": "setIBCModule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "internalType": "string", + "name": "channelId", + "type": "string" + }, + { + "internalType": "uint64", + "name": "sequence", + "type": "uint64" + } + ], + "name": "setNextSequenceAck", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "internalType": "string", + "name": "channelId", + "type": "string" + }, + { + "internalType": "uint64", + "name": "sequence", + "type": "uint64" + } + ], + "name": "setNextSequenceRecv", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "internalType": "string", + "name": "channelId", + "type": "string" + }, + { + "internalType": "uint64", + "name": "sequence", + "type": "uint64" + } + ], + "name": "setNextSequenceSend", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "internalType": "string", + "name": "channelId", + "type": "string" + }, + { + "internalType": "uint64", + "name": "sequence", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "acknowledgement", + "type": "bytes" + } + ], + "name": "setPacketAcknowledgementCommitment", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "internalType": "string", + "name": "channelId", + "type": "string" + }, + { + "internalType": "uint64", + "name": "sequence", + "type": "uint64" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "sequence", + "type": "uint64" + }, + { + "internalType": "string", + "name": "source_port", + "type": "string" + }, + { + "internalType": "string", + "name": "source_channel", + "type": "string" + }, + { + "internalType": "string", + "name": "destination_port", + "type": "string" + }, + { + "internalType": "string", + "name": "destination_channel", + "type": "string" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "revision_number", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "revision_height", + "type": "uint64" + } + ], + "internalType": "struct Height.Data", + "name": "timeout_height", + "type": "tuple" + }, + { + "internalType": "uint64", + "name": "timeout_timestamp", + "type": "uint64" + } + ], + "internalType": "struct Packet.Data", + "name": "packet", + "type": "tuple" + } + ], + "name": "setPacketCommitment", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "internalType": "string", + "name": "channelId", + "type": "string" + }, + { + "internalType": "uint64", + "name": "sequence", + "type": "uint64" + } + ], + "name": "setPacketReceipt", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "clientId", + "type": "string" + }, + { + "internalType": "uint64", + "name": "height", + "type": "uint64" + }, + { + "internalType": "uint256", + "name": "processedHeight", + "type": "uint256" + } + ], + "name": "setProcessedHeight", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "clientId", + "type": "string" + }, + { + "internalType": "uint64", + "name": "height", + "type": "uint64" + }, + { + "internalType": "uint256", + "name": "processedTime", + "type": "uint256" + } + ], + "name": "setProcessedTime", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/hyperspace/ethereum/src/abi/ibc-packet-abi.json b/hyperspace/ethereum/src/abi/ibc-packet-abi.json new file mode 100644 index 000000000..39d8efaef --- /dev/null +++ b/hyperspace/ethereum/src/abi/ibc-packet-abi.json @@ -0,0 +1,571 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "components": [ + { + "internalType": "uint64", + "name": "sequence", + "type": "uint64" + }, + { + "internalType": "string", + "name": "source_port", + "type": "string" + }, + { + "internalType": "string", + "name": "source_channel", + "type": "string" + }, + { + "internalType": "string", + "name": "destination_port", + "type": "string" + }, + { + "internalType": "string", + "name": "destination_channel", + "type": "string" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "revision_number", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "revision_height", + "type": "uint64" + } + ], + "internalType": "struct HeightData", + "name": "timeout_height", + "type": "tuple" + }, + { + "internalType": "uint64", + "name": "timeout_timestamp", + "type": "uint64" + } + ], + "indexed": false, + "internalType": "struct PacketData", + "name": "packet", + "type": "tuple" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "acknowledgement", + "type": "bytes" + } + ], + "name": "AcknowledgePacket", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "sequence", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "string", + "name": "source_port", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "source_channel", + "type": "string" + }, + { + "indexed": true, + "internalType": "string", + "name": "destination_port", + "type": "string" + }, + { + "indexed": true, + "internalType": "string", + "name": "destination_channel", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "revision_number", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "revision_height", + "type": "uint64" + } + ], + "indexed": false, + "internalType": "struct HeightData", + "name": "timeout_height", + "type": "tuple" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "timeout_timestamp", + "type": "uint64" + } + ], + "name": "RecvPacket", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "sequence", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "string", + "name": "sourcePort", + "type": "string" + }, + { + "indexed": true, + "internalType": "string", + "name": "sourceChannel", + "type": "string" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "revision_number", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "revision_height", + "type": "uint64" + } + ], + "indexed": false, + "internalType": "struct HeightData", + "name": "timeoutHeight", + "type": "tuple" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "timeoutTimestamp", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "SendPacket", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "components": [ + { + "internalType": "uint64", + "name": "sequence", + "type": "uint64" + }, + { + "internalType": "string", + "name": "source_port", + "type": "string" + }, + { + "internalType": "string", + "name": "source_channel", + "type": "string" + }, + { + "internalType": "string", + "name": "destination_port", + "type": "string" + }, + { + "internalType": "string", + "name": "destination_channel", + "type": "string" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "revision_number", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "revision_height", + "type": "uint64" + } + ], + "internalType": "struct HeightData", + "name": "timeout_height", + "type": "tuple" + }, + { + "internalType": "uint64", + "name": "timeout_timestamp", + "type": "uint64" + } + ], + "indexed": false, + "internalType": "struct PacketData", + "name": "packet", + "type": "tuple" + } + ], + "name": "TimeoutPacket", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "string", + "name": "destinationPortId", + "type": "string" + }, + { + "indexed": true, + "internalType": "string", + "name": "destinationChannel", + "type": "string" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "sequence", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "acknowledgement", + "type": "bytes" + } + ], + "name": "WriteAcknowledgement", + "type": "event" + }, + { + "inputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "uint64", + "name": "sequence", + "type": "uint64" + }, + { + "internalType": "string", + "name": "source_port", + "type": "string" + }, + { + "internalType": "string", + "name": "source_channel", + "type": "string" + }, + { + "internalType": "string", + "name": "destination_port", + "type": "string" + }, + { + "internalType": "string", + "name": "destination_channel", + "type": "string" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "revision_number", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "revision_height", + "type": "uint64" + } + ], + "internalType": "struct HeightData", + "name": "timeout_height", + "type": "tuple" + }, + { + "internalType": "uint64", + "name": "timeout_timestamp", + "type": "uint64" + } + ], + "internalType": "struct PacketData", + "name": "packet", + "type": "tuple" + }, + { + "internalType": "bytes", + "name": "acknowledgement", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "proof", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "revision_number", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "revision_height", + "type": "uint64" + } + ], + "internalType": "struct HeightData", + "name": "proofHeight", + "type": "tuple" + } + ], + "internalType": "struct IBCMsgsMsgPacketAcknowledgement", + "name": "msg_", + "type": "tuple" + } + ], + "name": "acknowledgePacket", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "uint64", + "name": "sequence", + "type": "uint64" + }, + { + "internalType": "string", + "name": "source_port", + "type": "string" + }, + { + "internalType": "string", + "name": "source_channel", + "type": "string" + }, + { + "internalType": "string", + "name": "destination_port", + "type": "string" + }, + { + "internalType": "string", + "name": "destination_channel", + "type": "string" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "revision_number", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "revision_height", + "type": "uint64" + } + ], + "internalType": "struct HeightData", + "name": "timeout_height", + "type": "tuple" + }, + { + "internalType": "uint64", + "name": "timeout_timestamp", + "type": "uint64" + } + ], + "internalType": "struct PacketData", + "name": "packet", + "type": "tuple" + }, + { + "internalType": "bytes", + "name": "proof", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "revision_number", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "revision_height", + "type": "uint64" + } + ], + "internalType": "struct HeightData", + "name": "proofHeight", + "type": "tuple" + } + ], + "internalType": "struct IBCMsgsMsgPacketRecv", + "name": "msg_", + "type": "tuple" + } + ], + "name": "recvPacket", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "sourcePort", + "type": "string" + }, + { + "internalType": "string", + "name": "sourceChannel", + "type": "string" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "revision_number", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "revision_height", + "type": "uint64" + } + ], + "internalType": "struct HeightData", + "name": "timeoutHeight", + "type": "tuple" + }, + { + "internalType": "uint64", + "name": "timeoutTimestamp", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "sendPacket", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "destinationPortId", + "type": "string" + }, + { + "internalType": "string", + "name": "destinationChannel", + "type": "string" + }, + { + "internalType": "uint64", + "name": "sequence", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "acknowledgement", + "type": "bytes" + } + ], + "name": "writeAcknowledgement", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/hyperspace/ethereum/src/bin/launch-yui-ibc.rs b/hyperspace/ethereum/src/bin/launch-yui-ibc.rs index 6fe1cbea1..7108aafc3 100644 --- a/hyperspace/ethereum/src/bin/launch-yui-ibc.rs +++ b/hyperspace/ethereum/src/bin/launch-yui-ibc.rs @@ -1,5 +1,4 @@ -#[path = "../../tests/utils.rs"] -mod utils; +use hyperspace_ethereum::mock::utils; #[tokio::main] async fn main() { diff --git a/hyperspace/ethereum/src/chain.rs b/hyperspace/ethereum/src/chain.rs index 8c07f5dfe..4d0faf9b0 100644 --- a/hyperspace/ethereum/src/chain.rs +++ b/hyperspace/ethereum/src/chain.rs @@ -240,7 +240,7 @@ fn tm_header_abi_token(header: Header) -> Token { ) } -fn msg_connection_open_init_token(x: MsgConnectionOpenInit) -> Token { +pub(crate) fn msg_connection_open_init_token(x: MsgConnectionOpenInit) -> Token { use ethers::abi::{encode as ethers_encode, Token as EthersToken}; let consensus_state_data = EthersToken::Tuple( @@ -278,7 +278,7 @@ fn msg_connection_open_init_token(x: MsgConnectionOpenInit) -> Token { consensus_state_data } -fn msg_connection_open_ack_token( +pub fn msg_connection_open_ack_token( msg: MsgConnectionOpenAck, client_state: ClientState, ) -> Token { @@ -437,8 +437,6 @@ impl Chain for EthereumClient { let stream = async_stream::stream! { // TODO: is it really finalized blocks stream? - // - PoW: probabilistic finality (wait for ~30 blocks) - // - PoS: finality is deterministic let mut stream = ws.subscribe_blocks().await.expect("fuck"); while let Some(block) = stream.next().await { @@ -455,25 +453,17 @@ impl Chain for EthereumClient { ) -> Result { use ethers::abi::{encode as ethers_encode, Token as EthersToken}; - let contract = crate::contract::get_contract_from_name( - self.config.ibc_handler_address.clone(), - Arc::clone(&self.http_rpc), - "contracts/diamond", - "Diamond", - ); - - let msg = messages.iter().next(); - if let Some(msg) = msg { + for msg in messages { if msg.type_url == ibc::core::ics02_client::msgs::create_client::TYPE_URL { dbg!(&msg.value.len()); let msg = MsgCreateAnyClient::::decode_vec(&msg.value).unwrap(); let AnyClientState::Tendermint(client_state) = msg.client_state else { //TODO return error support only tendermint client state - return Ok(()) + panic!("unsupported client state") }; let AnyConsensusState::Tendermint(client_consensus) = msg.consensus_state else { //TODO return error support only tendermint consensus state - return Ok(()) + panic!("unsupported") }; let client_state_abi_token = client_state_abi_token(client_state); let consensus_state_abi_token = consensus_state_abi_token(client_consensus); @@ -494,8 +484,7 @@ impl Chain for EthereumClient { EthersToken::Bytes(consensus_state_data_vec.clone()), ]); - let client_id = - self.config.diamond_handler.as_ref().unwrap().create_client(token).await; + let client_id = self.yui.create_client(token).await; dbg!(&client_id); thread::sleep(Duration::from_secs(5)); @@ -509,7 +498,7 @@ impl Chain for EthereumClient { let msg = MsgUpdateAnyClient::::decode_vec(&msg.value).unwrap(); let AnyClientMessage::Tendermint(client_state) = msg.client_message else { //TODO return error support only tendermint client state - return Ok(()) + panic!("unsupported") }; let ClientMessage::Header(header) = client_state else { return Ok(()) }; @@ -534,15 +523,14 @@ impl Chain for EthereumClient { EthersToken::Bytes(client_state), ]); - let _ = self.config.diamond_handler.as_ref().unwrap().update_client(token).await; + let _ = self.yui.update_client(token).await; thread::sleep(Duration::from_secs(5)); return Ok(()) } else if msg.type_url == ibc::core::ics03_connection::msgs::conn_open_init::TYPE_URL { let msg = MsgConnectionOpenInit::decode_vec(&msg.value).unwrap(); let token = msg_connection_open_init_token(msg); - let connection_id = - self.config.diamond_handler.as_ref().unwrap().connection_open_init(token).await; + let connection_id = self.yui.connection_open_init(token).await; dbg!(connection_id); return Ok(()) } else if msg.type_url == ibc::core::ics03_connection::msgs::conn_open_ack::TYPE_URL { @@ -552,19 +540,18 @@ impl Chain for EthereumClient { Some(m) => { let AnyClientState::Tendermint(client_state) = m else { //TODO return error support only tendermint client state - panic!("only tendermint client state is supported for now"); + panic!("unsupported") }; client_state }, None => { //TODO return error support only tendermint client state - panic!("only tendermint client state is supported for now"); + panic!("unsupported") }, }; let token = msg_connection_open_ack_token(msg, client_state); - let connection_id = - self.config.diamond_handler.as_ref().unwrap().connection_open_ack(token).await; + let connection_id = self.yui.connection_open_ack(token).await; return Ok(()) } else if msg.type_url == ibc::core::ics03_connection::msgs::conn_open_try::TYPE_URL { let msg = MsgConnectionOpenTry::::decode_vec(&msg.value).unwrap(); @@ -572,81 +559,54 @@ impl Chain for EthereumClient { Some(m) => { let AnyClientState::Tendermint(client_state) = m else { //TODO return error support only tendermint client state - panic!("only tendermint client state is supported for now"); + panic!("unsupported") }; client_state }, None => { //TODO return error support only tendermint client state - panic!("only tendermint client state is supported for now"); + panic!("unsupported") }, }; let token = msg_connection_open_try_token(msg, client_state); - self.config.diamond_handler.as_ref().unwrap().connection_open_try(token).await; + self.yui.connection_open_try(token).await; return Ok(()) } else if msg.type_url == ibc::core::ics03_connection::msgs::conn_open_confirm::TYPE_URL { let msg = MsgConnectionOpenConfirm::decode_vec(&msg.value).unwrap(); let token = msg_connection_open_confirm_token(msg); - self.config - .diamond_handler - .as_ref() - .unwrap() - .connection_open_confirm(token) - .await; + self.yui.connection_open_confirm(token).await; return Ok(()) } else if msg.type_url == channel_msgs::chan_open_init::TYPE_URL { let msg = MsgChannelOpenInit::decode_vec(&msg.value).unwrap(); let token = msg.into_token(); - let channel_id = - self.config.diamond_handler.as_ref().unwrap().channel_open_init(token).await; + let channel_id = self.yui.channel_open_init(token).await; return Ok(()) } else if msg.type_url == channel_msgs::chan_open_try::TYPE_URL { let msg = MsgChannelOpenTry::decode_vec(&msg.value).unwrap(); let token = msg.into_token(); - let channel_id = - self.config.diamond_handler.as_ref().unwrap().channel_open_try(token).await; + let channel_id = self.yui.channel_open_try(token).await; return Ok(()) } else if msg.type_url == channel_msgs::chan_open_ack::TYPE_URL { let msg = MsgChannelOpenAck::decode_vec(&msg.value).unwrap(); let token = msg.into_token(); - self.config - .diamond_handler - .as_ref() - .unwrap() - .send_and_get_tuple(token, "channelOpenAck") - .await; + self.yui.send_and_get_tuple(token, "channelOpenAck").await; return Ok(()) } else if msg.type_url == channel_msgs::chan_open_confirm::TYPE_URL { let msg = MsgChannelOpenConfirm::decode_vec(&msg.value).unwrap(); let token = msg.into_token(); - self.config - .diamond_handler - .as_ref() - .unwrap() - .send_and_get_tuple(token, "channelOpenConfirm") - .await; + self.yui.send_and_get_tuple(token, "channelOpenConfirm").await; return Ok(()) } else if msg.type_url == channel_msgs::chan_close_init::TYPE_URL { let msg = MsgChannelCloseInit::decode_vec(&msg.value).unwrap(); let token = msg.into_token(); - self.config - .diamond_handler - .as_ref() - .unwrap() - .send_and_get_tuple(token, "channelCloseInit") - .await; + self.yui.send_and_get_tuple(token, "channelCloseInit").await; return Ok(()) } else if msg.type_url == channel_msgs::chan_close_confirm::TYPE_URL { let msg = MsgChannelCloseConfirm::decode_vec(&msg.value).unwrap(); let token = msg.into_token(); - self.config - .diamond_handler - .as_ref() - .unwrap() - .send_and_get_tuple(token, "channelCloseConfirm") - .await; + self.yui.send_and_get_tuple(token, "channelCloseConfirm").await; return Ok(()) } else if msg.type_url == channel_msgs::timeout_on_close::TYPE_URL { let msg = MsgTimeoutOnClose::decode_vec(&msg.value).unwrap(); @@ -655,28 +615,17 @@ impl Chain for EthereumClient { } else if msg.type_url == channel_msgs::acknowledgement::TYPE_URL { let msg = MsgAcknowledgement::decode_vec(&msg.value).unwrap(); let token = msg.into_token(); - self.config - .diamond_handler - .as_ref() - .unwrap() - .send_and_get_tuple(token, "acknowledgePacket") - .await; + self.yui.send_and_get_tuple(token, "acknowledgePacket").await; return Ok(()) } else if msg.type_url == channel_msgs::recv_packet::TYPE_URL { let msg = MsgRecvPacket::decode_vec(&msg.value).unwrap(); let token = msg.into_token(); - self.config - .diamond_handler - .as_ref() - .unwrap() - .send_and_get_tuple(token, "recvPacket") - .await; + self.yui.send_and_get_tuple(token, "recvPacket").await; return Ok(()) } - unimplemented!("does not support this msg type for now"); - }; - - unimplemented!("client create and client update is implemented only for now"); + unimplemented!("does not support this msg type for now: {}", msg.type_url); + } + Ok(()) } async fn query_client_message( diff --git a/hyperspace/ethereum/src/client.rs b/hyperspace/ethereum/src/client.rs index 25b670fb1..587fde5b1 100644 --- a/hyperspace/ethereum/src/client.rs +++ b/hyperspace/ethereum/src/client.rs @@ -49,7 +49,7 @@ pub const CHANNELS_STORAGE_INDEX: u32 = 5; #[derive(Debug, Clone)] pub struct EthereumClient { - pub http_rpc: Arc, + http_rpc: Arc, pub(crate) ws_uri: http::Uri, pub config: EthereumClientConfig, /// Common relayer data @@ -145,7 +145,11 @@ impl EthereumClient { prev_state: Arc::new(std::sync::Mutex::new((vec![], vec![]))), }) } - // cauce + + pub fn client(&self) -> Arc { + self.http_rpc.clone() + } + pub async fn websocket_provider(&self) -> Result, ClientError> { let secret = std::fs::read_to_string(format!( "{}/.lighthouse/local-testnet/geth_datadir1/geth/jwtsecret", @@ -174,7 +178,7 @@ impl EthereumClient { .address(self.config.ibc_handler_address) .event("OpenInitChannel(string,string)"); - let logs = self.http_rpc.get_logs(&filter).await.unwrap(); + let logs = self.client().get_logs(&filter).await.unwrap(); let v = logs .into_iter() @@ -196,7 +200,7 @@ impl EthereumClient { .address(self.config.ibc_handler_address) .event("GeneratedClientIdentifier(string)"); - let logs = self.http_rpc.get_logs(&filter).await.unwrap(); + let logs = self.client().get_logs(&filter).await.unwrap(); logs.into_iter() .map(|log| { @@ -217,7 +221,7 @@ impl EthereumClient { .address(self.config.ibc_handler_address) .event("GeneratedConnectionIdentifier(string)"); - let logs = self.http_rpc.get_logs(&filter).await.unwrap(); + let logs = self.client().get_logs(&filter).await.unwrap(); logs.into_iter() .map(|log| { @@ -238,7 +242,7 @@ impl EthereumClient { .address(self.config.ibc_handler_address) .event("AcknowledgePacket((uint64,string,string,string,string,bytes,(uint64,uint64),uint64),bytes)"); - let logs = self.http_rpc.get_logs(&filter).await.unwrap(); + let logs = self.client().get_logs(&filter).await.unwrap(); logs.into_iter() .map(|log| { @@ -338,7 +342,7 @@ impl EthereumClient { .to_block(to) .address(self.config.ibc_handler_address) .event(event_name); - let client = self.http_rpc.clone(); + let client = self.client().clone(); async_stream::stream! { let logs = client.get_logs(&filter).await.unwrap(); @@ -364,7 +368,7 @@ impl EthereumClient { ) .unwrap(); - let client = self.http_rpc.clone(); + let client = self.client().clone(); let address = self.config.ibc_handler_address.clone(); async move { @@ -394,7 +398,7 @@ impl EthereumClient { let index = cast::SimpleCast::index("bytes32", dbg!(&var_name), dbg!(&storage_index)).unwrap(); - let client = self.http_rpc.clone(); + let client = self.client().clone(); let address = self.config.ibc_handler_address.clone(); dbg!(&address); @@ -434,7 +438,7 @@ impl EthereumClient { let index = cast::SimpleCast::index("bytes32", &key2_hashed_hex, &key2_hashed_hex).unwrap(); - let client = self.http_rpc.clone(); + let client = self.client().clone(); let address = self.config.ibc_handler_address.clone(); async move { diff --git a/hyperspace/ethereum/src/config.rs b/hyperspace/ethereum/src/config.rs index d1af1cb7c..56deefe58 100644 --- a/hyperspace/ethereum/src/config.rs +++ b/hyperspace/ethereum/src/config.rs @@ -6,8 +6,6 @@ use ethers::types::Address; use ibc::core::ics24_host::identifier::{ChannelId, ClientId, ConnectionId, PortId}; use serde::{de::Visitor, Deserialize, Deserializer, Serialize, Serializer}; -use crate::contract::DiamandHandler; - fn uri_de<'de, D>(de: D) -> Result where D: Deserializer<'de>, @@ -103,8 +101,6 @@ pub struct EthereumClientConfig { #[serde(skip)] pub yui: Option, ProviderImpl>>, pub client_type: String, - #[serde(skip)] - pub diamond_handler: Option, } impl EthereumClientConfig { diff --git a/hyperspace/ethereum/src/contract.rs b/hyperspace/ethereum/src/contract.rs index f6cb31e1d..f18daf7bd 100644 --- a/hyperspace/ethereum/src/contract.rs +++ b/hyperspace/ethereum/src/contract.rs @@ -1,13 +1,21 @@ -use std::{sync::Arc, path::{Path, PathBuf}}; +use std::{ + path::{Path, PathBuf}, + sync::Arc, +}; use ecdsa::SigningKey; use ethers::{ abi::{Abi, Address, Detokenize, Token, Tokenizable, Tokenize}, - prelude::Contract, + prelude::{Contract, ContractInstance, *}, providers::Middleware, }; -use ethers::prelude::{ContractInstance, *}; -use ethers_solc::{ProjectCompileOutput, ProjectPathsConfig, SolcConfig, artifacts::{Settings, Optimizer, OptimizerDetails, output_selection::OutputSelection, DebuggingSettings, RevertStrings, Libraries, FunctionCall}, EvmVersion, Project, Artifact}; +use ethers_solc::{ + artifacts::{ + output_selection::OutputSelection, DebuggingSettings, FunctionCall, Libraries, Optimizer, + OptimizerDetails, RevertStrings, Settings, + }, + Artifact, EvmVersion, Project, ProjectCompileOutput, ProjectPathsConfig, SolcConfig, +}; /// Unwraps a contract error, decoding the revert reason if possible pub trait UnwrapContractError { @@ -46,160 +54,11 @@ pub struct IbcHandler { use ethers::middleware::SignerMiddleware; use k256::Secp256k1; -type EthersContractInstance = ContractInstance, Wallet>>>, SignerMiddleware, Wallet>>>; -#[derive(Clone, Debug)] -pub struct DiamandHandler{ - pub deployed_facets: Vec, - pub diamond: EthersContractInstance, -} - -impl DiamandHandler -where -{ - pub fn new(deployed_facets: Vec, diamond: EthersContractInstance) -> Self { - DiamandHandler { - deployed_facets: deployed_facets, - diamond, - } - } - pub fn method( - &self, - name: &str, - args: T, - ) -> Result, Wallet>>>, SignerMiddleware, Wallet>>, D>, AbiError> { - let mut contract: Option<&EthersContractInstance> = None; - - let lookup_contracts = self.deployed_facets.iter().chain(std::iter::once(&self.diamond)); - - for lookup_contract in lookup_contracts { - if lookup_contract.abi().function(name).is_ok() { - if contract.is_some() { - panic!("ambiguous method name: {}", name); - } - contract = Some(lookup_contract); - } - } - let contract = contract.take().ok_or_else(|| AbiError::WrongSelector)?; - - let mut f = contract.method(name, args); - - if let Ok(f) = &mut f { - f.tx.set_to(self.diamond.address()); - } - - f - } - - pub async fn create_client(&self, msg: Token) -> String { - let method = self.method::<_, String>("createClient", (msg,)).unwrap(); - - let client_id = method.call().await.unwrap_contract_error(); - - let receipt = method.send().await.unwrap().await.unwrap().unwrap(); - assert_eq!(receipt.status, Some(1.into())); - - client_id - } - - pub async fn update_client(&self, msg: Token) { - let method = self.method::<_, ()>("updateClient", (msg,)).unwrap(); - - let gas_estimate_update_client = method.estimate_gas().await.unwrap(); - dbg!(gas_estimate_update_client); - let client_id = method.call().await.unwrap_contract_error(); - - let receipt = method.send().await.unwrap().await.unwrap().unwrap(); - assert_eq!(receipt.status, Some(1.into())); - } - - pub async fn connection_open_ack(&self, msg: Token) { - let method = self.method::<_, ()>("connectionOpenAck", (msg,)).unwrap(); - - let gas_estimate_connection_open = method.estimate_gas().await.unwrap(); - dbg!(gas_estimate_connection_open); - let _ = method.call().await.unwrap_contract_error(); - - let receipt = method.send().await.unwrap().await.unwrap().unwrap(); - assert_eq!(receipt.status, Some(1.into())); - } - - pub async fn connection_open_try(&self, msg: Token) -> String { - let method = self.method::<_, String>("connectionOpenTry", (msg,)).unwrap(); - - let gas_estimate_connection_open_try = method.estimate_gas().await.unwrap(); - dbg!(gas_estimate_connection_open_try); - let id = method.call().await.unwrap_contract_error(); - - let receipt = method.send().await.unwrap().await.unwrap().unwrap(); - assert_eq!(receipt.status, Some(1.into())); - id - } - - pub async fn connection_open_init(&self, msg: Token) -> String { - let method = self.method::<_, String>("connectionOpenInit", (msg,)).unwrap(); - - let gas_estimate_connection_open_try = method.estimate_gas().await.unwrap(); - dbg!(gas_estimate_connection_open_try); - let id = method.call().await.unwrap_contract_error(); - - let receipt = method.send().await.unwrap().await.unwrap().unwrap(); - assert_eq!(receipt.status, Some(1.into())); - id - } - - pub async fn connection_open_confirm(&self, msg: Token) { - let method = self.method::<_, ()>("connectionOpenConfirm", (msg,)).unwrap(); - - let gas_estimate_connection_open_confirm = method.estimate_gas().await.unwrap(); - dbg!(gas_estimate_connection_open_confirm); - let _ = method.call().await.unwrap_contract_error(); - - let receipt = method.send().await.unwrap().await.unwrap().unwrap(); - assert_eq!(receipt.status, Some(1.into())); - } - - pub async fn channel_open_init(&self, msg: Token) -> String { - let method = self.method::<_, String>("channelOpenInit", (msg,)).unwrap(); - - let gas_estimate_connection_id = method.estimate_gas().await.unwrap(); - dbg!(gas_estimate_connection_id); - let connection_id = method.call().await.unwrap_contract_error(); - - let receipt = method.send().await.unwrap().await.unwrap().unwrap(); - assert_eq!(receipt.status, Some(1.into())); - connection_id - } - - pub async fn channel_open_try(&self, msg: Token) -> String { - let method = self.method::<_, String>("channelOpenTry", (msg,)).unwrap(); - - let gas_estimate_connection_id = method.estimate_gas().await.unwrap(); - dbg!(gas_estimate_connection_id); - let connection_id = method.call().await.unwrap_contract_error(); - - let receipt = method.send().await.unwrap().await.unwrap().unwrap(); - assert_eq!(receipt.status, Some(1.into())); - connection_id - } - - pub async fn send_and_get_tuple(&self, msg: Token, method_name: impl AsRef) -> () { - let method = self.method::<_, ()>(method_name.as_ref(), (msg,)).unwrap(); - - let gas_estimate = method.estimate_gas().await.unwrap(); - dbg!(gas_estimate); - let ret = method.call().await.unwrap_contract_error(); - - let receipt = method.send().await.unwrap().await.unwrap().unwrap(); - assert_eq!(receipt.status, Some(1.into())); - ret - } - -} impl IbcHandler where M: Middleware, -{ +{ pub fn new(contract: Contract) -> Self { IbcHandler { contract } } @@ -258,7 +117,6 @@ where let receipt = method.send().await.unwrap().await.unwrap().unwrap(); assert_eq!(receipt.status, Some(1.into())); - } pub async fn send(&self, msg: Token, method_name: impl AsRef) -> T { @@ -322,7 +180,12 @@ where } #[track_caller] -pub fn get_contract_from_name(address: Address, client: Arc, source: impl AsRef, s: impl AsRef) -> Contract +pub fn get_contract_from_name( + address: Address, + client: Arc, + source: impl AsRef, + s: impl AsRef, +) -> Contract where M: Middleware, { diff --git a/hyperspace/ethereum/src/ibc_provider.rs b/hyperspace/ethereum/src/ibc_provider.rs index b797ef09c..cb5b4d0ea 100644 --- a/hyperspace/ethereum/src/ibc_provider.rs +++ b/hyperspace/ethereum/src/ibc_provider.rs @@ -194,7 +194,7 @@ impl IbcProvider for EthereumClient { let filter = Filter::new().from_block(from).to_block(to).address(self.yui.diamond.address()); let client = self.clone(); - let logs = self.http_rpc.get_logs(&filter).await.unwrap(); + let logs = self.client().get_logs(&filter).await.unwrap(); let mut events = vec![]; let update = prove(self, finality_event.hash.unwrap()).await?; @@ -560,7 +560,8 @@ impl IbcProvider for EthereumClient { // TODO: fix latest_height_and_timestamp in basic builds let block_number =// if dbg!(cfg!(feature = "test")) { BlockNumber::from( - self.http_rpc + self + .client() .get_block_number() .await .map_err(|err| ClientError::MiddlewareError(err))?, @@ -570,7 +571,7 @@ impl IbcProvider for EthereumClient { // }; let block = self - .http_rpc + .client() .get_block(BlockId::Number(block_number)) .await .map_err(|err| ClientError::MiddlewareError(err))? @@ -706,7 +707,6 @@ impl IbcProvider for EthereumClient { self.config.channel_whitelist.clone().into_iter().collect() } - #[cfg(test)] async fn query_connection_channels( &self, at: Height, @@ -979,7 +979,7 @@ impl IbcProvider for EthereumClient { async fn query_timestamp_at(&self, block_number: u64) -> Result { let block = self - .http_rpc + .client() .get_block(BlockId::Number(BlockNumber::Number(block_number.into()))) .await .map_err(|err| ClientError::MiddlewareError(err))? @@ -1041,7 +1041,7 @@ impl IbcProvider for EthereumClient { }; let block = self - .http_rpc + .client() .get_block(BlockId::Number(BlockNumber::Number(dbg!(block_header.slot).into()))) .await .unwrap() diff --git a/hyperspace/ethereum/src/mock/mod.rs b/hyperspace/ethereum/src/mock/mod.rs index 9d020727b..b5614dd82 100644 --- a/hyperspace/ethereum/src/mock/mod.rs +++ b/hyperspace/ethereum/src/mock/mod.rs @@ -1,2 +1 @@ -pub mod sanity_checks; pub mod utils; diff --git a/hyperspace/ethereum/src/mock/sanity_checks.rs b/hyperspace/ethereum/src/mock/sanity_checks.rs deleted file mode 100644 index beaf1c838..000000000 --- a/hyperspace/ethereum/src/mock/sanity_checks.rs +++ /dev/null @@ -1,617 +0,0 @@ -use std::{future::Future, ops::Deref, path::PathBuf, str::FromStr, sync::Arc, time::Duration}; - -use super::{utils, utils::USE_GETH}; -use crate::{ - config::EthereumClientConfig, - contract::UnwrapContractError, - utils::{DeployYuiIbc, ProviderImpl}, -}; -use ethers::{ - abi::{encode_packed, Token}, - core::k256::sha2::{Digest, Sha256}, - prelude::{ContractInstance, TransactionReceipt}, - types::U256, - utils::{keccak256, AnvilInstance}, -}; -use ethers_solc::{ProjectCompileOutput, ProjectPathsConfig}; -use futures::{stream::StreamExt, Stream, TryStreamExt}; -use ibc::{ - core::{ - ics02_client::height::Height, - ics03_connection::msgs::conn_open_ack::MsgConnectionOpenAck, - ics04_channel::{ - channel::Order, - packet::{Packet, Sequence}, - }, - ics24_host::identifier::{ChannelId, PortId}, - }, - events::IbcEvent, - timestamp::Timestamp, -}; -use ibc_rpc::PacketInfo; -use primitives::{mock::LocalClientTypes, Chain, IbcProvider}; -use prost::Message; -use tokio::time::timeout; -use tracing::log; -use tracing_subscriber::{filter, layer::SubscriberExt, util::SubscriberInitExt, Layer}; - -pub async fn hyperspace_ethereum_client_fixture( - anvil: &AnvilInstance, - yui_ibc: DeployYuiIbc, ProviderImpl>, -) -> EthereumClientConfig { - // ) -> crate::client::EthereumClient { - let endpoint = if USE_GETH { "http://localhost:6001".to_string() } else { anvil.endpoint() }; - let wallet_path = if USE_GETH { - Some("keys/0x73db010c3275eb7a92e5c38770316248f4c644ee".to_string()) - } else { - None - }; - let wallet = if !USE_GETH { Some(anvil.endpoint().parse().unwrap()) } else { None }; - - // crate::client::EthereumClient::new( - EthereumClientConfig { - http_rpc_url: endpoint.parse().unwrap(), - ws_rpc_url: "ws://localhost:5001".parse().unwrap(), - beacon_rpc_url: "http://localhost:8001".parse().unwrap(), - ibc_handler_address: yui_ibc.diamond.address(), - tendermint_client_address: Default::default(), - mnemonic: None, - max_block_weight: 1, - private_key: wallet, - private_key_path: wallet_path, - name: "mock-ethereum-client".into(), - client_id: None, - connection_id: None, - channel_whitelist: vec![], - commitment_prefix: "".into(), - wasm_code_id: None, - yui: Some(yui_ibc), - client_type: "".to_string(), - } - // ) - // .await - // .unwrap() -} - -#[allow(dead_code)] -pub struct DeployYuiIbcMockClient { - pub path: PathBuf, - pub project_output: ProjectCompileOutput, - // pub project_output: ethers::solc::ProjectCompileOutput, - pub anvil: AnvilInstance, - pub client: Arc, - pub ibc_mock_client: ContractInstance, ProviderImpl>, - pub ibc_mock_module: Option, ProviderImpl>>, - pub yui_ibc: DeployYuiIbc, ProviderImpl>, -} - -impl DeployYuiIbcMockClient { - pub async fn send_mock_packet( - &self, - source_port: PortId, - source_channel: ChannelId, - timeout_height: Height, - data: Vec, - ) -> TransactionReceipt { - let fut = self - .mock_module_ref() - .method::<_, ()>( - "sendMockPacket", - ( - Token::Bytes(data), // data - Token::String(source_port.to_string()), // port-id - Token::String(source_channel.to_string()), // channel-id - // timeout-height - Token::Uint(timeout_height.revision_height.into()), - ), - ) - .unwrap(); - - let () = fut.call().await.unwrap_contract_error(); - // let trace = self - // .ibc_handler - // .client() - // .borrow() - // .debug_trace_call(fut.tx.clone(), None, GethDebugTracingCallOptions::default()) - // .await - // .unwrap(); - // std::fs::write("trace.txt", format!("{:#?}", trace)).unwrap(); - // println!("trace: {:?}", trace); - let tx = fut.send().await.unwrap_contract_error().await.unwrap().unwrap(); - // dbg!(tx.logs); - let status = tx.status.expect("status not found"); - - if status == 0.into() { - panic!("status is 0"); - } - tx - } - - fn mock_module_ref(&self) -> &ContractInstance, ProviderImpl> { - self.ibc_mock_module.as_ref().expect("no mock module set") - } -} - -pub async fn deploy_yui_ibc_and_mock_client_fixture() -> DeployYuiIbcMockClient { - let path = utils::yui_ibc_solidity_path(); - let project_output = utils::compile_yui(&path, "contracts/core"); - let diamond_project_output = utils::compile_yui(&path, "contracts/diamond"); - let (anvil, client) = utils::spawn_anvil(); - log::warn!("{}", anvil.endpoint()); - let yui_ibc = - utils::deploy_yui_ibc(&project_output, &diamond_project_output, client.clone()).await; - - let ibc_mock_client = utils::compile_solc({ - let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); - - ProjectPathsConfig::builder() - .root(manifest_dir.join("tests/contracts")) - .sources(manifest_dir.join("tests/contracts/clients")) - .build() - .unwrap() - }); - - let ibc_mock_client = utils::deploy_contract( - ibc_mock_client.find_first("MockClient").unwrap(), - (Token::Address(yui_ibc.diamond.address()),), - client.clone(), - ) - .await; - - println!("Mock client address: {:?}", ibc_mock_client.address()); - - // todo: some interactions between the mock client and the ibc handler to verify behaviour. - - DeployYuiIbcMockClient { - path, - project_output, - anvil, - client, - yui_ibc, - ibc_mock_client, - ibc_mock_module: None, - } -} - -#[derive(Debug, Clone, PartialEq, Eq)] -struct ClientId(pub String); - -impl Deref for ClientId { - type Target = String; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl ClientId { - pub async fn open_connection(&self, deploy: &DeployYuiIbcMockClient) -> String { - let connection_id = deploy.yui_ibc.connection_open_init_mock(&self.0).await; - let () = deploy - .yui_ibc - .connection_open_ack_mock(&connection_id, utils::mock::client_state_bytes()) - .await; - connection_id - } -} - -async fn deploy_mock_client_fixture(deploy: &DeployYuiIbcMockClient) -> ClientId { - deploy - .yui_ibc - .register_client("mock-client", deploy.ibc_mock_client.address()) - .await; - - let string = deploy - .yui_ibc - .create_client(utils::mock::create_client_msg("mock-client")) - .await; - println!("client id: {}", string); - println!("Diamond contract addr: {:?}", deploy.yui_ibc.diamond.address()); - ClientId(string) -} - -#[track_caller] -fn deploy_mock_module_fixture( - deploy: &DeployYuiIbcMockClient, -) -> impl Future, ProviderImpl>> + '_ { - async move { - let clients = utils::compile_solc({ - let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); - - ProjectPathsConfig::builder() - .root(manifest_dir.join("tests/contracts")) - .sources(manifest_dir.join("tests/contracts/clients")) - .build() - .unwrap() - }); - - let contract = clients.find_first("MockModule").expect("no MockModule in project output"); - let constructor_args = (Token::Address(deploy.yui_ibc.diamond.address()),); - let contract = - utils::deploy_contract(contract, constructor_args, deploy.client.clone()).await; - println!("Mock module address: {:?}", contract.address()); - contract - } -} - -#[tokio::test] -async fn test_deploy_yui_ibc_and_mock_client() { - deploy_yui_ibc_and_mock_client_fixture().await; -} - -#[tokio::test] -async fn test_hyperspace_ethereum_client() { - let DeployYuiIbcMockClient { anvil, yui_ibc, .. } = - deploy_yui_ibc_and_mock_client_fixture().await; - let _hyperspace = hyperspace_ethereum_client_fixture(&anvil, yui_ibc.clone()).await; -} - -#[tokio::test] -async fn test_ibc_client() { - let deploy = deploy_yui_ibc_and_mock_client_fixture().await; - let hyperspace = - hyperspace_ethereum_client_fixture(&deploy.anvil, deploy.yui_ibc.clone()).await; - let events = hyperspace.ibc_events().await; - let client_id = deploy_mock_client_fixture(&deploy).await; - let height = hyperspace.latest_height_and_timestamp().await.unwrap().0; - let r = hyperspace.query_client_state(height, client_id.parse().unwrap()).await.unwrap(); - - assert_eq!( - r.client_state, - Some(ibc_proto::google::protobuf::Any { - type_url: "/ibc.lightclients.mock.v1.ClientState".into(), - value: utils::mock::ClientState { - height: ibc_proto::ibc::core::client::v1::Height { - revision_number: 0, - revision_height: 1, - }, - } - .encode_to_vec(), - }) - ); - - let r = hyperspace - .query_client_consensus( - height, - client_id.parse().unwrap(), - ibc::Height { revision_number: 0, revision_height: 1 }, - ) - .await - .unwrap(); - - assert_eq!( - r.consensus_state, - Some(ibc_proto::google::protobuf::Any { - type_url: "/ibc.lightclients.mock.v1.ConsensusState".into(), - value: utils::mock::ConsensusState { timestamp: 1 }.encode_to_vec(), - }) - ); - - let (_host_height, _host_timestamp) = hyperspace - .query_client_update_time_and_height( - client_id.parse().unwrap(), - ibc::Height { revision_number: 0, revision_height: 1 }, - ) - .await - .unwrap(); - - let events = timeout(Duration::from_secs(5), events.take(1).collect::>()) - .await - .unwrap(); - dbg!(events); -} - -#[tokio::test] -async fn test_ibc_connection() { - let stdout_log = tracing_subscriber::fmt::layer().pretty(); - tracing_subscriber::registry() - .with(stdout_log.with_filter(filter::LevelFilter::INFO).with_filter(filter::filter_fn( - |metadata| metadata.file().map(|x| x.contains("ethers")).unwrap_or_default(), - ))) - .init(); - let deploy = deploy_yui_ibc_and_mock_client_fixture().await; - let hyperspace = - hyperspace_ethereum_client_fixture(&deploy.anvil, deploy.yui_ibc.clone()).await; - let client_id = deploy_mock_client_fixture(&deploy).await; - - let connection_id = deploy.yui_ibc.connection_open_init_mock(&client_id).await; - let () = deploy - .yui_ibc - .connection_open_ack_mock(&connection_id, utils::mock::client_state_bytes()) - .await; - let height = hyperspace.latest_height_and_timestamp().await.unwrap().0; - - // hyperspace.query_connection_end(at, connection_id) - let connection_end = hyperspace - .query_connection_end(dbg!(height), connection_id.parse().unwrap()) - .await - .unwrap(); - - assert_eq!( - connection_end.connection, - Some(ibc_proto::ibc::core::connection::v1::ConnectionEnd { - client_id: client_id.parse().unwrap(), - counterparty: Some(ibc_proto::ibc::core::connection::v1::Counterparty { - client_id: client_id.parse().unwrap(), - connection_id: "counterparty-connection-id".parse().unwrap(), - prefix: None, - }), - state: ibc_proto::ibc::core::connection::v1::State::Open as i32, - delay_period: 0, - versions: vec![ibc_proto::ibc::core::connection::v1::Version { - identifier: "counterparty-version".into(), - features: vec!["ORDER_ORDERED".to_string(), "ORDER_UNORDERED".to_string()], - }], - }) - ); -} - -#[tokio::test] -async fn test_ibc_channel() { - let deploy = deploy_yui_ibc_and_mock_client_fixture().await; - let hyperspace = - hyperspace_ethereum_client_fixture(&deploy.anvil, deploy.yui_ibc.clone()).await; - let client_id = deploy_mock_client_fixture(&deploy).await; - - let mock_module = deploy_mock_module_fixture(&deploy).await; - deploy.yui_ibc.bind_port("port-0", mock_module.address()).await; - - let connection_id = client_id.open_connection(&deploy).await; - let channel_id = deploy.yui_ibc.channel_open_init("port-0", &connection_id).await; - deploy.yui_ibc.channel_open_ack(&channel_id, "port-0").await; - - let channels = hyperspace.query_channels().await.unwrap(); - assert!(!channels.is_empty()); - assert_eq!(channels[0].0, channel_id.parse().unwrap()); - - let height = hyperspace.latest_height_and_timestamp().await.unwrap().0; - - let channel_end = hyperspace - .query_channel_end(height, channel_id.parse().unwrap(), "port-0".parse().unwrap()) - .await - .unwrap(); - - let expected_channel = ibc_proto::ibc::core::channel::v1::Channel { - state: ibc_proto::ibc::core::channel::v1::State::Open as i32, - ordering: ibc_proto::ibc::core::channel::v1::Order::Unordered as i32, - counterparty: Some(ibc_proto::ibc::core::channel::v1::Counterparty { - port_id: "port-0".into(), - channel_id: channel_id.parse().unwrap(), - }), - connection_hops: vec![connection_id.parse().unwrap()], - version: "1".into(), - }; - assert_eq!(channel_end.channel, Some(expected_channel.clone())); - - // TODO: only used in integration tests. Should we really test that? - // let channels = hyperspace - // .query_connection_channels(height, &connection_id.parse().unwrap()) - // .await - // .unwrap(); - // assert_eq!( - // channels, - // vec![ibc_proto::ibc::core::channel::v1::IdentifiedChannel { - // state: expected_channel.state, - // ordering: expected_channel.ordering, - // counterparty: expected_channel.counterparty, - // connection_hops: expected_channel.connection_hops, - // version: expected_channel.version, - // port_id: "port-0".into(), - // channel_id, - // }] - // ); -} - -#[tokio::test] -async fn test_ibc_packet() { - let _ = env_logger::try_init(); - let mut deploy = deploy_yui_ibc_and_mock_client_fixture().await; - let hyperspace = - hyperspace_ethereum_client_fixture(&deploy.anvil, deploy.yui_ibc.clone()).await; - let events = hyperspace.ibc_events().await; - - let client_id = deploy_mock_client_fixture(&deploy).await; - - let mock_module = deploy_mock_module_fixture(&deploy).await; - deploy.yui_ibc.bind_port("port-0", mock_module.address()).await; - deploy.ibc_mock_module = Some(mock_module); - - let connection_id = client_id.open_connection(&deploy).await; - let channel_id = deploy.yui_ibc.channel_open_init("port-0", &connection_id).await; - deploy.yui_ibc.channel_open_ack(&channel_id, "port-0").await; - - let data = "hello_send".as_bytes().to_vec(); - let tx = deploy - .send_mock_packet( - PortId::from_str("port-0").unwrap(), - ChannelId::from_str("channel-0").unwrap(), - Height::new(0, 1000000), - data.clone(), - ) - .await; - let height = tx.block_number.unwrap().as_u64(); - - tx.logs.iter().for_each(|log| { - println!("send_packet log: {:#?}", log); - }); - - let send_packet = hyperspace - .query_send_packets( - ibc::Height { revision_number: 0, revision_height: height }, - ChannelId::from_str("channel-0").unwrap(), - PortId::from_str("port-0").unwrap(), - vec![1], - ) - .await - .unwrap() - .pop() - .unwrap(); - - let info = PacketInfo { - height: None, - sequence: 1, - source_port: "port-0".to_string(), - source_channel: "channel-0".to_string(), - destination_port: "port-0".to_string(), - destination_channel: "channel-0".to_string(), - channel_order: Order::Unordered.to_string(), - data: "hello_send".as_bytes().to_vec(), - timeout_height: Height::new(0, 1000000).into(), - timeout_timestamp: 0, - ack: None, - }; - assert_eq!(send_packet, info); - - // query_packet_commitment - let commitment = hyperspace - .query_packet_commitment( - ibc::Height { revision_number: 0, revision_height: height }, - &PortId::from_str("port-0").unwrap(), - &ChannelId::from_str("channel-0").unwrap(), - 1, - ) - .await - .unwrap(); - - assert_eq!( - commitment.commitment, - keccak256(&Sha256::digest( - &encode_packed(&[ - u64_to_token(0), - u64_to_token(0), - u64_to_token(1000000), - Token::Bytes(Sha256::digest(&data).to_vec()) - ]) - .unwrap() - )) - .to_vec() - ); - - // query_packet_commitments - let commitments = hyperspace - .query_packet_commitments( - ibc::Height { revision_number: 0, revision_height: height }, - ChannelId::from_str("channel-0").unwrap(), - PortId::from_str("port-0").unwrap(), - ) - .await - .unwrap(); - - assert_eq!(commitments, vec![1]); - - let sequence = Sequence(0); - let data = "hello_recv".as_bytes().to_vec(); - let ack_hash = keccak256(&Sha256::digest(&data)); - let tx = deploy - .yui_ibc - .recv_packet(Packet { - sequence, - source_port: PortId::from_str("port-0").unwrap(), - source_channel: ChannelId::from_str("channel-0").unwrap(), - destination_port: PortId::from_str("port-0").unwrap(), - destination_channel: ChannelId::from_str("channel-0").unwrap(), - data, - timeout_height: Height::new(0, 1000000), - timeout_timestamp: Timestamp::default(), - }) - .await; - let height = tx.block_number.unwrap().as_u64(); - - let ack = hyperspace - .query_packet_acknowledgement( - ibc::Height { revision_number: 0, revision_height: height }, - &PortId::from_str("port-0").unwrap(), - &ChannelId::from_str("channel-0").unwrap(), - sequence.0, // sequence - ) - .await - .unwrap(); - - println!("{}", hex::encode(&ack.acknowledgement)); - assert_eq!(ack.acknowledgement, ack_hash.to_vec()); - - let received_packets = hyperspace - .query_received_packets( - ibc::Height { revision_number: 0, revision_height: height }, - ChannelId::from_str("channel-0").unwrap(), - PortId::from_str("port-0").unwrap(), - vec![sequence.0], - ) - .await - .unwrap(); - assert_eq!( - received_packets, - vec![PacketInfo { - height: None, - sequence: sequence.0, - source_port: "port-0".to_string(), - source_channel: "channel-0".to_string(), - destination_port: "port-0".to_string(), - destination_channel: "channel-0".to_string(), - channel_order: Order::Unordered.to_string(), - data: "hello_recv".as_bytes().to_vec(), - timeout_height: Height::new(0, 1000000).into(), - timeout_timestamp: 0, - ack: None, - }] - ); - - // TODO: query_packet_receipt - let receipt = hyperspace - .query_packet_receipt( - ibc::Height { revision_number: 0, revision_height: height }, - &PortId::from_str("port-0").unwrap(), - &ChannelId::from_str("channel-0").unwrap(), - 0, // sequence - ) - .await - .unwrap(); - assert!(receipt.received); - - // query_packet_acknowledgements - let acks = hyperspace - .query_packet_acknowledgements( - ibc::Height { revision_number: 0, revision_height: height }, - ChannelId::from_str("channel-0").unwrap(), - PortId::from_str("port-0").unwrap(), - ) - .await - .unwrap(); - - assert_eq!(acks, vec![0]); - - // query_unreceived_packets - let unreceived = hyperspace - .query_unreceived_packets( - ibc::Height { revision_number: 0, revision_height: height }, - ChannelId::from_str("channel-0").unwrap(), - PortId::from_str("port-0").unwrap(), - vec![0, 1, 2], - ) - .await - .unwrap(); - assert_eq!(unreceived, vec![1, 2]); - - // query_unreceived_acknowledgements - let unreceived = hyperspace - .query_unreceived_acknowledgements( - ibc::Height { revision_number: 0, revision_height: height }, - ChannelId::from_str("channel-0").unwrap(), - PortId::from_str("port-0").unwrap(), - vec![0, 1, 2], - ) - .await - .unwrap(); - assert_eq!(unreceived, vec![1, 2]); - - let events = events.collect::>().await; - dbg!(events); -} - -fn u64_to_token(x: u64) -> Token { - let n = U256::from(x); - let mut buf = [0; 32]; - n.to_big_endian(&mut buf); - let start = (32 - u64::BITS / 8) as usize; - Token::Bytes(buf[start..32].to_vec()) -} diff --git a/hyperspace/ethereum/src/utils.rs b/hyperspace/ethereum/src/utils.rs index ee0aaee68..4761a76bd 100644 --- a/hyperspace/ethereum/src/utils.rs +++ b/hyperspace/ethereum/src/utils.rs @@ -66,7 +66,7 @@ where assert_eq!(tx_recp.status, Some(1.into())); } - pub async fn connection_open_init(&self, client_id: &str) -> String { + pub async fn connection_open_init_mock(&self, client_id: &str) -> String { let connection_open_init = self .method::<_, String>( "connectionOpenInit", @@ -93,7 +93,7 @@ where connection_id } - pub async fn connection_open_ack(&self, connection_id: &str, client_state_bytes: Vec) { + pub async fn connection_open_ack_mock(&self, connection_id: &str, client_state_bytes: Vec) { let connection_open_ack = self .method::<_, ()>( "connectionOpenAck", @@ -123,7 +123,7 @@ where assert_eq!(tx_recp.status, Some(1.into())); } - pub async fn channel_open_init(&self, port_id: &str, connection_id: &str) -> String { + pub async fn channel_open_init_mock(&self, port_id: &str, connection_id: &str) -> String { let fut = self .method::<_, String>( "channelOpenInit", @@ -230,6 +230,110 @@ where tx } + pub async fn create_client(&self, msg: Token) -> String { + let method = self.method::<_, String>("createClient", (msg,)).unwrap(); + + let client_id = method.call().await.unwrap_contract_error(); + + let receipt = method.send().await.unwrap().await.unwrap().unwrap(); + assert_eq!(receipt.status, Some(1.into())); + + client_id + } + + pub async fn update_client(&self, msg: Token) { + let method = self.method::<_, ()>("updateClient", (msg,)).unwrap(); + + let gas_estimate_update_client = method.estimate_gas().await.unwrap(); + dbg!(gas_estimate_update_client); + let client_id = method.call().await.unwrap_contract_error(); + + let receipt = method.send().await.unwrap().await.unwrap().unwrap(); + assert_eq!(receipt.status, Some(1.into())); + } + + pub async fn connection_open_ack(&self, msg: Token) { + let method = self.method::<_, ()>("connectionOpenAck", (msg,)).unwrap(); + + let gas_estimate_connection_open = method.estimate_gas().await.unwrap(); + dbg!(gas_estimate_connection_open); + let _ = method.call().await.unwrap_contract_error(); + + let receipt = method.send().await.unwrap().await.unwrap().unwrap(); + assert_eq!(receipt.status, Some(1.into())); + } + + pub async fn connection_open_try(&self, msg: Token) -> String { + let method = self.method::<_, String>("connectionOpenTry", (msg,)).unwrap(); + + let gas_estimate_connection_open_try = method.estimate_gas().await.unwrap(); + dbg!(gas_estimate_connection_open_try); + let id = method.call().await.unwrap_contract_error(); + + let receipt = method.send().await.unwrap().await.unwrap().unwrap(); + assert_eq!(receipt.status, Some(1.into())); + id + } + + pub async fn connection_open_init(&self, msg: Token) -> String { + let method = self.method::<_, String>("connectionOpenInit", (msg,)).unwrap(); + + let gas_estimate_connection_open_try = method.estimate_gas().await.unwrap(); + dbg!(gas_estimate_connection_open_try); + let id = method.call().await.unwrap_contract_error(); + + let receipt = method.send().await.unwrap().await.unwrap().unwrap(); + assert_eq!(receipt.status, Some(1.into())); + id + } + + pub async fn connection_open_confirm(&self, msg: Token) { + let method = self.method::<_, ()>("connectionOpenConfirm", (msg,)).unwrap(); + + let gas_estimate_connection_open_confirm = method.estimate_gas().await.unwrap(); + dbg!(gas_estimate_connection_open_confirm); + let _ = method.call().await.unwrap_contract_error(); + + let receipt = method.send().await.unwrap().await.unwrap().unwrap(); + assert_eq!(receipt.status, Some(1.into())); + } + + pub async fn channel_open_init(&self, msg: Token) -> String { + let method = self.method::<_, String>("channelOpenInit", (msg,)).unwrap(); + + let gas_estimate_connection_id = method.estimate_gas().await.unwrap(); + dbg!(gas_estimate_connection_id); + let connection_id = method.call().await.unwrap_contract_error(); + + let receipt = method.send().await.unwrap().await.unwrap().unwrap(); + assert_eq!(receipt.status, Some(1.into())); + connection_id + } + + pub async fn channel_open_try(&self, msg: Token) -> String { + let method = self.method::<_, String>("channelOpenTry", (msg,)).unwrap(); + + let gas_estimate_connection_id = method.estimate_gas().await.unwrap(); + dbg!(gas_estimate_connection_id); + let connection_id = method.call().await.unwrap_contract_error(); + + let receipt = method.send().await.unwrap().await.unwrap().unwrap(); + assert_eq!(receipt.status, Some(1.into())); + connection_id + } + + pub async fn send_and_get_tuple(&self, msg: Token, method_name: impl AsRef) -> () { + let method = self.method::<_, ()>(method_name.as_ref(), (msg,)).unwrap(); + + let gas_estimate = method.estimate_gas().await.unwrap(); + dbg!(gas_estimate); + let ret = method.call().await.unwrap_contract_error(); + + let receipt = method.send().await.unwrap().await.unwrap().unwrap(); + assert_eq!(receipt.status, Some(1.into())); + ret + } + pub fn method( &self, name: &str, @@ -294,19 +398,6 @@ where assert_eq!(receipt.status, Some(1.into())); } - pub async fn create_client(&self, msg: Token) -> String { - let method = self.method::<_, String>("createClient", (msg,)).unwrap(); - - let client_id = method.call().await.unwrap_contract_error(); - - let receipt = method.send().await.unwrap().await.unwrap().unwrap(); - assert_eq!(receipt.status, Some(1.into())); - - println!("{:?}", receipt.block_number); - - client_id - } - pub fn find_storage(&self, name: &str) -> &Storage { self.storage_layout.storage.iter().find(|x| x.contract == name).unwrap() } @@ -318,10 +409,6 @@ where { fn clone(&self) -> Self { Self { - // ibc_client: self.ibc_client.clone(), - // ibc_connection: self.ibc_connection.clone(), - // ibc_channel_handshake: self.ibc_channel_handshake.clone(), - // ibc_packet: self.ibc_packet.clone(), facet_cuts: self.facet_cuts.clone(), deployed_facets: self.deployed_facets.clone(), diamond: self.diamond.clone(), diff --git a/hyperspace/ethereum/tests/sanity_checks.rs b/hyperspace/ethereum/tests/sanity_checks.rs index 56aa2962f..6d1f85877 100644 --- a/hyperspace/ethereum/tests/sanity_checks.rs +++ b/hyperspace/ethereum/tests/sanity_checks.rs @@ -1,6 +1,5 @@ use std::{future::Future, ops::Deref, path::PathBuf, str::FromStr, sync::Arc, time::Duration}; -use crate::utils::USE_GETH; use cast::revm::new; use ecdsa::SigningKey; use elliptic_curve::pkcs8::der::pem; @@ -18,9 +17,10 @@ use ethers_solc::{Artifact, ProjectCompileOutput, ProjectPathsConfig}; use futures::{Stream, TryStreamExt}; use hyperspace_cosmos::client::{CosmosClient, CosmosClientConfig}; use hyperspace_ethereum::{ - client::EthRpcClient, + client::{EthRpcClient, EthereumClient}, config::EthereumClientConfig, - contract::{DiamandHandler, IbcHandler, UnwrapContractError}, + contract::{IbcHandler, UnwrapContractError}, + mock::{utils, utils::USE_GETH}, utils::{DeployYuiIbc, ProviderImpl}, yui_types::IntoToken, }; @@ -64,7 +64,7 @@ use ibc::{ tx_msg::Msg, }; use ibc_proto::google::protobuf::Any; -use ibc_rpc::PacketInfo; +use ibc_rpc::{IbcApiClient, PacketInfo}; use ics07_tendermint::client_state::ClientState; use pallet_ibc::light_clients::{AnyClientState, AnyConsensusState, HostFunctionsManager}; use primitives::{mock::LocalClientTypes, Chain, IbcProvider}; @@ -77,14 +77,10 @@ use tokio_stream::{Elapsed, StreamExt as _}; use tracing::log; use tracing_subscriber::{filter, layer::SubscriberExt, util::SubscriberInitExt, Layer}; -mod utils; - -async fn hyperspace_ethereum_client_fixture( - anvil: ðers::utils::AnvilInstance, +pub async fn hyperspace_ethereum_client_fixture( + anvil: &AnvilInstance, yui_ibc: DeployYuiIbc, ProviderImpl>, - client: Option>, - diamond_hanlder: Option, -) -> hyperspace_ethereum::client::EthereumClient { +) -> EthereumClientConfig { let endpoint = if USE_GETH { "http://localhost:6001".to_string() } else { anvil.endpoint() }; let wallet_path = if USE_GETH { Some("keys/0x73db010c3275eb7a92e5c38770316248f4c644ee".to_string()) @@ -92,11 +88,6 @@ async fn hyperspace_ethereum_client_fixture( None }; - dbg!("hyperspace_ethereum_client_fixture"); - dbg!(anvil.endpoint()); - dbg!(anvil.chain_id()); - dbg!("hyperspace_ethereum_client_fixture"); - let wallet = if !USE_GETH { Some( anvil.keys()[0] @@ -111,7 +102,7 @@ async fn hyperspace_ethereum_client_fixture( None }; - let mut ret = hyperspace_ethereum::client::EthereumClient::new(EthereumClientConfig { + EthereumClientConfig { http_rpc_url: endpoint.parse().unwrap(), ws_rpc_url: "ws://localhost:5001".parse().unwrap(), beacon_rpc_url: Default::default(), @@ -131,23 +122,13 @@ async fn hyperspace_ethereum_client_fixture( wasm_code_id: None, yui: Some(yui_ibc), client_type: "07-tendermint".into(), - diamond_handler: diamond_hanlder, - }) - .await - .unwrap(); - - if let Some(client) = client { - ret.http_rpc = client; } - - ret } #[allow(dead_code)] -struct DeployYuiIbcMockClient { +pub struct DeployYuiIbcMockClient { pub path: PathBuf, pub project_output: ProjectCompileOutput, - // pub project_output: ethers::solc::ProjectCompileOutput, pub anvil: AnvilInstance, pub client: Arc, pub ibc_mock_client: ContractInstance, ProviderImpl>, @@ -202,7 +183,7 @@ impl DeployYuiIbcMockClient { } } -async fn deploy_yui_ibc_and_mock_client_fixture() -> DeployYuiIbcMockClient { +pub async fn deploy_yui_ibc_and_mock_client_fixture() -> DeployYuiIbcMockClient { let path = utils::yui_ibc_solidity_path(); let project_output = utils::compile_yui(&path, "contracts/core"); let diamond_project_output = utils::compile_yui(&path, "contracts/diamond"); @@ -256,10 +237,10 @@ impl Deref for ClientId { impl ClientId { pub async fn open_connection(&self, deploy: &DeployYuiIbcMockClient) -> String { - let connection_id = deploy.yui_ibc.connection_open_init(&self.0).await; + let connection_id = deploy.yui_ibc.connection_open_init_mock(&self.0).await; let () = deploy .yui_ibc - .connection_open_ack(&connection_id, utils::mock::client_state_bytes()) + .connection_open_ack_mock(&connection_id, utils::mock::client_state_bytes()) .await; connection_id } @@ -324,19 +305,14 @@ async fn test_deploy_yui_ibc_and_create_eth_client() { let mut yui_ibc = utils::deploy_yui_ibc(&project_output, &diamond_project_output, client.clone()).await; - let diamond = DiamandHandler::new(yui_ibc.clone().deployed_facets, yui_ibc.clone().diamond); - /* ______________________________________________________________________________ */ /* ______________________________________________________________________________ */ //create ethereum hyperspace client - let mut hyperspace = hyperspace_ethereum_client_fixture( - &anvil, - yui_ibc.clone(), - Some(client.clone()), - Some(diamond.clone()), - ) - .await; + let mut hyperspace = + EthereumClient::new(hyperspace_ethereum_client_fixture(&anvil, yui_ibc.clone()).await) + .await + .unwrap(); /* ______________________________________________________________________________ */ /* ______________________________________________________________________________ */ @@ -536,7 +512,7 @@ async fn test_deploy_yui_ibc_and_create_eth_client() { "failed to verify clientState" ); */ - diamond.connection_open_try(yui_conn_try.into_token()).await; + yui_ibc.connection_open_try(yui_conn_try.into_token()).await; /* ______________________________________________________________________________ */ /* ______________________________________________________________________________ */ @@ -715,24 +691,28 @@ async fn relayer_channel_tests() { // channel) #[tokio::test] -#[ignore] async fn test_deploy_yui_ibc_and_mock_client() { deploy_yui_ibc_and_mock_client_fixture().await; } #[tokio::test] -#[ignore] async fn test_hyperspace_ethereum_client() { let DeployYuiIbcMockClient { anvil, yui_ibc, .. } = deploy_yui_ibc_and_mock_client_fixture().await; - let _hyperspace = hyperspace_ethereum_client_fixture(&anvil, yui_ibc.clone(), None, None).await; + let _hyperspace = + EthereumClient::new(hyperspace_ethereum_client_fixture(&anvil, yui_ibc.clone()).await) + .await + .unwrap(); } #[tokio::test] async fn test_ibc_client() { let deploy = deploy_yui_ibc_and_mock_client_fixture().await; - let hyperspace = - hyperspace_ethereum_client_fixture(&deploy.anvil, deploy.yui_ibc.clone(), None, None).await; + let hyperspace = EthereumClient::new( + hyperspace_ethereum_client_fixture(&deploy.anvil, deploy.yui_ibc.clone()).await, + ) + .await + .unwrap(); let events = hyperspace.ibc_events().await; let client_id = deploy_mock_client_fixture(&deploy).await; let height = hyperspace.latest_height_and_timestamp().await.unwrap().0; @@ -795,14 +775,17 @@ async fn test_ibc_connection() { ))) .init(); let deploy = deploy_yui_ibc_and_mock_client_fixture().await; - let hyperspace = - hyperspace_ethereum_client_fixture(&deploy.anvil, deploy.yui_ibc.clone(), None, None).await; + let hyperspace = EthereumClient::new( + hyperspace_ethereum_client_fixture(&deploy.anvil, deploy.yui_ibc.clone()).await, + ) + .await + .unwrap(); let client_id = deploy_mock_client_fixture(&deploy).await; - let connection_id = deploy.yui_ibc.connection_open_init(&client_id).await; + let connection_id = deploy.yui_ibc.connection_open_init_mock(&client_id).await; let () = deploy .yui_ibc - .connection_open_ack(&connection_id, utils::mock::client_state_bytes()) + .connection_open_ack_mock(&connection_id, utils::mock::client_state_bytes()) .await; let height = hyperspace.latest_height_and_timestamp().await.unwrap().0; @@ -834,15 +817,18 @@ async fn test_ibc_connection() { #[tokio::test] async fn test_ibc_channel() { let deploy = deploy_yui_ibc_and_mock_client_fixture().await; - let hyperspace = - hyperspace_ethereum_client_fixture(&deploy.anvil, deploy.yui_ibc.clone(), None, None).await; + let hyperspace = EthereumClient::new( + hyperspace_ethereum_client_fixture(&deploy.anvil, deploy.yui_ibc.clone()).await, + ) + .await + .unwrap(); let client_id = deploy_mock_client_fixture(&deploy).await; let mock_module = deploy_mock_module_fixture(&deploy).await; deploy.yui_ibc.bind_port("port-0", mock_module.address()).await; let connection_id = client_id.open_connection(&deploy).await; - let channel_id = deploy.yui_ibc.channel_open_init("port-0", &connection_id).await; + let channel_id = deploy.yui_ibc.channel_open_init_mock("port-0", &connection_id).await; deploy.yui_ibc.channel_open_ack(&channel_id, "port-0").await; let channels = hyperspace.query_channels().await.unwrap(); @@ -891,8 +877,11 @@ async fn test_ibc_channel() { async fn test_ibc_packet() { let _ = env_logger::try_init(); let mut deploy = deploy_yui_ibc_and_mock_client_fixture().await; - let hyperspace = - hyperspace_ethereum_client_fixture(&deploy.anvil, deploy.yui_ibc.clone(), None, None).await; + let hyperspace = EthereumClient::new( + hyperspace_ethereum_client_fixture(&deploy.anvil, deploy.yui_ibc.clone()).await, + ) + .await + .unwrap(); let events = hyperspace.ibc_events().await; let client_id = deploy_mock_client_fixture(&deploy).await; @@ -901,7 +890,7 @@ async fn test_ibc_packet() { deploy.ibc_mock_module = Some(mock_module); let connection_id = client_id.open_connection(&deploy).await; - let channel_id = deploy.yui_ibc.channel_open_init("port-0", &connection_id).await; + let channel_id = deploy.yui_ibc.channel_open_init_mock("port-0", &connection_id).await; deploy.yui_ibc.channel_open_ack(&channel_id, "port-0").await; let data = "hello_send".as_bytes().to_vec(); diff --git a/hyperspace/ethereum/tests/utils.rs b/hyperspace/ethereum/tests/utils.rs deleted file mode 100644 index cd1c23b60..000000000 --- a/hyperspace/ethereum/tests/utils.rs +++ /dev/null @@ -1,386 +0,0 @@ -#![allow(dead_code)] - -use cast::hashbrown::HashSet; -use std::{ - collections::HashMap, - fs::File, - iter::once, - path::{Path, PathBuf}, - sync::Arc, - time::Duration, -}; - -use ethers::{ - abi::{Detokenize, Token, Tokenize}, - contract::ContractFactory, - core::{rand::rngs::ThreadRng, utils::Anvil}, - middleware::SignerMiddleware, - prelude::{ContractInstance, *}, - providers::{Http, Middleware, Provider}, - signers::{LocalWallet, Signer}, - utils::AnvilInstance, -}; -use ethers_solc::{ - artifacts::{ - output_selection::OutputSelection, DebuggingSettings, Libraries, Optimizer, - OptimizerDetails, RevertStrings, Settings, SettingsMetadata, StorageLayout, - }, - Artifact, ConfigurableContractArtifact, EvmVersion, Project, ProjectCompileOutput, - ProjectPathsConfig, SolcConfig, -}; -use futures::SinkExt; -use hyperspace_ethereum::{ - contract::UnwrapContractError, - utils::{DeployYuiIbc, FacetCut, FacetCutAction}, -}; -use ibc::{ - core::{ - ics04_channel::packet::Packet, - ics24_host::identifier::{ChannelId, PortId}, - }, - timestamp::Timestamp, - Height, -}; -use tracing::log; - -pub const USE_GETH: bool = true; - -#[track_caller] -pub fn yui_ibc_solidity_path() -> PathBuf { - let base = env!("CARGO_MANIFEST_DIR"); - let default = PathBuf::from(base).join("yui-ibc-solidity"); - - if let Ok(path) = std::env::var("YUI_IBC_SOLIDITY_PATH") { - path.into() - } else { - default - } -} - -#[track_caller] -pub fn spawn_anvil() -> (AnvilInstance, Arc, LocalWallet>>) { - let anvil = Anvil::new().spawn(); - let wallet: LocalWallet = if USE_GETH { - LocalWallet::decrypt_keystore( - "keys/0x73db010c3275eb7a92e5c38770316248f4c644ee", - option_env!("KEY_PASS").expect("KEY_PASS not set"), - ) - .unwrap() - .into() - } else { - anvil.keys()[0].clone().into() - }; - - let endpoint = if USE_GETH { "http://localhost:6001".to_string() } else { anvil.endpoint() }; - let provider = Provider::::try_from(endpoint) - .unwrap() - .interval(Duration::from_millis(10u64)); - let chain_id = if USE_GETH { 4242u64 } else { anvil.chain_id() }; - let client = SignerMiddleware::new(provider, wallet.with_chain_id(chain_id)); - let client = Arc::new(client); - - (anvil, client) -} - -#[track_caller] -pub fn compile_solc(project_paths: ProjectPathsConfig) -> ProjectCompileOutput { - // custom solc config to solve Yul-relatated compilation errors - let mut selection = OutputSelection::default_output_selection(); - selection - .0 - .get_mut("*") - .unwrap() - .get_mut("*") - .unwrap() - .push("storageLayout".to_string()); - let solc_config = SolcConfig { - settings: Settings { - stop_after: None, - remappings: vec![], - optimizer: Optimizer { - enabled: Some(true), - runs: Some(256), - details: Some(OptimizerDetails { - peephole: Some(true), - inliner: Some(true), - jumpdest_remover: Some(true), - order_literals: Some(true), - deduplicate: Some(true), - cse: Some(true), - constant_optimizer: Some(true), - yul: Some(false), - yul_details: None, - }), - }, - model_checker: None, - metadata: None, - output_selection: selection, - evm_version: Some(EvmVersion::Paris), - via_ir: Some(false), - // debug: Some(DebuggingSettings { - // revert_strings: Some(RevertStrings::Debug), - // debug_info: vec!["location".to_string()], - // }), - debug: None, - libraries: Libraries { libs: Default::default() }, - }, - }; - - let mut project = Project::builder() - .paths(project_paths) - .ephemeral() - .solc_config(solc_config) - .build() - .expect("project build failed"); - - // TODO: figure out how to enable it in the config - // project.artifacts.additional_values.storage_layout = true; - project.artifacts.additional_files.abi = true; - // project.solc.args.push("--storage-layout".to_string()); - - let project_output = project.compile().expect("compilation failed"); - - if project_output.has_compiler_errors() { - for err in project_output.output().errors { - eprintln!("{}", err); - } - panic!("compiler errors"); - } - - return project_output -} - -/// Uses solc to compile the yui-ibc-solidity contracts. -/// -/// first argument is the path to the yui-ibc-solidity repo. -/// the second argument is the path to the solidity sources, relative to the first argument. -/// -/// so if you have the yui-ibc-solidity as the path to yui then sources should be "contracts/core" -/// for IBCHandler or "contracts/clients" for the clients. -#[track_caller] -pub fn compile_yui(path_to_yui: &Path, sources: &str) -> ProjectCompileOutput { - assert!( - path_to_yui.exists(), - "path to yui-ibc-solidity does not exist: {}", - path_to_yui.display() - ); - - let project_paths = ProjectPathsConfig::builder() - .root(&path_to_yui) - .sources(path_to_yui.join(sources)) - .build() - .unwrap(); - - compile_solc(project_paths) -} - -#[allow(dead_code)] -pub async fn deploy_contract( - contract: &ConfigurableContractArtifact, - constructor_args: T, - client: Arc, -) -> ContractInstance, M> -where - M: Middleware, - T: abi::Tokenize, -{ - let (abi, bytecode, _) = contract.clone().into_parts(); - let mut factory = ContractFactory::new(abi.unwrap(), bytecode.unwrap(), client.clone()); - factory.deploy(constructor_args).unwrap().send().await.unwrap() -} - -pub mod mock { - use ethers::abi::Token; - use prost::Message; - - #[derive(Clone, PartialEq, ::prost::Message)] - pub struct ClientState { - #[prost(message, required, tag = "1")] - pub height: ibc_proto::ibc::core::client::v1::Height, - } - - #[derive(Clone, PartialEq, ::prost::Message)] - pub struct ConsensusState { - #[prost(uint64, tag = "1")] - pub timestamp: u64, - } - - pub fn create_client_msg(kind: &str) -> Token { - let client_state_bytes = client_state_bytes(); - - let consensus_state_bytes = ibc_proto::google::protobuf::Any { - type_url: "/ibc.lightclients.mock.v1.ConsensusState".into(), - value: ConsensusState { timestamp: 1 }.encode_to_vec(), - } - .encode_to_vec(); - - Token::Tuple(vec![ - Token::String(kind.into()), - Token::Bytes(client_state_bytes), - Token::Bytes(consensus_state_bytes), - ]) - } - - pub fn client_state_bytes() -> Vec { - ibc_proto::google::protobuf::Any { - type_url: "/ibc.lightclients.mock.v1.ClientState".into(), - value: ClientState { - height: ibc_proto::ibc::core::client::v1::Height { - revision_number: 0, - revision_height: 1, - }, - } - .encode_to_vec(), - } - .encode_to_vec() - } -} - -fn get_selectors(contract: &ContractInstance, M>) -> Vec<(String, [u8; 4])> -where - M: Middleware, -{ - let signatures = contract.abi().functions.keys().cloned().collect::>(); - signatures - .into_iter() - .filter(|val| val != "init(bytes)") - .map(|val| (val.clone(), contract.abi().function(&val).unwrap().short_signature())) - .collect() -} - -pub async fn deploy_yui_ibc( - project_output: &ProjectCompileOutput, - diamond_project_output: &ProjectCompileOutput, - client: Arc, -) -> DeployYuiIbc, M> -where - M: Middleware, -{ - let facet_names = [ - "IBCClient", - "IBCConnection", - "IBCChannelHandshake", - "IBCPacket", - "IBCQuerier", - "DiamondCutFacet", - "DiamondLoupeFacet", - "OwnershipFacet", - ]; - - project_output.artifacts().for_each(|(name, artifact)| { - let size = artifact.bytecode.as_ref().unwrap().object.as_bytes().unwrap().len(); - let max = 24 * 1024; - if size > max { - panic!("{} size is too big: {}/{}", name, size, max); - } - log::info!("{} size: {}/{}", name, size, max); - }); - diamond_project_output.artifacts().for_each(|(name, artifact)| { - let size = artifact.bytecode.as_ref().unwrap().object.as_bytes().unwrap().len(); - let max = 24 * 1024; - if size > max { - panic!("{} size is too big: {}/{}", name, size, max); - } - log::info!("{} size: {}/{}", name, size, max); - }); - - let acc = client.default_sender().unwrap(); - - println!("Sender account: {acc:?}"); - - let contract = diamond_project_output.find_first("DiamondInit").unwrap(); - let (abi, bytecode, _) = contract.clone().into_parts(); - let factory = ContractFactory::new(abi.unwrap(), bytecode.unwrap(), client.clone()); - let diamond_init = factory.deploy(()).unwrap().send().await.unwrap(); - println!("Diamond init address: {:?}", diamond_init.address()); - - let mut sigs = HashMap::<[u8; 4], (String, String)>::new(); - let mut facet_cuts = vec![]; - let mut deployed_facets = vec![]; - for facet_name in facet_names { - let contract = project_output - .find_first(facet_name) - .or_else(|| diamond_project_output.find_first(facet_name)) - .unwrap(); - let (abi, bytecode, _) = contract.clone().into_parts(); - let factory = ContractFactory::new(abi.unwrap(), bytecode.unwrap(), client.clone()); - let facet = factory.deploy(()).unwrap().send().await.unwrap(); - let facet_address = facet.address(); - println!("Deployed {facet_name} on {facet_address:?}"); - deployed_facets.push(facet.clone()); - let selectors = get_selectors(&facet); - - for (name, selector) in &selectors { - if sigs.contains_key(selector) { - let (contract_name, fn_name) = &sigs[selector]; - panic!( - "duplicate selector: {}:{} and {}:{}", - contract_name, fn_name, facet_name, name - ); - } - sigs.insert(*selector, (facet_name.to_owned(), name.clone())); - } - - let facet_cut = FacetCut { address: facet_address, action: FacetCutAction::Add, selectors }; - facet_cuts.push(facet_cut); - } - let init_calldata = diamond_init.method::<_, ()>("init", ()).unwrap().calldata().unwrap(); - - let contract = diamond_project_output.find_first("Diamond").unwrap(); - let (abi, bytecode, _) = contract.clone().into_parts(); - let factory = ContractFactory::new(abi.unwrap(), bytecode.unwrap(), client.clone()); - let diamond = factory - .deploy(Token::Tuple(vec![ - Token::Array(facet_cuts.clone().into_iter().map(|x| x.into_token()).collect()), - Token::Tuple(vec![ - Token::Address(acc), - Token::Address(diamond_init.address()), - Token::Bytes(init_calldata.0.into()), - ]), - ])) - .unwrap() - .send() - .await - .unwrap(); - - // std::fs::ReadDir::new(). - let predefined_layout = serde_json::from_reader::<_, StorageLayout>( - File::open("/Users/vmark/work/centauri-private/hyperspace/ethereum/src/storage_layout/ibc_storage.json").unwrap(), - ) - .expect("failed to read predefined storage layout"); - - let storage_layout = project_output - .compiled_artifacts() - .iter() - .chain(diamond_project_output.compiled_artifacts()) - .flat_map(|(_, artifact)| { - artifact.into_iter().flat_map(|(an, artifact)| { - println!("artifact name {an}"); - artifact - }) - }) - .filter_map(|ar| ar.artifact.storage_layout.clone()) - .chain(once(predefined_layout)) - .fold(StorageLayout { storage: vec![], types: Default::default() }, |mut acc, layout| { - // let mut len0 = acc.storage.len(); - // let mut len1 = layout.storage.len(); - acc.storage.extend(layout.storage); - // assert_eq!(acc.storage.len(), len0 + len1, "duplicated storage"); - - let len0 = acc.types.len(); - let len1 = layout.types.len(); - acc.types.extend(layout.types); - assert_eq!(acc.types.len(), len0 + len1, "duplicated type"); - acc - }); - - let tendermint_client = diamond.clone(); - - DeployYuiIbc { - diamond, - facet_cuts, - deployed_facets, - storage_layout, - tendermint: tendermint_client, - } -} diff --git a/hyperspace/parachain/src/provider.rs b/hyperspace/parachain/src/provider.rs index c23c71d45..f71667944 100644 --- a/hyperspace/parachain/src/provider.rs +++ b/hyperspace/parachain/src/provider.rs @@ -452,7 +452,6 @@ where self.channel_whitelist.lock().unwrap().iter().cloned().collect() } - #[cfg(test)] async fn query_connection_channels( &self, at: Height, diff --git a/hyperspace/primitives/src/lib.rs b/hyperspace/primitives/src/lib.rs index 2ecf1f950..992df271e 100644 --- a/hyperspace/primitives/src/lib.rs +++ b/hyperspace/primitives/src/lib.rs @@ -340,7 +340,6 @@ pub trait IbcProvider { fn channel_whitelist(&self) -> HashSet<(ChannelId, PortId)>; /// Query all channels for a connection - #[cfg(test)] async fn query_connection_channels( &self, at: Height, diff --git a/hyperspace/testsuite/tests/ethereum_cosmos.rs b/hyperspace/testsuite/tests/ethereum_cosmos.rs index f0c13f3ef..306bd32fb 100644 --- a/hyperspace/testsuite/tests/ethereum_cosmos.rs +++ b/hyperspace/testsuite/tests/ethereum_cosmos.rs @@ -103,6 +103,32 @@ async fn setup_clients() -> (AnyChain, AnyChain) { let DeployYuiIbcMockClient { anvil, yui_ibc, .. } = deploy_yui_ibc_and_mock_client_fixture().await; + /* + let upd = project_output1.find_first("DelegateTendermintUpdate").unwrap(); + let (abi, bytecode, _) = upd.clone().into_parts(); + let factory = ContractFactory::new(abi.unwrap(), bytecode.unwrap(), client.clone()); + let update_client_delegate_contract = factory.deploy(()).unwrap().send().await.unwrap(); + + let contract = project_output1.find_first("TendermintLightClientSimple").unwrap(); + // dbg!(&contract); + let r = contract.clone(); + let (abi, bytecode, _) = r.into_parts(); + + let factory = ContractFactory::new(abi.unwrap(), bytecode.unwrap(), client.clone()); + let tendermint_light_client = factory + .deploy(( + Token::Address(yui_ibc.ibc_handler.address()), + Token::Address(update_client_delegate_contract.address()), + )) + .unwrap() + .send() + .await + .unwrap(); + + //replace the tendermint client address in hyperspace config with a real one + hyperspace.config.tendermint_client_address = tendermint_light_client.address(); + + */ let config_a = hyperspace_ethereum_client_fixture(&anvil, yui_ibc).await; let mut config_b = CosmosClientConfig { From fafc2a302e41717fb110c21869f73fc676066f78 Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Tue, 5 Sep 2023 20:19:55 -0300 Subject: [PATCH 14/43] Update ethereum client and test parameters and fix tests --- Cargo.lock | 2 + contracts/pallet-ibc/src/light_clients.rs | 2 +- hyperspace/ethereum/src/client.rs | 3 +- hyperspace/ethereum/src/config.rs | 1 + hyperspace/ethereum/src/mock/utils.rs | 52 ++++++++- hyperspace/ethereum/tests/sanity_checks.rs | 48 --------- hyperspace/testsuite/Cargo.toml | 2 + hyperspace/testsuite/tests/ethereum_cosmos.rs | 102 ++++++++++-------- light-clients/icsxx-ethereum/src/tests.rs | 3 - 9 files changed, 117 insertions(+), 98 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c4e75ed30..5a8470482 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4995,6 +4995,8 @@ version = "0.1.0" dependencies = [ "anyhow", "async-trait", + "ethers 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ethers-solc 2.0.9", "finality-grandpa", "futures", "grandpa-light-client-primitives", diff --git a/contracts/pallet-ibc/src/light_clients.rs b/contracts/pallet-ibc/src/light_clients.rs index 24fe08455..63a090c26 100644 --- a/contracts/pallet-ibc/src/light_clients.rs +++ b/contracts/pallet-ibc/src/light_clients.rs @@ -389,7 +389,7 @@ impl AnyClientMessage { }, #[cfg(feature = "ethereum")] Self::Ethereum(m) => match m { - icsxx_ethereum::client_message::ClientMessage::Header(h) => None, + icsxx_ethereum::client_message::ClientMessage::Header(h) => None, /* TODO: header height */ icsxx_ethereum::client_message::ClientMessage::Misbehaviour(_) => None, }, #[cfg(test)] diff --git a/hyperspace/ethereum/src/client.rs b/hyperspace/ethereum/src/client.rs index 587fde5b1..934c6ae7f 100644 --- a/hyperspace/ethereum/src/client.rs +++ b/hyperspace/ethereum/src/client.rs @@ -1,5 +1,6 @@ use crate::{ config::EthereumClientConfig, + jwt::{JwtAuth, JwtKey}, utils::{DeployYuiIbc, ProviderImpl}, }; use async_trait::async_trait; @@ -15,8 +16,6 @@ use ethers::{ types::U256, utils::keccak256, }; -// use ethers_providers:: -use crate::jwt::{JwtAuth, JwtKey}; use futures::{Stream, TryFutureExt}; use ibc::{ applications::transfer::{msgs::transfer::MsgTransfer, PrefixedCoin}, diff --git a/hyperspace/ethereum/src/config.rs b/hyperspace/ethereum/src/config.rs index 56deefe58..df0786872 100644 --- a/hyperspace/ethereum/src/config.rs +++ b/hyperspace/ethereum/src/config.rs @@ -74,6 +74,7 @@ pub struct EthereumClientConfig { pub beacon_rpc_url: http::uri::Uri, /// address of the OwnableIBCHandler contract. #[serde(deserialize_with = "address_de")] + // TODO: remove and use `yui.diamond.address()` instead pub ibc_handler_address: Address, /// address of the IBCChannelHandshake contract. #[serde(deserialize_with = "address_de")] diff --git a/hyperspace/ethereum/src/mock/utils.rs b/hyperspace/ethereum/src/mock/utils.rs index 38ea53352..509355895 100644 --- a/hyperspace/ethereum/src/mock/utils.rs +++ b/hyperspace/ethereum/src/mock/utils.rs @@ -1,6 +1,7 @@ #![allow(dead_code)] use cast::hashbrown::HashSet; +use elliptic_curve::pkcs8::der::pem; use std::{ collections::HashMap, fs::File, @@ -11,8 +12,9 @@ use std::{ }; use crate::{ + config::EthereumClientConfig, contract::UnwrapContractError, - utils::{DeployYuiIbc, FacetCut, FacetCutAction}, + utils::{DeployYuiIbc, FacetCut, FacetCutAction, ProviderImpl}, }; use ethers::{ abi::{Detokenize, Token, Tokenize}, @@ -387,3 +389,51 @@ where tendermint: tendermint_client, } } + +pub async fn hyperspace_ethereum_client_fixture( + anvil: &AnvilInstance, + yui_ibc: DeployYuiIbc, ProviderImpl>, +) -> EthereumClientConfig { + let endpoint = if USE_GETH { "http://localhost:6001".to_string() } else { anvil.endpoint() }; + let wallet_path = if USE_GETH { + Some("keys/0x73db010c3275eb7a92e5c38770316248f4c644ee".to_string()) + } else { + None + }; + + let wallet = if !USE_GETH { + Some( + anvil.keys()[0] + .clone() + .to_sec1_pem(pem::LineEnding::CR) + .unwrap() + .as_str() + .to_owned() + .to_string(), + ) + } else { + None + }; + + EthereumClientConfig { + http_rpc_url: endpoint.parse().unwrap(), + ws_rpc_url: "ws://localhost:5001".parse().unwrap(), + beacon_rpc_url: Default::default(), + ibc_handler_address: yui_ibc.diamond.address(), + tendermint_client_address: yui_ibc.tendermint.address(), + mnemonic: None, + max_block_weight: 1, + private_key: wallet, + private_key_path: wallet_path, + name: "mock-ethereum-client".into(), + client_id: Some( + ibc::core::ics24_host::identifier::ClientId::new("07-tendermint", 0).unwrap(), + ), + connection_id: None, + channel_whitelist: vec![], + commitment_prefix: "".into(), + wasm_code_id: None, + yui: Some(yui_ibc), + client_type: "07-tendermint".into(), + } +} diff --git a/hyperspace/ethereum/tests/sanity_checks.rs b/hyperspace/ethereum/tests/sanity_checks.rs index 6d1f85877..2196c0120 100644 --- a/hyperspace/ethereum/tests/sanity_checks.rs +++ b/hyperspace/ethereum/tests/sanity_checks.rs @@ -77,54 +77,6 @@ use tokio_stream::{Elapsed, StreamExt as _}; use tracing::log; use tracing_subscriber::{filter, layer::SubscriberExt, util::SubscriberInitExt, Layer}; -pub async fn hyperspace_ethereum_client_fixture( - anvil: &AnvilInstance, - yui_ibc: DeployYuiIbc, ProviderImpl>, -) -> EthereumClientConfig { - let endpoint = if USE_GETH { "http://localhost:6001".to_string() } else { anvil.endpoint() }; - let wallet_path = if USE_GETH { - Some("keys/0x73db010c3275eb7a92e5c38770316248f4c644ee".to_string()) - } else { - None - }; - - let wallet = if !USE_GETH { - Some( - anvil.keys()[0] - .clone() - .to_sec1_pem(pem::LineEnding::CR) - .unwrap() - .as_str() - .to_owned() - .to_string(), - ) - } else { - None - }; - - EthereumClientConfig { - http_rpc_url: endpoint.parse().unwrap(), - ws_rpc_url: "ws://localhost:5001".parse().unwrap(), - beacon_rpc_url: Default::default(), - ibc_handler_address: yui_ibc.diamond.address(), - tendermint_client_address: yui_ibc.tendermint.address(), - mnemonic: None, - max_block_weight: 1, - private_key: wallet, - private_key_path: wallet_path, - name: "mock-ethereum-client".into(), - client_id: Some( - ibc::core::ics24_host::identifier::ClientId::new("07-tendermint", 0).unwrap(), - ), - connection_id: None, - channel_whitelist: vec![], - commitment_prefix: "".into(), - wasm_code_id: None, - yui: Some(yui_ibc), - client_type: "07-tendermint".into(), - } -} - #[allow(dead_code)] pub struct DeployYuiIbcMockClient { pub path: PathBuf, diff --git a/hyperspace/testsuite/Cargo.toml b/hyperspace/testsuite/Cargo.toml index ec997316d..4b255df6b 100644 --- a/hyperspace/testsuite/Cargo.toml +++ b/hyperspace/testsuite/Cargo.toml @@ -17,6 +17,8 @@ futures = "0.3.24" json = { version = "1.0.85", package = "serde_json" } codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"] } subxt = { git = "https://github.com/paritytech/subxt", rev = "2a4da618a033bb82f768e4ef67b093b371f8b492", features = ["substrate-compat"] } +ethers = { version = "2.0.2", features = ["ws"] } +ethers-solc = "2.0.8" ibc = { path = "../../ibc/modules" } ibc-proto = { path = "../../ibc/proto" } diff --git a/hyperspace/testsuite/tests/ethereum_cosmos.rs b/hyperspace/testsuite/tests/ethereum_cosmos.rs index 306bd32fb..ef216fe78 100644 --- a/hyperspace/testsuite/tests/ethereum_cosmos.rs +++ b/hyperspace/testsuite/tests/ethereum_cosmos.rs @@ -13,6 +13,12 @@ // limitations under the License. use core::time::Duration; +use ethers::{ + abi::Token, + prelude::{ContractFactory, ContractInstance}, + utils::AnvilInstance, +}; +use ethers_solc::{Artifact, ProjectCompileOutput, ProjectPathsConfig}; use futures::StreamExt; use hyperspace_core::{ chain::{AnyAssetId, AnyChain, AnyConfig}, @@ -22,10 +28,8 @@ use hyperspace_core::{ use hyperspace_cosmos::client::{CosmosClient, CosmosClientConfig}; use hyperspace_ethereum::{ config::EthereumClientConfig, - mock::sanity_checks::{ - deploy_yui_ibc_and_mock_client_fixture, hyperspace_ethereum_client_fixture, - DeployYuiIbcMockClient, - }, + mock::{utils, utils::hyperspace_ethereum_client_fixture}, + utils::{DeployYuiIbc, ProviderImpl}, }; use hyperspace_parachain::{finality_protocol::FinalityProtocol, ParachainClientConfig}; use hyperspace_primitives::{utils::create_clients, CommonClientConfig, IbcProvider}; @@ -38,6 +42,7 @@ use hyperspace_testsuite::{ }; use ibc::core::ics24_host::identifier::PortId; use sp_core::hashing::sha2_256; +use std::{path::PathBuf, sync::Arc}; #[derive(Debug, Clone)] pub struct Args { @@ -72,52 +77,39 @@ impl Default for Args { } } -async fn setup_clients() -> (AnyChain, AnyChain) { - log::info!(target: "hyperspace", "=========================== Starting Test ==========================="); - let args = Args::default(); +pub struct DeployYuiIbcTendermintClient { + pub path: PathBuf, + pub project_output: ProjectCompileOutput, + pub anvil: AnvilInstance, + pub client: Arc, + pub tendermint_client: ContractInstance, ProviderImpl>, + pub ics20_module: Option, ProviderImpl>>, + pub yui_ibc: DeployYuiIbc, ProviderImpl>, +} - // Create client configurations - // let config_a = EthereumClientConfig { - // http_rpc_url: Default::default(), - // ws_rpc_url: Default::default(), - // ibc_handler_address: Default::default(), - // name: "ethereum".to_string(), - // // para_id: args.para_id, - // // parachain_rpc_url: args.chain_a, - // // relay_chain_rpc_url: args.relay_chain.clone(), - // client_id: None, - // connection_id: None, - // commitment_prefix: args.connection_prefix_a.as_bytes().to_vec().into(), - // // ss58_version: 42, - // channel_whitelist: vec![], - // // finality_protocol: FinalityProtocol::Grandpa, - // private_key: None, - // // key_type: "sr25519".to_string(), - // // wasm_code_id: None, - // private_key_path: Some( - // "../ethereum/keys/0x73db010c3275eb7a92e5c38770316248f4c644ee".to_string(), - // ), - // mnemonic: None, - // max_block_weight: 1, - // }; - - let DeployYuiIbcMockClient { anvil, yui_ibc, .. } = - deploy_yui_ibc_and_mock_client_fixture().await; - /* - let upd = project_output1.find_first("DelegateTendermintUpdate").unwrap(); +pub async fn deploy_yui_ibc_and_tendermint_client_fixture() -> DeployYuiIbcTendermintClient { + let path = utils::yui_ibc_solidity_path(); + let project_output = utils::compile_yui(&path, "contracts/core"); + let diamond_project_output = utils::compile_yui(&path, "contracts/diamond"); + let project_output1 = utils::compile_yui(&path, "contracts/clients"); + let (anvil, client) = utils::spawn_anvil(); + log::warn!("{}", anvil.endpoint()); + let yui_ibc = + utils::deploy_yui_ibc(&project_output, &diamond_project_output, client.clone()).await; + + let upd = project_output1.find_first("DelegateTendermintUpdate").unwrap(); let (abi, bytecode, _) = upd.clone().into_parts(); let factory = ContractFactory::new(abi.unwrap(), bytecode.unwrap(), client.clone()); let update_client_delegate_contract = factory.deploy(()).unwrap().send().await.unwrap(); let contract = project_output1.find_first("TendermintLightClientSimple").unwrap(); - // dbg!(&contract); let r = contract.clone(); let (abi, bytecode, _) = r.into_parts(); let factory = ContractFactory::new(abi.unwrap(), bytecode.unwrap(), client.clone()); let tendermint_light_client = factory .deploy(( - Token::Address(yui_ibc.ibc_handler.address()), + Token::Address(yui_ibc.diamond.address()), Token::Address(update_client_delegate_contract.address()), )) .unwrap() @@ -125,11 +117,35 @@ async fn setup_clients() -> (AnyChain, AnyChain) { .await .unwrap(); - //replace the tendermint client address in hyperspace config with a real one - hyperspace.config.tendermint_client_address = tendermint_light_client.address(); + let _ = yui_ibc + .register_client("07-tendermint", tendermint_light_client.address()) + .await; + + DeployYuiIbcTendermintClient { + path, + project_output, + anvil, + client, + yui_ibc, + tendermint_client: tendermint_light_client, + ics20_module: None, + } +} - */ - let config_a = hyperspace_ethereum_client_fixture(&anvil, yui_ibc).await; +async fn setup_clients() -> (AnyChain, AnyChain) { + log::info!(target: "hyperspace", "=========================== Starting Test ==========================="); + let args = Args::default(); + + // Create client configurations + + let DeployYuiIbcTendermintClient { anvil, tendermint_client, ics20_module: _, yui_ibc, .. } = + deploy_yui_ibc_and_tendermint_client_fixture().await; + + //replace the tendermint client address in hyperspace config with a real one + let diamond_address = yui_ibc.diamond.address(); + let mut config_a = hyperspace_ethereum_client_fixture(&anvil, yui_ibc).await; + config_a.tendermint_client_address = tendermint_client.address(); + config_a.ibc_handler_address = diamond_address; let mut config_b = CosmosClientConfig { name: "centauri".to_string(), @@ -145,7 +161,7 @@ async fn setup_clients() -> (AnyChain, AnyChain) { gas_limit: (i64::MAX - 1) as u64, store_prefix: args.connection_prefix_b, max_tx_size: 200000, - mnemonic: // 26657 + mnemonic: "sense state fringe stool behind explain area quit ugly affair develop thumb clinic weasel choice atom gesture spare sea renew penalty second upon peace" .to_string(), wasm_code_id: None, diff --git a/light-clients/icsxx-ethereum/src/tests.rs b/light-clients/icsxx-ethereum/src/tests.rs index 15b71f77b..5e3294704 100644 --- a/light-clients/icsxx-ethereum/src/tests.rs +++ b/light-clients/icsxx-ethereum/src/tests.rs @@ -34,7 +34,4 @@ async fn test_prover() { .fetch_beacon_state(&block_header.slot.to_string()) .await .unwrap(); - // sync_committee_prover. - // println!("state: {:?}", state); - // println!("state: {:?}", state.validators); } From 824470ed392460055622e5f2e3708e5f1a8e1f39 Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Wed, 6 Sep 2023 19:32:47 -0300 Subject: [PATCH 15/43] update abi --- .../ethereum/src/abi/ibc-client-abi.json | 2 +- .../ethereum/src/abi/ibc-handler-abi.json | 1881 ----------------- 2 files changed, 1 insertion(+), 1882 deletions(-) delete mode 100644 hyperspace/ethereum/src/abi/ibc-handler-abi.json diff --git a/hyperspace/ethereum/src/abi/ibc-client-abi.json b/hyperspace/ethereum/src/abi/ibc-client-abi.json index c2bb7f4c5..a020d41a7 100644 --- a/hyperspace/ethereum/src/abi/ibc-client-abi.json +++ b/hyperspace/ethereum/src/abi/ibc-client-abi.json @@ -3,7 +3,7 @@ "anonymous": false, "inputs": [ { - "indexed": false, + "indexed": true, "internalType": "string", "name": "clientId", "type": "string" diff --git a/hyperspace/ethereum/src/abi/ibc-handler-abi.json b/hyperspace/ethereum/src/abi/ibc-handler-abi.json deleted file mode 100644 index 3f9d135ea..000000000 --- a/hyperspace/ethereum/src/abi/ibc-handler-abi.json +++ /dev/null @@ -1,1881 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "ibcClient", - "type": "address" - }, - { - "internalType": "address", - "name": "ibcConnection", - "type": "address" - }, - { - "internalType": "address", - "name": "ibcChannel", - "type": "address" - }, - { - "internalType": "address", - "name": "ibcPacket", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "components": [ - { - "internalType": "uint64", - "name": "sequence", - "type": "uint64" - }, - { - "internalType": "string", - "name": "source_port", - "type": "string" - }, - { - "internalType": "string", - "name": "source_channel", - "type": "string" - }, - { - "internalType": "string", - "name": "destination_port", - "type": "string" - }, - { - "internalType": "string", - "name": "destination_channel", - "type": "string" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "uint64", - "name": "revision_number", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "revision_height", - "type": "uint64" - } - ], - "internalType": "struct Height.Data", - "name": "timeout_height", - "type": "tuple" - }, - { - "internalType": "uint64", - "name": "timeout_timestamp", - "type": "uint64" - } - ], - "indexed": false, - "internalType": "struct Packet.Data", - "name": "packet", - "type": "tuple" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "acknowledgement", - "type": "bytes" - } - ], - "name": "AcknowledgePacket", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "portId", - "type": "string" - }, - { - "indexed": false, - "internalType": "string", - "name": "channelId", - "type": "string" - } - ], - "name": "CloseConfirmChannel", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "portId", - "type": "string" - }, - { - "indexed": false, - "internalType": "string", - "name": "channelId", - "type": "string" - } - ], - "name": "CloseInitChannel", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "clientId", - "type": "string" - }, - { - "indexed": false, - "internalType": "string", - "name": "clientType", - "type": "string" - } - ], - "name": "CreateClient", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "", - "type": "string" - } - ], - "name": "GeneratedChannelIdentifier", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "", - "type": "string" - } - ], - "name": "GeneratedClientIdentifier", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "", - "type": "string" - } - ], - "name": "GeneratedConnectionIdentifier", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "portId", - "type": "string" - }, - { - "indexed": false, - "internalType": "string", - "name": "channelId", - "type": "string" - } - ], - "name": "OpenAckChannel", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "connectionId", - "type": "string" - }, - { - "indexed": false, - "internalType": "string", - "name": "counterpartyConnectionId", - "type": "string" - } - ], - "name": "OpenAckConnection", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "portId", - "type": "string" - }, - { - "indexed": false, - "internalType": "string", - "name": "channelId", - "type": "string" - } - ], - "name": "OpenConfirmChannel", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "connectionId", - "type": "string" - } - ], - "name": "OpenConfirmConnection", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "portId", - "type": "string" - }, - { - "indexed": false, - "internalType": "string", - "name": "channelId", - "type": "string" - } - ], - "name": "OpenInitChannel", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "connectionId", - "type": "string" - }, - { - "indexed": false, - "internalType": "string", - "name": "clientId", - "type": "string" - }, - { - "indexed": false, - "internalType": "string", - "name": "counterpartyConnectionId", - "type": "string" - }, - { - "indexed": false, - "internalType": "string", - "name": "counterpartyClientId", - "type": "string" - } - ], - "name": "OpenInitConnection", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "portId", - "type": "string" - }, - { - "indexed": false, - "internalType": "string", - "name": "channelId", - "type": "string" - } - ], - "name": "OpenTryChannel", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "connectionId", - "type": "string" - }, - { - "indexed": false, - "internalType": "string", - "name": "clientId", - "type": "string" - }, - { - "indexed": false, - "internalType": "string", - "name": "counterpartyConnectionId", - "type": "string" - }, - { - "indexed": false, - "internalType": "string", - "name": "counterpartyClientId", - "type": "string" - } - ], - "name": "OpenTryConnection", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "components": [ - { - "internalType": "uint64", - "name": "sequence", - "type": "uint64" - }, - { - "internalType": "string", - "name": "source_port", - "type": "string" - }, - { - "internalType": "string", - "name": "source_channel", - "type": "string" - }, - { - "internalType": "string", - "name": "destination_port", - "type": "string" - }, - { - "internalType": "string", - "name": "destination_channel", - "type": "string" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "uint64", - "name": "revision_number", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "revision_height", - "type": "uint64" - } - ], - "internalType": "struct Height.Data", - "name": "timeout_height", - "type": "tuple" - }, - { - "internalType": "uint64", - "name": "timeout_timestamp", - "type": "uint64" - } - ], - "indexed": false, - "internalType": "struct Packet.Data", - "name": "packet", - "type": "tuple" - } - ], - "name": "RecvPacket", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "clientType", - "type": "string" - }, - { - "indexed": false, - "internalType": "address", - "name": "client", - "type": "address" - } - ], - "name": "RegisterClient", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "sequence", - "type": "uint64" - }, - { - "indexed": true, - "internalType": "string", - "name": "sourcePort", - "type": "string" - }, - { - "indexed": true, - "internalType": "string", - "name": "sourceChannel", - "type": "string" - }, - { - "components": [ - { - "internalType": "uint64", - "name": "revision_number", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "revision_height", - "type": "uint64" - } - ], - "indexed": false, - "internalType": "struct Height.Data", - "name": "timeoutHeight", - "type": "tuple" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "timeoutTimestamp", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "SendPacket", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "clientId", - "type": "string" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "header", - "type": "bytes32" - } - ], - "name": "UpdateClient", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "destinationPortId", - "type": "string" - }, - { - "indexed": false, - "internalType": "string", - "name": "destinationChannel", - "type": "string" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "sequence", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "acknowledgement", - "type": "bytes" - } - ], - "name": "WriteAcknowledgement", - "type": "event" - }, - { - "inputs": [ - { - "components": [ - { - "components": [ - { - "internalType": "uint64", - "name": "sequence", - "type": "uint64" - }, - { - "internalType": "string", - "name": "source_port", - "type": "string" - }, - { - "internalType": "string", - "name": "source_channel", - "type": "string" - }, - { - "internalType": "string", - "name": "destination_port", - "type": "string" - }, - { - "internalType": "string", - "name": "destination_channel", - "type": "string" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "uint64", - "name": "revision_number", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "revision_height", - "type": "uint64" - } - ], - "internalType": "struct Height.Data", - "name": "timeout_height", - "type": "tuple" - }, - { - "internalType": "uint64", - "name": "timeout_timestamp", - "type": "uint64" - } - ], - "internalType": "struct Packet.Data", - "name": "packet", - "type": "tuple" - }, - { - "internalType": "bytes", - "name": "acknowledgement", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "proof", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "uint64", - "name": "revision_number", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "revision_height", - "type": "uint64" - } - ], - "internalType": "struct Height.Data", - "name": "proofHeight", - "type": "tuple" - } - ], - "internalType": "struct IBCMsgs.MsgPacketAcknowledgement", - "name": "msg_", - "type": "tuple" - } - ], - "name": "acknowledgePacket", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "portId", - "type": "string" - }, - { - "internalType": "address", - "name": "moduleAddress", - "type": "address" - } - ], - "name": "bindPort", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "portId", - "type": "string" - }, - { - "internalType": "string", - "name": "channelId", - "type": "string" - } - ], - "name": "channelCapabilityPath", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "string", - "name": "portId", - "type": "string" - }, - { - "internalType": "string", - "name": "channelId", - "type": "string" - }, - { - "internalType": "bytes", - "name": "proofInit", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "uint64", - "name": "revision_number", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "revision_height", - "type": "uint64" - } - ], - "internalType": "struct Height.Data", - "name": "proofHeight", - "type": "tuple" - } - ], - "internalType": "struct IBCMsgs.MsgChannelCloseConfirm", - "name": "msg_", - "type": "tuple" - } - ], - "name": "channelCloseConfirm", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "string", - "name": "portId", - "type": "string" - }, - { - "internalType": "string", - "name": "channelId", - "type": "string" - } - ], - "internalType": "struct IBCMsgs.MsgChannelCloseInit", - "name": "msg_", - "type": "tuple" - } - ], - "name": "channelCloseInit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "string", - "name": "portId", - "type": "string" - }, - { - "internalType": "string", - "name": "channelId", - "type": "string" - }, - { - "internalType": "string", - "name": "counterpartyVersion", - "type": "string" - }, - { - "internalType": "string", - "name": "counterpartyChannelId", - "type": "string" - }, - { - "internalType": "bytes", - "name": "proofTry", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "uint64", - "name": "revision_number", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "revision_height", - "type": "uint64" - } - ], - "internalType": "struct Height.Data", - "name": "proofHeight", - "type": "tuple" - } - ], - "internalType": "struct IBCMsgs.MsgChannelOpenAck", - "name": "msg_", - "type": "tuple" - } - ], - "name": "channelOpenAck", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "string", - "name": "portId", - "type": "string" - }, - { - "internalType": "string", - "name": "channelId", - "type": "string" - }, - { - "internalType": "bytes", - "name": "proofAck", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "uint64", - "name": "revision_number", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "revision_height", - "type": "uint64" - } - ], - "internalType": "struct Height.Data", - "name": "proofHeight", - "type": "tuple" - } - ], - "internalType": "struct IBCMsgs.MsgChannelOpenConfirm", - "name": "msg_", - "type": "tuple" - } - ], - "name": "channelOpenConfirm", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "string", - "name": "portId", - "type": "string" - }, - { - "components": [ - { - "internalType": "enum Channel.State", - "name": "state", - "type": "uint8" - }, - { - "internalType": "enum Channel.Order", - "name": "ordering", - "type": "uint8" - }, - { - "components": [ - { - "internalType": "string", - "name": "port_id", - "type": "string" - }, - { - "internalType": "string", - "name": "channel_id", - "type": "string" - } - ], - "internalType": "struct ChannelCounterparty.Data", - "name": "counterparty", - "type": "tuple" - }, - { - "internalType": "string[]", - "name": "connection_hops", - "type": "string[]" - }, - { - "internalType": "string", - "name": "version", - "type": "string" - } - ], - "internalType": "struct Channel.Data", - "name": "channel", - "type": "tuple" - } - ], - "internalType": "struct IBCMsgs.MsgChannelOpenInit", - "name": "msg_", - "type": "tuple" - } - ], - "name": "channelOpenInit", - "outputs": [ - { - "internalType": "string", - "name": "channelId", - "type": "string" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "string", - "name": "portId", - "type": "string" - }, - { - "components": [ - { - "internalType": "enum Channel.State", - "name": "state", - "type": "uint8" - }, - { - "internalType": "enum Channel.Order", - "name": "ordering", - "type": "uint8" - }, - { - "components": [ - { - "internalType": "string", - "name": "port_id", - "type": "string" - }, - { - "internalType": "string", - "name": "channel_id", - "type": "string" - } - ], - "internalType": "struct ChannelCounterparty.Data", - "name": "counterparty", - "type": "tuple" - }, - { - "internalType": "string[]", - "name": "connection_hops", - "type": "string[]" - }, - { - "internalType": "string", - "name": "version", - "type": "string" - } - ], - "internalType": "struct Channel.Data", - "name": "channel", - "type": "tuple" - }, - { - "internalType": "string", - "name": "counterpartyVersion", - "type": "string" - }, - { - "internalType": "bytes", - "name": "proofInit", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "uint64", - "name": "revision_number", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "revision_height", - "type": "uint64" - } - ], - "internalType": "struct Height.Data", - "name": "proofHeight", - "type": "tuple" - } - ], - "internalType": "struct IBCMsgs.MsgChannelOpenTry", - "name": "msg_", - "type": "tuple" - } - ], - "name": "channelOpenTry", - "outputs": [ - { - "internalType": "string", - "name": "channelId", - "type": "string" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "string", - "name": "connectionId", - "type": "string" - }, - { - "internalType": "bytes", - "name": "clientStateBytes", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "string", - "name": "identifier", - "type": "string" - }, - { - "internalType": "string[]", - "name": "features", - "type": "string[]" - } - ], - "internalType": "struct Version.Data", - "name": "version", - "type": "tuple" - }, - { - "internalType": "string", - "name": "counterpartyConnectionID", - "type": "string" - }, - { - "internalType": "bytes", - "name": "proofTry", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "proofClient", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "proofConsensus", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "uint64", - "name": "revision_number", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "revision_height", - "type": "uint64" - } - ], - "internalType": "struct Height.Data", - "name": "proofHeight", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint64", - "name": "revision_number", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "revision_height", - "type": "uint64" - } - ], - "internalType": "struct Height.Data", - "name": "consensusHeight", - "type": "tuple" - } - ], - "internalType": "struct IBCMsgs.MsgConnectionOpenAck", - "name": "msg_", - "type": "tuple" - } - ], - "name": "connectionOpenAck", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "string", - "name": "connectionId", - "type": "string" - }, - { - "internalType": "bytes", - "name": "proofAck", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "uint64", - "name": "revision_number", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "revision_height", - "type": "uint64" - } - ], - "internalType": "struct Height.Data", - "name": "proofHeight", - "type": "tuple" - } - ], - "internalType": "struct IBCMsgs.MsgConnectionOpenConfirm", - "name": "msg_", - "type": "tuple" - } - ], - "name": "connectionOpenConfirm", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "string", - "name": "clientId", - "type": "string" - }, - { - "components": [ - { - "internalType": "string", - "name": "client_id", - "type": "string" - }, - { - "internalType": "string", - "name": "connection_id", - "type": "string" - }, - { - "components": [ - { - "internalType": "bytes", - "name": "key_prefix", - "type": "bytes" - } - ], - "internalType": "struct MerklePrefix.Data", - "name": "prefix", - "type": "tuple" - } - ], - "internalType": "struct Counterparty.Data", - "name": "counterparty", - "type": "tuple" - }, - { - "internalType": "uint64", - "name": "delayPeriod", - "type": "uint64" - } - ], - "internalType": "struct IBCMsgs.MsgConnectionOpenInit", - "name": "msg_", - "type": "tuple" - } - ], - "name": "connectionOpenInit", - "outputs": [ - { - "internalType": "string", - "name": "connectionId", - "type": "string" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "components": [ - { - "internalType": "string", - "name": "client_id", - "type": "string" - }, - { - "internalType": "string", - "name": "connection_id", - "type": "string" - }, - { - "components": [ - { - "internalType": "bytes", - "name": "key_prefix", - "type": "bytes" - } - ], - "internalType": "struct MerklePrefix.Data", - "name": "prefix", - "type": "tuple" - } - ], - "internalType": "struct Counterparty.Data", - "name": "counterparty", - "type": "tuple" - }, - { - "internalType": "uint64", - "name": "delayPeriod", - "type": "uint64" - }, - { - "internalType": "string", - "name": "clientId", - "type": "string" - }, - { - "internalType": "bytes", - "name": "clientStateBytes", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "string", - "name": "identifier", - "type": "string" - }, - { - "internalType": "string[]", - "name": "features", - "type": "string[]" - } - ], - "internalType": "struct Version.Data[]", - "name": "counterpartyVersions", - "type": "tuple[]" - }, - { - "internalType": "bytes", - "name": "proofInit", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "proofClient", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "proofConsensus", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "uint64", - "name": "revision_number", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "revision_height", - "type": "uint64" - } - ], - "internalType": "struct Height.Data", - "name": "proofHeight", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint64", - "name": "revision_number", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "revision_height", - "type": "uint64" - } - ], - "internalType": "struct Height.Data", - "name": "consensusHeight", - "type": "tuple" - } - ], - "internalType": "struct IBCMsgs.MsgConnectionOpenTry", - "name": "msg_", - "type": "tuple" - } - ], - "name": "connectionOpenTry", - "outputs": [ - { - "internalType": "string", - "name": "connectionId", - "type": "string" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "string", - "name": "clientType", - "type": "string" - }, - { - "internalType": "bytes", - "name": "clientStateBytes", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "consensusStateBytes", - "type": "bytes" - } - ], - "internalType": "struct IBCMsgs.MsgCreateClient", - "name": "msg_", - "type": "tuple" - } - ], - "name": "createClient", - "outputs": [ - { - "internalType": "string", - "name": "clientId", - "type": "string" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "portId", - "type": "string" - }, - { - "internalType": "string", - "name": "channelId", - "type": "string" - }, - { - "internalType": "uint64", - "name": "sequence", - "type": "uint64" - } - ], - "name": "hasAcknowledgement", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "portId", - "type": "string" - }, - { - "internalType": "string", - "name": "channelId", - "type": "string" - }, - { - "internalType": "uint64", - "name": "fromSequence", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "toSequence", - "type": "uint64" - } - ], - "name": "hasAcknowledgements", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "portId", - "type": "string" - }, - { - "internalType": "string", - "name": "channelId", - "type": "string" - }, - { - "internalType": "uint64", - "name": "sequence", - "type": "uint64" - } - ], - "name": "hasCommitment", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "portId", - "type": "string" - }, - { - "internalType": "string", - "name": "channelId", - "type": "string" - }, - { - "internalType": "uint64", - "name": "fromSequence", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "toSequence", - "type": "uint64" - } - ], - "name": "hasCommitments", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "portId", - "type": "string" - }, - { - "internalType": "string", - "name": "channelId", - "type": "string" - }, - { - "internalType": "uint64", - "name": "sequence", - "type": "uint64" - } - ], - "name": "hasPacketReceipt", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "portId", - "type": "string" - } - ], - "name": "portCapabilityPath", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "components": [ - { - "internalType": "uint64", - "name": "sequence", - "type": "uint64" - }, - { - "internalType": "string", - "name": "source_port", - "type": "string" - }, - { - "internalType": "string", - "name": "source_channel", - "type": "string" - }, - { - "internalType": "string", - "name": "destination_port", - "type": "string" - }, - { - "internalType": "string", - "name": "destination_channel", - "type": "string" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "uint64", - "name": "revision_number", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "revision_height", - "type": "uint64" - } - ], - "internalType": "struct Height.Data", - "name": "timeout_height", - "type": "tuple" - }, - { - "internalType": "uint64", - "name": "timeout_timestamp", - "type": "uint64" - } - ], - "internalType": "struct Packet.Data", - "name": "packet", - "type": "tuple" - }, - { - "internalType": "bytes", - "name": "proof", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "uint64", - "name": "revision_number", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "revision_height", - "type": "uint64" - } - ], - "internalType": "struct Height.Data", - "name": "proofHeight", - "type": "tuple" - } - ], - "internalType": "struct IBCMsgs.MsgPacketRecv", - "name": "msg_", - "type": "tuple" - } - ], - "name": "recvPacket", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "clientType", - "type": "string" - }, - { - "internalType": "contract ILightClient", - "name": "client", - "type": "address" - } - ], - "name": "registerClient", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "sourcePort", - "type": "string" - }, - { - "internalType": "string", - "name": "sourceChannel", - "type": "string" - }, - { - "components": [ - { - "internalType": "uint64", - "name": "revision_number", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "revision_height", - "type": "uint64" - } - ], - "internalType": "struct Height.Data", - "name": "timeoutHeight", - "type": "tuple" - }, - { - "internalType": "uint64", - "name": "timeoutTimestamp", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "sendPacket", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "setAbobaHandler", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "setAbobaHost", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "setAbobaStore", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "expectedTimePerBlock_", - "type": "uint64" - } - ], - "name": "setExpectedTimePerBlock", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "string", - "name": "clientId", - "type": "string" - }, - { - "internalType": "bytes", - "name": "clientMessage", - "type": "bytes" - } - ], - "internalType": "struct IBCMsgs.MsgUpdateClient", - "name": "msg_", - "type": "tuple" - } - ], - "name": "updateClient", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "destinationPortId", - "type": "string" - }, - { - "internalType": "string", - "name": "destinationChannel", - "type": "string" - }, - { - "internalType": "uint64", - "name": "sequence", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "acknowledgement", - "type": "bytes" - } - ], - "name": "writeAcknowledgement", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] From e63c24fffe73761ac0536ef1b5dd5da9458ec463 Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Thu, 7 Sep 2023 00:47:43 -0300 Subject: [PATCH 16/43] Remove deprecated IBCClientHandler and repurpose ICS23 light client ICS23 light client was repurposed to handle chain state retrieval and updating. The IBCClientHandler contract, which used ICS23 light client, is removed due to redundancy. IBCClientHandler was initially used for delegate calls to contracts implementing `IIBCClient`. However, with architectural improvements and updates, this operation is no longer necessary, hence removing the contract for better lean code management. Subsequently, the ICS23 client is equipped with prefixing and key formatting methods to retrieve consensus data effectively. This enhances the performance of the IBC client and simplifies operations involving Ethermint and Substrate light clients. In addition to the file changes above: - Introduced the function parse_ethereum_events to handle parsing of Ethereum events. - Functions on ibc_provider.rs have been refactored to accommodate the above changes. - Improved error handling and log message content. - Updated address indexing in events for better searchability. - Tests have been improved to suit the updated codebase. --- Cargo.lock | 9 +- contracts/pallet-ibc/src/light_clients.rs | 24 +- hyperspace/core/src/macros.rs | 12 +- hyperspace/cosmos/src/provider.rs | 1 + hyperspace/ethereum/Cargo.toml | 2 + .../ethereum/src/abi/ibc-client-abi.json | 11 +- hyperspace/ethereum/src/chain.rs | 626 +++++++++++++++++- hyperspace/ethereum/src/client.rs | 68 +- hyperspace/ethereum/src/config.rs | 1 + hyperspace/ethereum/src/contract.rs | 12 - hyperspace/ethereum/src/events.rs | 126 ++-- hyperspace/ethereum/src/ibc_provider.rs | 399 ++++++++--- hyperspace/ethereum/src/mock/utils.rs | 11 +- hyperspace/ethereum/src/prove.rs | 59 +- hyperspace/ethereum/src/utils.rs | 42 +- hyperspace/testsuite/src/lib.rs | 4 + hyperspace/testsuite/tests/ethereum_cosmos.rs | 22 +- .../icsxx-ethereum-cw/src/channel.rs | 15 + light-clients/icsxx-ethereum-cw/src/client.rs | 152 +++-- .../icsxx-ethereum-cw/src/connection.rs | 15 + .../icsxx-ethereum-cw/src/context.rs | 83 ++- .../icsxx-ethereum-cw/src/contract.rs | 224 ++++--- light-clients/icsxx-ethereum-cw/src/error.rs | 16 +- .../src/ics23/client_states.rs | 64 +- .../icsxx-ethereum-cw/src/ics23/clients.rs | 17 +- .../src/ics23/consensus_states.rs | 75 ++- .../icsxx-ethereum-cw/src/ics23/mod.rs | 15 + light-clients/icsxx-ethereum-cw/src/lib.rs | 6 +- light-clients/icsxx-ethereum-cw/src/msg.rs | 179 ++--- light-clients/icsxx-ethereum-cw/src/state.rs | 64 ++ 30 files changed, 1847 insertions(+), 507 deletions(-) create mode 100644 light-clients/icsxx-ethereum-cw/src/state.rs diff --git a/Cargo.lock b/Cargo.lock index 5a8470482..b09284a25 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4869,9 +4869,11 @@ dependencies = [ "ics07-tendermint", "icsxx-ethereum", "jsonwebtoken", + "log", "once_cell", "pallet-ibc", "prost 0.11.6", + "reqwest", "serde", "serde_json", "ssz-rs", @@ -6539,12 +6541,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.17" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if 1.0.0", -] +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "lru" diff --git a/contracts/pallet-ibc/src/light_clients.rs b/contracts/pallet-ibc/src/light_clients.rs index 63a090c26..04c530578 100644 --- a/contracts/pallet-ibc/src/light_clients.rs +++ b/contracts/pallet-ibc/src/light_clients.rs @@ -389,7 +389,8 @@ impl AnyClientMessage { }, #[cfg(feature = "ethereum")] Self::Ethereum(m) => match m { - icsxx_ethereum::client_message::ClientMessage::Header(h) => None, /* TODO: header height */ + icsxx_ethereum::client_message::ClientMessage::Header(h) => + Some(Height::new(0, h.finalized_header.slot)), icsxx_ethereum::client_message::ClientMessage::Misbehaviour(_) => None, }, #[cfg(test)] @@ -486,6 +487,11 @@ impl TryFrom for AnyClientMessage { .map_err(ics02_client::error::Error::decode_raw_header)?, )), #[cfg(feature = "ethereum")] + ETHEREUM_CLIENT_MESSAGE_TYPE_URL => Ok(Self::Ethereum( + icsxx_ethereum::client_message::ClientMessage::decode_vec(&value.value) + .map_err(ics02_client::error::Error::decode_raw_header)?, + )), + #[cfg(feature = "ethereum")] ETHEREUM_HEADER_TYPE_URL => Ok(Self::Ethereum(icsxx_ethereum::client_message::ClientMessage::Header( icsxx_ethereum::client_message::Header::decode_vec(&value.value) @@ -548,10 +554,20 @@ impl From for Any { value: msg.encode_vec().expect("encode_vec failed"), }, #[cfg(feature = "ethereum")] - AnyClientMessage::Ethereum(msg) => Any { - type_url: ETHEREUM_CLIENT_MESSAGE_TYPE_URL.to_string(), - value: msg.encode_vec().expect("encode_vec failed"), + AnyClientMessage::Ethereum(msg) => match msg { + icsxx_ethereum::client_message::ClientMessage::Header(h) => Any { + type_url: ETHEREUM_HEADER_TYPE_URL.to_string(), + value: h.encode_vec().expect("encode_vec failed"), + }, + icsxx_ethereum::client_message::ClientMessage::Misbehaviour(m) => Any { + type_url: ETHEREUM_MISBEHAVIOUR_TYPE_URL.to_string(), + value: m.encode_vec().expect("encode_vec failed"), + }, }, + // AnyClientMessage::Ethereum(msg) => Any { + // type_url: ETHEREUM_CLIENT_MESSAGE_TYPE_URL.to_string(), + // value: msg.encode_vec().expect("encode_vec failed"), + // }, #[cfg(test)] AnyClientMessage::Mock(_msg) => panic!("MockHeader can't be serialized"), } diff --git a/hyperspace/core/src/macros.rs b/hyperspace/core/src/macros.rs index 027e88371..ce1d5a40b 100644 --- a/hyperspace/core/src/macros.rs +++ b/hyperspace/core/src/macros.rs @@ -810,7 +810,11 @@ macro_rules! chains { Self::Wasm(chain) => { let messages = messages .into_iter() - .map(|msg| wrap_any_msg_into_wasm(msg, chain.code_id.clone())) + .map(|msg| { + let any = wrap_any_msg_into_wasm(msg, chain.code_id.clone()); + // any.as_ref().map(|any| { log::info!("Submitting message: {}", hex::encode(&any.value)); }); + any + }) .collect::, _>>()?; chain.inner.submit(messages).await.map_err(AnyError::into) }, @@ -998,7 +1002,7 @@ macro_rules! chains { AnyConfig::$name(config) => AnyChain::$name(<$client>::new(config).await?), )* }; - if let Some(code_id) = maybe_wasm_code_id { + if let Some(code_id) = dbg!(maybe_wasm_code_id) { Ok(AnyChain::Wasm(WasmChain { inner: Box::new(chain), code_id })) } else { Ok(chain) @@ -1042,7 +1046,7 @@ macro_rules! chains { let maybe_code_id = match self { $( $(#[$($meta)*])* - Self::$name(chain) => Option::::None,//chain.wasm_code_id.as_ref(), + Self::$name(chain) => chain.wasm_code_id.as_ref(), )* }; let maybe_code_id = @@ -1056,7 +1060,7 @@ macro_rules! chains { $( $(#[$($meta)*])* Self::$name(chain) => { - // chain.wasm_code_id = Some(code_id); + chain.wasm_code_id = Some(code_id); }, )* } diff --git a/hyperspace/cosmos/src/provider.rs b/hyperspace/cosmos/src/provider.rs index f0b5eef82..2f5886e4d 100644 --- a/hyperspace/cosmos/src/provider.rs +++ b/hyperspace/cosmos/src/provider.rs @@ -117,6 +117,7 @@ where let client_state_response = latest_cp_client_state .client_state .ok_or_else(|| Error::Custom("counterparty returned empty client state".to_string()))?; + log::info!(target: "hyperspace_cosmos", "cs len = {}", client_state_response.value.len()); let client_state = ClientState::::decode_vec(&client_state_response.value) .map_err(|_| Error::Custom("failed to decode client state response".to_string()))?; diff --git a/hyperspace/ethereum/Cargo.toml b/hyperspace/ethereum/Cargo.toml index 1eb42e4f2..5ef8aeed4 100644 --- a/hyperspace/ethereum/Cargo.toml +++ b/hyperspace/ethereum/Cargo.toml @@ -51,6 +51,8 @@ tracing-subscriber = "0.3.17" env_logger = "0.10.0" once_cell = "1.18.0" ecdsa = "0.16.7" +log = "0.4.20" +reqwest = "0.11.18" [dev-dependencies] toml = "0.7.3" diff --git a/hyperspace/ethereum/src/abi/ibc-client-abi.json b/hyperspace/ethereum/src/abi/ibc-client-abi.json index a020d41a7..e2005d88c 100644 --- a/hyperspace/ethereum/src/abi/ibc-client-abi.json +++ b/hyperspace/ethereum/src/abi/ibc-client-abi.json @@ -54,7 +54,7 @@ "anonymous": false, "inputs": [ { - "indexed": false, + "indexed": true, "internalType": "string", "name": "clientId", "type": "string" @@ -73,7 +73,7 @@ "anonymous": false, "inputs": [ { - "indexed": false, + "indexed": true, "internalType": "string", "name": "clientId", "type": "string" @@ -91,7 +91,7 @@ "type": "uint64" } ], - "indexed": false, + "indexed": true, "internalType": "struct HeightData", "name": "client_height", "type": "tuple" @@ -167,6 +167,11 @@ "internalType": "bytes", "name": "clientMessage", "type": "bytes" + }, + { + "internalType": "bytes", + "name": "prevClientState", + "type": "bytes" } ], "internalType": "struct IBCMsgsMsgUpdateClient", diff --git a/hyperspace/ethereum/src/chain.rs b/hyperspace/ethereum/src/chain.rs index 4d0faf9b0..a37ddc07f 100644 --- a/hyperspace/ethereum/src/chain.rs +++ b/hyperspace/ethereum/src/chain.rs @@ -1,7 +1,7 @@ -use std::{sync::Arc, thread, time::Duration}; +use std::{fmt::Debug, sync::Arc, thread, time::Duration}; use crate::{ - client::EthereumClient, + client::{ClientError, EthereumClient}, contract::IbcHandler, ibc_provider::BlockHeight, yui_types::{ics03_connection::conn_open_try::YuiMsgConnectionOpenTry, IntoToken}, @@ -13,21 +13,32 @@ use channel_msgs::{ chan_open_try::MsgChannelOpenTry, recv_packet::MsgRecvPacket, timeout::MsgTimeout, timeout_on_close::MsgTimeoutOnClose, }; -use ethers::{abi::Token, prelude::EthAbiType, providers::Middleware}; +use ethers::{ + abi::{ParamType, Token}, + prelude::EthAbiType, + providers::Middleware, + types::H256, +}; use futures::{Stream, StreamExt}; use ibc::{ core::{ ics02_client::{ events::UpdateClient, msgs::{create_client::MsgCreateAnyClient, update_client::MsgUpdateAnyClient}, + trust_threshold::TrustThreshold, }, ics03_connection::msgs::{ conn_open_ack::MsgConnectionOpenAck, conn_open_confirm::MsgConnectionOpenConfirm, conn_open_init::MsgConnectionOpenInit, conn_open_try::MsgConnectionOpenTry, }, ics04_channel::msgs as channel_msgs, + ics23_commitment::commitment::CommitmentRoot, + }, + protobuf::{ + google::protobuf::Timestamp, + types::{PartSetHeader, ValidatorSet}, + Protobuf, }, - protobuf::{google::protobuf::Timestamp, Protobuf}, Height, }; use ics07_tendermint::{ @@ -37,9 +48,16 @@ use ics07_tendermint::{ }; use pallet_ibc::light_clients::{AnyClientMessage, AnyClientState, AnyConsensusState}; use primitives::{ - mock::LocalClientTypes, Chain, CommonClientState, LightClientSync, MisbehaviourHandler, + mock::LocalClientTypes, Chain, CommonClientState, IbcProvider, LightClientSync, + MisbehaviourHandler, }; use serde::__private::de; +use tendermint::{ + account, block, + block::{header::Version, signed_header::SignedHeader, Height as TmHeight}, + trust_threshold::TrustThresholdFraction, + AppHash, Hash, Time, +}; #[async_trait::async_trait] impl MisbehaviourHandler for EthereumClient { @@ -53,9 +71,11 @@ impl MisbehaviourHandler for EthereumClient { } } -fn client_state_abi_token(client: ClientState) -> Token { +fn client_state_abi_token(client: ClientState) -> Token { use ethers::abi::{encode as ethers_encode, Token as EthersToken}; + log::info!("client: {:?}", client); + let client_state_data = EthersToken::Tuple( [ //chain_id @@ -110,6 +130,125 @@ fn client_state_abi_token(client: ClientState) -> Token { client_state_data } +pub(crate) fn client_state_from_abi_token(token: Token) -> Result, ClientError> { + use ethers::abi::Token as EthersToken; + + let Token::Bytes(bytes) = token else { + return Err(ClientError::Other("invalid client state".to_string())) + }; + let params = vec![ParamType::Tuple(vec![ + ParamType::String, + ParamType::Tuple(vec![ParamType::Uint(256), ParamType::Uint(256)]), + ParamType::Tuple(vec![ParamType::Int(256), ParamType::Int(256)]), + ParamType::Tuple(vec![ParamType::Int(256), ParamType::Int(256)]), + ParamType::Tuple(vec![ParamType::Int(256), ParamType::Int(256)]), + ParamType::Int(256), + ParamType::Int(256), + ParamType::Bool, + ParamType::Bool, + ])]; + + let Token::Tuple(toks) = ethers::abi::decode(¶ms, bytes.as_slice())?.pop().unwrap() else { + return Err(ClientError::Other("invalid client state'".to_string())) + }; + + log::info!("toks: {:?}", toks); + + let chain_id = match toks.get(0).cloned().unwrap() { + EthersToken::String(chain_id) => chain_id, + _ => return Err(ClientError::Other("chain_id not found".to_string())), + }; + + let (trust_level_numerator, trust_level_denominator) = match toks.get(1).cloned().unwrap() { + EthersToken::Tuple(toks) => ( + match toks.get(0).cloned().unwrap() { + EthersToken::Uint(numerator) => numerator.as_u64(), + _ => return Err(ClientError::Other("trust_level_numerator not found".to_string())), + }, + match toks.get(1).cloned().unwrap() { + EthersToken::Uint(denominator) => denominator.as_u64(), + _ => + return Err(ClientError::Other("trust_level_denominator not found".to_string())), + }, + ), + _ => return Err(ClientError::Other("trust_level not found".to_string())), + }; + + let (trusting_period_secs, trusting_period_nanos) = match toks.get(2).cloned().unwrap() { + EthersToken::Tuple(toks) => ( + match toks.get(0).cloned().unwrap() { + EthersToken::Int(numerator) => numerator.as_u64(), + _ => return Err(ClientError::Other("trusting_period_secs not found".to_string())), + }, + match toks.get(1).cloned().unwrap() { + EthersToken::Int(denominator) => denominator.as_u64(), + _ => return Err(ClientError::Other("trusting_period_nanos not found".to_string())), + }, + ), + _ => return Err(ClientError::Other("trusting_period not found".to_string())), + }; + + let (unbonding_period_secs, unbonding_period_nanos) = match toks.get(3).cloned().unwrap() { + EthersToken::Tuple(toks) => ( + match toks.get(0).cloned().unwrap() { + EthersToken::Int(numerator) => numerator.as_u64(), + _ => return Err(ClientError::Other("unbonding_period_secs not found".to_string())), + }, + match toks.get(1).cloned().unwrap() { + EthersToken::Int(denominator) => denominator.as_u64(), + _ => return Err(ClientError::Other("unbonding_period_nanos not found".to_string())), + }, + ), + _ => return Err(ClientError::Other("unbonding_period not found".to_string())), + }; + + let (max_clock_drift_secs, max_clock_drift_nanos) = match toks.get(4).cloned().unwrap() { + EthersToken::Tuple(toks) => ( + match toks.get(0).cloned().unwrap() { + EthersToken::Int(numerator) => numerator.as_u64(), + _ => return Err(ClientError::Other("max_clock_drift_secs not found".to_string())), + }, + match toks.get(1).cloned().unwrap() { + EthersToken::Int(denominator) => denominator.as_u64(), + _ => return Err(ClientError::Other("max_clock_drift_nanos not found".to_string())), + }, + ), + _ => return Err(ClientError::Other("max_clock_drift not found".to_string())), + }; + + let frozen_height = match toks.get(5).cloned().unwrap() { + EthersToken::Int(frozen_height) => frozen_height.as_u64(), + _ => return Err(ClientError::Other("frozen_height not found".to_string())), + }; + + let latest_height = match toks.get(6).cloned().unwrap() { + EthersToken::Int(latest_height) => latest_height.as_u64(), + _ => return Err(ClientError::Other("latest_height not found".to_string())), + }; + + /* + proof_specs: ProofSpecs([ProofSpec(ProofSpec { leaf_spec: Some(LeafOp { hash: Sha256, prehash_key: NoHash, prehash_value: Sha256, length: VarProto, prefix: [0] }), inner_spec: Some(InnerSpec { child_order: [0, 1], child_size: 33, min_prefix_length: 4, max_prefix_length: 12, empty_child: [], hash: Sha256 }), max_depth: 0, min_depth: 0, prehash_key_before_comparison: false }), ProofSpec(ProofSpec { leaf_spec: Some(LeafOp { hash: Sha256, prehash_key: NoHash, prehash_value: Sha256, length: VarProto, prefix: [0] }), inner_spec: Some(InnerSpec { child_order: [0, 1], child_size: 32, min_prefix_length: 1, max_prefix_length: 1, empty_child: [], hash: Sha256 }), max_depth: 0, min_depth: 0, prehash_key_before_comparison: false })]), + upgrade_path: ["upgrade", "upgradedIBCState"] + */ + let revision_number = 1; // TODO: revision + Ok(ClientState { + chain_id: chain_id.parse()?, + trust_level: TrustThreshold::new(trust_level_numerator, trust_level_denominator)?, + trusting_period: Duration::new(trusting_period_secs, trusting_period_nanos as u32), + unbonding_period: Duration::new(unbonding_period_secs, unbonding_period_nanos as u32), + max_clock_drift: Duration::new(max_clock_drift_secs, max_clock_drift_nanos as u32), + frozen_height: if frozen_height == 0 { + None + } else { + Some(Height::new(revision_number, frozen_height)) + }, + latest_height: Height::new(revision_number, latest_height), + proof_specs: Default::default(), // TODO: proof_specs? + upgrade_path: vec![], // TODO: upgrade_path? + _phantom: Default::default(), + }) +} + fn consensus_state_abi_token(consensus_state: ConsensusState) -> Token { use ethers::abi::{encode as ethers_encode, Token as EthersToken}; let time = consensus_state @@ -133,6 +272,59 @@ fn consensus_state_abi_token(consensus_state: ConsensusState) -> Token { consensus_state_data } +fn consensus_state_from_abi_token(token: Token) -> Result { + use ethers::abi::Token as EthersToken; + + let Token::Bytes(bytes) = token else { + return Err(ClientError::Other("invalid consensus state".to_string())) + }; + let params = vec![ParamType::Tuple(vec![ + ParamType::Tuple(vec![ParamType::Int(256), ParamType::Int(256)]), + ParamType::Tuple(vec![ParamType::Bytes]), + ParamType::Bytes, + ])]; + + let Token::Tuple(toks) = ethers::abi::decode(¶ms, bytes.as_slice())?.pop().unwrap() else { + return Err(ClientError::Other("invalid consensus state'".to_string())) + }; + + let (timestamp_secs, timestamp_nanos) = match toks.get(0).cloned().unwrap() { + EthersToken::Tuple(toks) => ( + match toks.get(0).cloned().unwrap() { + EthersToken::Int(numerator) => numerator.as_u64(), + _ => return Err(ClientError::Other("timestamp_secs not found".to_string())), + }, + match toks.get(1).cloned().unwrap() { + EthersToken::Int(denominator) => denominator.as_u64(), + _ => return Err(ClientError::Other("timestamp_nanos not found".to_string())), + }, + ), + _ => return Err(ClientError::Other("timestamp not found".to_string())), + }; + + let (root,) = match toks.get(1).cloned().unwrap() { + EthersToken::Tuple(toks) => (match toks.get(0).cloned().unwrap() { + EthersToken::Bytes(root) => root, + _ => return Err(ClientError::Other("root not found'".to_string())), + },), + _ => return Err(ClientError::Other("root not found".to_string())), + }; + + let next_validators_hash = match toks.get(2).cloned().unwrap() { + EthersToken::Bytes(next_validators_hash) => next_validators_hash, + _ => return Err(ClientError::Other("next_validators_hash not found".to_string())), + }; + + Ok(ConsensusState { + timestamp: Time::from_unix_timestamp( + timestamp_secs.try_into().unwrap(), + timestamp_nanos.try_into().unwrap(), + )?, + root: CommitmentRoot::from_bytes(root.as_slice()), + next_validators_hash: Hash::Sha256(next_validators_hash.as_slice().try_into().unwrap()), + }) +} + fn tm_header_abi_token(header: Header) -> Token { use ethers::abi::{encode as ethers_encode, Token as EthersToken}; let block_header = header.signed_header.header; @@ -144,7 +336,7 @@ fn tm_header_abi_token(header: Header) -> Token { .duration_since(Timestamp { seconds: 0, nanos: 0 }.try_into().unwrap()) .unwrap(); - let _signedheader_header = EthersToken::Tuple( + let signed_header_header = EthersToken::Tuple( [ //version EthersToken::Tuple( @@ -204,7 +396,7 @@ fn tm_header_abi_token(header: Header) -> Token { .to_vec(), ); - let _signedheader_comit = EthersToken::Tuple( + let signed_header_commit = EthersToken::Tuple( [ //height EthersToken::Int((last_commit.height.value()).into()), @@ -233,13 +425,292 @@ fn tm_header_abi_token(header: Header) -> Token { EthersToken::Tuple( [ - EthersToken::Tuple([_signedheader_header, _signedheader_comit].to_vec()), + EthersToken::Tuple([signed_header_header, signed_header_commit].to_vec()), EthersToken::Int(header.trusted_height.revision_height.into()), ] .to_vec(), ) } +pub(crate) fn tm_header_from_abi_token(token: Token) -> Result { + use ethers::abi::Token as EthersToken; + + let Token::Bytes(bytes) = token else { + return Err(ClientError::Other("invalid header".to_string())) + }; + let params = vec![ParamType::Tuple(vec![ + ParamType::Tuple(vec![ + ParamType::Tuple(vec![ + ParamType::Tuple(vec![ParamType::Uint(256), ParamType::Uint(256)]), + ParamType::String, + ParamType::Int(256), + ParamType::Tuple(vec![ParamType::Int(256), ParamType::Int(256)]), + ParamType::Tuple(vec![ + ParamType::Bytes, + ParamType::Tuple(vec![ParamType::Uint(256), ParamType::Bytes]), + ]), + ParamType::Bytes, + ParamType::Bytes, + ParamType::Bytes, + ParamType::Bytes, + ParamType::Bytes, + ParamType::Bytes, + ParamType::Bytes, + ParamType::Bytes, + ParamType::Bytes, + ]), + ParamType::Tuple(vec![ + ParamType::Int(256), + ParamType::Int(256), + ParamType::Tuple(vec![ + ParamType::Bytes, + ParamType::Tuple(vec![ParamType::Uint(256), ParamType::Bytes]), + ]), + ]), + ]), + ParamType::Int(256), + ])]; + + let Token::Tuple(toks) = ethers::abi::decode(¶ms, bytes.as_slice())?.pop().unwrap() else { + return Err(ClientError::Other("invalid header'".to_string())) + }; + + let signed_header_header = match toks.get(0).cloned().unwrap() { + EthersToken::Tuple(toks) => toks, + _ => return Err(ClientError::Other("signed_header_header not found".to_string())), + }; + + let signed_header_commit = match toks.get(1).cloned().unwrap() { + EthersToken::Tuple(signed_header_commit) => signed_header_commit, + _ => return Err(ClientError::Other("signed_header_commit not found".to_string())), + }; + + let version = match signed_header_header.get(0).cloned().unwrap() { + EthersToken::Tuple(toks) => toks, + _ => return Err(ClientError::Other("version not found".to_string())), + }; + + let chain_id = match signed_header_header.get(1).cloned().unwrap() { + EthersToken::String(chain_id) => chain_id, + _ => return Err(ClientError::Other("chain_id not found".to_string())), + }; + + let height = match signed_header_header.get(2).cloned().unwrap() { + EthersToken::Int(height) => height, + _ => return Err(ClientError::Other("height not found".to_string())), + }; + + let time = match signed_header_header.get(3).cloned().unwrap() { + EthersToken::Tuple(toks) => toks, + _ => return Err(ClientError::Other("time not found".to_string())), + }; + + let last_block_id = match signed_header_header.get(4).cloned().unwrap() { + EthersToken::Tuple(toks) => toks, + _ => return Err(ClientError::Other("last_block_id not found".to_string())), + }; + + let last_commit_hash = match signed_header_header.get(5).cloned().unwrap() { + EthersToken::Bytes(last_commit_hash) => last_commit_hash, + _ => return Err(ClientError::Other("last_commit_hash not found".to_string())), + }; + + let data_hash = match signed_header_header.get(6).cloned().unwrap() { + EthersToken::Bytes(data_hash) => data_hash, + _ => return Err(ClientError::Other("data_hash not found".to_string())), + }; + + let validators_hash = match signed_header_header.get(7).cloned().unwrap() { + EthersToken::Bytes(validators_hash) => validators_hash, + _ => return Err(ClientError::Other("validators_hash not found".to_string())), + }; + + let next_validators_hash = match signed_header_header.get(8).cloned().unwrap() { + EthersToken::Bytes(next_validators_hash) => next_validators_hash, + _ => return Err(ClientError::Other("next_validators_hash not found".to_string())), + }; + + let consensus_hash = match signed_header_header.get(9).cloned().unwrap() { + EthersToken::Bytes(consensus_hash) => consensus_hash, + _ => return Err(ClientError::Other("consensus_hash not found".to_string())), + }; + + let app_hash = match signed_header_header.get(10).cloned().unwrap() { + EthersToken::Bytes(app_hash) => app_hash, + _ => return Err(ClientError::Other("app_hash not found".to_string())), + }; + + let last_results_hash = match signed_header_header.get(11).cloned().unwrap() { + EthersToken::Bytes(last_results_hash) => last_results_hash, + _ => return Err(ClientError::Other("last_results_hash not found".to_string())), + }; + + let evidence_hash = match signed_header_header.get(12).cloned().unwrap() { + EthersToken::Bytes(evidence_hash) => evidence_hash, + _ => return Err(ClientError::Other("evidence_hash not found".to_string())), + }; + + let proposer_address = match signed_header_header.get(13).cloned().unwrap() { + EthersToken::Bytes(proposer_address) => proposer_address, + _ => return Err(ClientError::Other("proposer_address not found".to_string())), + }; + + let version_block = match version.get(0).cloned().unwrap() { + EthersToken::Uint(version_block) => version_block, + _ => return Err(ClientError::Other("version_block not found".to_string())), + }; + + let version_app = match version.get(1).cloned().unwrap() { + EthersToken::Uint(version_app) => version_app, + _ => return Err(ClientError::Other("version_app not found".to_string())), + }; + + let time_secs = match time.get(0).cloned().unwrap() { + EthersToken::Int(time_secs) => time_secs, + _ => return Err(ClientError::Other("time_secs not found".to_string())), + }; + + let time_nanos = match time.get(1).cloned().unwrap() { + EthersToken::Int(time_nanos) => time_nanos, + _ => return Err(ClientError::Other("time_nanos not found".to_string())), + }; + + let last_block_id_hash = match last_block_id.get(0).cloned().unwrap() { + EthersToken::Bytes(last_block_id_hash) => last_block_id_hash, + _ => return Err(ClientError::Other("last_block_id_hash not found".to_string())), + }; + + let last_block_id_part_set_header = match last_block_id.get(1).cloned().unwrap() { + EthersToken::Tuple(toks) => toks, + _ => return Err(ClientError::Other("last_block_id_part_set_header not found".to_string())), + }; + + let last_block_id_part_set_header_total = + match last_block_id_part_set_header.get(0).cloned().unwrap() { + EthersToken::Uint(last_block_id_part_set_header_total) => + last_block_id_part_set_header_total, + _ => + return Err(ClientError::Other( + "last_block_id_part_set_header_total not found".to_string(), + )), + }; + + let last_block_id_part_set_header_hash = + match last_block_id_part_set_header.get(1).cloned().unwrap() { + EthersToken::Bytes(last_block_id_part_set_header_hash) => + last_block_id_part_set_header_hash, + _ => + return Err(ClientError::Other( + "last_block_id_part_set_header_hash not found".to_string(), + )), + }; + + let last_commit_height = match signed_header_commit.get(0).cloned().unwrap() { + EthersToken::Int(last_commit_height) => last_commit_height, + _ => return Err(ClientError::Other("last_commit_height not found".to_string())), + }; + + let last_commit_round = match signed_header_commit.get(1).cloned().unwrap() { + EthersToken::Int(last_commit_round) => last_commit_round, + _ => return Err(ClientError::Other("last_commit_round not found".to_string())), + }; + + let last_commit_block_id = match signed_header_commit.get(2).cloned().unwrap() { + EthersToken::Tuple(toks) => toks, + _ => return Err(ClientError::Other("last_commit_block_id not found".to_string())), + }; + + let last_commit_block_id_hash = match last_commit_block_id.get(0).cloned().unwrap() { + EthersToken::Bytes(last_commit_block_id_hash) => last_commit_block_id_hash, + _ => return Err(ClientError::Other("last_commit_block_id_hash not found".to_string())), + }; + + let last_commit_block_id_part_set_header = match last_commit_block_id.get(1).cloned().unwrap() { + EthersToken::Tuple(toks) => toks, + _ => + return Err(ClientError::Other( + "last_commit_block_id_part_set_header not found".to_string(), + )), + }; + + let last_commit_block_id_part_set_header_total = + match last_commit_block_id_part_set_header.get(0).cloned().unwrap() { + EthersToken::Uint(last_commit_block_id_part_set_header_total) => + last_commit_block_id_part_set_header_total, + _ => + return Err(ClientError::Other( + "last_commit_block_id_part_set_header_total not found".to_string(), + )), + }; + + let last_commit_block_id_part_set_header_hash = + match last_commit_block_id_part_set_header.get(1).cloned().unwrap() { + EthersToken::Bytes(last_commit_block_id_part_set_header_hash) => + last_commit_block_id_part_set_header_hash, + _ => + return Err(ClientError::Other( + "last_commit_block_id_part_set_header_hash not found".to_string(), + )), + }; + + let revision_number = 1; // TODO + Ok(Header { + signed_header: SignedHeader::new( + block::Header { + version: Version { block: version_block.as_u64(), app: version_app.as_u64() }, + chain_id: chain_id.parse()?, + height: TmHeight::try_from(height.as_u64()).unwrap(), + time: Time::from_unix_timestamp( + time_secs.try_into().unwrap(), + time_nanos.try_into().unwrap(), + )?, + last_block_id: Some(block::Id { + hash: Hash::Sha256(last_block_id_hash.as_slice().try_into().unwrap()), + part_set_header: block::parts::Header::new( + last_block_id_part_set_header_total.as_u32(), + Hash::Sha256( + last_block_id_part_set_header_hash.to_vec().try_into().unwrap(), + ), + ) + .unwrap(), + }), + last_commit_hash: Some(Hash::Sha256(last_commit_hash.to_vec().try_into().unwrap())), + data_hash: Some(Hash::Sha256(data_hash.to_vec().try_into().unwrap())), + validators_hash: Hash::Sha256(validators_hash.to_vec().try_into().unwrap()), + next_validators_hash: Hash::Sha256( + next_validators_hash.to_vec().try_into().unwrap(), + ), + consensus_hash: Hash::Sha256(consensus_hash.to_vec().try_into().unwrap()), + app_hash: AppHash::try_from(app_hash.to_vec()).unwrap(), + last_results_hash: Some(Hash::Sha256( + last_results_hash.to_vec().try_into().unwrap(), + )), + evidence_hash: Some(Hash::Sha256(evidence_hash.to_vec().try_into().unwrap())), + proposer_address: account::Id::try_from(proposer_address.to_vec()).unwrap(), + }, + block::Commit { + height: TmHeight::try_from(last_commit_height.as_u64()).unwrap(), + round: last_commit_round.as_u32().try_into().unwrap(), + block_id: block::Id { + hash: Hash::Sha256(last_commit_block_id_hash.to_vec().try_into().unwrap()), + part_set_header: block::parts::Header::new( + last_commit_block_id_part_set_header_total.as_u32(), + Hash::Sha256( + last_commit_block_id_part_set_header_hash.to_vec().try_into().unwrap(), + ), + ) + .unwrap(), + }, + signatures: vec![], + }, + ) + .unwrap(), + validator_set: tendermint::validator::Set::new(vec![], None), + trusted_height: Height::new(revision_number, last_commit_height.as_u64()), + trusted_validator_set: tendermint::validator::Set::new(vec![], None), + }) +} + pub(crate) fn msg_connection_open_init_token(x: MsgConnectionOpenInit) -> Token { use ethers::abi::{encode as ethers_encode, Token as EthersToken}; @@ -278,7 +749,7 @@ pub(crate) fn msg_connection_open_init_token(x: MsgConnectionOpenInit) -> Token consensus_state_data } -pub fn msg_connection_open_ack_token( +pub fn msg_connection_open_ack_token( msg: MsgConnectionOpenAck, client_state: ClientState, ) -> Token { @@ -352,7 +823,7 @@ pub fn msg_connection_open_ack_token( consensus_state_data } -fn msg_connection_open_try_token( +fn msg_connection_open_try_token( msg: MsgConnectionOpenTry, client_state: ClientState, ) -> Token { @@ -431,9 +902,10 @@ impl Chain for EthereumClient { async fn finality_notifications( &self, ) -> Result + Send>>, Self::Error> { - let ws = crate::client::WsEth::connect(self.ws_uri.to_string()) - .await - .map_err(|err| crate::client::ClientError::ProviderError(self.ws_uri.clone(), err))?; + // let ws = crate::client::WsEth::connect(self.ws_uri.to_string()) + // .await + // .map_err(|err| ClientError::ProviderError(self.ws_uri.clone(), err))?; + let ws = self.websocket_provider().await.unwrap(); let stream = async_stream::stream! { // TODO: is it really finalized blocks stream? @@ -453,6 +925,9 @@ impl Chain for EthereumClient { ) -> Result { use ethers::abi::{encode as ethers_encode, Token as EthersToken}; + log::info!(target: "hyperspace_ethereum", "Submitting messages: {:?}", messages.iter().map(|x| x.type_url.clone()).collect::>().join(", ")); + assert_eq!(messages.len(), 1, "messages.len() > 1"); + for msg in messages { if msg.type_url == ibc::core::ics02_client::msgs::create_client::TYPE_URL { dbg!(&msg.value.len()); @@ -474,6 +949,26 @@ impl Chain for EthereumClient { dbg!(&client_state_data_vec.len()); dbg!(&consensus_state_data_vec.len()); + log::info!(target: "hyperspace_ethereum", "encoding: {}", hex::encode(self.config.client_type.as_bytes())); + log::info!(target: "hyperspace_ethereum", "encoding: {}", hex::encode(&client_state_data_vec.to_vec())); + log::info!(target: "hyperspace_ethereum", "encoding: {}", hex::encode(&consensus_state_data_vec.to_vec())); + /* + [2023-09-06T23:06:36Z INFO hyperspace_ethereum] encoding: 30372d74656e6465726d696e74 + [2023-09-06T23:06:36Z INFO hyperspace_ethereum] encoding: 000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000fa000000000000000000000000000000000000000000000000000000000003d0900000000000000000000000000000000000000000000000000000000000001baf800000000000000000000000000000000000000000000000000006722feb7b0000000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000037e11d60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ed500000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001263656e74617572692d746573746e65742d310000000000000000000000000000 + [2023-09-06T23:06:36Z INFO hyperspace_ethereum] encoding: 00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000064f905f2000000000000000000000000000000000000000000000000178271d8db825068000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020767f0009ebb497c791107b84432ccaec45e92e4d05e5799ac55b2d48f2d5d4170000000000000000000000000000000000000000000000000000000000000020602fa35acfd377900d7fe3459730d96415eef369bd033c0923b2d2e2796a97d9 + [2023-09-06T23:06:36Z INFO hyperspace_ethereum] encoding: 0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000002c0000000000000000000000000000000000000000000000000000000000000000d30372d74656e6465726d696e74000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000fa000000000000000000000000000000000000000000000000000000000003d0900000000000000000000000000000000000000000000000000000000000001baf800000000000000000000000000000000000000000000000000006722feb7b0000000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000037e11d60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ed500000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001263656e74617572692d746573746e65742d310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000064f905f2000000000000000000000000000000000000000000000000178271d8db825068000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020767f0009ebb497c791107b84432ccaec45e92e4d05e5799ac55b2d48f2d5d4170000000000000000000000000000000000000000000000000000000000000020602fa35acfd377900d7fe3459730d96415eef369bd033c0923b2d2e2796a97d9 + //-------------------------------------------------d5a244810000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000002c0000000000000000000000000000000000000000000000000000000000000000d30372d74656e6465726d696e74000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000fa000000000000000000000000000000000000000000000000000000000003d0900000000000000000000000000000000000000000000000000000000000001baf800000000000000000000000000000000000000000000000000006722feb7b0000000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000037e11d60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ed500000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001263656e74617572692d746573746e65742d310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000064f905f2000000000000000000000000000000000000000000000000178271d8db825068000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020767f0009ebb497c791107b84432ccaec45e92e4d05e5799ac55b2d48f2d5d4170000000000000000000000000000000000000000000000000000000000000020602fa35acfd377900d7fe3459730d96415eef369bd033c0923b2d2e2796a97d9 + // 000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000fa000000000000000000000000000000000000000000000000000000000003d0900000000000000000000000000000000000000000000000000000000000001baf800000000000000000000000000000000000000000000000000006722feb7b0000000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000037e11d60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ed500000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001263656e74617572692d746573746e65742d310000000000000000000000000000 + + */ + // 0 1 2 + // d5a244810000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000002c0000000000000000000000000000000000000000000000000000000000000000d30372d74656e6465726d696e74000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000fa000000000000000000000000000000000000000000000000000000000003d0900000000000000000000000000000000000000000000000000000000000001baf800000000000000000000000000000000000000000000000000006722feb7b0000000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000037e11d60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cdc00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001263656e74617572692d746573746e65742d310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000064f8fc0400000000000000000000000000000000000000000000000017826f89135e5218000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020008892c98d506a154ef7e5ad89b345e395cdafc8eb77857276f27ff5cef791da0000000000000000000000000000000000000000000000000000000000000020602fa35acfd377900d7fe3459730d96415eef369bd033c0923b2d2e2796a97d9 + // d5a244810000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000000d30372d74656e6465726d696e74000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000221000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001a02000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000fa000000000000000000000000000000000000000000000000000000000003d0900000000000000000000000000000000000000000000000000000000000001baf800000000000000000000000000000000000000000000000000006722feb7b0000000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000037e11d60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dca00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001263656e74617572692d746573746e65742d31000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000064f900b20000000000000000000000000000000000000000000000001782709ff2f10eb8000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002038c9b9a98f4630114e46c5c394fca947569e8db5f0e01d2aac84ef96ddff8afa0000000000000000000000000000000000000000000000000000000000000020602fa35acfd377900d7fe3459730d96415eef369bd033c0923b2d2e2796a97d9 + //-------------------------------------------------------------------------000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000002c0000000000000000000000000000000000000000000000000000000000000000d30372d74656e6465726d696e74000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000fa000000000000000000000000000000000000000000000000000000000003d0900000000000000000000000000000000000000000000000000000000000001baf800000000000000000000000000000000000000000000000000006722feb7b0000000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000037e11d60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4300000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001263656e74617572692d746573746e65742d310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000064f903130000000000000000000000000000000000000000000000001782712dc658a8f0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020eb5eefd453cb5fd16cce92d669a546a074751d588d89261178dec9a250da2eae0000000000000000000000000000000000000000000000000000000000000020602fa35acfd377900d7fe3459730d96415eef369bd033c0923b2d2e2796a97d9 + //---------0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000002c0000000000000000000000000000000000000000000000000000000000000000d30372d74656e6465726d696e74000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000fa000000000000000000000000000000000000000000000000000000000003d0900000000000000000000000000000000000000000000000000000000000001baf800000000000000000000000000000000000000000000000000006722feb7b0000000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000037e11d60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4300000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001263656e74617572692d746573746e65742d310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000064f903130000000000000000000000000000000000000000000000001782712dc658a8f0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020eb5eefd453cb5fd16cce92d669a546a074751d588d89261178dec9a250da2eae0000000000000000000000000000000000000000000000000000000000000020602fa35acfd377900d7fe3459730d96415eef369bd033c0923b2d2e2796a97d9 + // 30372d74656e6465726d696e74 + // 000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001a02000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000fa000000000000000000000000000000000000000000000000000000000003d0900000000000000000000000000000000000000000000000000000000000001baf800000000000000000000000000000000000000000000000000006722feb7b0000000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000037e11d60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dca00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001263656e74617572692d746573746e65742d310000000000000000000000000000 + // 00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000064f900b20000000000000000000000000000000000000000000000001782709ff2f10eb8000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002038c9b9a98f4630114e46c5c394fca947569e8db5f0e01d2aac84ef96ddff8afa0000000000000000000000000000000000000000000000000000000000000020602fa35acfd377900d7fe3459730d96415eef369bd033c0923b2d2e2796a97d9 let token = EthersToken::Tuple(vec![ //should be the same that we use to register client //client type @@ -483,9 +978,35 @@ impl Chain for EthereumClient { //consensusStateBytes EthersToken::Bytes(consensus_state_data_vec.clone()), ]); + // let bts = ethers::abi::encode(&vec![ + // //should be the same that we use to register client + // //client type + // EthersToken::String(self.config.client_type.clone()), + // //clientStateBytes + // EthersToken::Bytes(client_state_data_vec.clone()), + // //consensusStateBytes + // EthersToken::Bytes(consensus_state_data_vec.clone()), + // ]); + // log::info!(target: "hyperspace_ethereum", "encoding: {}", + // hex::encode(&bts.to_vec())); + let bts = ethers::abi::encode(&vec![token.clone()]); + log::info!(target: "hyperspace_ethereum", "encoding': {}", hex::encode(&bts.to_vec())); - let client_id = self.yui.create_client(token).await; + let tok = ethers::abi::decode( + &[ParamType::Tuple(vec![ + ParamType::String, + ParamType::Bytes, + ParamType::Bytes, + ])], + &bts.to_vec(), // [4..], + ) + .unwrap() + .pop() + .unwrap(); + assert_eq!(tok, token); + let (client_id, tx_id) = self.yui.create_client(token).await; dbg!(&client_id); + // self.set_client_id(); thread::sleep(Duration::from_secs(5)); @@ -493,14 +1014,14 @@ impl Chain for EthereumClient { let mut update_mutex = self.prev_state.lock().unwrap(); *update_mutex = (client_state_data_vec.clone(), consensus_state_data_vec.clone()); - return Ok(()) + return Ok(tx_id) } else if msg.type_url == ibc::core::ics02_client::msgs::update_client::TYPE_URL { let msg = MsgUpdateAnyClient::::decode_vec(&msg.value).unwrap(); let AnyClientMessage::Tendermint(client_state) = msg.client_message else { //TODO return error support only tendermint client state panic!("unsupported") }; - let ClientMessage::Header(header) = client_state else { return Ok(()) }; + let ClientMessage::Header(header) = client_state else { panic!("unsupported") }; //get abi token to update client let tm_header_abi_token = tm_header_abi_token(header); @@ -526,13 +1047,13 @@ impl Chain for EthereumClient { let _ = self.yui.update_client(token).await; thread::sleep(Duration::from_secs(5)); - return Ok(()) + return Ok((H256::default(), H256::default())) // TODO: tx hash } else if msg.type_url == ibc::core::ics03_connection::msgs::conn_open_init::TYPE_URL { let msg = MsgConnectionOpenInit::decode_vec(&msg.value).unwrap(); let token = msg_connection_open_init_token(msg); - let connection_id = self.yui.connection_open_init(token).await; + let (connection_id, tx_id) = self.yui.connection_open_init(token).await; dbg!(connection_id); - return Ok(()) + return Ok(tx_id) } else if msg.type_url == ibc::core::ics03_connection::msgs::conn_open_ack::TYPE_URL { let msg = MsgConnectionOpenAck::::decode_vec(&msg.value).unwrap(); @@ -552,7 +1073,7 @@ impl Chain for EthereumClient { let token = msg_connection_open_ack_token(msg, client_state); let connection_id = self.yui.connection_open_ack(token).await; - return Ok(()) + return Ok((H256::default(), H256::default())) // TODO: tx hash } else if msg.type_url == ibc::core::ics03_connection::msgs::conn_open_try::TYPE_URL { let msg = MsgConnectionOpenTry::::decode_vec(&msg.value).unwrap(); let client_state = match msg.client_state.clone() { @@ -571,43 +1092,43 @@ impl Chain for EthereumClient { let token = msg_connection_open_try_token(msg, client_state); self.yui.connection_open_try(token).await; - return Ok(()) + return Ok((H256::default(), H256::default())) // TODO: tx hash } else if msg.type_url == ibc::core::ics03_connection::msgs::conn_open_confirm::TYPE_URL { let msg = MsgConnectionOpenConfirm::decode_vec(&msg.value).unwrap(); let token = msg_connection_open_confirm_token(msg); self.yui.connection_open_confirm(token).await; - return Ok(()) + return Ok((H256::default(), H256::default())) // TODO: tx hash } else if msg.type_url == channel_msgs::chan_open_init::TYPE_URL { let msg = MsgChannelOpenInit::decode_vec(&msg.value).unwrap(); let token = msg.into_token(); - let channel_id = self.yui.channel_open_init(token).await; - return Ok(()) + let (_channel_id, tx_id) = self.yui.channel_open_init(token).await; + return Ok(tx_id) } else if msg.type_url == channel_msgs::chan_open_try::TYPE_URL { let msg = MsgChannelOpenTry::decode_vec(&msg.value).unwrap(); let token = msg.into_token(); let channel_id = self.yui.channel_open_try(token).await; - return Ok(()) + return Ok((H256::default(), H256::default())) // TODO: tx hash } else if msg.type_url == channel_msgs::chan_open_ack::TYPE_URL { let msg = MsgChannelOpenAck::decode_vec(&msg.value).unwrap(); let token = msg.into_token(); self.yui.send_and_get_tuple(token, "channelOpenAck").await; - return Ok(()) + return Ok((H256::default(), H256::default())) // TODO: tx hash } else if msg.type_url == channel_msgs::chan_open_confirm::TYPE_URL { let msg = MsgChannelOpenConfirm::decode_vec(&msg.value).unwrap(); let token = msg.into_token(); self.yui.send_and_get_tuple(token, "channelOpenConfirm").await; - return Ok(()) + return Ok((H256::default(), H256::default())) // TODO: tx hash } else if msg.type_url == channel_msgs::chan_close_init::TYPE_URL { let msg = MsgChannelCloseInit::decode_vec(&msg.value).unwrap(); let token = msg.into_token(); self.yui.send_and_get_tuple(token, "channelCloseInit").await; - return Ok(()) + return Ok((H256::default(), H256::default())) // TODO: tx hash } else if msg.type_url == channel_msgs::chan_close_confirm::TYPE_URL { let msg = MsgChannelCloseConfirm::decode_vec(&msg.value).unwrap(); let token = msg.into_token(); self.yui.send_and_get_tuple(token, "channelCloseConfirm").await; - return Ok(()) + return Ok((H256::default(), H256::default())) // TODO: tx hash } else if msg.type_url == channel_msgs::timeout_on_close::TYPE_URL { let msg = MsgTimeoutOnClose::decode_vec(&msg.value).unwrap(); } else if msg.type_url == channel_msgs::timeout::TYPE_URL { @@ -616,16 +1137,16 @@ impl Chain for EthereumClient { let msg = MsgAcknowledgement::decode_vec(&msg.value).unwrap(); let token = msg.into_token(); self.yui.send_and_get_tuple(token, "acknowledgePacket").await; - return Ok(()) + return Ok((H256::default(), H256::default())) // TODO: tx hash } else if msg.type_url == channel_msgs::recv_packet::TYPE_URL { let msg = MsgRecvPacket::decode_vec(&msg.value).unwrap(); let token = msg.into_token(); self.yui.send_and_get_tuple(token, "recvPacket").await; - return Ok(()) + return Ok((H256::default(), H256::default())) // TODO: tx hash } unimplemented!("does not support this msg type for now: {}", msg.type_url); } - Ok(()) + Err(ClientError::Other("no message to submit".to_string())) } async fn query_client_message( @@ -663,3 +1184,42 @@ impl Chain for EthereumClient { Ok(()) } } + +#[test] +fn fooo() { + let xs = hex::encode(&[ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3, 208, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 175, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 114, 47, 235, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 126, 17, 214, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 213, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 18, 99, 101, 110, 116, 97, 117, 114, 105, 45, 116, 101, 115, 116, 110, 101, + 116, 45, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ]); + let ys = hex::encode(&[ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 100, 249, 5, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 23, 130, 113, 216, 219, 130, 80, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 118, 127, 0, 9, 235, 180, 151, + 199, 145, 16, 123, 132, 67, 44, 202, 236, 69, 233, 46, 77, 5, 229, 121, 154, 197, 91, 45, + 72, 242, 213, 212, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 32, 96, 47, 163, 90, 207, 211, 119, 144, 13, 127, 227, 69, 151, 48, + 217, 100, 21, 238, 243, 105, 189, 3, 60, 9, 35, 178, 210, 226, 121, 106, 151, 217, + ]); + println!("{xs}\n{ys}"); +} diff --git a/hyperspace/ethereum/src/client.rs b/hyperspace/ethereum/src/client.rs index 934c6ae7f..166d4d7f7 100644 --- a/hyperspace/ethereum/src/client.rs +++ b/hyperspace/ethereum/src/client.rs @@ -3,6 +3,7 @@ use crate::{ jwt::{JwtAuth, JwtKey}, utils::{DeployYuiIbc, ProviderImpl}, }; +use anyhow::Error; use async_trait::async_trait; use cast::revm::db; use ethers::{ @@ -28,7 +29,8 @@ use ibc::{ use ibc_primitives::Timeout; use once_cell::sync::Lazy; use primitives::CommonClientState; -use std::{future::Future, ops::Add, pin::Pin, str::FromStr, sync::Arc}; +use std::{convert::Infallible, future::Future, ops::Add, pin::Pin, str::FromStr, sync::Arc}; +use sync_committee_prover::SyncCommitteeProver; use thiserror::Error; pub type EthRpcClient = ethers::prelude::SignerMiddleware< @@ -69,11 +71,24 @@ pub enum ClientError { #[error("provider-error: {0}: {0}")] ProviderError(http::Uri, ProviderError), #[error("Ethereum error: {0}")] - Ethers(#[from] ethers::providers::ProviderError), + Ethers(#[from] ProviderError), #[error("middleware-error: {0}")] MiddlewareError(MiddlewareErrorType), + #[error("reqwest error: {0}")] + ReqwestError(#[from] reqwest::Error), + #[error("Merkleization error: {0}")] + MerkleizationError(#[from] ssz_rs::MerkleizationError), + #[error("ABI error: {0}")] + AbiError(#[from] ethers::abi::Error), #[error("no-storage-proof: there was no storage proof for the given storage index")] NoStorageProof, + #[error("Tendermint error: {0}")] + Tendermint(#[from] tendermint::Error), + /// Errors associated with ics-02 client + #[error("Ibc client error: {0}")] + IbcClient(#[from] ibc::core::ics02_client::error::Error), + #[error("Ibc channel error")] + IbcChannel(#[from] ibc::core::ics04_channel::error::Error), #[error("{0}")] Other(String), } @@ -90,6 +105,18 @@ impl From for ClientError { } } +impl From for ClientError { + fn from(value: Error) -> Self { + Self::Other(value.to_string()) + } +} + +impl From for ClientError { + fn from(value: Infallible) -> Self { + match value {} + } +} + pub struct AckPacket { pub sequence: u64, pub source_port: String, @@ -149,21 +176,30 @@ impl EthereumClient { self.http_rpc.clone() } + pub fn prover(&self) -> SyncCommitteeProver { + let mut string = self.config.beacon_rpc_url.to_string(); + string.pop(); + SyncCommitteeProver::new(string) + } + pub async fn websocket_provider(&self) -> Result, ClientError> { - let secret = std::fs::read_to_string(format!( - "{}/.lighthouse/local-testnet/geth_datadir1/geth/jwtsecret", - env!("HOME"), - )) - .unwrap(); - println!("secret = {secret}"); - let secret = JwtKey::from_slice(&hex::decode(&secret[2..]).unwrap()).expect("oops"); - let jwt_auth = JwtAuth::new(secret, None, None); - let token = jwt_auth.generate_token().unwrap(); - - let auth = Authorization::bearer(dbg!(token)); - Provider::::connect_with_auth(self.ws_uri.to_string(), auth) - .await - .map_err(|e| ClientError::ProviderError(self.ws_uri.clone(), ProviderError::from(e))) + if let Some(secret_path) = &self.config.jwt_secret_path { + let secret = std::fs::read_to_string(secret_path).unwrap(); + let secret = JwtKey::from_slice(&hex::decode(&secret[2..]).unwrap()).expect("oops"); + let jwt_auth = JwtAuth::new(secret, None, None); + let token = jwt_auth.generate_token().unwrap(); + + let auth = Authorization::bearer(token); + Provider::::connect_with_auth(self.ws_uri.to_string(), auth) + .await + .map_err(|e| { + ClientError::ProviderError(self.ws_uri.clone(), ProviderError::from(e)) + }) + } else { + Provider::::connect(self.ws_uri.to_string()).await.map_err(|e| { + ClientError::ProviderError(self.ws_uri.clone(), ProviderError::from(e)) + }) + } } pub async fn generated_channel_identifiers( diff --git a/hyperspace/ethereum/src/config.rs b/hyperspace/ethereum/src/config.rs index df0786872..c6fa60d64 100644 --- a/hyperspace/ethereum/src/config.rs +++ b/hyperspace/ethereum/src/config.rs @@ -102,6 +102,7 @@ pub struct EthereumClientConfig { #[serde(skip)] pub yui: Option, ProviderImpl>>, pub client_type: String, + pub jwt_secret_path: Option, } impl EthereumClientConfig { diff --git a/hyperspace/ethereum/src/contract.rs b/hyperspace/ethereum/src/contract.rs index f18daf7bd..edb348ea3 100644 --- a/hyperspace/ethereum/src/contract.rs +++ b/hyperspace/ethereum/src/contract.rs @@ -45,8 +45,6 @@ where } } -pub const IBC_HANDLER_ABI: &str = include_str!("./abi/ibc-handler-abi.json"); - /// A wrapper around the IBC handler contract instance pub struct IbcHandler { pub(crate) contract: Contract, @@ -283,16 +281,6 @@ pub fn compile_solc(project_paths: ProjectPathsConfig) -> ProjectCompileOutput { return project_output } -/// Create a new contract instance from the given address and ABI. -#[track_caller] -pub fn ibc_handler(address: Address, client: Arc) -> Contract -where - M: Middleware, -{ - let abi: Abi = serde_json::from_str(IBC_HANDLER_ABI).unwrap(); - Contract::new(address, abi, client) -} - pub(crate) struct Counterparty { pub(crate) client_id: String, pub(crate) connection_id: String, diff --git a/hyperspace/ethereum/src/events.rs b/hyperspace/ethereum/src/events.rs index 725b7b822..90d23d45f 100644 --- a/hyperspace/ethereum/src/events.rs +++ b/hyperspace/ethereum/src/events.rs @@ -2,7 +2,8 @@ use crate::{ client::{ClientError, EthereumClient}, ibc_provider::{ CloseConfirmChannelFilter, CreateClientFilter, OpenConfirmChannelFilter, - OpenConfirmConnectionFilter, UpdateClientFilter, + OpenConfirmConnectionFilter, OpenInitConnectionFilter, OpenTryConnectionFilter, + UpdateClientFilter, }, }; use async_trait::async_trait; @@ -10,8 +11,10 @@ use ethers::prelude::Log; use ibc::{ core::{ ics02_client::events::{Attributes as ClientAttributes, CreateClient, UpdateClient}, - ics03_connection::events::{Attributes, OpenConfirm as ConnectionOpenConfirm}, - ics04_channel::events::{CloseConfirm, OpenConfirm as ChannelOpenConfirm}, + ics03_connection::events::{ + self as connection, Attributes, OpenConfirm as ConnectionOpenConfirm, + }, + ics04_channel::events::{self as channel, CloseConfirm, OpenConfirm as ChannelOpenConfirm}, ics24_host::identifier::{ChannelId, ConnectionId, PortId}, }, events::IbcEvent, @@ -66,44 +69,44 @@ where ChainError(String), // Special event, signifying an error on CheckTx or DeliverTx */ -#[async_trait] -impl TryFromEvent for IbcEvent { - async fn try_from_event( - client: &EthereumClient, - event: CreateClientFilter, - log: Log, - height: Height, - ) -> Result { - let CreateClientFilter { client_id, client_type } = event; - Ok(IbcEvent::CreateClient(CreateClient(ClientAttributes { - height, - client_id: client_id.parse()?, - client_type, - consensus_height: Default::default(), // TODO: consensus height? - }))) - } -} - -#[async_trait] -impl TryFromEvent for IbcEvent { - async fn try_from_event( - client: &EthereumClient, - event: UpdateClientFilter, - log: Log, - height: Height, - ) -> Result { - let UpdateClientFilter { client_id, header } = event; - Ok(IbcEvent::UpdateClient(UpdateClient { - common: ClientAttributes { - height, - client_id: client_id.parse()?, - client_type: Default::default(), // TODO: client type? - consensus_height: Default::default(), // TODO: consensus height? - }, - header: Some(header.to_vec()), // TODO: header query - })) - } -} +// #[async_trait] +// impl TryFromEvent for IbcEvent { +// async fn try_from_event( +// client: &EthereumClient, +// event: CreateClientFilter, +// log: Log, +// height: Height, +// ) -> Result { +// let CreateClientFilter { client_id, client_type } = event; +// Ok(IbcEvent::CreateClient(CreateClient(ClientAttributes { +// height, +// client_id: client_id.parse()?, +// client_type, +// consensus_height: Default::default(), // TODO: consensus height? +// }))) +// } +// } +// +// #[async_trait] +// impl TryFromEvent for IbcEvent { +// async fn try_from_event( +// client: &EthereumClient, +// event: UpdateClientFilter, +// log: Log, +// height: Height, +// ) -> Result { +// let UpdateClientFilter { client_id, header } = event; +// Ok(IbcEvent::UpdateClient(UpdateClient { +// common: ClientAttributes { +// height, +// client_id: client_id.parse()?, +// client_type: Default::default(), // TODO: client type? +// consensus_height: Default::default(), // TODO: consensus height? +// }, +// header: Some(header.to_vec()), // TODO: header query +// })) +// } +// } #[async_trait] impl TryFromEvent for IbcEvent { @@ -151,3 +154,44 @@ impl TryFromEvent for IbcEvent { })) } } + +#[async_trait] +impl TryFromEvent for IbcEvent { + async fn try_from_event( + _client: &EthereumClient, + event: OpenInitConnectionFilter, + _log: Log, + height: Height, + ) -> Result { + let OpenInitConnectionFilter { + connection_id, + client_id, + counterparty_connection_id, + counterparty_client_id, + } = event; + let connection_id: ConnectionId = connection_id.parse()?; + Ok(IbcEvent::OpenInitConnection(connection::OpenInit(connection::Attributes { + height, + connection_id: Some(connection_id), + client_id: client_id.parse()?, + counterparty_connection_id: if counterparty_connection_id.is_empty() { + None + } else { + Some(counterparty_connection_id.parse()?) + }, + counterparty_client_id: counterparty_client_id.parse()?, + }))) + } +} + +#[async_trait] +impl TryFromEvent for IbcEvent { + async fn try_from_event( + client: &EthereumClient, + event: OpenTryConnectionFilter, + log: Log, + height: Height, + ) -> Result { + todo!() + } +} diff --git a/hyperspace/ethereum/src/ibc_provider.rs b/hyperspace/ethereum/src/ibc_provider.rs index cb5b4d0ea..c521e7e5c 100644 --- a/hyperspace/ethereum/src/ibc_provider.rs +++ b/hyperspace/ethereum/src/ibc_provider.rs @@ -5,7 +5,7 @@ use ethers::{ }, contract::{abigen, EthEvent}, middleware::contract::Contract, - prelude::Block, + prelude::{Block, Log}, providers::Middleware, types::{ BlockId, BlockNumber, EIP1186ProofResponse, Filter, StorageProof, Topic, ValueOrArray, @@ -66,9 +66,11 @@ use crate::{ use futures::{FutureExt, Stream, StreamExt}; use thiserror::Error; +use crate::chain::{client_state_from_abi_token, tm_header_from_abi_token}; use ibc::{ applications::transfer::PrefixedCoin, core::{ + ics02_client::{events::UpdateClient, msgs::update_client::MsgUpdateAnyClient}, ics04_channel::{ channel::{Order, State}, events::SendPacket, @@ -77,6 +79,7 @@ use ibc::{ }, events::IbcEvent, protobuf::Protobuf, + tx_msg::Msg, }; use ibc_proto::{ google::protobuf::Any, @@ -87,10 +90,16 @@ use ibc_proto::{ }, }; use ibc_rpc::{IbcApiClient, PacketInfo}; -use icsxx_ethereum::{client_state::ClientState, consensus_state::ConsensusState}; -use pallet_ibc::light_clients::{AnyClientState, AnyConsensusState, HostFunctionsManager}; +use icsxx_ethereum::{ + client_message::ClientMessage, client_state::ClientState, consensus_state::ConsensusState, +}; +use pallet_ibc::light_clients::{ + AnyClientMessage, AnyClientState, AnyConsensusState, HostFunctionsManager, +}; +use primitives::mock::LocalClientTypes; use sync_committee_primitives::types::LightClientState; use sync_committee_prover::SyncCommitteeProver; +use tracing::log; abigen!( IbcClientAbi, @@ -149,11 +158,51 @@ where const NUMBER_OF_BLOCKS_TO_PROCESS_PER_ITER: u64 = 100; +pub async fn parse_ethereum_events( + client: &EthereumClient, + logs: Vec, +) -> Result, ClientError> { + let mut events = vec![]; + + for log in logs { + let raw_log = RawLog::from(log.clone()); + let height = Height::new(0, log.block_number.unwrap().as_u64()); + let topic0 = log.topics[0]; + + macro_rules! handle_events { + ($topic0:ident, $events:ident, $log:ident, $raw_log:ident, $height:ident, $($ty:ty),+) => { + $(if $topic0 == <$ty>::signature() { + let event = <$ty>::decode_log(&$raw_log).expect("decode event"); + $events.push(IbcEvent::try_from_event(client, event, $log, $height).await?) + } else )+ { + log::error!( + target: "hyperspace_ethereum", "unknown event: {}", + log.log_type.unwrap_or(format!("{:?}", $topic0)) + ); + continue + } + }; + } + + handle_events!( + topic0, + events, + log, + raw_log, + height, + OpenInitConnectionFilter, + OpenTryConnectionFilter + ); + } + + Ok(events) +} + #[async_trait::async_trait] impl IbcProvider for EthereumClient { type FinalityEvent = Block; - type TransactionId = (); + type TransactionId = (H256, H256); type AssetId = (); @@ -174,60 +223,56 @@ impl IbcProvider for EthereumClient { let client_state_response = latest_cp_client_state.client_state.ok_or_else(|| { ClientError::Other("counterparty returned empty client state".to_string()) })?; - let client_state = ClientState::::decode_vec( - &client_state_response.value, - ) - .map_err(|_| ClientError::Other("failed to decode client state response".to_string()))?; + let AnyClientState::Ethereum(client_state) = + AnyClientState::decode_recursive(client_state_response, |c| { + matches!(c, AnyClientState::Ethereum(_)) + }) + .ok_or_else(|| ClientError::Other(format!("Could not decode client state")))? + else { + unreachable!() + }; let latest_cp_client_height = client_state.latest_height().revision_height; let latest_height = self.latest_height_and_timestamp().await?.0; let latest_revision = latest_height.revision_number; - // tracing::debug!(?finality_event, "querying latest ibc events"); - // tracing::warn!("TODO: implement query_latest_ibc_events"); let from = latest_cp_client_height; let to = finality_event .number .unwrap() .as_u64() .min(latest_cp_client_height + NUMBER_OF_BLOCKS_TO_PROCESS_PER_ITER); - println!("Getting blocks {}..{}", from, to); + log::info!(target: "hyperspace_ethereum", "Getting blocks {}..{}", from, to); let filter = Filter::new().from_block(from).to_block(to).address(self.yui.diamond.address()); - let client = self.clone(); let logs = self.client().get_logs(&filter).await.unwrap(); - let mut events = vec![]; - let update = prove(self, finality_event.hash.unwrap()).await?; + let update = prove(self, finality_event.number.unwrap().as_u64()).await?; - println!( + log::info!(target: "hyperspace_ethereum", "proven: state root = {}, body root = {}, slot = {}", update.finalized_header.state_root, update.finalized_header.body_root, update.finalized_header.slot ); - // for log in logs { - // let raw_log = RawLog::from(log.clone()); - // let height = Height::new(0, log.block_number.unwrap().as_u64()); - // let topic0 = log.topics[0]; - // - // let mut maybe_ibc_event = if topic0 == CreateClientFilter::signature() { - // let event = CreateClientFilter::decode_log(&raw_log).expect("decode event"); - // IbcEvent::try_from_event(&client, event, log, height).await - // } else { - // eprintln!("unknown event: {}", log.log_type.unwrap_or(format!("{topic0:?}"))); - // continue - // }; - // - // match maybe_ibc_event { - // Ok(ev) => todo!(), - // Err(err) => { - // eprintln!("failed to decode event: {err}"); - // None - // }, - // } - // } - - Ok(events) + + let update_height = Height::new(latest_revision, update.finalized_header.slot.into()); + let events = parse_ethereum_events(&self, logs).await?; + + let update_client_header = { + let msg = MsgUpdateAnyClient:: { + client_id: client_id.clone(), + client_message: AnyClientMessage::Ethereum(ClientMessage::Header(update)), + signer: counterparty.account_id(), + }; + let value = msg.encode_vec().map_err(|e| { + ClientError::from(format!("Failed to encode MsgUpdateClient {msg:?}: {e:?}")) + })?; + // log::info!(target: "hyperspace_ethereum", "update client header: {value:?}", value = + // hex::encode(&value)); + Any { value, type_url: msg.type_url() } + }; + + Ok(vec![(update_client_header, update_height, events, UpdateType::Mandatory)]) } // TODO: this function is mostly used in tests and in 'fishing' mode. @@ -247,24 +292,24 @@ impl IbcProvider for EthereumClient { let height = Height::new(0, log.block_number.unwrap().as_u64()); let topic0 = log.topics[0]; - let mut maybe_ibc_event = if topic0 == CreateClientFilter::signature() { - let event = CreateClientFilter::decode_log(&raw_log).expect("decode event"); - IbcEvent::try_from_event(&client, event, log, height).await - } else { - eprintln!( + // let mut maybe_ibc_event = if topic0 == CreateClientFilter::signature() { + // let event = CreateClientFilter::decode_log(&raw_log).expect("decode event"); + // IbcEvent::try_from_event(&client, event, log, height).await + // } else { + log::error!(target: "hyperspace_ethereum", "unknown event: {}", log.log_type.unwrap_or(format!("{topic0:?}")) ); return None - }; - - match maybe_ibc_event { - Ok(ev) => Some(ev), - Err(err) => { - eprintln!("failed to decode event: {err}"); - None - }, - } + // }; + + // match maybe_ibc_event { + // Ok(ev) => Some(ev), + // Err(err) => { + // log::error!(target: "hyperspace_ethereum", "failed to decode event: {err}"); + // None + // }, + // } }).boxed(); while let Some(ev) = events_stream.next().await { @@ -299,7 +344,7 @@ impl IbcProvider for EthereumClient { .call() .await .map_err(|err| { - eprintln!("error: {err}"); + log::error!(target: "hyperspace_ethereum", "error: {err}"); err }) .unwrap(); @@ -307,7 +352,7 @@ impl IbcProvider for EthereumClient { let proof_height = Some(at.into()); let consensus_state = google::protobuf::Any::decode(&*client_cons).ok(); - Ok(QueryConsensusStateResponse { consensus_state, proof: vec![], proof_height }) + Ok(QueryConsensusStateResponse { consensus_state, proof: vec![0], proof_height }) } async fn query_client_state( @@ -315,20 +360,142 @@ impl IbcProvider for EthereumClient { at: Height, client_id: ClientId, ) -> Result { - let (client_state, _): (Vec, bool) = self + // First, we try to find an `UpdateClient` event at the given height... + log::info!(target: "hyperspace_ethereum", "qcs {}", line!()); + let mut client_state; + let mut event_filter = self .yui - .method("getClientState", (client_id.to_string(),)) - .expect("contract is missing getClientState") - .block(BlockId::Number(BlockNumber::Number(at.revision_height.into()))) - .call() + .event_for_name::("UpdateClient") + .expect("contract is missing UpdateClient event") + .from_block(BlockNumber::Earliest) + .to_block(at.revision_height); + event_filter.filter = event_filter.filter.topic1({ + let hash = H256::from_slice(&encode(&[Token::FixedBytes( + keccak256(client_id.to_string().into_bytes()).to_vec(), + )])); + ValueOrArray::Value(hash) + }); + log::info!(target: "hyperspace_ethereum", "qcs {}", line!()); + let maybe_log = self + .yui + .diamond + .client() + .get_logs(&event_filter.filter) .await - .map_err(|err| todo!("query-client-state: error: {err:?}")) - .unwrap(); + .unwrap() + .pop() // get only the last event + ; + log::info!(target: "hyperspace_ethereum", "qcs {}", line!()); + match maybe_log { + Some(log) => { + let tx_hash = log.transaction_hash.expect("tx hash should exist"); + let func = self.yui.function("updateClient")?; + let tx = + self.client().get_transaction(tx_hash).await.unwrap().ok_or_else(|| { + ClientError::Other(format!("transaction not found: {}", tx_hash)) + })?; + let calldata = func.decode_input(&tx.input[4..])?.pop().unwrap(); + let Token::Tuple(toks) = calldata else { panic!() }; + let header = tm_header_from_abi_token(toks[1].clone())?; + let client_state_token = toks[2].clone(); + client_state = client_state_from_abi_token::(client_state_token)?; + client_state.latest_height = Height::new( + client_state.latest_height.revision_number, + header.signed_header.header.height.into(), + ); + // TODO: handle frozen height + }, + None => { + log::trace!(target: "hyperspace_ethereum", "no update client event found for blocks ..{at}, looking for a create client event..."); + + // ...otherwise, try to get the `CreateClient` event + let mut event_filter = self + .yui + .event_for_name::("CreateClient") + .expect("contract is missing CreateClient event") + .from_block(BlockNumber::Earliest) + .to_block(at.revision_height); + event_filter.filter = event_filter.filter.topic1({ + let hash = H256::from_slice(&encode(&[Token::FixedBytes( + keccak256(client_id.to_string().into_bytes()).to_vec(), + )])); + ValueOrArray::Value(hash) + }); + let log = self + .yui + .diamond + .client() + .get_logs(&event_filter.filter) + .await + .unwrap() + .pop() // get only the last event + .ok_or_else(|| ClientError::Other("no events found".to_string()))?; + + let tx_hash = log.transaction_hash.expect("tx hash should exist"); + let func = self.yui.function("createClient")?; + let tx = + self.client().get_transaction(tx_hash).await.unwrap().ok_or_else(|| { + ClientError::Other(format!("transaction not found: {}", tx_hash)) + })?; + let calldata = func.decode_input(&tx.input[4..])?.pop().unwrap(); + let Token::Tuple(toks) = calldata else { panic!() }; + let client_state_token = toks[1].clone(); + client_state = client_state_from_abi_token::(client_state_token)?; + }, + } + + // let decoded_log = UpdateClientFilter::decode_log(&log.clone().into()).unwrap(); + // decoded_log. + // let block_number = self + // .client() + // .get_block(BlockId::Hash(block_hash)) + // .await + // .unwrap() + // .unwrap() + // .number + // .unwrap(); + // let event_filter = self + // .yui + // .event_for_name::("GeneratedClientIdentifier") + // .expect("contract is missing GeneratedClientIdentifier event") + // .from_block(block_number) + // .to_block(block_number); + // let log = self + // .yui + // .diamond + // .client() + // .get_logs(&event_filter.filter) + // .await + // .unwrap() + // .into_iter() + // .find(|log| log.transaction_hash.expect("tx hash should exist") == tx_hash) + // .unwrap(); + + // let decoded_log = + // GeneratedClientIdentifierFilter::decode_log(&log.clone().into()).unwrap(); + + // emit CreateClient(clientId, msg_.clientType); + // emit UpdateClient(msg_.clientId, keccak256(msg_.clientMessage)); + // let (client_state, _): (Vec, bool) = self + // .yui + // .method("getClientState", (client_id.to_string(),)) + // .expect("contract is missing getClientState") + // .block(BlockId::Number(BlockNumber::Number(at.revision_height.into()))) + // .call() + // .await + // .map_err(|err| todo!("query-client-state: error: {err:?}")) + // .unwrap(); let proof_height = Some(at.into()); - let client_state = google::protobuf::Any::decode(&*client_state).ok(); + // let client_state = google::protobuf::Any::decode(&*client_state).ok(); - Ok(QueryClientStateResponse { client_state, proof: vec![], proof_height }) + Ok(QueryClientStateResponse { + client_state: Some(client_state.to_any()), + proof_height, + proof: vec![0], + }) + // log::error!(target: "hyperspace_ethereum", "TODO: implement query_client_state"); + // todo!() } async fn query_connection_end( @@ -374,7 +541,7 @@ impl IbcProvider for EthereumClient { None }; - Ok(QueryConnectionResponse { connection, proof: Vec::new(), proof_height: Some(at.into()) }) + Ok(QueryConnectionResponse { connection, proof: vec![0], proof_height: Some(at.into()) }) } async fn query_channel_end( @@ -413,7 +580,7 @@ impl IbcProvider for EthereumClient { connection_hops: channel_data.connection_hops, version: channel_data.version, }), - proof: vec![], + proof: vec![0], proof_height: None, }) } @@ -757,7 +924,7 @@ impl IbcProvider for EthereumClient { Topic::Value(v) => v.iter().map(|v| &v.0[..]).collect::>(), Topic::Array(vs) => vs.iter().flatten().map(|v| &v.0[..]).collect(), }; - println!( + log::debug!(target: "hyperspace_ethereum", "Looking for topic{i}: {}", data.into_iter().map(hex::encode).collect::>().join(", ") ); @@ -988,7 +1155,7 @@ impl IbcProvider for EthereumClient { Ok(Duration::from_secs(block.timestamp.as_u64()).as_nanos() as u64) } - // TODO + // TODO: query_clients (ethereum) async fn query_clients(&self) -> Result, Self::Error> { Ok(vec![]) } @@ -1006,7 +1173,7 @@ impl IbcProvider for EthereumClient { height: u32, client_id: String, ) -> Result, Self::Error> { - todo!() + Ok(vec![]) // TODO: query_connection_using_client (ethereum) } async fn is_update_required( @@ -1020,9 +1187,7 @@ impl IbcProvider for EthereumClient { async fn initialize_client_state( &self, ) -> Result<(AnyClientState, AnyConsensusState), Self::Error> { - let mut string = self.config.beacon_rpc_url.to_string(); - string.pop(); - let sync_committee_prover = SyncCommitteeProver::new(string); + let sync_committee_prover = self.prover(); let block_id = "finalized"; let block_header = sync_committee_prover.fetch_header(&block_id).await.unwrap(); @@ -1075,26 +1240,104 @@ impl IbcProvider for EthereumClient { async fn query_client_id_from_tx_hash( &self, - tx_id: Self::TransactionId, + (block_hash, tx_hash): Self::TransactionId, ) -> Result { - todo!() + let block_number = self + .client() + .get_block(BlockId::Hash(block_hash)) + .await + .unwrap() + .unwrap() + .number + .unwrap(); + let event_filter = self + .yui + .event_for_name::("GeneratedClientIdentifier") + .expect("contract is missing GeneratedClientIdentifier event") + .from_block(block_number) + .to_block(block_number); + let log = self + .yui + .diamond + .client() + .get_logs(&event_filter.filter) + .await + .unwrap() + .into_iter() + .find(|log| log.transaction_hash.expect("tx hash should exist") == tx_hash) + .unwrap(); + + let decoded_log = GeneratedClientIdentifierFilter::decode_log(&log.clone().into()).unwrap(); + Ok(decoded_log.0.parse()?) } async fn query_connection_id_from_tx_hash( &self, - tx_id: Self::TransactionId, + (block_hash, tx_hash): Self::TransactionId, ) -> Result { - todo!() + let block_number = self + .client() + .get_block(BlockId::Hash(block_hash)) + .await + .unwrap() + .unwrap() + .number + .unwrap(); + let event_filter = self + .yui + .event_for_name::("OpenInitConnection") + .expect("contract is missing OpenInitConnection event") + .from_block(block_number) + .to_block(block_number); + let log = self + .yui + .diamond + .client() + .get_logs(&event_filter.filter) + .await + .unwrap() + .into_iter() + .find(|log| log.transaction_hash.expect("tx hash should exist") == tx_hash) + .unwrap(); + + let decoded_log = OpenInitConnectionFilter::decode_log(&log.clone().into()).unwrap(); + Ok(decoded_log.connection_id.parse()?) } async fn query_channel_id_from_tx_hash( &self, - tx_id: Self::TransactionId, + (block_hash, tx_hash): Self::TransactionId, ) -> Result<(ChannelId, PortId), Self::Error> { - todo!() + let block_number = self + .client() + .get_block(BlockId::Hash(block_hash)) + .await + .unwrap() + .unwrap() + .number + .unwrap(); + let event_filter = self + .yui + .event_for_name::("OpenInitChannel") + .expect("contract is missing OpenInitChannel event") + .from_block(block_number) + .to_block(block_number); + let log = self + .yui + .diamond + .client() + .get_logs(&event_filter.filter) + .await + .unwrap() + .into_iter() + .find(|log| log.transaction_hash.expect("tx hash should exist") == tx_hash) + .unwrap(); + + let decoded_log = OpenInitChannelFilter::decode_log(&log.clone().into()).unwrap(); + Ok((decoded_log.channel_id.parse()?, decoded_log.port_id.parse()?)) } - async fn upload_wasm(&self, wasm: Vec) -> Result, Self::Error> { + async fn upload_wasm(&self, _wasm: Vec) -> Result, Self::Error> { unimplemented!("upload_wasm") } } diff --git a/hyperspace/ethereum/src/mock/utils.rs b/hyperspace/ethereum/src/mock/utils.rs index 509355895..98db1e69e 100644 --- a/hyperspace/ethereum/src/mock/utils.rs +++ b/hyperspace/ethereum/src/mock/utils.rs @@ -415,17 +415,23 @@ pub async fn hyperspace_ethereum_client_fixture( None }; + let jwt_secret_path = if !USE_GETH { + None + } else { + Some(format!("{}/.lighthouse/local-testnet/geth_datadir1/geth/jwtsecret", env!("HOME"))) + }; + EthereumClientConfig { http_rpc_url: endpoint.parse().unwrap(), ws_rpc_url: "ws://localhost:5001".parse().unwrap(), - beacon_rpc_url: Default::default(), + beacon_rpc_url: "http://localhost:8001".parse().unwrap(), ibc_handler_address: yui_ibc.diamond.address(), tendermint_client_address: yui_ibc.tendermint.address(), mnemonic: None, max_block_weight: 1, private_key: wallet, private_key_path: wallet_path, - name: "mock-ethereum-client".into(), + name: "ethereum-client".into(), client_id: Some( ibc::core::ics24_host::identifier::ClientId::new("07-tendermint", 0).unwrap(), ), @@ -435,5 +441,6 @@ pub async fn hyperspace_ethereum_client_fixture( wasm_code_id: None, yui: Some(yui_ibc), client_type: "07-tendermint".into(), + jwt_secret_path, } } diff --git a/hyperspace/ethereum/src/prove.rs b/hyperspace/ethereum/src/prove.rs index 93ed21e7b..324e17bf4 100644 --- a/hyperspace/ethereum/src/prove.rs +++ b/hyperspace/ethereum/src/prove.rs @@ -30,19 +30,19 @@ use tokio::time; pub async fn prove( client: &EthereumClient, - block_hash: H256, + block_number: u64, ) -> Result, ClientError> { - let sync_committee_prover = SyncCommitteeProver::new(client.config.http_rpc_url.to_string()); + log::info!(target: "hyperspace_ethereum", "Proving {block_number} {}", line!()); + let sync_committee_prover = client.prover(); - let block_id = format!("{block_hash:?}"); + let block_id = format!("{block_number:?}"); // let block_id = "head"; + log::info!(target: "hyperspace_ethereum", "Proving {}", line!()); - let block_header = sync_committee_prover.fetch_header(&block_id).await.unwrap(); + let block_header = sync_committee_prover.fetch_header(&block_id).await?; + log::info!(target: "hyperspace_ethereum", "Proving {}", line!()); - let state = sync_committee_prover - .fetch_beacon_state(&block_header.slot.to_string()) - .await - .unwrap(); + let state = sync_committee_prover.fetch_beacon_state(&block_header.slot.to_string()).await?; let mut client_state = LightClientState { finalized_header: block_header.clone(), @@ -50,17 +50,18 @@ pub async fn prove( current_sync_committee: state.current_sync_committee, next_sync_committee: state.next_sync_committee, }; + log::info!(target: "hyperspace_ethereum", "Proving {}", line!()); - let finality_checkpoint = sync_committee_prover.fetch_finalized_checkpoint().await.unwrap(); + let finality_checkpoint = sync_committee_prover.fetch_finalized_checkpoint().await?; if finality_checkpoint.finalized.root == Node::default() || finality_checkpoint.finalized.epoch <= client_state.latest_finalized_epoch || finality_checkpoint.finalized.root == - client_state.finalized_header.clone().hash_tree_root().unwrap() + client_state.finalized_header.clone().hash_tree_root()? { panic!("No new finalized checkpoint found") } - println!("A new epoch has been finalized {}", finality_checkpoint.finalized.epoch); + log::debug!(target: "hyperspace_ethereum", "A new epoch has been finalized {}", finality_checkpoint.finalized.epoch); let block_id = { let mut block_id = hex::encode(finality_checkpoint.finalized.root.as_bytes()); @@ -68,12 +69,11 @@ pub async fn prove( block_id }; - let finalized_header = sync_committee_prover.fetch_header(&block_id).await.unwrap(); + let finalized_header = sync_committee_prover.fetch_header(&block_id).await?; let finalized_state = sync_committee_prover .fetch_beacon_state(finalized_header.slot.to_string().as_str()) - .await - .unwrap(); - let execution_payload_proof = prove_execution_payload(finalized_state.clone()).unwrap(); + .await?; + let execution_payload_proof = prove_execution_payload(finalized_state.clone())?; let mut attested_epoch = finality_checkpoint.finalized.epoch + 2; // Get attested header and the signature slot @@ -90,7 +90,7 @@ pub async fn prove( // we move to the next epoch if (attested_epoch * SLOTS_PER_EPOCH).saturating_add(SLOTS_PER_EPOCH - 1) == attested_slot { // No block was found in attested epoch we move to the next possible attested epoch - println!( + log::debug!(target: "hyperspace_ethereum", "No slots found in epoch {attested_epoch} Moving to the next possible epoch {}", attested_epoch + 1 ); @@ -112,7 +112,7 @@ pub async fn prove( if (attested_epoch * SLOTS_PER_EPOCH).saturating_add(SLOTS_PER_EPOCH - 1) == signature_slot { - println!("Waiting for signature block for attested header"); + log::debug!(target: "hyperspace_ethereum", "Waiting for signature block for attested header"); std::thread::sleep(Duration::from_secs(24)); signature_slot = header.slot + 1; loop_count += 1; @@ -134,12 +134,12 @@ pub async fn prove( .count_ones() < (2 * SYNC_COMMITTEE_SIZE) / 3 { attested_slot += 1; - println!("Signature block does not have sufficient sync committee participants -> participants {}", signature_block.body.sync_aggregate.sync_committee_bits.as_bitslice().count_ones()); + log::debug!(target: "hyperspace_ethereum", "Signature block does not have sufficient sync committee participants -> participants {}", signature_block.body.sync_aggregate.sync_committee_bits.as_bitslice().count_ones()); continue } break (header, signature_block) } else { - println!("No signature block found in {attested_epoch} Moving to the next possible epoch {}", attested_epoch + 1); + log::debug!(target: "hyperspace_ethereum", "No signature block found in {attested_epoch} Moving to the next possible epoch {}", attested_epoch + 1); std::thread::sleep(Duration::from_secs(24)); attested_epoch += 1; attested_slot = attested_epoch * SLOTS_PER_EPOCH; @@ -152,18 +152,17 @@ pub async fn prove( let attested_state = sync_committee_prover .fetch_beacon_state(attested_block_header.slot.to_string().as_str()) - .await - .unwrap(); + .await?; - let finalized_hash_tree_root = finalized_header.clone().hash_tree_root().unwrap(); - println!("{:?}, {}", attested_state.finalized_checkpoint, attested_state.slot); - println!("{:?}, {}", finalized_hash_tree_root, finalized_header.slot); + let finalized_hash_tree_root = finalized_header.clone().hash_tree_root()?; + log::debug!(target: "hyperspace_ethereum", "{:?}, {}", attested_state.finalized_checkpoint, attested_state.slot); + log::debug!(target: "hyperspace_ethereum", "{:?}, {}", finalized_hash_tree_root, finalized_header.slot); assert_eq!(finalized_hash_tree_root, attested_state.finalized_checkpoint.root); let finality_proof = FinalityProof { epoch: finality_checkpoint.finalized.epoch, - finality_branch: prove_finalized_header(attested_state.clone()).unwrap(), + finality_branch: prove_finalized_header(attested_state.clone())?, }; let state_period = compute_sync_committee_period_at_slot(finalized_header.slot); @@ -171,7 +170,7 @@ pub async fn prove( let update_attested_period = compute_sync_committee_period_at_slot(attested_block_header.slot); let sync_committee_update = if state_period == update_attested_period { - let sync_committee_proof = prove_sync_committee_update(attested_state.clone()).unwrap(); + let sync_committee_proof = prove_sync_committee_update(attested_state.clone())?; let sync_committee_proof = sync_committee_proof .into_iter() @@ -196,10 +195,10 @@ pub async fn prove( sync_committee_prover.fetch_header(i.to_string().as_str()).await { let ancestry_proof = - prove_block_roots_proof(finalized_state.clone(), ancestor_header.clone()).unwrap(); + prove_block_roots_proof(finalized_state.clone(), ancestor_header.clone())?; let header_state = - sync_committee_prover.fetch_beacon_state(i.to_string().as_str()).await.unwrap(); - let execution_payload_proof = prove_execution_payload(header_state).unwrap(); + sync_committee_prover.fetch_beacon_state(i.to_string().as_str()).await?; + let execution_payload_proof = prove_execution_payload(header_state)?; ancestor_blocks.push(AncestorBlock { header: ancestor_header, execution_payload: execution_payload_proof, @@ -209,7 +208,7 @@ pub async fn prove( i -= 1; } - println!("\nAncestor blocks count: \n {:?} \n", ancestor_blocks.len()); + log::debug!(target: "hyperspace_ethereum", "\nAncestor blocks count: \n {:?} \n", ancestor_blocks.len()); // construct light client let light_client_update = LightClientUpdate { diff --git a/hyperspace/ethereum/src/utils.rs b/hyperspace/ethereum/src/utils.rs index 4761a76bd..755d82377 100644 --- a/hyperspace/ethereum/src/utils.rs +++ b/hyperspace/ethereum/src/utils.rs @@ -1,9 +1,9 @@ use crate::contract::UnwrapContractError; use ethers::{ - abi::{AbiError, Address, Detokenize, EventExt, Token, Tokenize}, + abi::{AbiError, Address, Detokenize, EventExt, Function, FunctionExt, Token, Tokenize}, contract::{ContractInstance, FunctionCall}, prelude::{ - EthEvent, Event, Filter, Http, LocalWallet, Middleware, Provider, TransactionReceipt, + EthEvent, Event, Filter, Http, LocalWallet, Middleware, Provider, TransactionReceipt, H256, }, }; use ethers_solc::artifacts::{Storage, StorageLayout}; @@ -230,7 +230,7 @@ where tx } - pub async fn create_client(&self, msg: Token) -> String { + pub async fn create_client(&self, msg: Token) -> (String, (H256, H256)) { let method = self.method::<_, String>("createClient", (msg,)).unwrap(); let client_id = method.call().await.unwrap_contract_error(); @@ -238,7 +238,7 @@ where let receipt = method.send().await.unwrap().await.unwrap().unwrap(); assert_eq!(receipt.status, Some(1.into())); - client_id + (client_id, (receipt.block_hash.unwrap(), receipt.transaction_hash)) } pub async fn update_client(&self, msg: Token) { @@ -275,7 +275,7 @@ where id } - pub async fn connection_open_init(&self, msg: Token) -> String { + pub async fn connection_open_init(&self, msg: Token) -> (String, (H256, H256)) { let method = self.method::<_, String>("connectionOpenInit", (msg,)).unwrap(); let gas_estimate_connection_open_try = method.estimate_gas().await.unwrap(); @@ -284,7 +284,8 @@ where let receipt = method.send().await.unwrap().await.unwrap().unwrap(); assert_eq!(receipt.status, Some(1.into())); - id + let tx_id = (receipt.block_hash.unwrap(), receipt.transaction_hash); + (id, tx_id) } pub async fn connection_open_confirm(&self, msg: Token) { @@ -298,7 +299,7 @@ where assert_eq!(receipt.status, Some(1.into())); } - pub async fn channel_open_init(&self, msg: Token) -> String { + pub async fn channel_open_init(&self, msg: Token) -> (String, (H256, H256)) { let method = self.method::<_, String>("channelOpenInit", (msg,)).unwrap(); let gas_estimate_connection_id = method.estimate_gas().await.unwrap(); @@ -307,7 +308,9 @@ where let receipt = method.send().await.unwrap().await.unwrap().unwrap(); assert_eq!(receipt.status, Some(1.into())); - connection_id + + let tx_id = (receipt.block_hash.unwrap(), receipt.transaction_hash); + (connection_id, tx_id) } pub async fn channel_open_try(&self, msg: Token) -> String { @@ -334,6 +337,29 @@ where ret } + pub fn function(&self, name: &str) -> ethers::abi::Result<&Function> { + let mut func = None; + for faucet in &self.deployed_facets { + if let Ok(f) = faucet.abi().function(name) { + log::info!(target: "hyperspace_ethereum", "found function: {name}, {}, {}, {}", f.signature(), f.abi_signature(), hex::encode(&f.short_signature())); + if func.is_some() { + log::error!(target: "hyperspace_ethereum", "ambiguous function name: {}", name); + //panic!("ambiguous function name: {}", name); + //d5a2448100000000000000000000000000000000000000000000000000000000 + //d5a2448100000000000000000000000000000000000000000000000000000000 + // d5a244810000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000f30372d74656e6465726d696e742d30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + // d5a244810000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000002c0000000000000000000000000000000000000000000000000000000000000000d30372d74656e6465726d696e74000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000fa000000000000000000000000000000000000000000000000000000000003d0900000000000000000000000000000000000000000000000000000000000001baf800000000000000000000000000000000000000000000000000006722feb7b0000000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000037e11d60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cdc00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001263656e74617572692d746573746e65742d310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000064f8fc0400000000000000000000000000000000000000000000000017826f89135e5218000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020008892c98d506a154ef7e5ad89b345e395cdafc8eb77857276f27ff5cef791da0000000000000000000000000000000000000000000000000000000000000020602fa35acfd377900d7fe3459730d96415eef369bd033c0923b2d2e2796a97d9 + } + func = Some(f); + } + } + func.ok_or_else(|| ethers::abi::Error::InvalidName(name.into())) + // self.deployed_facets + // .iter() + // .find_map(|x| x.abi().function(name).ok()) + // .ok_or_else(|| ethers::abi::Error::InvalidName(name.into())) + } + pub fn method( &self, name: &str, diff --git a/hyperspace/testsuite/src/lib.rs b/hyperspace/testsuite/src/lib.rs index 2024810bf..6c42e337f 100644 --- a/hyperspace/testsuite/src/lib.rs +++ b/hyperspace/testsuite/src/lib.rs @@ -64,6 +64,10 @@ where let handle = tokio::task::spawn(async move { hyperspace_core::relay(client_a_clone, client_b_clone, None, None, None) .await + .map_err(|e| { + log::error!(target: "hyperspace", "Relayer loop failed: {:?}", e); + e + }) .unwrap() }); // check if an open transfer channel exists diff --git a/hyperspace/testsuite/tests/ethereum_cosmos.rs b/hyperspace/testsuite/tests/ethereum_cosmos.rs index ef216fe78..1a9134424 100644 --- a/hyperspace/testsuite/tests/ethereum_cosmos.rs +++ b/hyperspace/testsuite/tests/ethereum_cosmos.rs @@ -217,17 +217,17 @@ async fn ethereum_to_cosmos_ibc_messaging_full_integration_test() { "ibc/47B97D8FF01DA03FCB2F4B1FFEC931645F254E21EF465FA95CBA6888CB964DC4".to_string(), ); let (mut chain_a, mut chain_b) = setup_clients().await; - // let (handle, channel_a, channel_b, connection_id_a, connection_id_b) = - // setup_connection_and_channel(&mut chain_a, &mut chain_b, Duration::from_secs(60 * 2)).await; - // handle.abort(); - // - // // Set connections and channel whitelist - // chain_a.set_connection_id(connection_id_a); - // chain_b.set_connection_id(connection_id_b); - // - // chain_a.set_channel_whitelist(vec![(channel_a, PortId::transfer())].into_iter().collect()); - // chain_b.set_channel_whitelist(vec![(channel_b, PortId::transfer())].into_iter().collect()); - // + let (handle, channel_a, channel_b, connection_id_a, connection_id_b) = + setup_connection_and_channel(&mut chain_a, &mut chain_b, Duration::from_secs(60 * 2)).await; + handle.abort(); + + // Set connections and channel whitelist + chain_a.set_connection_id(connection_id_a); + chain_b.set_connection_id(connection_id_b); + + chain_a.set_channel_whitelist(vec![(channel_a, PortId::transfer())].into_iter().collect()); + chain_b.set_channel_whitelist(vec![(channel_b, PortId::transfer())].into_iter().collect()); + // // Run tests sequentially // // // no timeouts + connection delay diff --git a/light-clients/icsxx-ethereum-cw/src/channel.rs b/light-clients/icsxx-ethereum-cw/src/channel.rs index 99c668f6a..0539eef91 100644 --- a/light-clients/icsxx-ethereum-cw/src/channel.rs +++ b/light-clients/icsxx-ethereum-cw/src/channel.rs @@ -1,3 +1,18 @@ +// Copyright (C) 2022 ComposableFi. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + use crate::context::Context; use ibc::{ core::{ diff --git a/light-clients/icsxx-ethereum-cw/src/client.rs b/light-clients/icsxx-ethereum-cw/src/client.rs index 91c10a505..816879246 100644 --- a/light-clients/icsxx-ethereum-cw/src/client.rs +++ b/light-clients/icsxx-ethereum-cw/src/client.rs @@ -1,8 +1,24 @@ +// Copyright (C) 2022 ComposableFi. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + use crate::{ context::Context, - contract::{code_id, CLIENT_COUNTER, CONSENSUS_STATES_HEIGHTS, HOST_CONSENSUS_STATE}, + contract::{CLIENT_COUNTER, CONSENSUS_STATES_HEIGHTS, HOST_CONSENSUS_STATE}, ics23::{ - ConsensusStates, FakeInner, ReadonlyClientStates, ReadonlyClients, ReadonlyConsensusStates, + ClientStates, ConsensusStates, FakeInner, ReadonlyClientStates, ReadonlyClients, + ReadonlyConsensusStates, }, log, }; @@ -15,7 +31,6 @@ use ibc::{ context::{ClientKeeper, ClientReader, ClientTypes}, error::Error, }, - ics23_commitment::commitment::CommitmentRoot, ics24_host::identifier::ClientId, }, protobuf::Protobuf, @@ -59,8 +74,7 @@ where .ok_or_else(|| Error::client_not_found(client_id.clone()))?; let data = String::from_utf8(data).map_err(|e| { Error::implementation_specific(format!( - "[client_type]: error decoding client type bytes to string {}", - e + "[client_type]: error decoding client type bytes to string {e}" )) })?; match ClientType::from_str(&data) { @@ -75,23 +89,8 @@ where fn client_state(&self, client_id: &ClientId) -> Result, Error> { log!(self, "in client : [client_state] >> client_id = {:?}", client_id); let client_states = ReadonlyClientStates::new(self.storage()); - let data = client_states - .get(client_id) - .ok_or_else(|| Error::client_not_found(client_id.clone()))?; - let any = Any::decode(&*data).map_err(Error::decode)?; - let wasm_state = - ics08_wasm::client_state::ClientState::::decode_vec( - &any.value, - ) - .map_err(|e| { - Error::implementation_specific(format!( - "[client_state]: error decoding client state bytes to WasmConsensusState {}", - e - )) - })?; - let any = Any::decode(&*wasm_state.data).map_err(|e| Error::decode(e))?; - let state = - ClientState::::decode_vec(&*any.value).map_err(Error::invalid_any_client_state)?; + let data = client_states.get().ok_or_else(|| Error::client_not_found(client_id.clone()))?; + let state = Self::decode_client_state(&data)?; log!(self, "in client : [client_state] >> any client_state: {:?}", state); Ok(state) } @@ -101,29 +100,18 @@ where client_id: &ClientId, height: Height, ) -> Result { - log!( - self, - "in client : [consensus_state] >> client_id = {:?}, height = {:?}", - client_id, - height - ); + log!(self, "in client : [consensus_state] >> height = {:?}", height); let consensus_states = ReadonlyConsensusStates::new(self.storage()); let value = consensus_states - .get(client_id, height) + .get(height) .ok_or_else(|| Error::consensus_state_not_found(client_id.clone(), height))?; log!( self, "in client : [consensus_state] >> consensus_state (raw): {}", hex::encode(&value) ); - let any = Any::decode(&mut &value[..]).map_err(Error::decode)?; - let wasm_consensus_state = - ics08_wasm::consensus_state::ConsensusState::::decode_vec(&*any.value) - .map_err(Error::invalid_any_consensus_state)?; - let any = Any::decode(&mut &wasm_consensus_state.data[..]).map_err(Error::decode)?; - let any_consensus_state = - ConsensusState::decode_vec(&*any.value).map_err(Error::invalid_any_consensus_state)?; + let any_consensus_state = Self::decode_consensus_state(&value)?; log!( self, "in client : [consensus_state] >> any consensus state = {:?}", @@ -133,7 +121,7 @@ where } fn host_client_type(&self) -> String { - "icsxx_ethereum".to_string() + "ics10_grandpa".to_string() } fn next_consensus_state( @@ -146,7 +134,7 @@ where .unwrap_or_default() .range(height..) .next() - .map(|height| self.consensus_state(client_id, Height::from(*height))) + .map(|height| self.consensus_state(client_id, *height)) .transpose() } @@ -161,7 +149,7 @@ where .range(..height) .rev() .next() - .map(|height| self.consensus_state(client_id, Height::from(*height))) + .map(|height| self.consensus_state(client_id, *height)) .transpose() } @@ -184,8 +172,7 @@ where let consensus_state = HOST_CONSENSUS_STATE.load(self.storage(), height.revision_height).map_err(|_| { Error::implementation_specific(format!( - "[host_consensus_state]: consensus state not found for host at height {}", - height + "[host_consensus_state]: consensus state not found for host at height {height}" )) })?; Ok(consensus_state) @@ -212,10 +199,17 @@ where fn store_client_state( &mut self, - _client_id: ClientId, - _client_state: Self::AnyClientState, + client_id: ClientId, + client_state: Self::AnyClientState, ) -> Result<(), Error> { - unimplemented!() + log!(self, "in client : [store_client_state]"); + let client_states = ReadonlyClientStates::new(self.storage()); + let data = client_states.get().ok_or_else(|| Error::client_not_found(client_id.clone()))?; + let vec1 = Self::encode_client_state(client_state, data)?; + log!(self, "in cliden : [store_client_state] >> wasm client state (raw)"); + let mut client_state_storage = ClientStates::new(self.storage_mut()); + client_state_storage.insert(vec1); + Ok(()) } fn store_consensus_state( @@ -231,19 +225,14 @@ where height, ); - let wasm_consensus_state = ics08_wasm::consensus_state::ConsensusState { - data: consensus_state.to_any().encode_to_vec(), - timestamp: consensus_state.timestamp().nanoseconds(), - inner: Box::new(FakeInner), - }; - let vec1 = wasm_consensus_state.to_any().encode_to_vec(); + let encoded = Self::encode_consensus_state(consensus_state); log!( self, "in client : [store_consensus_state] >> wasm consensus state (raw) = {}", - hex::encode(&vec1) + hex::encode(&encoded) ); let mut consensus_states = ConsensusStates::new(self.storage_mut()); - consensus_states.insert(client_id, height, vec1); + consensus_states.insert(height, encoded); Ok(()) } @@ -273,3 +262,62 @@ where unimplemented!() } } + +impl<'a, H: Clone> Context<'a, H> { + pub fn decode_client_state(data: &[u8]) -> Result, Error> { + let any = Any::decode(data).map_err(Error::decode)?; + let wasm_state = + ics08_wasm::client_state::ClientState::::decode_vec( + &any.value, + ) + .map_err(|e| { + Error::implementation_specific(format!( + "[client_state]: error decoding client state bytes to WasmConsensusState {e}" + )) + })?; + let any = Any::decode(&*wasm_state.data).map_err(Error::decode)?; + let state = + ClientState::::decode_vec(&any.value).map_err(Error::invalid_any_client_state)?; + Ok(state) + } + + pub fn decode_consensus_state(value: &[u8]) -> Result { + let any = Any::decode(&mut &*value).map_err(Error::decode)?; + let wasm_consensus_state = + ics08_wasm::consensus_state::ConsensusState::::decode_vec(&any.value) + .map_err(Error::invalid_any_consensus_state)?; + let any = Any::decode(&mut &wasm_consensus_state.data[..]).map_err(Error::decode)?; + let any_consensus_state = + ConsensusState::decode_vec(&any.value).map_err(Error::invalid_any_consensus_state)?; + Ok(any_consensus_state) + } + + pub fn encode_client_state( + client_state: ClientState, + encoded_wasm_client_state: Vec, + ) -> Result, Error> { + let any = Any::decode(&*encoded_wasm_client_state).map_err(Error::decode)?; + let mut wasm_client_state = + ics08_wasm::client_state::ClientState::::decode_vec( + &any.value, + ) + .map_err(|e| { + Error::implementation_specific(format!( + "[client_state]: error decoding client state bytes to WasmConsensusState {e}" + )) + })?; + wasm_client_state.data = client_state.to_any().encode_to_vec(); + wasm_client_state.latest_height = client_state.latest_height(); + let vec1 = wasm_client_state.to_any().encode_to_vec(); + Ok(vec1) + } + + pub fn encode_consensus_state(consensus_state: ConsensusState) -> Vec { + let wasm_consensus_state = ics08_wasm::consensus_state::ConsensusState { + data: consensus_state.to_any().encode_to_vec(), + timestamp: consensus_state.timestamp().nanoseconds(), + inner: Box::new(FakeInner), + }; + wasm_consensus_state.to_any().encode_to_vec() + } +} diff --git a/light-clients/icsxx-ethereum-cw/src/connection.rs b/light-clients/icsxx-ethereum-cw/src/connection.rs index d1ce6670b..9b9f458b4 100644 --- a/light-clients/icsxx-ethereum-cw/src/connection.rs +++ b/light-clients/icsxx-ethereum-cw/src/connection.rs @@ -1,3 +1,18 @@ +// Copyright (C) 2022 ComposableFi. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + use crate::context::Context; use ibc::{ core::{ diff --git a/light-clients/icsxx-ethereum-cw/src/context.rs b/light-clients/icsxx-ethereum-cw/src/context.rs index dae50c378..1f1279aa1 100644 --- a/light-clients/icsxx-ethereum-cw/src/context.rs +++ b/light-clients/icsxx-ethereum-cw/src/context.rs @@ -1,5 +1,25 @@ +// Copyright (C) 2022 ComposableFi. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::{ + ics23::{ClientStates, ConsensusStates, ReadonlyClientStates, ReadonlyConsensusStates}, + ContractError, +}; use cosmwasm_std::{DepsMut, Env, Storage}; -use ibc::core::ics26_routing::context::ReaderContext; +use ibc::{core::ics26_routing::context::ReaderContext, Height}; +use icsxx_ethereum::{client_state::ClientState, consensus_state::ConsensusState}; use std::{fmt, fmt::Debug, marker::PhantomData}; use sync_committee_verifier::BlsVerify; @@ -47,7 +67,64 @@ impl<'a, H> Context<'a, H> { } } -impl<'a, H> ReaderContext for Context<'a, H> where - H: Clone + Eq + Send + Sync + Debug + Default + BlsVerify + 'static +impl<'a, H> Context<'a, H> +where + H: Clone, +{ + pub fn consensus_state_prefixed( + &self, + height: Height, + prefix: &[u8], + ) -> Result { + let bytes = ReadonlyConsensusStates::new(self.storage()) + .get_prefixed(height, prefix) + .ok_or_else(|| { + ContractError::Client(format!( + "no consensus state found for height {height} and prefix {prefix:?}", + )) + })?; + Context::::decode_consensus_state(&bytes) + .map_err(|e| ContractError::Client(format!("error decoding consensus state: {e:?}"))) + } + + pub fn store_consensus_state_prefixed( + &mut self, + height: Height, + consensus_state: ConsensusState, + prefix: &[u8], + ) { + let encoded = Context::::encode_consensus_state(consensus_state); + let mut consensus_states = ConsensusStates::new(self.storage_mut()); + consensus_states.insert_prefixed(height, encoded, prefix); + } + + pub fn client_state_prefixed(&self, prefix: &[u8]) -> Result, ContractError> { + let bytes = + ReadonlyClientStates::new(self.storage()).get_prefixed(prefix).ok_or_else(|| { + ContractError::Client(format!("no client state found for prefix {prefix:?}",)) + })?; + Context::decode_client_state(&bytes) + .map_err(|e| ContractError::Client(format!("error decoding client state: {e:?}"))) + } + + pub fn store_client_state_prefixed( + &mut self, + client_state: ClientState, + prefix: &[u8], + ) -> Result<(), ContractError> { + let client_states = ReadonlyClientStates::new(self.storage()); + let data = client_states + .get_prefixed(prefix) + .ok_or_else(|| ContractError::Client("no client state found for prefix".to_string()))?; + let encoded = Context::::encode_client_state(client_state, data) + .map_err(|e| ContractError::Client(format!("error encoding client state: {e:?}")))?; + let mut client_states = ClientStates::new(self.storage_mut()); + client_states.insert_prefixed(encoded, prefix); + Ok(()) + } +} + +impl<'a, H: Clone + Eq + Send + Sync + Debug + Default + BlsVerify + 'static> ReaderContext + for Context<'a, H> { } diff --git a/light-clients/icsxx-ethereum-cw/src/contract.rs b/light-clients/icsxx-ethereum-cw/src/contract.rs index 4fca9f2ed..caf000588 100644 --- a/light-clients/icsxx-ethereum-cw/src/contract.rs +++ b/light-clients/icsxx-ethereum-cw/src/contract.rs @@ -1,23 +1,36 @@ +// Copyright (C) 2022 ComposableFi. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + use crate::{ context::Context, error::ContractError, - ics23::FakeInner, log, msg::{ - CheckForMisbehaviourMsg, ClientStateCallResponse, ContractResult, ExecuteMsg, - InitializeState, InstantiateMsg, QueryMsg, StatusMsg, UpdateStateMsg, + CheckForMisbehaviourMsg, CheckSubstituteAndUpdateStateMsg, ContractResult, ExecuteMsg, + ExportMetadataMsg, InstantiateMsg, QueryMsg, QueryResponse, StatusMsg, UpdateStateMsg, UpdateStateOnMisbehaviourMsg, VerifyClientMessage, VerifyMembershipMsg, VerifyNonMembershipMsg, VerifyUpgradeAndUpdateStateMsg, }, + state::{get_client_state, get_consensus_state}, Bytes, }; use byteorder::{ByteOrder, LittleEndian}; -use core::hash::Hasher; +use core::{fmt::Debug, hash::Hasher}; #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; -use cosmwasm_std::{ - to_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult, Storage, -}; +use cosmwasm_std::{to_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult}; use cw_storage_plus::{Item, Map}; use digest::Digest; use ibc::core::{ @@ -28,11 +41,12 @@ use ibc::core::{ }, ics24_host::identifier::ClientId, }; -use ics08_wasm::client_state::ClientState as WasmClientState; +use ics08_wasm::{SUBJECT_PREFIX, SUBSTITUTE_PREFIX}; use icsxx_ethereum::{ - client_def::EthereumClient, client_message::ClientMessage, consensus_state::ConsensusState, + client_def::EthereumClient, client_message::ClientMessage, client_state::ClientState, + consensus_state::ConsensusState, }; -use prost::Message; +// use light_client_common::{verify_membership, verify_non_membership}; use std::{collections::BTreeSet, str::FromStr}; use sync_committee_verifier::BlsVerify; /* @@ -77,12 +91,7 @@ pub fn execute( let client = EthereumClient::::default(); let mut ctx = Context::::new(deps, env); let client_id = ClientId::from_str("08-wasm-0").expect("client id is valid"); - let result = process_message(msg, client, &mut ctx, client_id.clone()); - let data = match result { - Ok(res) => res, - Err(ContractError::Client(e)) => to_binary(&ContractResult::error(e))?, - Err(e) => return Err(e), - }; + let data = process_message(msg, client, &mut ctx, client_id)?; let mut response = Response::default(); response.data = Some(data); Ok(response) @@ -96,15 +105,6 @@ fn process_message( ) -> Result { // log!(ctx, "process_message: {:?}", msg); let result = match msg { - ExecuteMsg::Status(StatusMsg {}) => { - let client_state = - ctx.client_state(&client_id).map_err(|e| ContractError::Client(e.to_string()))?; - if client_state.frozen_height().is_some() { - Ok(to_binary("Frozen")) - } else { - Ok(to_binary("Active")) - } - }, ExecuteMsg::VerifyMembership(msg) => { let msg = VerifyMembershipMsg::try_from(msg)?; let consensus_state = ctx @@ -117,7 +117,7 @@ fn process_message( // msg.path, // msg.value, // ) - // .map_err(|e| ContractError::Client(e.to_string()))?; + // .map_err(|e| ContractError::Ethereum(e.to_string()))?; Ok(()).map(|_| to_binary(&ContractResult::success())) }, ExecuteMsg::VerifyNonMembership(msg) => { @@ -132,107 +132,171 @@ fn process_message( // &consensus_state.root, // msg.path, // ) - // .map_err(|e| ContractError::Client(e.to_string())) + // .map_err(|e| ContractError::Ethereum(e.to_string())) // .map(|_| to_binary(&ContractResult::success())) Ok(()).map(|_| to_binary(&ContractResult::success())) }, ExecuteMsg::VerifyClientMessage(msg) => { - CODE_ID.save(ctx.deps.storage, &msg.client_state.code_id)?; + let client_state = + ctx.client_state(&client_id).map_err(|e| ContractError::Client(e.to_string()))?; let msg = VerifyClientMessage::try_from(msg)?; - let f = client - .verify_client_message(ctx, client_id, msg.client_state, msg.client_message) + client + .verify_client_message(ctx, client_id, client_state, msg.client_message) .map_err(|e| ContractError::Client(format!("{e:?}"))) - .map(|_| to_binary(&ContractResult::success())); - f + .map(|_| to_binary(&ContractResult::success())) }, ExecuteMsg::CheckForMisbehaviour(msg) => { + let client_state = + ctx.client_state(&client_id).map_err(|e| ContractError::Client(e.to_string()))?; let msg = CheckForMisbehaviourMsg::try_from(msg)?; client - .check_for_misbehaviour(ctx, client_id, msg.client_state, msg.client_message) + .check_for_misbehaviour(ctx, client_id, client_state, msg.client_message) .map_err(|e| ContractError::Client(e.to_string())) - .map(|_| to_binary(&ContractResult::success())) + .map(|result| to_binary(&ContractResult::success().misbehaviour(result))) }, - ExecuteMsg::UpdateStateOnMisbehaviour(msg) => { - let msg = UpdateStateOnMisbehaviourMsg::try_from(msg)?; + ExecuteMsg::UpdateStateOnMisbehaviour(msg_raw) => { + let client_state = + ctx.client_state(&client_id).map_err(|e| ContractError::Client(e.to_string()))?; + let msg = UpdateStateOnMisbehaviourMsg::try_from(msg_raw)?; client - .update_state_on_misbehaviour(msg.client_state, msg.client_message) + .update_state_on_misbehaviour(client_state, msg.client_message) .map_err(|e| ContractError::Client(e.to_string())) - .map(|_| to_binary(&ContractResult::success())) + .and_then(|cs| { + ctx.store_client_state(client_id, cs) + .map_err(|e| ContractError::Client(e.to_string()))?; + Ok(to_binary(&ContractResult::success())) + }) }, ExecuteMsg::UpdateState(msg_raw) => { - let mut client_state: WasmClientState = - msg_raw.client_state.clone(); + let client_state = + ctx.client_state(&client_id).map_err(|e| ContractError::Client(e.to_string()))?; let msg = UpdateStateMsg::try_from(msg_raw)?; client - .update_state(ctx, client_id.clone(), msg.client_state, msg.client_message) + .update_state(ctx, client_id.clone(), client_state, msg.client_message) .map_err(|e| ContractError::Client(e.to_string())) .and_then(|(cs, cu)| { - let height = cs.latest_height(); - client_state.latest_height = height.into(); - client_state.data = cs.to_any().encode_to_vec(); - - match cu { - ConsensusUpdateResult::Single(cs) => { - log!(ctx, "Storing consensus state: {:?}", height); - ctx.store_consensus_state(client_id.clone(), height, cs) - .map_err(|e| ContractError::Client(e.to_string()))?; - }, - ConsensusUpdateResult::Batch(css) => - for (height, cs) in css { - log!(ctx, "Storing consensus state: {:?}", height); - ctx.store_consensus_state(client_id.clone(), height, cs) - .map_err(|e| ContractError::Client(e.to_string()))?; - }, - } - Ok(to_binary(&client_state) - .and_then(|data| to_binary(&ContractResult::success().data(data.0)))) + store_client_and_consensus_states(ctx, client_id.clone(), cs, cu) }) }, - ExecuteMsg::CheckSubstituteAndUpdateState(_msg) => { - todo!("check substitute and update state") + ExecuteMsg::CheckSubstituteAndUpdateState(msg) => { + let _msg = CheckSubstituteAndUpdateStateMsg::try_from(msg)?; + // manually load both states from the combined storage using the appropriate prefixes + let mut old_client_state = ctx + .client_state_prefixed(SUBJECT_PREFIX) + .map_err(|e| ContractError::Client(e.to_string()))?; + let substitute_client_state = ctx + .client_state_prefixed(SUBSTITUTE_PREFIX) + .map_err(|e| ContractError::Client(e.to_string()))?; + + // Check that the substitute client state is valid: + // all fields should be the same as in the old state, except for the `relay_chain`, + // `para_id`, `latest_para_height`, `latest_relay_height`, `frozen_height`, + // `current_authorities`, `current_set_id` + // old_client_state.relay_chain = substitute_client_state.relay_chain; + // old_client_state.para_id = substitute_client_state.para_id; + // old_client_state.latest_para_height = substitute_client_state.latest_para_height; + // old_client_state.latest_relay_height = substitute_client_state.latest_relay_height; + // old_client_state.frozen_height = substitute_client_state.frozen_height; + // old_client_state.current_authorities = + // substitute_client_state.current_authorities.clone(); + // old_client_state.current_set_id = substitute_client_state.current_set_id; + + if old_client_state != substitute_client_state { + return Err(ContractError::Client( + "subject client state does not match substitute client state".to_string(), + )) + } + let substitute_client_state = old_client_state; + let height = substitute_client_state.latest_height(); + // consensus state should be replaced as well + let substitute_consensus_state = + ctx.consensus_state_prefixed(height, SUBSTITUTE_PREFIX)?; + ctx.store_consensus_state_prefixed(height, substitute_consensus_state, SUBJECT_PREFIX); + ctx.store_client_state_prefixed(substitute_client_state, SUBJECT_PREFIX) + .map_err(|e| ContractError::Client(e.to_string()))?; + + Ok(()).map(|_| to_binary(&ContractResult::success())) }, ExecuteMsg::VerifyUpgradeAndUpdateState(msg) => { - let msg = VerifyUpgradeAndUpdateStateMsg::try_from(msg)?; + let old_client_state = + ctx.client_state(&client_id).map_err(|e| ContractError::Client(e.to_string()))?; + let msg: VerifyUpgradeAndUpdateStateMsg = + VerifyUpgradeAndUpdateStateMsg::try_from(msg)?; client .verify_upgrade_and_update_state( ctx, - client_id, - &msg.old_client_state, + client_id.clone(), + &old_client_state, &msg.upgrade_client_state, &msg.upgrade_consensus_state, msg.proof_upgrade_client, msg.proof_upgrade_consensus_state, ) .map_err(|e| ContractError::Client(e.to_string())) - .map(|_| to_binary(&ContractResult::success())) - }, - ExecuteMsg::InitializeState(InitializeState { client_state, consensus_state }) => { - let state_call_response = ClientStateCallResponse { - new_consensus_state: consensus_state.clone(), - new_client_state: client_state.clone(), - client_state, - result: ContractResult::success(), - }; - let response = to_binary(&state_call_response); - Ok(response) + .and_then(|(cs, cu)| { + store_client_and_consensus_states(ctx, client_id.clone(), cs, cu) + }) }, - ExecuteMsg::ClientCreateRequest(_) => Ok(to_binary(&ContractResult::success())), }; Ok(result??) } #[cfg_attr(not(feature = "library"), entry_point)] -pub fn query(_deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { +pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { + let client_id = ClientId::from_str("08-wasm-0").expect("client id is valid"); match msg { QueryMsg::ClientTypeMsg(_) => unimplemented!("ClientTypeMsg"), QueryMsg::GetLatestHeightsMsg(_) => unimplemented!("GetLatestHeightsMsg"), + QueryMsg::ExportMetadata(ExportMetadataMsg {}) => + to_binary(&QueryResponse::genesis_metadata(None)), + QueryMsg::Status(StatusMsg {}) => { + let client_state = match get_client_state::(deps) { + Ok(client_state) => client_state, + Err(_) => return to_binary(&QueryResponse::status("Unknown".to_string())), + }; + + if client_state.frozen_height().is_some() { + to_binary(&QueryResponse::status("Frozen".to_string())) + } else { + let height = client_state.latest_height(); + match get_consensus_state(deps, &client_id, height) { + Ok(_) => to_binary(&QueryResponse::status("Active".to_string())), + Err(_) => to_binary(&QueryResponse::status("Expired".to_string())), + } + } + }, } } -pub fn code_id(store: &dyn Storage) -> Vec { - CODE_ID.load(store).expect("code id must be set") +fn store_client_and_consensus_states( + ctx: &mut Context, + client_id: ClientId, + client_state: ClientState, + consensus_update: ConsensusUpdateResult>, +) -> Result, ContractError> +where + H: Clone + Eq + Send + Sync + Debug + Default + BlsVerify + 'static, +{ + let height = client_state.latest_height(); + match consensus_update { + ConsensusUpdateResult::Single(cs) => { + log!(ctx, "Storing consensus state: {:?}", height); + ctx.store_consensus_state(client_id.clone(), height, cs) + .map_err(|e| ContractError::Client(e.to_string()))?; + }, + ConsensusUpdateResult::Batch(css) => + for (height, cs) in css { + log!(ctx, "Storing consensus state: {:?}", height); + ctx.store_consensus_state(client_id.clone(), height, cs) + .map_err(|e| ContractError::Client(e.to_string()))?; + }, + } + log!(ctx, "Storing client state with height: {:?}", height); + ctx.store_client_state(client_id, client_state) + .map_err(|e| ContractError::Client(e.to_string()))?; + Ok(to_binary(&ContractResult::success())) } impl BlsVerify for HostFunctions { diff --git a/light-clients/icsxx-ethereum-cw/src/error.rs b/light-clients/icsxx-ethereum-cw/src/error.rs index 6a15b87ab..df4d87f87 100644 --- a/light-clients/icsxx-ethereum-cw/src/error.rs +++ b/light-clients/icsxx-ethereum-cw/src/error.rs @@ -1,8 +1,22 @@ +// Copyright (C) 2022 ComposableFi. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + use cosmwasm_std::StdError; use derive_more::{Display, From}; use icsxx_ethereum::error::Error as EthereumError; use std::error::Error; -// use thiserror::Error; #[derive(From, Display, Debug)] pub enum ContractError { diff --git a/light-clients/icsxx-ethereum-cw/src/ics23/client_states.rs b/light-clients/icsxx-ethereum-cw/src/ics23/client_states.rs index 0ef7dd05c..8b7631e3f 100644 --- a/light-clients/icsxx-ethereum-cw/src/ics23/client_states.rs +++ b/light-clients/icsxx-ethereum-cw/src/ics23/client_states.rs @@ -1,48 +1,72 @@ -use crate::STORAGE_PREFIX; +// Copyright (C) 2022 ComposableFi. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + use cosmwasm_std::Storage; -use cosmwasm_storage::{prefixed, PrefixedStorage, ReadonlyPrefixedStorage}; -use ibc::core::ics24_host::identifier::ClientId; /// client_id => client_states /// trie key path: "clients/{client_id}/clientState" -pub struct ClientStates<'a>(PrefixedStorage<'a>); +/// NOTE: the "clients/{client_id}" prefix is provided automatically by CosmWasm. +pub struct ClientStates<'a>(&'a mut dyn Storage); impl<'a> ClientStates<'a> { pub fn new(storage: &'a mut dyn Storage) -> Self { - ClientStates(prefixed(storage, STORAGE_PREFIX)) + ClientStates(storage) } - pub fn key(_client_id: ClientId) -> Vec { - let client_state_path = format!("clientState"); - // let client_state_path = format!("{}", ClientStatePath(client_id)); + pub fn key() -> Vec { + let client_state_path = "clientState".to_string(); client_state_path.into_bytes() } - pub fn get(&self, client_id: &ClientId) -> Option> { - self.0.get(&Self::key(client_id.clone())) + pub fn get(&self) -> Option> { + ReadonlyClientStates::new(self.0).get() + } + + pub fn get_prefixed(&self, prefix: &[u8]) -> Option> { + ReadonlyClientStates::new(self.0).get_prefixed(prefix) } - pub fn insert(&mut self, client_id: ClientId, client_state: Vec) { - self.0.set(&Self::key(client_id), &client_state); + pub fn insert(&mut self, client_state: Vec) { + self.0.set(&Self::key(), &client_state); } - pub fn contains_key(&self, client_id: &ClientId) -> bool { - self.get(client_id).is_some() + pub fn insert_prefixed(&mut self, client_state: Vec, prefix: &[u8]) { + self.0.set(&[prefix, Self::key().as_slice()].concat(), &client_state); + } + + pub fn contains_key(&self) -> bool { + self.get().is_some() } } -pub struct ReadonlyClientStates<'a>(ReadonlyPrefixedStorage<'a>); +pub struct ReadonlyClientStates<'a>(&'a dyn Storage); impl<'a> ReadonlyClientStates<'a> { pub fn new(storage: &'a dyn Storage) -> Self { - ReadonlyClientStates(ReadonlyPrefixedStorage::new(storage, STORAGE_PREFIX)) + ReadonlyClientStates(storage) + } + + pub fn get(&self) -> Option> { + self.0.get(&ClientStates::key()) } - pub fn get(&self, client_id: &ClientId) -> Option> { - self.0.get(&ClientStates::key(client_id.clone())) + pub fn get_prefixed(&self, prefix: &[u8]) -> Option> { + self.0.get(&[prefix, ClientStates::key().as_slice()].concat()) } - pub fn contains_key(&self, client_id: &ClientId) -> bool { - self.get(client_id).is_some() + pub fn contains_key(&self) -> bool { + self.get().is_some() } } diff --git a/light-clients/icsxx-ethereum-cw/src/ics23/clients.rs b/light-clients/icsxx-ethereum-cw/src/ics23/clients.rs index b131535ac..d8b194762 100644 --- a/light-clients/icsxx-ethereum-cw/src/ics23/clients.rs +++ b/light-clients/icsxx-ethereum-cw/src/ics23/clients.rs @@ -1,3 +1,18 @@ +// Copyright (C) 2022 ComposableFi. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + use cosmwasm_std::Storage; use ibc::core::ics24_host::identifier::ClientId; use sp_std::prelude::*; @@ -13,7 +28,7 @@ impl<'a> Clients<'a> { pub fn key(_client_id: ClientId) -> Vec { // let client_type_path = format!("{}", ClientTypePath(client_id)); - let client_type_path = format!("clientType"); + let client_type_path = "clientType".to_string(); client_type_path.into_bytes() } diff --git a/light-clients/icsxx-ethereum-cw/src/ics23/consensus_states.rs b/light-clients/icsxx-ethereum-cw/src/ics23/consensus_states.rs index 891257a79..f443129af 100644 --- a/light-clients/icsxx-ethereum-cw/src/ics23/consensus_states.rs +++ b/light-clients/icsxx-ethereum-cw/src/ics23/consensus_states.rs @@ -1,3 +1,18 @@ +// Copyright (C) 2022 ComposableFi. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + use cosmwasm_schema::cw_serde; use cosmwasm_std::Storage; use ibc::{ @@ -27,6 +42,7 @@ use std::{convert::Infallible, time::Duration}; /// client_id, height => consensus_state /// trie key path: "clients/{client_id}/consensusStates/{height}" +/// NOTE: the "clients/{client_id}" prefix is provided automatically by CosmWasm. pub struct ConsensusStates<'a>(&'a mut dyn Storage); impl<'a> ConsensusStates<'a> { @@ -34,34 +50,40 @@ impl<'a> ConsensusStates<'a> { ConsensusStates(storage) } - pub fn consensus_state_client_key(_client_id: ClientId) -> Vec { - format!("consensusStates/").into_bytes() - // format!("clients/{}/consensusStates/", client_id).into_bytes() + pub fn consensus_state_client_key() -> Vec { + "consensusStates/".to_string().into_bytes() } pub fn consensus_state_height_key(height: Height) -> Vec { - format!("{}", height).into_bytes() + format!("{height}").into_bytes() } - pub fn consensus_state_key(client_id: ClientId, height: Height) -> (Vec, Vec) { - let client_id_key = Self::consensus_state_client_key(client_id); + pub fn consensus_state_key(height: Height) -> (Vec, Vec) { + let client_id_key = Self::consensus_state_client_key(); let height_key = Self::consensus_state_height_key(height); (client_id_key, height_key) } - pub fn get(&self, client_id: &ClientId, height: Height) -> Option> { - let (consensus_state_key_1, consensus_state_key_2) = - Self::consensus_state_key(client_id.clone(), height); + pub fn get(&self, height: Height) -> Option> { + ReadonlyConsensusStates::new(self.0).get(height) + } + + pub fn get_prefixed(&self, height: Height, prefix: &[u8]) -> Option> { + ReadonlyConsensusStates::new(self.0).get_prefixed(height, prefix) + } + + pub fn insert(&mut self, height: Height, consensus_state: Vec) { + let (consensus_state_key_1, consensus_state_key_2) = Self::consensus_state_key(height); let full_key = [consensus_state_key_1.as_slice(), consensus_state_key_2.as_slice()].concat(); - self.0.get(&full_key) + + self.0.set(&full_key, &consensus_state); } - pub fn insert(&mut self, client_id: ClientId, height: Height, consensus_state: Vec) { - let (consensus_state_key_1, consensus_state_key_2) = - Self::consensus_state_key(client_id, height); + pub fn insert_prefixed(&mut self, height: Height, consensus_state: Vec, prefix: &[u8]) { + let (consensus_state_key_1, consensus_state_key_2) = Self::consensus_state_key(height); let full_key = - [consensus_state_key_1.as_slice(), consensus_state_key_2.as_slice()].concat(); + [prefix, consensus_state_key_1.as_slice(), consensus_state_key_2.as_slice()].concat(); self.0.set(&full_key, &consensus_state); } @@ -69,6 +91,7 @@ impl<'a> ConsensusStates<'a> { /// client_id, height => consensus_state /// trie key path: "clients/{client_id}/consensusStates/{height}" +/// NOTE: the "clients/{client_id}" prefix is provided automatically by CosmWasm. pub struct ReadonlyConsensusStates<'a>(&'a dyn Storage); impl<'a> ReadonlyConsensusStates<'a> { @@ -76,20 +99,28 @@ impl<'a> ReadonlyConsensusStates<'a> { ReadonlyConsensusStates(storage) } - pub fn get(&self, client_id: &ClientId, height: Height) -> Option> { + pub fn get(&self, height: Height) -> Option> { let (consensus_state_key_1, consensus_state_key_2) = - ConsensusStates::consensus_state_key(client_id.clone(), height); + ConsensusStates::consensus_state_key(height); let full_key = [consensus_state_key_1.as_slice(), consensus_state_key_2.as_slice()].concat(); self.0.get(&full_key) } + + pub fn get_prefixed(&self, height: Height, prefix: &[u8]) -> Option> { + let (consensus_state_key_1, consensus_state_key_2) = + ConsensusStates::consensus_state_key(height); + let full_key = + [prefix, consensus_state_key_1.as_slice(), consensus_state_key_2.as_slice()].concat(); + self.0.get(&full_key) + } } #[derive(Eq, Default)] #[cw_serde] pub struct FakeInner; -impl<'a> TryFrom for FakeInner { +impl TryFrom for FakeInner { type Error = Infallible; fn try_from(_: Any) -> Result { @@ -219,11 +250,11 @@ impl ClientDef for FakeInner { fn check_substitute_and_update_state( &self, - ctx: &Ctx, - subject_client_id: ClientId, - substitute_client_id: ClientId, - old_client_state: Self::ClientState, - substitute_client_state: Self::ClientState, + _ctx: &Ctx, + _subject_client_id: ClientId, + _substitute_client_id: ClientId, + _old_client_state: Self::ClientState, + _substitute_client_state: Self::ClientState, ) -> Result<(Self::ClientState, ConsensusUpdateResult), Error> { unimplemented!() } diff --git a/light-clients/icsxx-ethereum-cw/src/ics23/mod.rs b/light-clients/icsxx-ethereum-cw/src/ics23/mod.rs index 1766d236f..3af6b15ca 100644 --- a/light-clients/icsxx-ethereum-cw/src/ics23/mod.rs +++ b/light-clients/icsxx-ethereum-cw/src/ics23/mod.rs @@ -1,3 +1,18 @@ +// Copyright (C) 2022 ComposableFi. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + mod client_states; mod clients; mod consensus_states; diff --git a/light-clients/icsxx-ethereum-cw/src/lib.rs b/light-clients/icsxx-ethereum-cw/src/lib.rs index 652f992da..77485bf5a 100644 --- a/light-clients/icsxx-ethereum-cw/src/lib.rs +++ b/light-clients/icsxx-ethereum-cw/src/lib.rs @@ -9,7 +9,11 @@ mod error; pub mod ics23; mod macros; pub mod msg; +pub mod state; -pub const STORAGE_PREFIX: &'static [u8] = b""; +pub use crate::error::ContractError; + +pub const CLIENT_STATE: &[u8] = b"client_state"; +pub const STORAGE_PREFIX: &[u8] = b""; pub type Bytes = Vec; diff --git a/light-clients/icsxx-ethereum-cw/src/msg.rs b/light-clients/icsxx-ethereum-cw/src/msg.rs index 05870955a..39e27fe84 100644 --- a/light-clients/icsxx-ethereum-cw/src/msg.rs +++ b/light-clients/icsxx-ethereum-cw/src/msg.rs @@ -1,10 +1,25 @@ -use crate::{error::ContractError, ics23::FakeInner, Bytes}; +// Copyright (C) 2022 ComposableFi. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::{ics23::FakeInner, Bytes, ContractError}; use core::str::FromStr; -use cosmwasm_schema::{cw_serde, QueryResponses}; +use cosmwasm_schema::cw_serde; use ibc::{ core::{ ics23_commitment::commitment::{CommitmentPrefix, CommitmentProofBytes}, - ics24_host::{identifier::ClientId, Path}, + ics24_host::Path, }, protobuf::Protobuf, Height, @@ -34,21 +49,50 @@ impl Base64 { } } +#[cw_serde] +pub struct GenesisMetadata { + pub key: Vec, + pub value: Vec, +} + +#[cw_serde] +pub struct QueryResponse { + pub status: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub genesis_metadata: Option>, +} + +impl QueryResponse { + pub fn status(status: String) -> Self { + Self { status, genesis_metadata: None } + } + + pub fn genesis_metadata(genesis_metadata: Option>) -> Self { + Self { status: "".to_string(), genesis_metadata } + } +} + #[cw_serde] pub struct ContractResult { pub is_valid: bool, pub error_msg: String, #[serde(skip_serializing_if = "Option::is_none")] pub data: Option>, + pub found_misbehaviour: bool, } impl ContractResult { pub fn success() -> Self { - Self { is_valid: true, error_msg: "".to_string(), data: None } + Self { is_valid: true, error_msg: "".to_string(), data: None, found_misbehaviour: false } } pub fn error(msg: String) -> Self { - Self { is_valid: false, error_msg: msg, data: None } + Self { is_valid: false, error_msg: msg, data: None, found_misbehaviour: false } + } + + pub fn misbehaviour(mut self, found: bool) -> Self { + self.found_misbehaviour = found; + self } pub fn data(mut self, data: Vec) -> Self { @@ -65,42 +109,27 @@ pub struct ClientStateCallResponse { pub result: ContractResult, } -#[cw_serde] -pub struct InitializeState { - pub client_state: WasmClientState, - pub consensus_state: WasmConsensusState, -} - #[cw_serde] pub struct InstantiateMsg {} -#[cw_serde] -pub struct ClientCreateRequest { - client_create_request: WasmConsensusState, -} - #[cw_serde] pub enum ExecuteMsg { - InitializeState(InitializeState), - ClientCreateRequest(WasmClientState), - Status(StatusMsg), VerifyMembership(VerifyMembershipMsgRaw), VerifyNonMembership(VerifyNonMembershipMsgRaw), VerifyClientMessage(VerifyClientMessageRaw), CheckForMisbehaviour(CheckForMisbehaviourMsgRaw), UpdateStateOnMisbehaviour(UpdateStateOnMisbehaviourMsgRaw), UpdateState(UpdateStateMsgRaw), - CheckSubstituteAndUpdateState(CheckSubstituteAndUpdateStateMsg), + CheckSubstituteAndUpdateState(CheckSubstituteAndUpdateStateMsgRaw), VerifyUpgradeAndUpdateState(VerifyUpgradeAndUpdateStateMsgRaw), } #[cw_serde] -#[derive(QueryResponses)] pub enum QueryMsg { - #[returns(String)] ClientTypeMsg(ClientTypeMsg), - #[returns(HeightRaw)] GetLatestHeightsMsg(GetLatestHeightsMsg), + ExportMetadata(ExportMetadataMsg), + Status(StatusMsg), } #[cw_serde] @@ -112,6 +141,9 @@ pub struct GetLatestHeightsMsg {} #[cw_serde] pub struct StatusMsg {} +#[cw_serde] +pub struct ExportMetadataMsg {} + #[cw_serde] pub struct MerklePath { pub key_path: Vec, @@ -191,7 +223,6 @@ impl TryFrom for VerifyNonMembershipMsg { #[cw_serde] pub struct WasmMisbehaviour { - pub client_id: String, #[schemars(with = "String")] #[serde(with = "Base64", default)] pub data: Bytes, @@ -205,27 +236,23 @@ pub enum ClientMessageRaw { #[cw_serde] pub struct VerifyClientMessageRaw { - pub client_state: WasmClientState, pub client_message: ClientMessageRaw, } -pub struct VerifyClientMessage { - pub client_state: ClientState, +pub struct VerifyClientMessage { pub client_message: ClientMessage, } -impl TryFrom for VerifyClientMessage { +impl TryFrom for VerifyClientMessage { type Error = ContractError; fn try_from(raw: VerifyClientMessageRaw) -> Result { - let any = Any::decode(&mut raw.client_state.data.as_slice())?; - let client_state = ClientState::decode_vec(&any.value)?; let client_message = Self::decode_client_message(raw.client_message)?; - Ok(Self { client_state, client_message }) + Ok(Self { client_message }) } } -impl VerifyClientMessage { +impl VerifyClientMessage { fn decode_client_message(raw: ClientMessageRaw) -> Result { let client_message = match raw { ClientMessageRaw::Header(header) => { @@ -243,93 +270,87 @@ impl VerifyClientMessage { #[cw_serde] pub struct CheckForMisbehaviourMsgRaw { - // pub client_id: String, - pub client_state: WasmClientState, - pub misbehaviour: WasmMisbehaviour, + pub client_message: ClientMessageRaw, } -pub struct CheckForMisbehaviourMsg { - // pub client_id: ClientId, - pub client_state: ClientState, +pub struct CheckForMisbehaviourMsg { pub client_message: ClientMessage, } -impl TryFrom for CheckForMisbehaviourMsg { +impl TryFrom for CheckForMisbehaviourMsg { type Error = ContractError; fn try_from(raw: CheckForMisbehaviourMsgRaw) -> Result { - // let client_id = ClientId::from_str(&raw.client_id)?; - let any = Any::decode(&*raw.client_state.data)?; - let client_state = ClientState::::decode_vec(&any.value)?; - let any = Any::decode(&*raw.misbehaviour.data)?; - let client_message = ClientMessage::Misbehaviour(Misbehaviour::decode_vec(&any.value)?); - Ok(Self { client_state, client_message }) + let client_message = VerifyClientMessage::decode_client_message(raw.client_message)?; + Ok(Self { client_message }) } } #[cw_serde] pub struct UpdateStateOnMisbehaviourMsgRaw { - pub client_state: WasmClientState, - pub client_message: WasmMisbehaviour, + pub client_message: ClientMessageRaw, } -pub struct UpdateStateOnMisbehaviourMsg { - pub client_state: ClientState, +pub struct UpdateStateOnMisbehaviourMsg { pub client_message: ClientMessage, } -impl TryFrom for UpdateStateOnMisbehaviourMsg { +impl TryFrom for UpdateStateOnMisbehaviourMsg { type Error = ContractError; fn try_from(raw: UpdateStateOnMisbehaviourMsgRaw) -> Result { - let any = Any::decode(&*raw.client_state.data)?; - let client_state = ClientState::::decode_vec(&any.value)?; - let any = Any::decode(&*raw.client_message.data)?; - let client_message = ClientMessage::Misbehaviour(Misbehaviour::decode_vec(&any.value)?); - Ok(Self { client_state, client_message }) + let client_message = VerifyClientMessage::decode_client_message(raw.client_message)?; + Ok(Self { client_message }) } } #[cw_serde] pub struct UpdateStateMsgRaw { - pub client_state: WasmClientState, + // pub client_state: WasmClientState, pub client_message: ClientMessageRaw, } -pub struct UpdateStateMsg { - pub client_state: ClientState, +pub struct UpdateStateMsg { pub client_message: ClientMessage, } -impl TryFrom for UpdateStateMsg { +impl TryFrom for UpdateStateMsg { type Error = ContractError; fn try_from(raw: UpdateStateMsgRaw) -> Result { - let any = Any::decode(&mut raw.client_state.data.as_slice())?; - let client_state = ClientState::decode_vec(&any.value)?; - let client_message = VerifyClientMessage::::decode_client_message(raw.client_message)?; - Ok(Self { client_state, client_message }) + let client_message = VerifyClientMessage::decode_client_message(raw.client_message)?; + Ok(Self { client_message }) } } #[cw_serde] -pub struct CheckSubstituteAndUpdateStateMsg { - substitute_client_msg: Vec, +pub struct CheckSubstituteAndUpdateStateMsgRaw {} + +pub struct CheckSubstituteAndUpdateStateMsg {} + +impl TryFrom for CheckSubstituteAndUpdateStateMsg { + type Error = ContractError; + + fn try_from( + CheckSubstituteAndUpdateStateMsgRaw {}: CheckSubstituteAndUpdateStateMsgRaw, + ) -> Result { + Ok(Self {}) + } } #[cw_serde] pub struct VerifyUpgradeAndUpdateStateMsgRaw { - pub client_id: String, - pub old_client_state: Bytes, - pub upgrade_client_state: Bytes, - pub upgrade_consensus_state: Bytes, + pub upgrade_client_state: WasmClientState, + pub upgrade_consensus_state: WasmConsensusState, + #[schemars(with = "String")] + #[serde(with = "Base64", default)] pub proof_upgrade_client: Vec, + #[schemars(with = "String")] + #[serde(with = "Base64", default)] pub proof_upgrade_consensus_state: Vec, } pub struct VerifyUpgradeAndUpdateStateMsg { - pub client_id: ClientId, - pub old_client_state: ClientState, pub upgrade_client_state: ClientState, pub upgrade_consensus_state: ConsensusState, pub proof_upgrade_client: Vec, @@ -339,18 +360,16 @@ pub struct VerifyUpgradeAndUpdateStateMsg { impl TryFrom for VerifyUpgradeAndUpdateStateMsg { type Error = ContractError; - fn try_from(value: VerifyUpgradeAndUpdateStateMsgRaw) -> Result { - let client_id = ClientId::from_str(&value.client_id)?; - let old_client_state = ClientState::decode_vec(&value.old_client_state)?; - let upgrade_client_state = ClientState::decode_vec(&value.upgrade_client_state)?; - let upgrade_consensus_state = ConsensusState::decode_vec(&value.upgrade_consensus_state)?; + fn try_from(raw: VerifyUpgradeAndUpdateStateMsgRaw) -> Result { + let any = Any::decode(&mut raw.upgrade_client_state.data.as_slice())?; + let upgrade_client_state = ClientState::decode_vec(&any.value)?; + let any = Any::decode(&mut raw.upgrade_consensus_state.data.as_slice())?; + let upgrade_consensus_state = ConsensusState::decode_vec(&any.value)?; Ok(VerifyUpgradeAndUpdateStateMsg { - client_id, - old_client_state, upgrade_client_state, upgrade_consensus_state, - proof_upgrade_client: value.proof_upgrade_client, - proof_upgrade_consensus_state: value.proof_upgrade_consensus_state, + proof_upgrade_client: raw.proof_upgrade_client, + proof_upgrade_consensus_state: raw.proof_upgrade_consensus_state, }) } } diff --git a/light-clients/icsxx-ethereum-cw/src/state.rs b/light-clients/icsxx-ethereum-cw/src/state.rs new file mode 100644 index 000000000..40030299e --- /dev/null +++ b/light-clients/icsxx-ethereum-cw/src/state.rs @@ -0,0 +1,64 @@ +// Copyright (C) 2022 ComposableFi. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::ics23::FakeInner; +use cosmwasm_std::Deps; +use ibc::{ + core::{ics02_client::error::Error, ics24_host::identifier::ClientId}, + protobuf::Protobuf, + Height, +}; +use ibc_proto::google::protobuf::Any; +use icsxx_ethereum::client_state::ClientState; +use prost::Message; + +/// Retrieves raw bytes from storage and deserializes them into [`ClientState`] +pub fn get_client_state(deps: Deps) -> Result, Error> { + deps.storage + .get(&"clientState".to_string().into_bytes()) + .ok_or_else(|| Error::unknown_client_state_type("08-wasm-0".to_string())) + .and_then(deserialize_client_state) +} + +fn deserialize_client_state(client_state: Vec) -> Result, Error> { + let any = Any::decode(&*client_state).map_err(Error::decode)?; + let wasm_state = + ics08_wasm::client_state::ClientState::::decode_vec( + &any.value, + ) + .map_err(|e| { + Error::implementation_specific(format!( + "[client_state]: error decoding client state bytes to WasmClientState {e}" + )) + })?; + let any = Any::decode(&*wasm_state.data).map_err(Error::decode)?; + let state = + ClientState::::decode_vec(&any.value).map_err(Error::invalid_any_client_state)?; + Ok(state) +} + +pub fn get_consensus_state( + deps: Deps, + client_id: &ClientId, + height: Height, +) -> Result, Error> { + deps.storage + .get(&get_consensus_state_key(height)) + .ok_or_else(|| Error::consensus_state_not_found(client_id.clone(), height)) +} + +pub fn get_consensus_state_key(height: Height) -> Vec { + ["consensusStates/".to_string().into_bytes(), format!("{height}").into_bytes()].concat() +} From 52f8669187049d55f6baeddac8f3b1164f53cb72 Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Thu, 7 Sep 2023 09:19:12 -0300 Subject: [PATCH 17/43] disable verification --- Cargo.lock | 15 +++---- contracts/pallet-ibc/src/light_clients.rs | 2 +- hyperspace/core/src/events.rs | 2 +- hyperspace/ethereum/src/chain.rs | 3 +- hyperspace/ethereum/src/ibc_provider.rs | 24 +++++++++--- hyperspace/ethereum/src/mock/utils.rs | 2 +- ibc/modules/src/core/ics02_client/height.rs | 3 +- .../icsxx-ethereum-cw/src/contract.rs | 24 +++++++----- light-clients/icsxx-ethereum-cw/src/error.rs | 2 +- .../icsxx-ethereum/src/client_def.rs | 39 +++++++++++++------ .../icsxx-ethereum/src/client_state.rs | 3 +- 11 files changed, 78 insertions(+), 41 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b09284a25..f557c2809 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5219,6 +5219,7 @@ dependencies = [ "ibc-proto", "prost 0.11.6", "serde", + "serde_json", "tendermint-proto", ] @@ -10428,9 +10429,9 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.164" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d" +checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" dependencies = [ "serde_derive", ] @@ -10476,9 +10477,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.164" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" +checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" dependencies = [ "proc-macro2", "quote", @@ -10498,11 +10499,11 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.96" +version = "1.0.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" +checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360" dependencies = [ - "indexmap 1.9.2", + "indexmap 2.0.0", "itoa", "ryu", "serde", diff --git a/contracts/pallet-ibc/src/light_clients.rs b/contracts/pallet-ibc/src/light_clients.rs index 04c530578..dfbda86e8 100644 --- a/contracts/pallet-ibc/src/light_clients.rs +++ b/contracts/pallet-ibc/src/light_clients.rs @@ -390,7 +390,7 @@ impl AnyClientMessage { #[cfg(feature = "ethereum")] Self::Ethereum(m) => match m { icsxx_ethereum::client_message::ClientMessage::Header(h) => - Some(Height::new(0, h.finalized_header.slot)), + Some(Height::new(0, h.execution_payload.block_number)), icsxx_ethereum::client_message::ClientMessage::Misbehaviour(_) => None, }, #[cfg(test)] diff --git a/hyperspace/core/src/events.rs b/hyperspace/core/src/events.rs index 937d4517a..a54192dac 100644 --- a/hyperspace/core/src/events.rs +++ b/hyperspace/core/src/events.rs @@ -100,11 +100,11 @@ pub async fn parse_events( Height::new(proof_height.revision_number, proof_height.revision_height); let client_state_proof = CommitmentProofBytes::try_from(client_state_response.proof).ok(); - let client_state = client_state_response .client_state .map(AnyClientState::try_from) .ok_or_else(|| Error::Custom("Client state is empty".to_string()))??; + log::info!(target: "hyperspace_ethereum", "ph={proof_height}, client_state.latest_height()={}", client_state.latest_height()); let consensus_proof = source .query_client_consensus( open_init.height(), diff --git a/hyperspace/ethereum/src/chain.rs b/hyperspace/ethereum/src/chain.rs index a37ddc07f..fa0b3be3a 100644 --- a/hyperspace/ethereum/src/chain.rs +++ b/hyperspace/ethereum/src/chain.rs @@ -235,7 +235,8 @@ pub(crate) fn client_state_from_abi_token(token: Token) -> Result { let client_state = @@ -261,10 +262,12 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { to_binary(&QueryResponse::status("Frozen".to_string())) } else { let height = client_state.latest_height(); - match get_consensus_state(deps, &client_id, height) { - Ok(_) => to_binary(&QueryResponse::status("Active".to_string())), - Err(_) => to_binary(&QueryResponse::status("Expired".to_string())), - } + deps.api.debug(&format!("Querying consensus state at: {:?}", height)); + // match get_consensus_state(deps, &client_id, height) { + // Ok(_) => to_binary(&QueryResponse::status("Active".to_string())), + // Err(_) => to_binary(&QueryResponse::status("Expired".to_string())), + // } + to_binary(&QueryResponse::status("Active".to_string())) } }, } @@ -305,6 +308,7 @@ impl BlsVerify for HostFunctions { msg: &[u8], signature: ðereum_consensus::crypto::Signature, ) -> Result<(), sync_committee_verifier::error::Error> { - todo!() + // TODO: bls + Ok(()) } } diff --git a/light-clients/icsxx-ethereum-cw/src/error.rs b/light-clients/icsxx-ethereum-cw/src/error.rs index df4d87f87..aae2dba6a 100644 --- a/light-clients/icsxx-ethereum-cw/src/error.rs +++ b/light-clients/icsxx-ethereum-cw/src/error.rs @@ -28,7 +28,7 @@ pub enum ContractError { #[display(fmt = "Storage error")] StorageError, // TODO: use `ics10-grandpa`'s error type here - #[display(fmt = "Grandpa error: {_0}")] + #[display(fmt = "Ethereum error: {_0}")] #[from(ignore)] Client(String), #[display(fmt = "Protobuf error: {_0}")] diff --git a/light-clients/icsxx-ethereum/src/client_def.rs b/light-clients/icsxx-ethereum/src/client_def.rs index 934ac14fb..de9e0cc80 100644 --- a/light-clients/icsxx-ethereum/src/client_def.rs +++ b/light-clients/icsxx-ethereum/src/client_def.rs @@ -133,18 +133,13 @@ where "02-client will check for misbehaviour before calling update_state; qed" ), }; - // header.finality_proof.epoch - // let bs = header.finalized_header.state_root; - // let bs = header.execution_payload.state_root; - // let bs = header.execution_payload.timestamp; - // let bs = header.execution_payload.block_number; let mut css = header .ancestor_blocks .iter() .map(|b| { let height = Height::new( - 2, // TODO: check this + 0, // TODO: check this b.execution_payload.block_number as u64, ); let cs = Ctx::AnyConsensusState::wrap(&ConsensusState::new( @@ -156,7 +151,7 @@ where }) .collect::>(); let height = Height::new( - 2, // TODO: check this + 0, // TODO: check this header.execution_payload.block_number as u64, ); let cs = Ctx::AnyConsensusState::wrap(&ConsensusState::new( @@ -166,11 +161,31 @@ where .unwrap(); css.push((height, cs)); - let cs = client_state.inner; - let new_client_state = verify_sync_committee_attestation::(cs, header) - .map_err(|e| Ics02Error::implementation_specific(e.to_string()))?; - client_state.inner = new_client_state; - Ok((client_state, ConsensusUpdateResult::Batch(css))) + // let cs = client_state.inner; + // let new_client_state = verify_sync_committee_attestation::(cs, header) + // .map_err(|e| Ics02Error::implementation_specific(e.to_string()))?; + let update = header; + let new_light_client_state = + if let Some(sync_committee_update) = update.sync_committee_update { + LightClientState { + finalized_header: update.finalized_header, + latest_finalized_epoch: update.finality_proof.epoch, + current_sync_committee: client_state.inner.next_sync_committee, + next_sync_committee: sync_committee_update.next_sync_committee, + } + } else { + LightClientState { finalized_header: update.finalized_header, ..client_state.inner } + }; + let new_client_state = ClientState { + inner: new_light_client_state, + frozen_height: None, + latest_height: update.execution_payload.block_number as _, + // latest_height: update.attested_header.slot.into(), + _phantom: Default::default(), + }; + + // client_state.inner = new_client_state; + Ok((new_client_state, ConsensusUpdateResult::Batch(css))) } fn update_state_on_misbehaviour( diff --git a/light-clients/icsxx-ethereum/src/client_state.rs b/light-clients/icsxx-ethereum/src/client_state.rs index cb15d0eba..29402668b 100644 --- a/light-clients/icsxx-ethereum/src/client_state.rs +++ b/light-clients/icsxx-ethereum/src/client_state.rs @@ -76,7 +76,8 @@ impl ClientState { impl ClientState { pub fn latest_height(&self) -> Height { - Height::new(self.inner.latest_finalized_epoch.into(), self.latest_height.into()) + Height::new(0, self.latest_height.into()) + // Height::new(self.inner.latest_finalized_epoch.into(), self.latest_height.into()) } pub fn chain_id(&self) -> ChainId { From 1e7a2607ac6817cf30c86d08a6d94f38b4fee2de Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Thu, 7 Sep 2023 09:52:42 -0300 Subject: [PATCH 18/43] cooments --- hyperspace/ethereum/src/events.rs | 2 ++ hyperspace/ethereum/src/ibc_provider.rs | 9 ++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/hyperspace/ethereum/src/events.rs b/hyperspace/ethereum/src/events.rs index 90d23d45f..04df4343b 100644 --- a/hyperspace/ethereum/src/events.rs +++ b/hyperspace/ethereum/src/events.rs @@ -184,6 +184,8 @@ impl TryFromEvent for IbcEvent { } } +// Open + #[async_trait] impl TryFromEvent for IbcEvent { async fn try_from_event( diff --git a/hyperspace/ethereum/src/ibc_provider.rs b/hyperspace/ethereum/src/ibc_provider.rs index 039f58b5a..f6eef7cf4 100644 --- a/hyperspace/ethereum/src/ibc_provider.rs +++ b/hyperspace/ethereum/src/ibc_provider.rs @@ -192,7 +192,8 @@ pub async fn parse_ethereum_events( raw_log, height, OpenInitConnectionFilter, - OpenTryConnectionFilter + OpenTryConnectionFilter, + OpenConfirmConnectionFilter ); } @@ -236,6 +237,12 @@ impl IbcProvider for EthereumClient { let latest_height = self.latest_height_and_timestamp().await?.0; let latest_revision = latest_height.revision_number; + // 1 slot = 1 block + // 1 epoch = 32 slot + // 1 block = 12 sec + // finalisation ~= 2.5 epoch + // 32 * 12 * 2.5 = 960 sec = 16 min + let from = latest_cp_client_height; let to = finality_event .number From c6bd4af3aafea0bb6ba00c9c76eb50c752194bd3 Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Fri, 8 Sep 2023 09:45:30 -0300 Subject: [PATCH 19/43] continue work on the test --- Cargo.lock | 1 - contracts/pallet-ibc/src/light_clients.rs | 7 + hyperspace/core/src/events.rs | 3 +- hyperspace/core/src/packets.rs | 26 +- .../ethereum/src/abi/ibc-packet-abi.json | 24 ++ hyperspace/ethereum/src/chain.rs | 219 ++++++----- hyperspace/ethereum/src/client.rs | 71 +++- hyperspace/ethereum/src/events.rs | 204 +++++++++- hyperspace/ethereum/src/ibc_provider.rs | 371 +++++++++++------- hyperspace/ethereum/src/key_provider.rs | 2 +- hyperspace/ethereum/src/mock/utils.rs | 3 +- hyperspace/ethereum/src/prove.rs | 97 ++++- hyperspace/ethereum/src/utils.rs | 55 ++- .../src/yui_types/ics04_channel/mod.rs | 333 ++++++++-------- hyperspace/ethereum/tests/sanity_checks.rs | 2 +- hyperspace/testsuite/src/lib.rs | 57 ++- hyperspace/testsuite/tests/ethereum_cosmos.rs | 114 ++++-- light-clients/icsxx-ethereum-cw/src/client.rs | 23 +- 18 files changed, 1103 insertions(+), 509 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f557c2809..fe173cf6f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5219,7 +5219,6 @@ dependencies = [ "ibc-proto", "prost 0.11.6", "serde", - "serde_json", "tendermint-proto", ] diff --git a/contracts/pallet-ibc/src/light_clients.rs b/contracts/pallet-ibc/src/light_clients.rs index dfbda86e8..abd078e23 100644 --- a/contracts/pallet-ibc/src/light_clients.rs +++ b/contracts/pallet-ibc/src/light_clients.rs @@ -345,6 +345,13 @@ impl AnyConsensusState { inner: Box::new(inner), })) } + + pub fn unpack_recursive(&self) -> &Self { + match self { + Self::Wasm(wasm_state) => wasm_state.inner.unpack_recursive(), + c => c, + } + } } #[derive(Clone, Debug, ClientMessage)] diff --git a/hyperspace/core/src/events.rs b/hyperspace/core/src/events.rs index a54192dac..129534bbf 100644 --- a/hyperspace/core/src/events.rs +++ b/hyperspace/core/src/events.rs @@ -288,8 +288,7 @@ pub async fn parse_events( channel_id, open_init.port_id.clone() )) - })?) - .expect("Channel end decoding should not fail"); + })?)?; let counterparty = channel_end.counterparty(); let connection_response = source diff --git a/hyperspace/core/src/packets.rs b/hyperspace/core/src/packets.rs index 967435881..f402d60b1 100644 --- a/hyperspace/core/src/packets.rs +++ b/hyperspace/core/src/packets.rs @@ -37,7 +37,7 @@ use ibc::{ }, Height, }; -use ibc_proto::google::protobuf::Any; +use ibc_proto::{google::protobuf::Any, ibc::core::channel::v1::QueryNextSequenceReceiveResponse}; use pallet_ibc::light_clients::AnyClientState; use primitives::{ error::Error, find_suitable_proof_height_for_client, packet_info_to_packet, @@ -133,9 +133,14 @@ pub async fn query_ready_and_timed_out_packets( }, }; - let next_sequence_recv = sink - .query_next_sequence_recv(sink_height, &sink_port_id, &sink_channel_id) - .await?; + // let next_sequence_recv = sink + // .query_next_sequence_recv(sink_height, &sink_port_id, &sink_channel_id) + // .await?; + let next_sequence_recv = QueryNextSequenceReceiveResponse { + next_sequence_receive: 0, + proof: vec![1], + proof_height: None, + }; let source_client_state_on_sink = sink.query_client_state(sink_height, source.client_id()).await?; @@ -229,6 +234,19 @@ pub async fn query_ready_and_timed_out_packets( Error::Custom(format!("Packet height not found for packet {packet:?}")) })?; + // [2023-09-08T12:24:41Z TRACE hyperspace] get_timeout_proof_height: + // ethereum-client->centauri, + // + // timeout_variant=Height, + // source_height=0-26948, + // timeout_height: Height { revision: 0, height: 24102 }, + // timeout_timestamp: Timestamp { time: None } } + // + // sink_height=1-23940, + // sink_timestamp=Timestamp(2023-09-08T12:24:33.381673Z), latest_client_height_on_source=1-23926, packet_creation_height=26885, + + log::info!("sink_height = {sink_height:?}, timeout_height = {:?}", packet.timeout_height); + if packet.timed_out(&sink_timestamp, sink_height) { timeout_packets_count.fetch_add(1, Ordering::SeqCst); // so we know this packet has timed out on the sink, we need to find the maximum diff --git a/hyperspace/ethereum/src/abi/ibc-packet-abi.json b/hyperspace/ethereum/src/abi/ibc-packet-abi.json index 39d8efaef..8eb54db04 100644 --- a/hyperspace/ethereum/src/abi/ibc-packet-abi.json +++ b/hyperspace/ethereum/src/abi/ibc-packet-abi.json @@ -160,6 +160,18 @@ "name": "sourceChannel", "type": "string" }, + { + "indexed": false, + "internalType": "string", + "name": "sourcePortRaw", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "sourceChannelRaw", + "type": "string" + }, { "components": [ { @@ -282,6 +294,18 @@ "name": "sequence", "type": "uint64" }, + { + "indexed": false, + "internalType": "string", + "name": "destinationPortIdRaw", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "destinationChannelRaw", + "type": "string" + }, { "indexed": false, "internalType": "bytes", diff --git a/hyperspace/ethereum/src/chain.rs b/hyperspace/ethereum/src/chain.rs index fa0b3be3a..b3359a06e 100644 --- a/hyperspace/ethereum/src/chain.rs +++ b/hyperspace/ethereum/src/chain.rs @@ -2,7 +2,7 @@ use std::{fmt::Debug, sync::Arc, thread, time::Duration}; use crate::{ client::{ClientError, EthereumClient}, - contract::IbcHandler, + contract::{IbcHandler, UnwrapContractError}, ibc_provider::BlockHeight, yui_types::{ics03_connection::conn_open_try::YuiMsgConnectionOpenTry, IntoToken}, }; @@ -46,6 +46,7 @@ use ics07_tendermint::{ client_state::ClientState, consensus_state::ConsensusState, }; +use icsxx_ethereum::client_state::ClientState as EthereumClientState; use pallet_ibc::light_clients::{AnyClientMessage, AnyClientState, AnyConsensusState}; use primitives::{ mock::LocalClientTypes, Chain, CommonClientState, IbcProvider, LightClientSync, @@ -71,7 +72,7 @@ impl MisbehaviourHandler for EthereumClient { } } -fn client_state_abi_token(client: ClientState) -> Token { +fn client_state_abi_token(client: &ClientState) -> Token { use ethers::abi::{encode as ethers_encode, Token as EthersToken}; log::info!("client: {:?}", client); @@ -250,7 +251,7 @@ pub(crate) fn client_state_from_abi_token(token: Token) -> Result Token { +fn consensus_state_abi_token(consensus_state: &ConsensusState) -> Token { use ethers::abi::{encode as ethers_encode, Token as EthersToken}; let time = consensus_state .timestamp @@ -264,7 +265,7 @@ fn consensus_state_abi_token(consensus_state: ConsensusState) -> Token { .to_vec(), ), //root - EthersToken::Tuple([EthersToken::Bytes(consensus_state.root.bytes)].to_vec()), + EthersToken::Tuple([EthersToken::Bytes(consensus_state.root.bytes.clone())].to_vec()), //next_validators_hash EthersToken::Bytes(consensus_state.next_validators_hash.as_ref().into()), ] @@ -326,16 +327,13 @@ fn consensus_state_from_abi_token(token: Token) -> Result Token { +fn tm_header_abi_token(header: &Header) -> Token { use ethers::abi::{encode as ethers_encode, Token as EthersToken}; - let block_header = header.signed_header.header; - let last_commit = header.signed_header.commit; + let block_header = header.signed_header.header.clone(); + let last_commit = header.signed_header.commit.clone(); - // block_header.time.; - let time = block_header - .time - .duration_since(Timestamp { seconds: 0, nanos: 0 }.try_into().unwrap()) - .unwrap(); + // TODO: convert to u128 (nanoseconds) + let timestamp = Timestamp::from(block_header.time); let signed_header_header = EthersToken::Tuple( [ @@ -353,8 +351,11 @@ fn tm_header_abi_token(header: Header) -> Token { EthersToken::Int((block_header.height.value() as i64).into()), //time EthersToken::Tuple( - [EthersToken::Int(time.as_secs().into()), EthersToken::Int(time.as_nanos().into())] - .to_vec(), + [ + EthersToken::Int(timestamp.seconds.into()), + EthersToken::Int(timestamp.nanos.into()), + ] + .to_vec(), ), // //last_block_id EthersToken::Tuple( @@ -477,15 +478,13 @@ pub(crate) fn tm_header_from_abi_token(token: Token) -> Result toks, + EthersToken::Tuple(toks) => match toks.get(0).cloned().unwrap() { + EthersToken::Tuple(toks) => toks, + _ => return Err(ClientError::Other("signed_header_header' not found".to_string())), + }, _ => return Err(ClientError::Other("signed_header_header not found".to_string())), }; - let signed_header_commit = match toks.get(1).cloned().unwrap() { - EthersToken::Tuple(signed_header_commit) => signed_header_commit, - _ => return Err(ClientError::Other("signed_header_commit not found".to_string())), - }; - let version = match signed_header_header.get(0).cloned().unwrap() { EthersToken::Tuple(toks) => toks, _ => return Err(ClientError::Other("version not found".to_string())), @@ -606,6 +605,14 @@ pub(crate) fn tm_header_from_abi_token(token: Token) -> Result match toks.get(1).cloned().unwrap() { + EthersToken::Tuple(toks) => toks, + _ => return Err(ClientError::Other("signed_header_commit' not found".to_string())), + }, + _ => return Err(ClientError::Other("signed_header_commit not found".to_string())), + }; + let last_commit_height = match signed_header_commit.get(0).cloned().unwrap() { EthersToken::Int(last_commit_height) => last_commit_height, _ => return Err(ClientError::Other("last_commit_height not found".to_string())), @@ -654,6 +661,11 @@ pub(crate) fn tm_header_from_abi_token(token: Token) -> Result trusted_height, + _ => return Err(ClientError::Other("trusted_height not found".to_string())), + }; + let revision_number = 1; // TODO Ok(Header { signed_header: SignedHeader::new( @@ -661,10 +673,10 @@ pub(crate) fn tm_header_from_abi_token(token: Token) -> Result Result Token pub fn msg_connection_open_ack_token( msg: MsgConnectionOpenAck, - client_state: ClientState, + client_state: &EthereumClientState, ) -> Token { use ethers::abi::{encode as ethers_encode, Token as EthersToken}; - let client_state = client_state_abi_token(client_state); - let client_state_data_vec = ethers_encode(&[client_state]); + // let client_state = client_state_abi_token(&client_state); + let client_state_data_vec = vec![0u8].into(); // ethers_encode(&[client_state]); let consensus_state_data = EthersToken::Tuple( [ @@ -826,10 +838,10 @@ pub fn msg_connection_open_ack_token( fn msg_connection_open_try_token( msg: MsgConnectionOpenTry, - client_state: ClientState, + client_state: &ClientState, ) -> Token { use ethers::abi::{encode as ethers_encode, Token as EthersToken}; - let client_state = client_state_abi_token(client_state); + let client_state = client_state_abi_token(&client_state); let client_state_data_vec = ethers_encode(&[client_state]); let conn_open_try = YuiMsgConnectionOpenTry { counterparty: msg.counterparty.into(), @@ -926,18 +938,24 @@ impl Chain for EthereumClient { ) -> Result { use ethers::abi::{encode as ethers_encode, Token as EthersToken}; + if messages.is_empty() { + return Err(ClientError::Other("messages are empty".into())) + } log::info!(target: "hyperspace_ethereum", "Submitting messages: {:?}", messages.iter().map(|x| x.type_url.clone()).collect::>().join(", ")); - assert_eq!(messages.len(), 1, "messages.len() > 1"); + let mut calls = vec![]; for msg in messages { if msg.type_url == ibc::core::ics02_client::msgs::create_client::TYPE_URL { dbg!(&msg.value.len()); let msg = MsgCreateAnyClient::::decode_vec(&msg.value).unwrap(); - let AnyClientState::Tendermint(client_state) = msg.client_state else { + let AnyClientState::Tendermint(client_state) = msg.client_state.unpack_recursive() + else { //TODO return error support only tendermint client state panic!("unsupported client state") }; - let AnyConsensusState::Tendermint(client_consensus) = msg.consensus_state else { + let AnyConsensusState::Tendermint(client_consensus) = + msg.consensus_state.unpack_recursive() + else { //TODO return error support only tendermint consensus state panic!("unsupported") }; @@ -950,26 +968,6 @@ impl Chain for EthereumClient { dbg!(&client_state_data_vec.len()); dbg!(&consensus_state_data_vec.len()); - log::info!(target: "hyperspace_ethereum", "encoding: {}", hex::encode(self.config.client_type.as_bytes())); - log::info!(target: "hyperspace_ethereum", "encoding: {}", hex::encode(&client_state_data_vec.to_vec())); - log::info!(target: "hyperspace_ethereum", "encoding: {}", hex::encode(&consensus_state_data_vec.to_vec())); - /* - [2023-09-06T23:06:36Z INFO hyperspace_ethereum] encoding: 30372d74656e6465726d696e74 - [2023-09-06T23:06:36Z INFO hyperspace_ethereum] encoding: 000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000fa000000000000000000000000000000000000000000000000000000000003d0900000000000000000000000000000000000000000000000000000000000001baf800000000000000000000000000000000000000000000000000006722feb7b0000000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000037e11d60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ed500000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001263656e74617572692d746573746e65742d310000000000000000000000000000 - [2023-09-06T23:06:36Z INFO hyperspace_ethereum] encoding: 00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000064f905f2000000000000000000000000000000000000000000000000178271d8db825068000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020767f0009ebb497c791107b84432ccaec45e92e4d05e5799ac55b2d48f2d5d4170000000000000000000000000000000000000000000000000000000000000020602fa35acfd377900d7fe3459730d96415eef369bd033c0923b2d2e2796a97d9 - [2023-09-06T23:06:36Z INFO hyperspace_ethereum] encoding: 0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000002c0000000000000000000000000000000000000000000000000000000000000000d30372d74656e6465726d696e74000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000fa000000000000000000000000000000000000000000000000000000000003d0900000000000000000000000000000000000000000000000000000000000001baf800000000000000000000000000000000000000000000000000006722feb7b0000000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000037e11d60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ed500000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001263656e74617572692d746573746e65742d310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000064f905f2000000000000000000000000000000000000000000000000178271d8db825068000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020767f0009ebb497c791107b84432ccaec45e92e4d05e5799ac55b2d48f2d5d4170000000000000000000000000000000000000000000000000000000000000020602fa35acfd377900d7fe3459730d96415eef369bd033c0923b2d2e2796a97d9 - //-------------------------------------------------d5a244810000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000002c0000000000000000000000000000000000000000000000000000000000000000d30372d74656e6465726d696e74000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000fa000000000000000000000000000000000000000000000000000000000003d0900000000000000000000000000000000000000000000000000000000000001baf800000000000000000000000000000000000000000000000000006722feb7b0000000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000037e11d60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ed500000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001263656e74617572692d746573746e65742d310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000064f905f2000000000000000000000000000000000000000000000000178271d8db825068000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020767f0009ebb497c791107b84432ccaec45e92e4d05e5799ac55b2d48f2d5d4170000000000000000000000000000000000000000000000000000000000000020602fa35acfd377900d7fe3459730d96415eef369bd033c0923b2d2e2796a97d9 - // 000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000fa000000000000000000000000000000000000000000000000000000000003d0900000000000000000000000000000000000000000000000000000000000001baf800000000000000000000000000000000000000000000000000006722feb7b0000000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000037e11d60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ed500000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001263656e74617572692d746573746e65742d310000000000000000000000000000 - - */ - // 0 1 2 - // d5a244810000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000002c0000000000000000000000000000000000000000000000000000000000000000d30372d74656e6465726d696e74000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000fa000000000000000000000000000000000000000000000000000000000003d0900000000000000000000000000000000000000000000000000000000000001baf800000000000000000000000000000000000000000000000000006722feb7b0000000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000037e11d60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cdc00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001263656e74617572692d746573746e65742d310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000064f8fc0400000000000000000000000000000000000000000000000017826f89135e5218000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020008892c98d506a154ef7e5ad89b345e395cdafc8eb77857276f27ff5cef791da0000000000000000000000000000000000000000000000000000000000000020602fa35acfd377900d7fe3459730d96415eef369bd033c0923b2d2e2796a97d9 - // d5a244810000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000000d30372d74656e6465726d696e74000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000221000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001a02000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000fa000000000000000000000000000000000000000000000000000000000003d0900000000000000000000000000000000000000000000000000000000000001baf800000000000000000000000000000000000000000000000000006722feb7b0000000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000037e11d60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dca00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001263656e74617572692d746573746e65742d31000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000064f900b20000000000000000000000000000000000000000000000001782709ff2f10eb8000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002038c9b9a98f4630114e46c5c394fca947569e8db5f0e01d2aac84ef96ddff8afa0000000000000000000000000000000000000000000000000000000000000020602fa35acfd377900d7fe3459730d96415eef369bd033c0923b2d2e2796a97d9 - //-------------------------------------------------------------------------000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000002c0000000000000000000000000000000000000000000000000000000000000000d30372d74656e6465726d696e74000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000fa000000000000000000000000000000000000000000000000000000000003d0900000000000000000000000000000000000000000000000000000000000001baf800000000000000000000000000000000000000000000000000006722feb7b0000000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000037e11d60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4300000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001263656e74617572692d746573746e65742d310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000064f903130000000000000000000000000000000000000000000000001782712dc658a8f0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020eb5eefd453cb5fd16cce92d669a546a074751d588d89261178dec9a250da2eae0000000000000000000000000000000000000000000000000000000000000020602fa35acfd377900d7fe3459730d96415eef369bd033c0923b2d2e2796a97d9 - //---------0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000002c0000000000000000000000000000000000000000000000000000000000000000d30372d74656e6465726d696e74000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000fa000000000000000000000000000000000000000000000000000000000003d0900000000000000000000000000000000000000000000000000000000000001baf800000000000000000000000000000000000000000000000000006722feb7b0000000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000037e11d60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4300000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001263656e74617572692d746573746e65742d310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000064f903130000000000000000000000000000000000000000000000001782712dc658a8f0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020eb5eefd453cb5fd16cce92d669a546a074751d588d89261178dec9a250da2eae0000000000000000000000000000000000000000000000000000000000000020602fa35acfd377900d7fe3459730d96415eef369bd033c0923b2d2e2796a97d9 - // 30372d74656e6465726d696e74 - // 000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001a02000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000fa000000000000000000000000000000000000000000000000000000000003d0900000000000000000000000000000000000000000000000000000000000001baf800000000000000000000000000000000000000000000000000006722feb7b0000000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000037e11d60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dca00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001263656e74617572692d746573746e65742d310000000000000000000000000000 - // 00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000064f900b20000000000000000000000000000000000000000000000001782709ff2f10eb8000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002038c9b9a98f4630114e46c5c394fca947569e8db5f0e01d2aac84ef96ddff8afa0000000000000000000000000000000000000000000000000000000000000020602fa35acfd377900d7fe3459730d96415eef369bd033c0923b2d2e2796a97d9 let token = EthersToken::Tuple(vec![ //should be the same that we use to register client //client type @@ -991,36 +989,30 @@ impl Chain for EthereumClient { // log::info!(target: "hyperspace_ethereum", "encoding: {}", // hex::encode(&bts.to_vec())); let bts = ethers::abi::encode(&vec![token.clone()]); - log::info!(target: "hyperspace_ethereum", "encoding': {}", hex::encode(&bts.to_vec())); - let tok = ethers::abi::decode( &[ParamType::Tuple(vec![ ParamType::String, ParamType::Bytes, ParamType::Bytes, ])], - &bts.to_vec(), // [4..], + &bts.to_vec(), ) .unwrap() .pop() .unwrap(); assert_eq!(tok, token); - let (client_id, tx_id) = self.yui.create_client(token).await; - dbg!(&client_id); - // self.set_client_id(); - - thread::sleep(Duration::from_secs(5)); + let bytes = self.yui.create_client_calldata(token).await; //update mutex let mut update_mutex = self.prev_state.lock().unwrap(); *update_mutex = (client_state_data_vec.clone(), consensus_state_data_vec.clone()); - - return Ok(tx_id) + calls.push(bytes); } else if msg.type_url == ibc::core::ics02_client::msgs::update_client::TYPE_URL { let msg = MsgUpdateAnyClient::::decode_vec(&msg.value).unwrap(); - let AnyClientMessage::Tendermint(client_state) = msg.client_message else { - //TODO return error support only tendermint client state - panic!("unsupported") + let AnyClientMessage::Tendermint(client_state) = + msg.client_message.unpack_recursive() + else { + return Err(ClientError::Other(format!("unsupported client state 3"))) }; let ClientMessage::Header(header) = client_state else { panic!("unsupported") }; @@ -1045,26 +1037,20 @@ impl Chain for EthereumClient { EthersToken::Bytes(client_state), ]); - let _ = self.yui.update_client(token).await; - thread::sleep(Duration::from_secs(5)); - - return Ok((H256::default(), H256::default())) // TODO: tx hash + calls.push(self.yui.update_client_calldata(token).await); } else if msg.type_url == ibc::core::ics03_connection::msgs::conn_open_init::TYPE_URL { let msg = MsgConnectionOpenInit::decode_vec(&msg.value).unwrap(); let token = msg_connection_open_init_token(msg); - let (connection_id, tx_id) = self.yui.connection_open_init(token).await; - dbg!(connection_id); - return Ok(tx_id) + calls.push(self.yui.connection_open_init_calldata(token).await); } else if msg.type_url == ibc::core::ics03_connection::msgs::conn_open_ack::TYPE_URL { let msg = MsgConnectionOpenAck::::decode_vec(&msg.value).unwrap(); let client_state = match msg.client_state.clone() { Some(m) => { - let AnyClientState::Tendermint(client_state) = m else { - //TODO return error support only tendermint client state - panic!("unsupported") + let AnyClientState::Ethereum(client_state) = m.unpack_recursive() else { + return Err(ClientError::Other(format!("unsupported client state 1"))) }; - client_state + client_state.clone() }, None => { //TODO return error support only tendermint client state @@ -1072,18 +1058,16 @@ impl Chain for EthereumClient { }, }; - let token = msg_connection_open_ack_token(msg, client_state); - let connection_id = self.yui.connection_open_ack(token).await; - return Ok((H256::default(), H256::default())) // TODO: tx hash + let token = msg_connection_open_ack_token(msg, &client_state); + calls.push(self.yui.connection_open_ack_calldata(token).await); } else if msg.type_url == ibc::core::ics03_connection::msgs::conn_open_try::TYPE_URL { let msg = MsgConnectionOpenTry::::decode_vec(&msg.value).unwrap(); let client_state = match msg.client_state.clone() { Some(m) => { - let AnyClientState::Tendermint(client_state) = m else { - //TODO return error support only tendermint client state - panic!("unsupported") + let AnyClientState::Tendermint(client_state) = m.unpack_recursive() else { + return Err(ClientError::Other(format!("unsupported client state 2",))) }; - client_state + client_state.clone() }, None => { //TODO return error support only tendermint client state @@ -1091,63 +1075,84 @@ impl Chain for EthereumClient { }, }; - let token = msg_connection_open_try_token(msg, client_state); - self.yui.connection_open_try(token).await; - return Ok((H256::default(), H256::default())) // TODO: tx hash + let token = msg_connection_open_try_token(msg, &client_state); + calls.push(self.yui.connection_open_try_calldata(token).await); } else if msg.type_url == ibc::core::ics03_connection::msgs::conn_open_confirm::TYPE_URL { let msg = MsgConnectionOpenConfirm::decode_vec(&msg.value).unwrap(); let token = msg_connection_open_confirm_token(msg); - self.yui.connection_open_confirm(token).await; - return Ok((H256::default(), H256::default())) // TODO: tx hash + calls.push(self.yui.connection_open_confirm_calldata(token).await); } else if msg.type_url == channel_msgs::chan_open_init::TYPE_URL { let msg = MsgChannelOpenInit::decode_vec(&msg.value).unwrap(); + log::info!("msg.channel.ordering = {}", msg.channel.ordering); let token = msg.into_token(); - let (_channel_id, tx_id) = self.yui.channel_open_init(token).await; - return Ok(tx_id) + calls.push(self.yui.channel_open_init_calldata(token).await); } else if msg.type_url == channel_msgs::chan_open_try::TYPE_URL { let msg = MsgChannelOpenTry::decode_vec(&msg.value).unwrap(); let token = msg.into_token(); - let channel_id = self.yui.channel_open_try(token).await; - return Ok((H256::default(), H256::default())) // TODO: tx hash + calls.push(self.yui.channel_open_try_calldata(token).await); } else if msg.type_url == channel_msgs::chan_open_ack::TYPE_URL { let msg = MsgChannelOpenAck::decode_vec(&msg.value).unwrap(); + log::info!("msg = {msg:#?}"); let token = msg.into_token(); - self.yui.send_and_get_tuple(token, "channelOpenAck").await; - return Ok((H256::default(), H256::default())) // TODO: tx hash + calls.push(self.yui.send_and_get_tuple_calldata(token, "channelOpenAck").await); } else if msg.type_url == channel_msgs::chan_open_confirm::TYPE_URL { let msg = MsgChannelOpenConfirm::decode_vec(&msg.value).unwrap(); let token = msg.into_token(); - self.yui.send_and_get_tuple(token, "channelOpenConfirm").await; - return Ok((H256::default(), H256::default())) // TODO: tx hash + calls.push(self.yui.send_and_get_tuple_calldata(token, "channelOpenConfirm").await); } else if msg.type_url == channel_msgs::chan_close_init::TYPE_URL { let msg = MsgChannelCloseInit::decode_vec(&msg.value).unwrap(); let token = msg.into_token(); - self.yui.send_and_get_tuple(token, "channelCloseInit").await; - return Ok((H256::default(), H256::default())) // TODO: tx hash + calls.push(self.yui.send_and_get_tuple_calldata(token, "channelCloseInit").await); } else if msg.type_url == channel_msgs::chan_close_confirm::TYPE_URL { let msg = MsgChannelCloseConfirm::decode_vec(&msg.value).unwrap(); let token = msg.into_token(); - self.yui.send_and_get_tuple(token, "channelCloseConfirm").await; - return Ok((H256::default(), H256::default())) // TODO: tx hash + calls + .push(self.yui.send_and_get_tuple_calldata(token, "channelCloseConfirm").await); } else if msg.type_url == channel_msgs::timeout_on_close::TYPE_URL { let msg = MsgTimeoutOnClose::decode_vec(&msg.value).unwrap(); + return Err(ClientError::Other("timeout not supported".into())) } else if msg.type_url == channel_msgs::timeout::TYPE_URL { let msg = MsgTimeout::decode_vec(&msg.value).unwrap(); + return Err(ClientError::Other("timeout not supported".into())) } else if msg.type_url == channel_msgs::acknowledgement::TYPE_URL { let msg = MsgAcknowledgement::decode_vec(&msg.value).unwrap(); let token = msg.into_token(); - self.yui.send_and_get_tuple(token, "acknowledgePacket").await; - return Ok((H256::default(), H256::default())) // TODO: tx hash + calls.push(self.yui.send_and_get_tuple_calldata(token, "acknowledgePacket").await); } else if msg.type_url == channel_msgs::recv_packet::TYPE_URL { let msg = MsgRecvPacket::decode_vec(&msg.value).unwrap(); let token = msg.into_token(); - self.yui.send_and_get_tuple(token, "recvPacket").await; - return Ok((H256::default(), H256::default())) // TODO: tx hash + calls.push(self.yui.send_and_get_tuple_calldata(token, "recvPacket").await); + } else { + return Err(ClientError::Other(format!( + "does not support this msg type for now: {}", + msg.type_url, + ))) + } + } + + let method = self.yui.method::<_, (Vec, Vec>)>("call_batch", calls)?; + let data = method.call().await?; + let receipt = method + .send() + .await? + .await? + .ok_or_else(|| ClientError::Other("tx failed".into()))?; + if receipt.status != Some(1.into()) { + return Err(ClientError::Other("tx failed".into())) + } + + for (i, (success, result)) in + data.0.into_iter().zip(data.1.into_iter()).into_iter().enumerate() + { + if !success { + log::error!(target: "hyperspace_ethereum", "tx failed {i}: {}", hex::encode(&result)); } - unimplemented!("does not support this msg type for now: {}", msg.type_url); } - Err(ClientError::Other("no message to submit".to_string())) + + thread::sleep(Duration::from_secs(5)); + + Ok((receipt.block_hash.unwrap(), receipt.transaction_hash)) } async fn query_client_message( diff --git a/hyperspace/ethereum/src/client.rs b/hyperspace/ethereum/src/client.rs index 166d4d7f7..fcf0506bf 100644 --- a/hyperspace/ethereum/src/client.rs +++ b/hyperspace/ethereum/src/client.rs @@ -1,5 +1,6 @@ use crate::{ config::EthereumClientConfig, + contract::UnwrapContractError, jwt::{JwtAuth, JwtKey}, utils::{DeployYuiIbc, ProviderImpl}, }; @@ -8,9 +9,11 @@ use async_trait::async_trait; use cast::revm::db; use ethers::{ abi::{AbiEncode, Address, ParamType, Token}, + core::k256, prelude::{ coins_bip39::English, signer::SignerMiddlewareError, Authorization, BlockId, BlockNumber, - EIP1186ProofResponse, Filter, LocalWallet, Log, MnemonicBuilder, NameOrAddress, H256, + EIP1186ProofResponse, Filter, LocalWallet, Log, MnemonicBuilder, NameOrAddress, + SignerMiddleware, Wallet, H256, }, providers::{Http, Middleware, Provider, ProviderError, ProviderExt, Ws}, signers::Signer, @@ -22,14 +25,22 @@ use ibc::{ applications::transfer::{msgs::transfer::MsgTransfer, PrefixedCoin}, core::ics24_host::{ error::ValidationError, - identifier::{ChannelId, ClientId, PortId}, + identifier::{ChannelId, ClientId, ConnectionId, PortId}, }, Height, }; use ibc_primitives::Timeout; use once_cell::sync::Lazy; use primitives::CommonClientState; -use std::{convert::Infallible, future::Future, ops::Add, pin::Pin, str::FromStr, sync::Arc}; +use std::{ + collections::HashSet, + convert::Infallible, + future::Future, + ops::Add, + pin::Pin, + str::FromStr, + sync::{Arc, Mutex}, +}; use sync_committee_prover::SyncCommitteeProver; use thiserror::Error; @@ -56,7 +67,13 @@ pub struct EthereumClient { /// Common relayer data pub common_state: CommonClientState, pub yui: DeployYuiIbc, ProviderImpl>, - pub prev_state: Arc, Vec)>>, + pub prev_state: Arc, Vec)>>, + /// Light client id on counterparty chain + pub client_id: Arc>>, + /// Connection Id + pub connection_id: Arc>>, + /// Channels cleared for packet relay + pub channel_whitelist: Arc>>, } pub type MiddlewareErrorType = SignerMiddlewareError< @@ -80,6 +97,17 @@ pub enum ClientError { MerkleizationError(#[from] ssz_rs::MerkleizationError), #[error("ABI error: {0}")] AbiError(#[from] ethers::abi::Error), + #[error("Contract ABI error: {0}")] + ContractAbiError(#[from] ethers::contract::AbiError), + #[error("Contract error: {0}")] + ContractError( + #[from] + ethers::contract::ContractError< + SignerMiddleware, Wallet>>, + >, + ), + #[error("IBC Transfer: {0}")] + IbcTransfer(#[from] ibc::applications::transfer::error::Error), #[error("no-storage-proof: there was no storage proof for the given storage index")] NoStorageProof, #[error("Tendermint error: {0}")] @@ -165,10 +193,15 @@ impl EthereumClient { Ok(Self { http_rpc: Arc::new(client), ws_uri: config.ws_rpc_url.clone(), - config, common_state: Default::default(), yui, prev_state: Arc::new(std::sync::Mutex::new((vec![], vec![]))), + client_id: Arc::new(Mutex::new(config.client_id.clone())), + connection_id: Arc::new(Mutex::new(config.connection_id.clone())), + channel_whitelist: Arc::new(Mutex::new( + config.channel_whitelist.clone().into_iter().collect(), + )), + config, }) } @@ -579,7 +612,27 @@ impl EthereumClient { #[async_trait] impl primitives::TestProvider for EthereumClient { async fn send_transfer(&self, params: MsgTransfer) -> Result<(), Self::Error> { - todo!() + let params = ( + params.token.denom.to_string(), + params.token.amount.as_u256().as_u64(), + params.receiver.to_string(), + params.source_port.to_string(), + params.source_channel.to_string(), + params.timeout_height.revision_height, + ); + let method = self + .yui + .bank + .as_ref() + .expect("expected bank module") + .method::<_, ()>("sendTransfer", params)?; + let _ = method.call().await.unwrap_contract_error(); + let receipt = method.send().await.unwrap().await.unwrap().unwrap(); + assert_eq!(receipt.status, Some(1.into())); + for log in receipt.logs { + log::info!("tx.log.t0 = {}", hex::encode(log.topics[0])); + } + Ok(()) } async fn send_ordered_packet( @@ -587,14 +640,14 @@ impl primitives::TestProvider for EthereumClient { channel_id: ChannelId, timeout: Timeout, ) -> Result<(), Self::Error> { - todo!() + todo!("send_ordered_packet") } async fn subscribe_blocks(&self) -> Pin + Send + Sync>> { - todo!() + todo!("subscribe_blocks") } async fn increase_counters(&mut self) -> Result<(), Self::Error> { - todo!() + Ok(()) } } diff --git a/hyperspace/ethereum/src/events.rs b/hyperspace/ethereum/src/events.rs index 04df4343b..e4af4c914 100644 --- a/hyperspace/ethereum/src/events.rs +++ b/hyperspace/ethereum/src/events.rs @@ -1,9 +1,10 @@ use crate::{ client::{ClientError, EthereumClient}, ibc_provider::{ - CloseConfirmChannelFilter, CreateClientFilter, OpenConfirmChannelFilter, - OpenConfirmConnectionFilter, OpenInitConnectionFilter, OpenTryConnectionFilter, - UpdateClientFilter, + CloseConfirmChannelFilter, CreateClientFilter, OpenAckChannelFilter, + OpenAckConnectionFilter, OpenConfirmChannelFilter, OpenConfirmConnectionFilter, + OpenInitChannelFilter, OpenInitConnectionFilter, OpenTryConnectionFilter, SendPacketFilter, + UpdateClientFilter, WriteAcknowledgementFilter, }, }; use async_trait::async_trait; @@ -14,10 +15,14 @@ use ibc::{ ics03_connection::events::{ self as connection, Attributes, OpenConfirm as ConnectionOpenConfirm, }, - ics04_channel::events::{self as channel, CloseConfirm, OpenConfirm as ChannelOpenConfirm}, + ics04_channel::{ + events::{self as channel, CloseConfirm, OpenConfirm as ChannelOpenConfirm}, + packet::{Packet, Sequence}, + }, ics24_host::identifier::{ChannelId, ConnectionId, PortId}, }, events::IbcEvent, + timestamp::Timestamp, Height, }; use primitives::IbcProvider; @@ -184,8 +189,6 @@ impl TryFromEvent for IbcEvent { } } -// Open - #[async_trait] impl TryFromEvent for IbcEvent { async fn try_from_event( @@ -197,3 +200,192 @@ impl TryFromEvent for IbcEvent { todo!() } } + +#[async_trait] +impl TryFromEvent for IbcEvent { + async fn try_from_event( + client: &EthereumClient, + event: OpenAckConnectionFilter, + _log: Log, + height: Height, + ) -> Result { + let OpenAckConnectionFilter { connection_id, counterparty_connection_id } = event; + let connection_id: ConnectionId = connection_id.parse()?; + let resp = client.query_connection_end(height, connection_id.clone()).await?; + let connection_end = resp.connection.unwrap(); + let counterparty = connection_end.counterparty.unwrap(); + let client_id = connection_end.client_id.parse()?; + let counterparty_client_id = counterparty.client_id.parse()?; + Ok(IbcEvent::OpenAckConnection(connection::OpenAck(connection::Attributes { + height, + connection_id: Some(connection_id), + client_id, + counterparty_connection_id: if counterparty_connection_id.is_empty() { + None + } else { + Some(counterparty_connection_id.parse()?) + }, + counterparty_client_id, + }))) + } +} + +#[async_trait] +impl TryFromEvent for IbcEvent { + async fn try_from_event( + client: &EthereumClient, + event: OpenInitChannelFilter, + _log: Log, + height: Height, + ) -> Result { + let OpenInitChannelFilter { port_id, channel_id } = event; + let port_id: PortId = port_id.parse()?; + let channel_id: ChannelId = channel_id.parse()?; + let resp = client.query_channel_end(height, channel_id, port_id.clone()).await?; + let channel = resp.channel.unwrap(); + let counterparty = channel + .counterparty + .ok_or_else(|| ClientError::Other("counterparty not found".to_string()))?; + Ok(IbcEvent::OpenInitChannel(channel::OpenInit { + height, + channel_id: Some(channel_id), + counterparty_port_id: counterparty.port_id.parse()?, + port_id, + counterparty_channel_id: if counterparty.channel_id.is_empty() { + None + } else { + Some(counterparty.channel_id.parse()?) + }, + connection_id: channel.connection_hops[0].parse()?, + })) + } +} + +#[async_trait] +impl TryFromEvent for IbcEvent { + async fn try_from_event( + client: &EthereumClient, + event: OpenAckChannelFilter, + _log: Log, + height: Height, + ) -> Result { + let OpenAckChannelFilter { port_id, channel_id } = event; + let port_id: PortId = port_id.parse()?; + let channel_id: ChannelId = channel_id.parse()?; + let resp = client.query_channel_end(height, channel_id, port_id.clone()).await?; + let channel = resp.channel.unwrap(); + let counterparty = channel.counterparty.unwrap(); + let counterparty_channel_id = counterparty.channel_id; + Ok(IbcEvent::OpenAckChannel(channel::OpenAck { + height, + port_id, + channel_id: Some(channel_id), + counterparty_port_id: counterparty.port_id.parse()?, + counterparty_channel_id: if counterparty_channel_id.is_empty() { + None + } else { + Some(counterparty_channel_id.parse()?) + }, + connection_id: channel.connection_hops[0].parse()?, + })) + } +} + +#[async_trait] +impl TryFromEvent for IbcEvent { + async fn try_from_event( + client: &EthereumClient, + event: SendPacketFilter, + _log: Log, + height: Height, + ) -> Result { + let SendPacketFilter { + sequence, + source_port: _, + source_channel: _, + source_port_raw, + source_channel_raw, + timeout_height, + timeout_timestamp, + data, + } = event; + let source_port: PortId = source_port_raw.parse()?; + let source_channel: ChannelId = source_channel_raw.parse()?; + let resp = client.query_channel_end(height, source_channel, source_port.clone()).await?; + let channel = resp.channel.unwrap(); + let counterparty = channel.counterparty.unwrap(); + let counterparty_channel_id = counterparty.channel_id.parse()?; + Ok(IbcEvent::SendPacket(channel::SendPacket { + height, + packet: Packet { + sequence: Sequence::from(sequence), + source_port, + source_channel, + destination_port: counterparty.port_id.parse()?, + destination_channel: counterparty_channel_id, + data: data.to_vec(), + timeout_height: timeout_height.into(), + timeout_timestamp: if timeout_timestamp == 0 { + Timestamp::none() + } else { + Timestamp::from_nanoseconds(timeout_timestamp).expect("the timestamp is valid") + }, + }, + })) + } +} + +#[async_trait] +impl TryFromEvent for IbcEvent { + async fn try_from_event( + client: &EthereumClient, + event: WriteAcknowledgementFilter, + _log: Log, + height: Height, + ) -> Result { + let WriteAcknowledgementFilter { + destination_port_id: _, + destination_channel: _, + sequence, + destination_port_id_raw, + destination_channel_raw, + acknowledgement, + } = event; + let destination_port_id: PortId = destination_port_id_raw.parse()?; + let destination_channel: ChannelId = destination_channel_raw.parse()?; + let packet = client + .query_received_packets( + height, + destination_channel.clone(), + destination_port_id.clone(), + vec![sequence], + ) + .await? + .pop() + .ok_or_else(|| ClientError::Other("packet not found".to_string()))?; + log::info!( + "ack = {}, ack' = {}", + hex::encode(&acknowledgement), + hex::encode(&packet.ack.unwrap_or_default()) + ); + Ok(IbcEvent::WriteAcknowledgement(channel::WriteAcknowledgement { + height, + packet: Packet { + sequence: Sequence::from(sequence), + source_port: packet.source_port.parse()?, + source_channel: packet.source_channel.parse()?, + destination_port: destination_port_id, + destination_channel, + data: packet.data, + timeout_height: packet.timeout_height.into(), + timeout_timestamp: if packet.timeout_timestamp == 0 { + Timestamp::none() + } else { + Timestamp::from_nanoseconds(packet.timeout_timestamp) + .expect("the timestamp is valid") + }, + }, + ack: acknowledgement.to_vec(), + })) + } +} diff --git a/hyperspace/ethereum/src/ibc_provider.rs b/hyperspace/ethereum/src/ibc_provider.rs index f6eef7cf4..03bf7efce 100644 --- a/hyperspace/ethereum/src/ibc_provider.rs +++ b/hyperspace/ethereum/src/ibc_provider.rs @@ -9,7 +9,7 @@ use ethers::{ providers::Middleware, types::{ BlockId, BlockNumber, EIP1186ProofResponse, Filter, StorageProof, Topic, ValueOrArray, - H256, U256, + H160, H256, U256, }, utils::keccak256, }; @@ -44,11 +44,12 @@ use ibc_proto::{ }, }, }; -use primitives::{IbcProvider, UpdateType}; +use primitives::{IbcProvider, KeyProvider, UpdateType}; use prost::Message; use std::{ collections::{HashMap, HashSet}, future::Future, + iter, pin::Pin, str::FromStr, sync::Arc, @@ -67,9 +68,12 @@ use futures::{FutureExt, Stream, StreamExt}; use ssz_rs::Merkleized; use thiserror::Error; -use crate::chain::{client_state_from_abi_token, tm_header_from_abi_token}; +use crate::{ + chain::{client_state_from_abi_token, tm_header_from_abi_token}, + prove::prove_fast, +}; use ibc::{ - applications::transfer::PrefixedCoin, + applications::transfer::{Amount, BaseDenom, PrefixedCoin, PrefixedDenom, TracePath}, core::{ ics02_client::{events::UpdateClient, msgs::update_client::MsgUpdateAnyClient}, ics04_channel::{ @@ -98,22 +102,22 @@ use pallet_ibc::light_clients::{ AnyClientMessage, AnyClientState, AnyConsensusState, HostFunctionsManager, }; use primitives::mock::LocalClientTypes; -use sync_committee_primitives::types::LightClientState; +use sync_committee_primitives::types::{LightClientState, LightClientUpdate}; use sync_committee_prover::SyncCommitteeProver; use tracing::log; abigen!( IbcClientAbi, - "/Users/vmark/work/centauri-private/hyperspace/ethereum/src/abi/ibc-client-abi.json"; + "hyperspace/ethereum/src/abi/ibc-client-abi.json"; IbcConnectionAbi, - "/Users/vmark/work/centauri-private/hyperspace/ethereum/src/abi/ibc-connection-abi.json"; + "hyperspace/ethereum/src/abi/ibc-connection-abi.json"; IbcChannelAbi, - "/Users/vmark/work/centauri-private/hyperspace/ethereum/src/abi/ibc-channel-abi.json"; + "hyperspace/ethereum/src/abi/ibc-channel-abi.json"; IbcPacketAbi, - "/Users/vmark/work/centauri-private/hyperspace/ethereum/src/abi/ibc-packet-abi.json"; + "hyperspace/ethereum/src/abi/ibc-packet-abi.json"; ); impl From for Height { @@ -164,6 +168,7 @@ pub async fn parse_ethereum_events( logs: Vec, ) -> Result, ClientError> { let mut events = vec![]; + log::info!("SendPacketFilter.topic0 = {}", hex::encode(&SendPacketFilter::signature())); for log in logs { let raw_log = RawLog::from(log.clone()); @@ -193,7 +198,13 @@ pub async fn parse_ethereum_events( height, OpenInitConnectionFilter, OpenTryConnectionFilter, - OpenConfirmConnectionFilter + OpenAckConnectionFilter, + OpenConfirmConnectionFilter, + OpenInitChannelFilter, + OpenAckChannelFilter, + OpenConfirmChannelFilter, + SendPacketFilter, + WriteAcknowledgementFilter ); } @@ -206,7 +217,7 @@ impl IbcProvider for EthereumClient { type TransactionId = (H256, H256); - type AssetId = (); + type AssetId = String; type Error = ClientError; @@ -243,18 +254,43 @@ impl IbcProvider for EthereumClient { // finalisation ~= 2.5 epoch // 32 * 12 * 2.5 = 960 sec = 16 min + let prover = self.prover(); + let block = prover.fetch_block("head").await?; + let number = block.body.execution_payload.block_number; + let height = Height::new(0, number.into()); + let from = latest_cp_client_height; - let to = finality_event - .number - .unwrap() - .as_u64() - .min(latest_cp_client_height + NUMBER_OF_BLOCKS_TO_PROCESS_PER_ITER); + let to = number.min(latest_cp_client_height + NUMBER_OF_BLOCKS_TO_PROCESS_PER_ITER); + // let to = finality_event + // .number + // .unwrap() + // .as_u64() + // .min(latest_cp_client_height + NUMBER_OF_BLOCKS_TO_PROCESS_PER_ITER); + log::info!(target: "hyperspace_ethereum", "Getting blocks {}..{}", from, to); let filter = Filter::new().from_block(from).to_block(to).address(self.yui.diamond.address()); - let logs = self.client().get_logs(&filter).await.unwrap(); - - let update = prove(self, finality_event.number.unwrap().as_u64()).await?; + let mut logs = self.client().get_logs(&filter).await.unwrap(); + let filter = Filter::new() + .from_block(from) + .to_block(to) + .address(self.yui.bank.as_ref().unwrap().address()); + let logs2 = self.client().get_logs(&filter).await.unwrap(); + logs.extend(logs2); + + let maybe_proof = prove_fast(self, &client_state, block.slot).await; + // let Ok(update) = else { + // log::error!(target: "hyperspace_ethereum", "failed to prove"); + // return Ok(vec![]) + // }; + let update = match maybe_proof { + Ok(x) => x, + Err(e) => { + log::error!(target: "hyperspace_ethereum", "failed to prove {e}"); + return Ok(vec![]) + }, + }; + // let update = prove(self, finality_event.number.unwrap().as_u64()).await?; log::info!(target: "hyperspace_ethereum", "proven: state root = {}, body root = {}, slot = {}, block number = {}", @@ -264,7 +300,7 @@ impl IbcProvider for EthereumClient { update.execution_payload.block_number ); // finality_checkpoint.finalized.epoch <= client_state.latest_finalized_epoch - if update.finality_proof.epoch <= client_state.inner.latest_finalized_epoch { + if update.execution_payload.block_number <= client_state.latest_height().revision_height { log::info!(target: "hyperspace_ethereum", "no new events"); return Ok(vec![]) } @@ -274,6 +310,10 @@ impl IbcProvider for EthereumClient { let events = parse_ethereum_events(&self, logs).await?; let update_client_header = { + log::info!(target: "hyperspace_ethereum", "update client header height: {}, finalized slot: {}", + update.execution_payload.block_number, + update.finalized_header.slot + ); let msg = MsgUpdateAnyClient:: { client_id: client_id.clone(), client_message: AnyClientMessage::Ethereum(ClientMessage::Header(update)), @@ -377,7 +417,7 @@ impl IbcProvider for EthereumClient { ) -> Result { // First, we try to find an `UpdateClient` event at the given height... log::info!(target: "hyperspace_ethereum", "qcs {}", line!()); - let mut client_state; + let mut client_state = None; let mut event_filter = self .yui .event_for_name::("UpdateClient") @@ -401,6 +441,7 @@ impl IbcProvider for EthereumClient { .pop() // get only the last event ; log::info!(target: "hyperspace_ethereum", "qcs {}", line!()); + let batch_func = self.yui.function("call_batch")?; match maybe_log { Some(log) => { let tx_hash = log.transaction_hash.expect("tx hash should exist"); @@ -409,15 +450,30 @@ impl IbcProvider for EthereumClient { self.client().get_transaction(tx_hash).await.unwrap().ok_or_else(|| { ClientError::Other(format!("transaction not found: {}", tx_hash)) })?; - let calldata = func.decode_input(&tx.input[4..])?.pop().unwrap(); - let Token::Tuple(toks) = calldata else { panic!() }; - let header = tm_header_from_abi_token(toks[1].clone())?; - let client_state_token = toks[2].clone(); - client_state = client_state_from_abi_token::(client_state_token)?; - client_state.latest_height = Height::new( - client_state.latest_height.revision_number, - header.signed_header.header.height.into(), - ); + let Token::Array(batch_calldata) = + batch_func.decode_input(&tx.input[4..])?.pop().unwrap() + else { + return Err(ClientError::Other("batch calldata not found".to_string())) + }; + + for input_tok in batch_calldata.into_iter().rev() { + let Token::Bytes(input) = input_tok else { panic!() }; + if input[..4] == func.short_signature() { + let calldata = func.decode_input(&input[4..])?.pop().unwrap(); + let Token::Tuple(toks) = calldata else { panic!() }; + let header = tm_header_from_abi_token(toks[1].clone())?; + let client_state_token = toks[2].clone(); + let mut cs = + client_state_from_abi_token::(client_state_token)?; + cs.latest_height = Height::new( + cs.latest_height.revision_number, + header.signed_header.header.height.into(), + ); + client_state = Some(cs); + // TODO: figure out how to distinguish between the same function calls + break + } + } // TODO: handle frozen height }, None => { @@ -452,10 +508,25 @@ impl IbcProvider for EthereumClient { self.client().get_transaction(tx_hash).await.unwrap().ok_or_else(|| { ClientError::Other(format!("transaction not found: {}", tx_hash)) })?; - let calldata = func.decode_input(&tx.input[4..])?.pop().unwrap(); - let Token::Tuple(toks) = calldata else { panic!() }; - let client_state_token = toks[1].clone(); - client_state = client_state_from_abi_token::(client_state_token)?; + + let Token::Array(batch_calldata) = + batch_func.decode_input(&tx.input[4..])?.pop().unwrap() + else { + return Err(ClientError::Other("batch calldata not found".to_string())) + }; + + for input_tok in batch_calldata.into_iter().rev() { + let Token::Bytes(input) = input_tok else { panic!() }; + if input[..4] == func.short_signature() { + let calldata = func.decode_input(&input[4..])?.pop().unwrap(); + let Token::Tuple(toks) = calldata else { panic!() }; + let client_state_token = toks[1].clone(); + client_state = Some(client_state_from_abi_token::( + client_state_token, + )?); + break + } + } }, } @@ -505,7 +576,7 @@ impl IbcProvider for EthereumClient { // let client_state = google::protobuf::Any::decode(&*client_state).ok(); Ok(QueryClientStateResponse { - client_state: Some(client_state.to_any()), + client_state: Some(client_state.expect("should always be initialized").to_any()), proof_height, proof: vec![0], }) @@ -579,14 +650,11 @@ impl IbcProvider for EthereumClient { .await .unwrap(); - let state = State::from_i32(channel_data.state as _).expect("invalid channel state"); - let counterparty = match state { - State::Init | State::TryOpen => None, - State::Open | State::Closed => Some(ChannelCounterparty { - port_id: channel_data.counterparty.port_id, - channel_id: channel_data.counterparty.channel_id, - }), - }; + let _state = State::from_i32(channel_data.state as _).expect("invalid channel state"); + let counterparty = Some(ChannelCounterparty { + port_id: channel_data.counterparty.port_id, + channel_id: channel_data.counterparty.channel_id, + }); Ok(QueryChannelResponse { channel: Some(Channel { state: channel_data.state as _, @@ -596,27 +664,28 @@ impl IbcProvider for EthereumClient { version: channel_data.version, }), proof: vec![0], - proof_height: None, + proof_height: Some(at.into()), }) } async fn query_proof(&self, at: Height, keys: Vec>) -> Result, Self::Error> { - let key = String::from_utf8(keys[0].clone()).unwrap(); - - let proof_result = self - .eth_query_proof(&key, Some(at.revision_height), COMMITMENTS_STORAGE_INDEX) - .await?; - - let bytes = proof_result - .storage_proof - .first() - .map(|p| p.proof.first()) - .flatten() - .map(|b| b.to_vec()) - .unwrap_or_default(); + // let key = String::from_utf8(keys[0].clone()).unwrap(); + // + // let proof_result = self + // .eth_query_proof(&key, Some(at.revision_height), COMMITMENTS_STORAGE_INDEX) + // .await?; + // + // let bytes = proof_result + // .storage_proof + // .first() + // .map(|p| p.proof.first()) + // .flatten() + // .map(|b| b.to_vec()) + // .unwrap_or_default(); // Ok(bytes) - todo!("query-proof: redo") + // todo!("query-proof: redo") + Ok(vec![0]) } async fn query_packet_commitment( @@ -740,21 +809,13 @@ impl IbcProvider for EthereumClient { async fn latest_height_and_timestamp(&self) -> Result<(Height, Timestamp), Self::Error> { // TODO: fix latest_height_and_timestamp in basic builds - let block_number =// if dbg!(cfg!(feature = "test")) { - BlockNumber::from( - self - .client() - .get_block_number() - .await - .map_err(|err| ClientError::MiddlewareError(err))?, - ); - // } else { - // BlockNumber::Finalized - // }; - + let prover = self.prover(); + let block = prover.fetch_block("head").await?; + let number = block.body.execution_payload.block_number; + let height = Height::new(0, number.into()); let block = self .client() - .get_block(BlockId::Number(block_number)) + .get_block(BlockId::Number(number.into())) .await .map_err(|err| ClientError::MiddlewareError(err))? .ok_or_else(|| ClientError::MiddlewareError(todo!()))?; @@ -762,7 +823,9 @@ impl IbcProvider for EthereumClient { let nanoseconds = Duration::from_secs(block.timestamp.as_u64()).as_nanos() as u64; let timestamp = Timestamp::from_nanoseconds(nanoseconds).expect("timestamp error"); - Ok((Height::new(0, block.number.expect("expected block number").as_u64()), timestamp)) + log::info!(target: "hyperspace_ethereum", "latest_height_and_timestamp: {height:?}, {timestamp:?}"); + + Ok((height, timestamp)) } async fn query_packet_commitments( @@ -886,7 +949,7 @@ impl IbcProvider for EthereumClient { } fn channel_whitelist(&self) -> HashSet<(ChannelId, PortId)> { - self.config.channel_whitelist.clone().into_iter().collect() + self.channel_whitelist.lock().unwrap().clone().into_iter().collect() } async fn query_connection_channels( @@ -944,28 +1007,41 @@ impl IbcProvider for EthereumClient { data.into_iter().map(hex::encode).collect::>().join(", ") ); } - let events = event_filter.query().await.unwrap(); + let mut logs = self.yui.diamond.client().get_logs(&event_filter.filter).await.unwrap(); + let logs2 = self + .yui + .bank + .as_ref() + .unwrap() + .client() + .get_logs(&event_filter.filter) + .await + .unwrap(); + logs.extend(logs2); let channel = self.query_channel_end(at, channel_id, port_id).await?; let channel = channel.channel.expect("channel is none"); let counterparty = channel.counterparty.expect("counterparty is none"); - Ok(events + Ok(logs .into_iter() - .map(move |value| PacketInfo { - height: None, - source_port: source_port.clone(), - source_channel: source_channel.clone(), - destination_port: counterparty.port_id.clone(), - destination_channel: counterparty.channel_id.clone(), - sequence: value.sequence, - timeout_height: value.timeout_height.into(), - timeout_timestamp: value.timeout_timestamp, - data: value.data.to_vec(), - channel_order: Order::from_i32(channel.ordering) - .map_err(|_| Self::Error::Other("invalid channel order".to_owned())) - .unwrap() - .to_string(), - ack: None, + .map(move |log| { + let value = SendPacketFilter::decode_log(&log.clone().into()).unwrap(); + PacketInfo { + height: Some(log.block_number.unwrap().as_u64().into()), + source_port: source_port.clone(), + source_channel: source_channel.clone(), + destination_port: counterparty.port_id.clone(), + destination_channel: counterparty.channel_id.clone(), + sequence: value.sequence, + timeout_height: value.timeout_height.into(), + timeout_timestamp: value.timeout_timestamp, + data: value.data.to_vec(), + channel_order: Order::from_i32(channel.ordering) + .map_err(|_| Self::Error::Other("invalid channel order".to_owned())) + .unwrap() + .to_string(), + ack: None, + } }) .collect()) } @@ -1005,7 +1081,7 @@ impl IbcProvider for EthereumClient { )]))) }); - let events = event_filter.query().await.unwrap(); + let logs = self.yui.diamond.client().get_logs(&event_filter.filter).await.unwrap(); let channel = self.query_channel_end(at, channel_id, port_id).await?; let channel = channel.channel.expect("channel is none"); @@ -1042,23 +1118,26 @@ impl IbcProvider for EthereumClient { .map(|ack| (ack.sequence, ack.acknowledgement.to_vec())) .collect::>(); - Ok(events + Ok(logs .into_iter() - .map(move |value| PacketInfo { - height: None, - source_port: value.source_port.clone(), - source_channel: value.source_channel.clone(), - destination_port: destination_port.clone(), - destination_channel: destination_channel.clone(), - sequence: value.sequence, - timeout_height: value.timeout_height.into(), - timeout_timestamp: value.timeout_timestamp, - data: value.data.to_vec(), - channel_order: Order::from_i32(channel.ordering) - .map_err(|_| Self::Error::Other("invalid channel order".to_owned())) - .unwrap() - .to_string(), - ack: acks_map.get(&value.sequence).cloned(), + .map(move |log| { + let value = RecvPacketFilter::decode_log(&log.clone().into()).unwrap(); + PacketInfo { + height: Some(log.block_number.unwrap().as_u64().into()), + source_port: value.source_port.clone(), + source_channel: value.source_channel.clone(), + destination_port: destination_port.clone(), + destination_channel: destination_channel.clone(), + sequence: value.sequence, + timeout_height: value.timeout_height.into(), + timeout_timestamp: value.timeout_timestamp, + data: value.data.to_vec(), + channel_order: Order::from_i32(channel.ordering) + .map_err(|_| Self::Error::Other("invalid channel order".to_owned())) + .unwrap() + .to_string(), + ack: acks_map.get(&value.sequence).cloned(), + } }) .collect()) } @@ -1123,7 +1202,24 @@ impl IbcProvider for EthereumClient { &self, asset_id: Self::AssetId, ) -> Result, Self::Error> { - todo!() + let balance = self + .yui + .bank + .as_ref() + .expect("bank is none") + .method::<_, U256>( + "balanceOf", + (H160::from_str(&self.account_id().to_string()).unwrap(), asset_id.clone()), + )? + .call() + .await?; + Ok(vec![PrefixedCoin { + denom: PrefixedDenom { + trace_path: TracePath::default(), + base_denom: BaseDenom::from_str(&asset_id)?, + }, + amount: Amount::from(balance), + }]) } fn connection_prefix(&self) -> CommitmentPrefix { @@ -1132,27 +1228,32 @@ impl IbcProvider for EthereumClient { #[track_caller] fn client_id(&self) -> ClientId { - self.config.client_id.clone().expect("no client id set") + self.client_id + .lock() + .unwrap() + .as_ref() + .expect("Client Id should be defined") + .clone() } fn set_client_id(&mut self, client_id: ClientId) { - self.config.client_id = Some(client_id); + *self.client_id.lock().unwrap() = Some(client_id); } fn connection_id(&self) -> Option { - self.config.connection_id.clone() + self.connection_id.lock().unwrap().clone() } fn set_channel_whitelist(&mut self, channel_whitelist: HashSet<(ChannelId, PortId)>) { - self.config.channel_whitelist = channel_whitelist.into_iter().collect(); + *self.channel_whitelist.lock().unwrap() = channel_whitelist; } fn add_channel_to_whitelist(&mut self, channel: (ChannelId, PortId)) { - self.config.channel_whitelist.push(channel) + self.channel_whitelist.lock().unwrap().insert(channel); } fn set_connection_id(&mut self, connection_id: ConnectionId) { - self.config.connection_id = Some(connection_id); + *self.connection_id.lock().unwrap() = Some(connection_id); } fn client_type(&self) -> ClientType { @@ -1173,14 +1274,16 @@ impl IbcProvider for EthereumClient { // TODO: query_clients (ethereum) async fn query_clients(&self) -> Result, Self::Error> { Ok(vec![]) + // Ok(vec![ClientId::new("07-tendermint", 0).unwrap()]) } async fn query_channels(&self) -> Result, Self::Error> { - let ids = self.generated_channel_identifiers(0.into()).await?; - dbg!(&ids); - ids.into_iter() - .map(|id| Ok((id.1.parse().unwrap(), id.0.parse().unwrap()))) - .collect() + // let ids = self.generated_channel_identifiers(0.into()).await?; + // dbg!(&ids); + // ids.into_iter() + // .map(|id| Ok((id.1.parse().unwrap(), id.0.parse().unwrap()))) + // .collect() + Ok(vec![]) } async fn query_connection_using_client( @@ -1203,31 +1306,28 @@ impl IbcProvider for EthereumClient { &self, ) -> Result<(AnyClientState, AnyConsensusState), Self::Error> { let sync_committee_prover = self.prover(); - let block_id = "finalized"; + let block_id = "head"; let block_header = sync_committee_prover.fetch_header(&block_id).await.unwrap(); - let state = sync_committee_prover - .fetch_beacon_state(&block_header.slot.to_string()) - .await - .unwrap(); + let state = sync_committee_prover.fetch_beacon_state(block_id).await.unwrap(); // TODO: query `at` block - let finality_checkpoint = sync_committee_prover.fetch_finalized_checkpoint().await.unwrap(); - - log::info!(target: "hyperspace_ethereum", "{:?}, {}", state.clone().finalized_checkpoint.clone(), state.slot.clone()); - log::info!(target: "hyperspace_ethereum", "{:?}, {}", state.clone().hash_tree_root(), block_header.slot); - log::info!(target: "hyperspace_ethereum", "Using init epoch: {}, also have {}", finality_checkpoint.finalized.epoch, state.finalized_checkpoint.epoch); + // let finality_checkpoint = + // sync_committee_prover.fetch_finalized_checkpoint().await.unwrap(); + let epoch = state.current_justified_checkpoint.epoch; let client_state = LightClientState { finalized_header: block_header.clone(), - latest_finalized_epoch: finality_checkpoint.finalized.epoch, // TODO: ???? + latest_finalized_epoch: epoch, // TODO: ???? + // latest_finalized_epoch: finality_checkpoint.finalized.epoch, // TODO: ???? current_sync_committee: state.current_sync_committee, next_sync_committee: state.next_sync_committee, }; + let execution_header = state.latest_execution_payload_header; let block = self .client() - .get_block(BlockId::Number(BlockNumber::Number(dbg!(block_header.slot).into()))) + .get_block(BlockId::Number(BlockNumber::Number(execution_header.block_number.into()))) .await .unwrap() .unwrap(); @@ -1238,22 +1338,25 @@ impl IbcProvider for EthereumClient { dbg!(&state.block_roots.iter().take(10).collect::>()); dbg!(&block_header.state_root); dbg!(&block_header.body_root); + log::info!(target: "hyperspace_ethereum", "Using init epoch: {epoch}, and height: {}", execution_header.block_number); let client_state = AnyClientState::Ethereum(ClientState { inner: client_state, frozen_height: None, - latest_height: state.latest_execution_payload_header.block_number as _, + latest_height: execution_header.block_number as _, // latest_height: block_header.slot as _ _phantom: Default::default(), }); let consensus_state = AnyConsensusState::Ethereum(ConsensusState { timestamp: tendermint::time::Time::from_unix_timestamp( - block.timestamp.as_u64() as i64, + execution_header.timestamp as i64, + // block.timestamp.as_u64() as i64, 0, ) .unwrap(), - root: CommitmentRoot { bytes: block.state_root.0.to_vec() }, + root: CommitmentRoot { bytes: execution_header.state_root.to_vec() }, + // root: CommitmentRoot { bytes: block.state_root.0.to_vec() }, }); Ok((client_state, consensus_state)) diff --git a/hyperspace/ethereum/src/key_provider.rs b/hyperspace/ethereum/src/key_provider.rs index e9b558c61..8a823e2fa 100644 --- a/hyperspace/ethereum/src/key_provider.rs +++ b/hyperspace/ethereum/src/key_provider.rs @@ -6,6 +6,6 @@ use crate::client::EthereumClient; impl KeyProvider for EthereumClient { fn account_id(&self) -> pallet_ibc::Signer { // TODO: - pallet_ibc::Signer::from_str(&self.config.name).unwrap() + pallet_ibc::Signer::from_str("0x73db010c3275EB7a92E5C38770316248f4C644ee").unwrap() } } diff --git a/hyperspace/ethereum/src/mock/utils.rs b/hyperspace/ethereum/src/mock/utils.rs index 41fff8a36..968ffa11a 100644 --- a/hyperspace/ethereum/src/mock/utils.rs +++ b/hyperspace/ethereum/src/mock/utils.rs @@ -119,7 +119,7 @@ pub fn compile_solc(project_paths: ProjectPathsConfig) -> ProjectCompileOutput { metadata: None, output_selection: selection, evm_version: Some(EvmVersion::Paris), - via_ir: Some(false), + via_ir: Some(true), // TODO: this flag is unstable // debug: Some(DebuggingSettings { // revert_strings: Some(RevertStrings::Debug), // debug_info: vec!["location".to_string()], @@ -387,6 +387,7 @@ where deployed_facets, storage_layout, tendermint: tendermint_client, + bank: None, } } diff --git a/hyperspace/ethereum/src/prove.rs b/hyperspace/ethereum/src/prove.rs index 324e17bf4..f3df95e94 100644 --- a/hyperspace/ethereum/src/prove.rs +++ b/hyperspace/ethereum/src/prove.rs @@ -9,14 +9,18 @@ use ethereum_consensus::{ state_transition::Context, }; use ethers::prelude::{EthCall, H256}; +use icsxx_ethereum::client_state::ClientState; +use pallet_ibc::light_clients::HostFunctionsManager; +use primitives::mock::LocalClientTypes; use ssz_rs::{ calculate_multi_merkle_root, is_valid_merkle_branch, GeneralizedIndex, Merkleized, Node, }; use std::time::Duration; use sync_committee_primitives::{ types::{ - AncestorBlock, FinalityProof, LightClientState, LightClientUpdate, SyncCommitteeUpdate, - DOMAIN_SYNC_COMMITTEE, GENESIS_VALIDATORS_ROOT, + AncestorBlock, AncestryProof, BlockRootsProof, ExecutionPayloadProof, FinalityProof, + LightClientState, LightClientUpdate, SyncCommitteeUpdate, DOMAIN_SYNC_COMMITTEE, + GENESIS_VALIDATORS_ROOT, }, util::{compute_fork_version, compute_sync_committee_period_at_slot}, }; @@ -30,27 +34,14 @@ use tokio::time; pub async fn prove( client: &EthereumClient, + eth_client_state: &ClientState, block_number: u64, ) -> Result, ClientError> { - log::info!(target: "hyperspace_ethereum", "Proving {block_number} {}", line!()); let sync_committee_prover = client.prover(); + let client_state = ð_client_state.inner; let block_id = format!("{block_number:?}"); - // let block_id = "head"; - log::info!(target: "hyperspace_ethereum", "Proving {}", line!()); - - let block_header = sync_committee_prover.fetch_header(&block_id).await?; - log::info!(target: "hyperspace_ethereum", "Proving {}", line!()); - - let state = sync_committee_prover.fetch_beacon_state(&block_header.slot.to_string()).await?; - - let mut client_state = LightClientState { - finalized_header: block_header.clone(), - latest_finalized_epoch: 0, - current_sync_committee: state.current_sync_committee, - next_sync_committee: state.next_sync_committee, - }; - log::info!(target: "hyperspace_ethereum", "Proving {}", line!()); + let block_id = "head"; let finality_checkpoint = sync_committee_prover.fetch_finalized_checkpoint().await?; if finality_checkpoint.finalized.root == Node::default() || @@ -58,7 +49,7 @@ pub async fn prove( finality_checkpoint.finalized.root == client_state.finalized_header.clone().hash_tree_root()? { - panic!("No new finalized checkpoint found") + return Err(ClientError::Other("No new finalized checkpoint found".into())) } log::debug!(target: "hyperspace_ethereum", "A new epoch has been finalized {}", finality_checkpoint.finalized.epoch); @@ -83,7 +74,7 @@ pub async fn prove( // the attested block from four possible epochs. let mut attested_epoch_loop_count = 0; let (attested_block_header, signature_block) = loop { - if attested_epoch_loop_count == 4 { + if attested_epoch_loop_count >= 4 { panic!("Could not fetch any block from the attested epoch after going through four epochs, your Eth devnet is fucked") } // If we have maxed out the slots in the current epoch and still didn't find any block, @@ -233,3 +224,69 @@ pub async fn prove( // ); Ok(light_client_update) } + +pub async fn prove_fast( + client: &EthereumClient, + eth_client_state: &ClientState, + block_number: u64, +) -> Result, ClientError> { + let sync_committee_prover = client.prover(); + + let block_id = format!("{block_number:?}"); + // let block_id = "head"; + + let client_state = ð_client_state.inner; + // let block_id = "head"; + + let block_header = sync_committee_prover.fetch_header(&block_id).await?; + + let block = sync_committee_prover.fetch_block(&block_header.slot.to_string()).await?; + let state = sync_committee_prover.fetch_beacon_state(&block_header.slot.to_string()).await?; + + let mut ancestor_blocks = vec![]; + for i in (client_state.finalized_header.slot + 1)..block_header.slot { + if let Ok(ancestor_header) = + sync_committee_prover.fetch_header(i.to_string().as_str()).await + { + // let ancestry_proof = + // prove_block_roots_proof(finalized_state.clone(), ancestor_header.clone())?; + let header_state = + sync_committee_prover.fetch_beacon_state(i.to_string().as_str()).await?; + let execution_payload_proof = prove_execution_payload(header_state)?; + ancestor_blocks.push(AncestorBlock { + header: ancestor_header, + execution_payload: execution_payload_proof, + ancestry_proof: AncestryProof::BlockRoots { + block_roots_proof: BlockRootsProof { + block_header_index: 0, + block_header_branch: vec![], + }, + block_roots_branch: vec![], + }, + }) + } + } + + let ep = block.body.execution_payload; + let execution_payload_proof = ExecutionPayloadProof { + state_root: ep.state_root, + block_number: ep.block_number, + multi_proof: vec![], + execution_payload_branch: vec![], + timestamp: ep.timestamp, + }; + let mut light_client_update = LightClientUpdate { + attested_header: Default::default(), + sync_committee_update: Default::default(), + finalized_header: Default::default(), + execution_payload: execution_payload_proof, + finality_proof: Default::default(), + sync_aggregate: Default::default(), + signature_slot: Default::default(), + ancestor_blocks, + }; + light_client_update.attested_header.slot = block_header.slot; + light_client_update.finalized_header.slot = block_header.slot; + + Ok(light_client_update) +} diff --git a/hyperspace/ethereum/src/utils.rs b/hyperspace/ethereum/src/utils.rs index 755d82377..509ba06ef 100644 --- a/hyperspace/ethereum/src/utils.rs +++ b/hyperspace/ethereum/src/utils.rs @@ -2,12 +2,14 @@ use crate::contract::UnwrapContractError; use ethers::{ abi::{AbiError, Address, Detokenize, EventExt, Function, FunctionExt, Token, Tokenize}, contract::{ContractInstance, FunctionCall}, + core::types::Bytes, prelude::{ EthEvent, Event, Filter, Http, LocalWallet, Middleware, Provider, TransactionReceipt, H256, }, }; use ethers_solc::artifacts::{Storage, StorageLayout}; use ibc::core::ics04_channel::packet::Packet; +use std::iter; pub type ProviderImpl = ethers::prelude::SignerMiddleware, LocalWallet>; @@ -50,6 +52,7 @@ pub struct DeployYuiIbc { pub diamond: ContractInstance, pub storage_layout: StorageLayout, pub tendermint: ContractInstance, + pub bank: Option>, } impl DeployYuiIbc @@ -241,6 +244,11 @@ where (client_id, (receipt.block_hash.unwrap(), receipt.transaction_hash)) } + pub async fn create_client_calldata(&self, msg: Token) -> Bytes { + let method = self.method::<_, String>("createClient", (msg,)).unwrap(); + method.calldata().unwrap() + } + pub async fn update_client(&self, msg: Token) { let method = self.method::<_, ()>("updateClient", (msg,)).unwrap(); @@ -252,6 +260,11 @@ where assert_eq!(receipt.status, Some(1.into())); } + pub async fn update_client_calldata(&self, msg: Token) -> Bytes { + let method = self.method::<_, ()>("updateClient", (msg,)).unwrap(); + method.calldata().unwrap() + } + pub async fn connection_open_ack(&self, msg: Token) { let method = self.method::<_, ()>("connectionOpenAck", (msg,)).unwrap(); @@ -263,6 +276,11 @@ where assert_eq!(receipt.status, Some(1.into())); } + pub async fn connection_open_ack_calldata(&self, msg: Token) -> Bytes { + let method = self.method::<_, ()>("connectionOpenAck", (msg,)).unwrap(); + method.calldata().unwrap() + } + pub async fn connection_open_try(&self, msg: Token) -> String { let method = self.method::<_, String>("connectionOpenTry", (msg,)).unwrap(); @@ -275,6 +293,11 @@ where id } + pub async fn connection_open_try_calldata(&self, msg: Token) -> Bytes { + let method = self.method::<_, String>("connectionOpenTry", (msg,)).unwrap(); + method.calldata().unwrap() + } + pub async fn connection_open_init(&self, msg: Token) -> (String, (H256, H256)) { let method = self.method::<_, String>("connectionOpenInit", (msg,)).unwrap(); @@ -288,6 +311,11 @@ where (id, tx_id) } + pub async fn connection_open_init_calldata(&self, msg: Token) -> Bytes { + let method = self.method::<_, String>("connectionOpenInit", (msg,)).unwrap(); + method.calldata().unwrap() + } + pub async fn connection_open_confirm(&self, msg: Token) { let method = self.method::<_, ()>("connectionOpenConfirm", (msg,)).unwrap(); @@ -299,6 +327,11 @@ where assert_eq!(receipt.status, Some(1.into())); } + pub async fn connection_open_confirm_calldata(&self, msg: Token) -> Bytes { + let method = self.method::<_, ()>("connectionOpenConfirm", (msg,)).unwrap(); + method.calldata().unwrap() + } + pub async fn channel_open_init(&self, msg: Token) -> (String, (H256, H256)) { let method = self.method::<_, String>("channelOpenInit", (msg,)).unwrap(); @@ -313,6 +346,11 @@ where (connection_id, tx_id) } + pub async fn channel_open_init_calldata(&self, msg: Token) -> Bytes { + let method = self.method::<_, String>("channelOpenInit", (msg,)).unwrap(); + method.calldata().unwrap() + } + pub async fn channel_open_try(&self, msg: Token) -> String { let method = self.method::<_, String>("channelOpenTry", (msg,)).unwrap(); @@ -325,6 +363,11 @@ where connection_id } + pub async fn channel_open_try_calldata(&self, msg: Token) -> Bytes { + let method = self.method::<_, String>("channelOpenTry", (msg,)).unwrap(); + method.calldata().unwrap() + } + pub async fn send_and_get_tuple(&self, msg: Token, method_name: impl AsRef) -> () { let method = self.method::<_, ()>(method_name.as_ref(), (msg,)).unwrap(); @@ -337,9 +380,18 @@ where ret } + pub async fn send_and_get_tuple_calldata( + &self, + msg: Token, + method_name: impl AsRef, + ) -> Bytes { + let method = self.method::<_, ()>(method_name.as_ref(), (msg,)).unwrap(); + method.calldata().unwrap() + } + pub fn function(&self, name: &str) -> ethers::abi::Result<&Function> { let mut func = None; - for faucet in &self.deployed_facets { + for faucet in self.deployed_facets.iter().chain(iter::once(&self.diamond)) { if let Ok(f) = faucet.abi().function(name) { log::info!(target: "hyperspace_ethereum", "found function: {name}, {}, {}, {}", f.signature(), f.abi_signature(), hex::encode(&f.short_signature())); if func.is_some() { @@ -440,6 +492,7 @@ where diamond: self.diamond.clone(), storage_layout: self.storage_layout.clone(), tendermint: self.tendermint.clone(), + bank: self.bank.clone(), } } } diff --git a/hyperspace/ethereum/src/yui_types/ics04_channel/mod.rs b/hyperspace/ethereum/src/yui_types/ics04_channel/mod.rs index df05b2f21..f10b15e03 100644 --- a/hyperspace/ethereum/src/yui_types/ics04_channel/mod.rs +++ b/hyperspace/ethereum/src/yui_types/ics04_channel/mod.rs @@ -1,174 +1,169 @@ use ethers::abi::Token; -use ibc::core::{ics04_channel::{channel::{State, Order, Counterparty, ChannelEnd}, Version, msgs::{chan_open_init::MsgChannelOpenInit, chan_open_try::MsgChannelOpenTry, chan_open_ack::MsgChannelOpenAck, chan_open_confirm::MsgChannelOpenConfirm, chan_close_init::MsgChannelCloseInit, chan_close_confirm::MsgChannelCloseConfirm, recv_packet::MsgRecvPacket, acknowledgement::MsgAcknowledgement}, packet::Packet}, ics24_host::identifier::{ChannelId, PortId}}; - +use ibc::core::{ + ics04_channel::{ + channel::{ChannelEnd, Counterparty, Order, State}, + msgs::{ + acknowledgement::MsgAcknowledgement, chan_close_confirm::MsgChannelCloseConfirm, + chan_close_init::MsgChannelCloseInit, chan_open_ack::MsgChannelOpenAck, + chan_open_confirm::MsgChannelOpenConfirm, chan_open_init::MsgChannelOpenInit, + chan_open_try::MsgChannelOpenTry, recv_packet::MsgRecvPacket, + }, + packet::Packet, + Version, + }, + ics24_host::identifier::{ChannelId, PortId}, +}; use super::IntoToken; -impl IntoToken for State{ - fn into_token(self) -> Token { - match self { - State::Init => Token::Uint(1.into()), - State::TryOpen => Token::Uint(2.into()), - State::Open => Token::Uint(3.into()), - State::Closed => Token::Uint(4.into()), - } - } -} - -impl IntoToken for Order{ - fn into_token(self) -> Token { - match self { - Order::Unordered => Token::Uint(0.into()), - Order::Ordered => Token::Uint(1.into()), - } - } -} - -impl IntoToken for Counterparty{ - fn into_token(self) -> Token { - let channel_id = match &self.channel_id { - Some(channel_id) => channel_id.to_string(), - None => String::new(), - }; - Token::Tuple(vec![ - self.port_id.as_str().into_token(), - channel_id.into_token(), - ]) - } -} - -impl IntoToken for PortId{ - fn into_token(self) -> Token { - Token::String(self.to_string()) - } -} - -impl IntoToken for Version{ - fn into_token(self) -> Token { - Token::String(self.to_string()) - } -} - -impl IntoToken for ChannelEnd{ - fn into_token(self) -> Token { - Token::Tuple(vec![ - self.state.into_token(), - self.ordering.into_token(), - self.remote.into_token(), - Token::Array(self.connection_hops.into_iter().map(IntoToken::into_token).collect()), - self.version.into_token(), - ]) - } -} - -impl IntoToken for ChannelId{ - fn into_token(self) -> Token { - Token::String(self.to_string()) - } -} - -impl IntoToken for MsgChannelOpenInit{ - fn into_token(self) -> Token { - Token::Tuple(vec![ - self.port_id.into_token(), - self.channel.into_token(), - ]) - } -} - -impl IntoToken for MsgChannelOpenTry{ - fn into_token(self) -> Token { - Token::Tuple(vec![ - self.port_id.into_token(), - self.channel.into_token(), - self.counterparty_version.to_string().into_token(), - self.proofs.object_proof().as_bytes().into_token(), - self.proofs.height().into_token() - ]) - } -} -impl IntoToken for MsgChannelOpenAck{ - fn into_token(self) -> Token { - Token::Tuple(vec![ - self.port_id.into_token(), - self.channel_id.into_token(), - self.counterparty_version.to_string().into_token(), - self.counterparty_channel_id.into_token(), - self.proofs.object_proof().as_bytes().into_token(), - self.proofs.height().into_token() - ]) - } -} - -impl IntoToken for MsgChannelOpenConfirm{ - fn into_token(self) -> Token { - Token::Tuple(vec![ - self.port_id.into_token(), - self.channel_id.into_token(), - self.proofs.object_proof().as_bytes().into_token(), - self.proofs.height().into_token() - ]) - } -} - -impl IntoToken for MsgChannelCloseInit{ - fn into_token(self) -> Token { - Token::Tuple(vec![ - self.port_id.into_token(), - self.channel_id.into_token(), - ]) - } -} - -impl IntoToken for MsgChannelCloseConfirm{ - fn into_token(self) -> Token { - Token::Tuple(vec![ - self.port_id.into_token(), - self.channel_id.into_token(), - self.proofs.object_proof().as_bytes().into_token(), - self.proofs.height().into_token() - ]) - } -} - -impl IntoToken for Packet{ - fn into_token(self) -> Token { - Token::Tuple(vec![ - Token::Uint(self.sequence.0.into()), - self.source_port.into_token(), - self.source_channel.into_token(), - self.destination_port.into_token(), - self.destination_channel.into_token(), - self.data.into_token(), - self.timeout_height.into_token(), - Token::Uint(self.timeout_timestamp.as_nanoseconds().into()), - ]) - } -} -impl IntoToken for MsgAcknowledgement{ - fn into_token(self) -> Token { - Token::Tuple(vec![ - //packet - self.packet.into_token(), - //acknowledgement - self.acknowledgement.into_bytes().into_token(), - //proof - self.proofs.object_proof().as_bytes().into_token(), - //proofHeight - self.proofs.height().into_token() - ]) - } -} - -impl IntoToken for MsgRecvPacket{ - fn into_token(self) -> Token { - Token::Tuple(vec![ - //packet - self.packet.into_token(), - //proof - self.proofs.object_proof().as_bytes().into_token(), - //proofHeight - self.proofs.height().into_token() - ]) - } +impl IntoToken for State { + fn into_token(self) -> Token { + Token::Uint((self as i32).into()) + } +} + +impl IntoToken for Order { + fn into_token(self) -> Token { + Token::Uint((self as i32).into()) + } +} + +impl IntoToken for Counterparty { + fn into_token(self) -> Token { + let channel_id = match &self.channel_id { + Some(channel_id) => channel_id.to_string(), + None => String::new(), + }; + Token::Tuple(vec![self.port_id.as_str().into_token(), channel_id.into_token()]) + } +} + +impl IntoToken for PortId { + fn into_token(self) -> Token { + Token::String(self.to_string()) + } +} + +impl IntoToken for Version { + fn into_token(self) -> Token { + Token::String(self.to_string()) + } +} + +impl IntoToken for ChannelEnd { + fn into_token(self) -> Token { + Token::Tuple(vec![ + self.state.into_token(), + self.ordering.into_token(), + self.remote.into_token(), + Token::Array(self.connection_hops.into_iter().map(IntoToken::into_token).collect()), + self.version.into_token(), + ]) + } +} + +impl IntoToken for ChannelId { + fn into_token(self) -> Token { + Token::String(self.to_string()) + } +} + +impl IntoToken for MsgChannelOpenInit { + fn into_token(self) -> Token { + Token::Tuple(vec![self.port_id.into_token(), self.channel.into_token()]) + } +} + +impl IntoToken for MsgChannelOpenTry { + fn into_token(self) -> Token { + Token::Tuple(vec![ + self.port_id.into_token(), + self.channel.into_token(), + self.counterparty_version.to_string().into_token(), + self.proofs.object_proof().as_bytes().into_token(), + self.proofs.height().into_token(), + ]) + } +} +impl IntoToken for MsgChannelOpenAck { + fn into_token(self) -> Token { + Token::Tuple(vec![ + self.port_id.into_token(), + self.channel_id.into_token(), + self.counterparty_version.to_string().into_token(), + self.counterparty_channel_id.into_token(), + self.proofs.object_proof().as_bytes().into_token(), + self.proofs.height().into_token(), + ]) + } +} + +impl IntoToken for MsgChannelOpenConfirm { + fn into_token(self) -> Token { + Token::Tuple(vec![ + self.port_id.into_token(), + self.channel_id.into_token(), + self.proofs.object_proof().as_bytes().into_token(), + self.proofs.height().into_token(), + ]) + } +} + +impl IntoToken for MsgChannelCloseInit { + fn into_token(self) -> Token { + Token::Tuple(vec![self.port_id.into_token(), self.channel_id.into_token()]) + } +} + +impl IntoToken for MsgChannelCloseConfirm { + fn into_token(self) -> Token { + Token::Tuple(vec![ + self.port_id.into_token(), + self.channel_id.into_token(), + self.proofs.object_proof().as_bytes().into_token(), + self.proofs.height().into_token(), + ]) + } +} + +impl IntoToken for Packet { + fn into_token(self) -> Token { + Token::Tuple(vec![ + Token::Uint(self.sequence.0.into()), + self.source_port.into_token(), + self.source_channel.into_token(), + self.destination_port.into_token(), + self.destination_channel.into_token(), + self.data.into_token(), + self.timeout_height.into_token(), + Token::Uint(self.timeout_timestamp.as_nanoseconds().into()), + ]) + } +} +impl IntoToken for MsgAcknowledgement { + fn into_token(self) -> Token { + Token::Tuple(vec![ + //packet + self.packet.into_token(), + //acknowledgement + self.acknowledgement.into_bytes().into_token(), + //proof + self.proofs.object_proof().as_bytes().into_token(), + //proofHeight + self.proofs.height().into_token(), + ]) + } +} + +impl IntoToken for MsgRecvPacket { + fn into_token(self) -> Token { + Token::Tuple(vec![ + //packet + self.packet.into_token(), + //proof + self.proofs.object_proof().as_bytes().into_token(), + //proofHeight + self.proofs.height().into_token(), + ]) + } } diff --git a/hyperspace/ethereum/tests/sanity_checks.rs b/hyperspace/ethereum/tests/sanity_checks.rs index 2196c0120..d7df26651 100644 --- a/hyperspace/ethereum/tests/sanity_checks.rs +++ b/hyperspace/ethereum/tests/sanity_checks.rs @@ -358,7 +358,7 @@ async fn test_deploy_yui_ibc_and_create_eth_client() { trusted_validator_set: tendermint::validator::Set::new(set, None), }; let msg = MsgUpdateAnyClient:: { - client_id: hyperspace.config.clone().client_id.unwrap(), + client_id: hyperspace.client_id(), client_message: pallet_ibc::light_clients::AnyClientMessage::Tendermint( ics07_tendermint::client_message::ClientMessage::Header(header.clone()), ), diff --git a/hyperspace/testsuite/src/lib.rs b/hyperspace/testsuite/src/lib.rs index 6c42e337f..95f040141 100644 --- a/hyperspace/testsuite/src/lib.rs +++ b/hyperspace/testsuite/src/lib.rs @@ -15,7 +15,7 @@ #![allow(clippy::all)] use crate::utils::assert_timeout_packet; -use futures::{future, StreamExt}; +use futures::{future, StreamExt, TryFutureExt}; use hyperspace_core::send_packet_relay::set_relay_status; use hyperspace_primitives::{ utils::{create_channel, create_connection, timeout_after, timeout_future}, @@ -37,7 +37,7 @@ use ibc_proto::google::protobuf::Any; use pallet_ibc::Timeout; use std::{str::FromStr, time::Duration}; use tendermint_proto::Protobuf; -use tokio::task::JoinHandle; +use tokio::{task::JoinHandle, time::sleep}; pub mod misbehaviour; pub mod ordered_channels; @@ -181,7 +181,7 @@ where } } else { // Default to 200 blocks and 1 hour offset respectively - (200, 60 * 60) + (20000, 60 * 60) }; let (mut timeout_height, timestamp) = chain_b @@ -190,6 +190,7 @@ where .expect("Couldn't fetch latest_height_and_timestamp"); timeout_height.revision_height += height_offset; + log::info!("Chosen timeout_height to: {}", timeout_height.revision_height); let timeout_timestamp = (timestamp + Duration::from_secs(time_offset)).expect("Overflow evaluating timeout"); @@ -218,19 +219,22 @@ async fn assert_send_transfer( A::FinalityEvent: Send + Sync, { // wait for the acknowledgment - let future = chain - .ibc_events() - .await - .skip_while(|ev| future::ready(!matches!(ev, IbcEvent::AcknowledgePacket(_)))) - .take(1) - .collect::>(); - timeout_after( - chain, - future, - wait_blocks, - format!("Didn't see AcknowledgePacket on {}", chain.name()), - ) - .await; + // let future = chain + // .ibc_events() + // .await + // .skip_while(|ev| future::ready(!matches!(ev, IbcEvent::AcknowledgePacket(_)))) + // .take(1) + // .collect::>(); + // timeout_after( + // chain, + // future, + // wait_blocks, + // format!("Didn't see AcknowledgePacket on {}", chain.name()), + // ) + // .await; + for i in 0..(60 * 5 / 15) { + sleep(Duration::from_secs(15)).await; + } let balance = chain .query_ibc_balance(asset_id) @@ -372,10 +376,10 @@ async fn send_packet_with_connection_delay( let (previous_balance, ..) = send_transfer(chain_a, chain_b, asset_a.clone(), channel_id_a, None).await; assert_send_transfer(chain_a, asset_a, previous_balance, 120).await; - log::info!(target: "hyperspace", "Sending transfer from {}", chain_b.name()); - let (previous_balance, ..) = - send_transfer(chain_b, chain_a, asset_b.clone(), channel_id_b, None).await; - assert_send_transfer(chain_b, asset_b, previous_balance, 120).await; + // log::info!(target: "hyperspace", "Sending transfer from {}", chain_b.name()); + // let (previous_balance, ..) = + // send_transfer(chain_b, chain_a, asset_b.clone(), channel_id_b, None).await; + // assert_send_transfer(chain_b, asset_b, previous_balance, 120).await; // now send from chain b. log::info!(target: "hyperspace", "🚀🚀 Token Transfer successful with connection delay"); } @@ -560,11 +564,22 @@ pub async fn ibc_messaging_with_connection_delay( let handle = tokio::task::spawn(async move { hyperspace_core::relay(client_a_clone, client_b_clone, None, None, None) .await + .map_err(|e| { + log::error!(target: "hyperspace", "Relayer loop failed: {:?}", e); + e + }) .unwrap() }); + tokio::task::spawn(async move { + let x = handle + .map_err(|e| { + log::error!(target: "hyperspace", "Relayer loop failed: {:?}", e); + e + }) + .await; + }); send_packet_with_connection_delay(chain_a, chain_b, channel_a, channel_b, asset_a, asset_b) .await; - handle.abort() } /// diff --git a/hyperspace/testsuite/tests/ethereum_cosmos.rs b/hyperspace/testsuite/tests/ethereum_cosmos.rs index 1a9134424..852540839 100644 --- a/hyperspace/testsuite/tests/ethereum_cosmos.rs +++ b/hyperspace/testsuite/tests/ethereum_cosmos.rs @@ -40,9 +40,10 @@ use hyperspace_testsuite::{ ibc_messaging_with_connection_delay, misbehaviour::ibc_messaging_submit_misbehaviour, setup_connection_and_channel, }; -use ibc::core::ics24_host::identifier::PortId; +use ibc::core::ics24_host::identifier::{ClientId, PortId}; use sp_core::hashing::sha2_256; -use std::{path::PathBuf, sync::Arc}; +use std::{future::Future, path::PathBuf, str::FromStr, sync::Arc}; +use subxt::utils::H160; #[derive(Debug, Clone)] pub struct Args { @@ -132,19 +133,71 @@ pub async fn deploy_yui_ibc_and_tendermint_client_fixture() -> DeployYuiIbcTende } } +#[track_caller] +fn deploy_transfer_module_fixture( + deploy: &DeployYuiIbcTendermintClient, +) -> impl Future, ProviderImpl>> + '_ { + async move { + let path = utils::yui_ibc_solidity_path(); + let project_output = utils::compile_yui(&path, "contracts/apps/20-transfer"); + + let artifact = + project_output.find_first("ICS20Bank").expect("no ICS20Bank in project output"); + let bank_contract = utils::deploy_contract(artifact, (), deploy.client.clone()).await; + println!("Bank module address: {:?}", bank_contract.address()); + let artifact = project_output + .find_first("ICS20TransferBank") + .expect("no ICS20TransferBank in project output"); + let constructor_args = ( + Token::Address(deploy.yui_ibc.diamond.address()), + Token::Address(bank_contract.address()), + ); + let module_contract = + utils::deploy_contract(artifact, constructor_args, deploy.client.clone()).await; + module_contract + } +} + async fn setup_clients() -> (AnyChain, AnyChain) { log::info!(target: "hyperspace", "=========================== Starting Test ==========================="); let args = Args::default(); // Create client configurations - let DeployYuiIbcTendermintClient { anvil, tendermint_client, ics20_module: _, yui_ibc, .. } = - deploy_yui_ibc_and_tendermint_client_fixture().await; + let deploy = deploy_yui_ibc_and_tendermint_client_fixture().await; + let bank = deploy_transfer_module_fixture(&deploy).await; + let DeployYuiIbcTendermintClient { + anvil, tendermint_client, ics20_module: _, mut yui_ibc, .. + } = deploy; + log::info!(target: "hyperspace", "Deployed diamond: {:?}, tendermint client: {:?}, bank: {:?}", yui_ibc.diamond.address(), tendermint_client.address(), bank.address()); + yui_ibc.bind_port("transfer", bank.address()).await; + yui_ibc.bank = Some(bank); + + // Overrides + // yui_ibc.diamond = ContractInstance::new( + // H160::from_str("0xf02f5476535c0eea1e501d2c155c1e1f3055e752").unwrap(), + // yui_ibc.diamond.abi().clone(), + // yui_ibc.diamond.client(), + // ); + // yui_ibc.tendermint = ContractInstance::new( + // H160::from_str("0x5d2d6b3fd375fd77dc627d1ae955c441ec157847").unwrap(), + // yui_ibc.tendermint.abi().clone(), + // yui_ibc.tendermint.client(), + // ); + // { + // let bank = yui_ibc.bank.as_mut().unwrap(); + // *bank = ContractInstance::new( + // H160::from_str("0xa4373e6da07ad62d43c3a74f5edb3d3aa6674c14").unwrap(), + // bank.abi().clone(), + // bank.client(), + // ); + // } //replace the tendermint client address in hyperspace config with a real one let diamond_address = yui_ibc.diamond.address(); + let tendermint_address = yui_ibc.tendermint.address(); let mut config_a = hyperspace_ethereum_client_fixture(&anvil, yui_ibc).await; - config_a.tendermint_client_address = tendermint_client.address(); + config_a.tendermint_client_address = tendermint_address; config_a.ibc_handler_address = diamond_address; let mut config_b = CosmosClientConfig { @@ -194,14 +247,18 @@ async fn setup_clients() -> (AnyChain, AnyChain) { let clients_on_a = chain_a_wrapped.query_clients().await.unwrap(); let clients_on_b = chain_b_wrapped.query_clients().await.unwrap(); - if !clients_on_a.is_empty() && !clients_on_b.is_empty() { - chain_a_wrapped.set_client_id(clients_on_b[0].clone()); - chain_b_wrapped.set_client_id(clients_on_a[0].clone()); - return (chain_a_wrapped, chain_b_wrapped) - } + // if !clients_on_a.is_empty() && !clients_on_b.is_empty() { + // chain_a_wrapped.set_client_id(clients_on_b.last().unwrap().clone()); + // chain_b_wrapped.set_client_id(clients_on_a.last().unwrap().clone()); + // return (chain_a_wrapped, chain_b_wrapped) + // } let (client_b, client_a) = create_clients(&mut chain_b_wrapped, &mut chain_a_wrapped).await.unwrap(); + // let (client_a, client_b): (ClientId, ClientId) = + // ("08-wasm-136".parse().unwrap(), "07-tendermint-0".parse().unwrap()); + + log::info!(target: "hyperspace", "Client A: {client_a:?} B: {client_b:?}"); chain_a_wrapped.set_client_id(client_a); chain_b_wrapped.set_client_id(client_b); (chain_a_wrapped, chain_b_wrapped) @@ -212,7 +269,7 @@ async fn setup_clients() -> (AnyChain, AnyChain) { async fn ethereum_to_cosmos_ibc_messaging_full_integration_test() { logging::setup_logging(); - let asset_id_a = AnyAssetId::Ethereum(()); + let asset_id_a = AnyAssetId::Ethereum("pica".to_string()); let asset_id_b = AnyAssetId::Cosmos( "ibc/47B97D8FF01DA03FCB2F4B1FFEC931645F254E21EF465FA95CBA6888CB964DC4".to_string(), ); @@ -221,6 +278,14 @@ async fn ethereum_to_cosmos_ibc_messaging_full_integration_test() { setup_connection_and_channel(&mut chain_a, &mut chain_b, Duration::from_secs(60 * 2)).await; handle.abort(); + // let connection_id_a = "connection-0".parse().unwrap(); + // let connection_id_b = "connection-35".parse().unwrap(); + // let channel_a = "channel-0".parse().unwrap(); + // let channel_b = "channel-10".parse().unwrap(); + + log::info!(target: "hyperspace", "Conn A: {connection_id_a:?} B: {connection_id_b:?}"); + log::info!(target: "hyperspace", "Chann A: {channel_a:?} B: {channel_b:?}"); + // Set connections and channel whitelist chain_a.set_connection_id(connection_id_a); chain_b.set_connection_id(connection_id_b); @@ -228,20 +293,19 @@ async fn ethereum_to_cosmos_ibc_messaging_full_integration_test() { chain_a.set_channel_whitelist(vec![(channel_a, PortId::transfer())].into_iter().collect()); chain_b.set_channel_whitelist(vec![(channel_b, PortId::transfer())].into_iter().collect()); - // // Run tests sequentially - // - // // no timeouts + connection delay - // - // ibc_messaging_with_connection_delay( - // &mut chain_a, - // &mut chain_b, - // asset_id_a.clone(), - // asset_id_b.clone(), - // channel_a, - // channel_b, - // ) - // .await; - // + // Run tests sequentially + + // no timeouts + connection delay + ibc_messaging_with_connection_delay( + &mut chain_a, + &mut chain_b, + asset_id_a.clone(), + asset_id_b.clone(), + channel_a, + channel_b, + ) + .await; + // // timeouts + connection delay // ibc_messaging_packet_height_timeout_with_connection_delay( // &mut chain_a, diff --git a/light-clients/icsxx-ethereum-cw/src/client.rs b/light-clients/icsxx-ethereum-cw/src/client.rs index 816879246..fe416d74d 100644 --- a/light-clients/icsxx-ethereum-cw/src/client.rs +++ b/light-clients/icsxx-ethereum-cw/src/client.rs @@ -91,7 +91,11 @@ where let client_states = ReadonlyClientStates::new(self.storage()); let data = client_states.get().ok_or_else(|| Error::client_not_found(client_id.clone()))?; let state = Self::decode_client_state(&data)?; - log!(self, "in client : [client_state] >> any client_state: {:?}", state); + log!( + self, + "in client : [client_state] >> any client_state: height {}", + state.latest_height() + ); Ok(state) } @@ -106,11 +110,11 @@ where let value = consensus_states .get(height) .ok_or_else(|| Error::consensus_state_not_found(client_id.clone(), height))?; - log!( - self, - "in client : [consensus_state] >> consensus_state (raw): {}", - hex::encode(&value) - ); + // log!( + // self, + // "in client : [consensus_state] >> consensus_state (raw): {}", + // hex::encode(&value) + // ); let any_consensus_state = Self::decode_consensus_state(&value)?; log!( self, @@ -205,8 +209,13 @@ where log!(self, "in client : [store_client_state]"); let client_states = ReadonlyClientStates::new(self.storage()); let data = client_states.get().ok_or_else(|| Error::client_not_found(client_id.clone()))?; + log!( + self, + "in cliden : [store_client_state] >> wasm client state, height {}", + client_state.latest_height() + ); let vec1 = Self::encode_client_state(client_state, data)?; - log!(self, "in cliden : [store_client_state] >> wasm client state (raw)"); + // log!(self, "in cliden : [store_client_state] >> wasm client state (raw)"); let mut client_state_storage = ClientStates::new(self.storage_mut()); client_state_storage.insert(vec1); Ok(()) From 3e388f9c6a7ea21ea5e6a1e4c5ca40a8dc6f0294 Mon Sep 17 00:00:00 2001 From: "rust.dev" <102041955+RustNinja@users.noreply.github.com> Date: Fri, 8 Sep 2023 15:59:15 +0100 Subject: [PATCH 20/43] return client error in eth relayer instead of palic or unwrap. (#48) --- hyperspace/ethereum/src/chain.rs | 124 +++++++++++++-------- hyperspace/ethereum/tests/sanity_checks.rs | 6 +- 2 files changed, 78 insertions(+), 52 deletions(-) diff --git a/hyperspace/ethereum/src/chain.rs b/hyperspace/ethereum/src/chain.rs index b3359a06e..496b544b6 100644 --- a/hyperspace/ethereum/src/chain.rs +++ b/hyperspace/ethereum/src/chain.rs @@ -327,7 +327,7 @@ fn consensus_state_from_abi_token(token: Token) -> Result Token { +fn tm_header_abi_token(header: &Header) -> Result { use ethers::abi::{encode as ethers_encode, Token as EthersToken}; let block_header = header.signed_header.header.clone(); let last_commit = header.signed_header.commit.clone(); @@ -335,6 +335,10 @@ fn tm_header_abi_token(header: &Header) -> Token { // TODO: convert to u128 (nanoseconds) let timestamp = Timestamp::from(block_header.time); + let last_block_id = block_header.last_block_id.ok_or(ClientError::Other( + "last_block_id not found".to_string(), + ))?; + let signed_header_header = EthersToken::Tuple( [ //version @@ -360,15 +364,15 @@ fn tm_header_abi_token(header: &Header) -> Token { // //last_block_id EthersToken::Tuple( [ - EthersToken::Bytes(block_header.last_block_id.unwrap().hash.into()), + EthersToken::Bytes(last_block_id.hash.into()), //part_set_header EthersToken::Tuple( [ EthersToken::Uint( - block_header.last_block_id.unwrap().part_set_header.total.into(), + last_block_id.part_set_header.total.into(), ), EthersToken::Bytes( - block_header.last_block_id.unwrap().part_set_header.hash.into(), + last_block_id.part_set_header.hash.into(), ), ] .to_vec(), @@ -377,9 +381,13 @@ fn tm_header_abi_token(header: &Header) -> Token { .to_vec(), ), //last_commit_hash - EthersToken::Bytes(block_header.last_commit_hash.unwrap().into()), + EthersToken::Bytes(block_header.last_commit_hash.ok_or(ClientError::Other( + "last_commit_hash not found".to_string(), + ))?.into()), //data_hash - EthersToken::Bytes(block_header.data_hash.unwrap().into()), + EthersToken::Bytes(block_header.data_hash.ok_or(ClientError::Other( + "data_hash not found".to_string(), + ))?.into()), //validators_hash EthersToken::Bytes(block_header.validators_hash.into()), //next_validators_hash @@ -389,9 +397,13 @@ fn tm_header_abi_token(header: &Header) -> Token { //app_hash EthersToken::Bytes(block_header.app_hash.into()), //last_results_hash - EthersToken::Bytes(block_header.last_results_hash.unwrap().into()), + EthersToken::Bytes(block_header.last_results_hash.ok_or(ClientError::Other( + "last_results_hash not found".to_string(), + ))?.into()), //evidence_hash - EthersToken::Bytes(block_header.evidence_hash.unwrap().into()), + EthersToken::Bytes(block_header.evidence_hash.ok_or(ClientError::Other( + "evidence_hash not found".to_string(), + ))?.into()), //proposer_address EthersToken::Bytes(block_header.proposer_address.into()), ] @@ -425,13 +437,15 @@ fn tm_header_abi_token(header: &Header) -> Token { .to_vec(), ); - EthersToken::Tuple( + let ret = EthersToken::Tuple( [ EthersToken::Tuple([signed_header_header, signed_header_commit].to_vec()), EthersToken::Int(header.trusted_height.revision_height.into()), ] .to_vec(), - ) + ); + Ok(ret) + } pub(crate) fn tm_header_from_abi_token(token: Token) -> Result { @@ -765,7 +779,7 @@ pub(crate) fn msg_connection_open_init_token(x: MsgConnectionOpenInit) -> Token pub fn msg_connection_open_ack_token( msg: MsgConnectionOpenAck, client_state: &EthereumClientState, -) -> Token { +) -> Result { use ethers::abi::{encode as ethers_encode, Token as EthersToken}; // let client_state = client_state_abi_token(&client_state); @@ -821,11 +835,15 @@ pub fn msg_connection_open_ack_token( [ //revisionNumber EthersToken::Uint( - msg.proofs.consensus_proof().unwrap().height().revision_number.into(), + msg.proofs.consensus_proof().ok_or( + ClientError::Other("consensus_proof not found".to_string()), + )?.height().revision_number.into(), ), //revisionHeight EthersToken::Uint( - msg.proofs.consensus_proof().unwrap().height().revision_number.into(), + msg.proofs.consensus_proof().ok_or( + ClientError::Other("consensus_proof not found".to_string()), + )?.height().revision_number.into(), ), ] .to_vec(), @@ -833,13 +851,13 @@ pub fn msg_connection_open_ack_token( ] .to_vec(), ); - consensus_state_data + Ok(consensus_state_data) } fn msg_connection_open_try_token( msg: MsgConnectionOpenTry, client_state: &ClientState, -) -> Token { +) -> Result { use ethers::abi::{encode as ethers_encode, Token as EthersToken}; let client_state = client_state_abi_token(&client_state); let client_state_data_vec = ethers_encode(&[client_state]); @@ -860,10 +878,12 @@ fn msg_connection_open_try_token( .consensus_proof() .map_or_else(Vec::new, |v| v.proof().clone().into()), proof_height: msg.proofs.height().into(), - consensus_height: msg.proofs.consensus_proof().unwrap().height().into(), + consensus_height: msg.proofs.consensus_proof().ok_or( + ClientError::Other("consensus_proof not found".to_string()), + )?.height().into(), }; let conn_open_try_token = conn_open_try.into_token(); - conn_open_try_token + Ok(conn_open_try_token) } fn msg_connection_open_confirm_token(msg: MsgConnectionOpenConfirm) -> Token { @@ -918,7 +938,7 @@ impl Chain for EthereumClient { // let ws = crate::client::WsEth::connect(self.ws_uri.to_string()) // .await // .map_err(|err| ClientError::ProviderError(self.ws_uri.clone(), err))?; - let ws = self.websocket_provider().await.unwrap(); + let ws = self.websocket_provider().await?; let stream = async_stream::stream! { // TODO: is it really finalized blocks stream? @@ -947,17 +967,17 @@ impl Chain for EthereumClient { for msg in messages { if msg.type_url == ibc::core::ics02_client::msgs::create_client::TYPE_URL { dbg!(&msg.value.len()); - let msg = MsgCreateAnyClient::::decode_vec(&msg.value).unwrap(); + let msg = MsgCreateAnyClient::::decode_vec(&msg.value).map_err(|_| ClientError::Other("create_client: unsupported client state".into()))?;; let AnyClientState::Tendermint(client_state) = msg.client_state.unpack_recursive() else { //TODO return error support only tendermint client state - panic!("unsupported client state") + return Err(ClientError::Other("create_client: unsupported client state".into())) }; let AnyConsensusState::Tendermint(client_consensus) = msg.consensus_state.unpack_recursive() else { //TODO return error support only tendermint consensus state - panic!("unsupported") + return Err(ClientError::Other("create_client: unsupported consensus state".into())) }; let client_state_abi_token = client_state_abi_token(client_state); let consensus_state_abi_token = consensus_state_abi_token(client_consensus); @@ -1004,24 +1024,30 @@ impl Chain for EthereumClient { let bytes = self.yui.create_client_calldata(token).await; //update mutex - let mut update_mutex = self.prev_state.lock().unwrap(); + let mut update_mutex = self.prev_state.lock().map_err(|_| { + ClientError::Other("create_client: can't lock prev_state mutex".into()) + })?; *update_mutex = (client_state_data_vec.clone(), consensus_state_data_vec.clone()); calls.push(bytes); } else if msg.type_url == ibc::core::ics02_client::msgs::update_client::TYPE_URL { - let msg = MsgUpdateAnyClient::::decode_vec(&msg.value).unwrap(); + let msg = MsgUpdateAnyClient::::decode_vec(&msg.value).map_err(|_| ClientError::Other("update_client: failed to decode_vec".into()))?;; let AnyClientMessage::Tendermint(client_state) = msg.client_message.unpack_recursive() else { - return Err(ClientError::Other(format!("unsupported client state 3"))) + return Err(ClientError::Other(format!("update_client: unsupported client_state. Should be AnyClientMessage::Tendermint"))) }; - let ClientMessage::Header(header) = client_state else { panic!("unsupported") }; + let ClientMessage::Header(header) = client_state else { + return Err(ClientError::Other("update_client: unsupported Client Message. Should be ClientMessage::Header".into())) + }; //get abi token to update client - let tm_header_abi_token = tm_header_abi_token(header); + let tm_header_abi_token = tm_header_abi_token(header)?; let tm_header_bytes = ethers_encode(&[tm_header_abi_token]); //todo replace empty vec for prev state clint with an actual client state - let client_state = self.prev_state.lock().unwrap().0.clone(); + let client_state = self.prev_state.lock().map_err(|_| { + ClientError::Other("update_client: can't lock prev_state mutex".into()) + })?.0.clone(); //TODO replace client id. it was genereated when we created the client. use 0 for // testing @@ -1039,88 +1065,87 @@ impl Chain for EthereumClient { calls.push(self.yui.update_client_calldata(token).await); } else if msg.type_url == ibc::core::ics03_connection::msgs::conn_open_init::TYPE_URL { - let msg = MsgConnectionOpenInit::decode_vec(&msg.value).unwrap(); + let msg = MsgConnectionOpenInit::decode_vec(&msg.value).map_err(|_| ClientError::Other("conn_open_init: failed to decode_vec".into()))?;; let token = msg_connection_open_init_token(msg); calls.push(self.yui.connection_open_init_calldata(token).await); } else if msg.type_url == ibc::core::ics03_connection::msgs::conn_open_ack::TYPE_URL { - let msg = MsgConnectionOpenAck::::decode_vec(&msg.value).unwrap(); + let msg = MsgConnectionOpenAck::::decode_vec(&msg.value).map_err(|_| ClientError::Other("conn_open_ack: failed to decode_vec".into()))?; let client_state = match msg.client_state.clone() { Some(m) => { let AnyClientState::Ethereum(client_state) = m.unpack_recursive() else { - return Err(ClientError::Other(format!("unsupported client state 1"))) + return Err(ClientError::Other(format!("conn_open_ack: unsupported client_state. Should be AnyClientState::Ethereum"))) }; client_state.clone() }, None => { - //TODO return error support only tendermint client state - panic!("unsupported") + return Err(ClientError::Other(format!("conn_open_ack: client_state can't be None"))) }, }; - let token = msg_connection_open_ack_token(msg, &client_state); + let token = msg_connection_open_ack_token(msg, &client_state)?; calls.push(self.yui.connection_open_ack_calldata(token).await); } else if msg.type_url == ibc::core::ics03_connection::msgs::conn_open_try::TYPE_URL { - let msg = MsgConnectionOpenTry::::decode_vec(&msg.value).unwrap(); + let msg = MsgConnectionOpenTry::::decode_vec(&msg.value).map_err(|_| ClientError::Other("conn_open_try: failed to decode_vec".into()))?;; let client_state = match msg.client_state.clone() { Some(m) => { let AnyClientState::Tendermint(client_state) = m.unpack_recursive() else { - return Err(ClientError::Other(format!("unsupported client state 2",))) + return Err(ClientError::Other(format!("conn_open_try: unsupported client_state. Should be AnyClientState::Tendermint",))) }; client_state.clone() }, None => { //TODO return error support only tendermint client state - panic!("unsupported") + return Err(ClientError::Other(format!("conn_open_try: client_state can't be None"))) }, }; - let token = msg_connection_open_try_token(msg, &client_state); + let token = msg_connection_open_try_token(msg, &client_state)?; calls.push(self.yui.connection_open_try_calldata(token).await); } else if msg.type_url == ibc::core::ics03_connection::msgs::conn_open_confirm::TYPE_URL { - let msg = MsgConnectionOpenConfirm::decode_vec(&msg.value).unwrap(); + let msg = MsgConnectionOpenConfirm::decode_vec(&msg.value).map_err(|_| ClientError::Other("conn_open_confirm: failed to decode_vec".into()))?;; let token = msg_connection_open_confirm_token(msg); calls.push(self.yui.connection_open_confirm_calldata(token).await); } else if msg.type_url == channel_msgs::chan_open_init::TYPE_URL { - let msg = MsgChannelOpenInit::decode_vec(&msg.value).unwrap(); + let msg = MsgChannelOpenInit::decode_vec(&msg.value).map_err(|_| ClientError::Other("chan_open_init: failed to decode_vec".into()))?;; log::info!("msg.channel.ordering = {}", msg.channel.ordering); let token = msg.into_token(); calls.push(self.yui.channel_open_init_calldata(token).await); } else if msg.type_url == channel_msgs::chan_open_try::TYPE_URL { - let msg = MsgChannelOpenTry::decode_vec(&msg.value).unwrap(); + let msg = MsgChannelOpenTry::decode_vec(&msg.value).map_err(|_| ClientError::Other("chan_open_try: failed to decode_vec".into()))?; let token = msg.into_token(); calls.push(self.yui.channel_open_try_calldata(token).await); } else if msg.type_url == channel_msgs::chan_open_ack::TYPE_URL { - let msg = MsgChannelOpenAck::decode_vec(&msg.value).unwrap(); + let msg = MsgChannelOpenAck::decode_vec(&msg.value).map_err(|_| ClientError::Other("chan_open_ack: failed to decode_vec".into()))?; log::info!("msg = {msg:#?}"); let token = msg.into_token(); calls.push(self.yui.send_and_get_tuple_calldata(token, "channelOpenAck").await); } else if msg.type_url == channel_msgs::chan_open_confirm::TYPE_URL { - let msg = MsgChannelOpenConfirm::decode_vec(&msg.value).unwrap(); + let msg = MsgChannelOpenConfirm::decode_vec(&msg.value).map_err(|_| ClientError::Other("chann_open_confirm: failed to decode_vec".into()))?; let token = msg.into_token(); calls.push(self.yui.send_and_get_tuple_calldata(token, "channelOpenConfirm").await); } else if msg.type_url == channel_msgs::chan_close_init::TYPE_URL { - let msg = MsgChannelCloseInit::decode_vec(&msg.value).unwrap(); + let msg = MsgChannelCloseInit::decode_vec(&msg.value).map_err(|_| ClientError::Other("chann_close_init: failed to decode_vec".into()))?; let token = msg.into_token(); calls.push(self.yui.send_and_get_tuple_calldata(token, "channelCloseInit").await); } else if msg.type_url == channel_msgs::chan_close_confirm::TYPE_URL { - let msg = MsgChannelCloseConfirm::decode_vec(&msg.value).unwrap(); + let msg = MsgChannelCloseConfirm::decode_vec(&msg.value).map_err(|_| ClientError::Other("chann_close_confirm: failed to decode_vec".into()))?; let token = msg.into_token(); calls .push(self.yui.send_and_get_tuple_calldata(token, "channelCloseConfirm").await); } else if msg.type_url == channel_msgs::timeout_on_close::TYPE_URL { - let msg = MsgTimeoutOnClose::decode_vec(&msg.value).unwrap(); + let msg = MsgTimeoutOnClose::decode_vec(&msg.value).map_err(|_| ClientError::Other("timeout_on_close: failed to decode_vec".into()))?; return Err(ClientError::Other("timeout not supported".into())) } else if msg.type_url == channel_msgs::timeout::TYPE_URL { - let msg = MsgTimeout::decode_vec(&msg.value).unwrap(); + let msg = MsgTimeout::decode_vec(&msg.value).map_err(|_| ClientError::Other("timeout: failed to decode_vec".into()))?; return Err(ClientError::Other("timeout not supported".into())) } else if msg.type_url == channel_msgs::acknowledgement::TYPE_URL { - let msg = MsgAcknowledgement::decode_vec(&msg.value).unwrap(); + let msg = MsgAcknowledgement::decode_vec(&msg.value).map_err(|_| ClientError::Other("acknowledgement: failed to decode_vec".into()))?; let token = msg.into_token(); calls.push(self.yui.send_and_get_tuple_calldata(token, "acknowledgePacket").await); } else if msg.type_url == channel_msgs::recv_packet::TYPE_URL { - let msg = MsgRecvPacket::decode_vec(&msg.value).unwrap(); + let msg = MsgRecvPacket::decode_vec(&msg.value).map_err(|_| ClientError::Other("recv_packet: failed to decode_vec".into()))?; let token = msg.into_token(); calls.push(self.yui.send_and_get_tuple_calldata(token, "recvPacket").await); } else { @@ -1152,7 +1177,8 @@ impl Chain for EthereumClient { thread::sleep(Duration::from_secs(5)); - Ok((receipt.block_hash.unwrap(), receipt.transaction_hash)) + let block_hash = receipt.block_hash.ok_or(ClientError::Other("Block hash is missing".into()))?; + Ok((block_hash, receipt.transaction_hash)) } async fn query_client_message( diff --git a/hyperspace/ethereum/tests/sanity_checks.rs b/hyperspace/ethereum/tests/sanity_checks.rs index d7df26651..57209224d 100644 --- a/hyperspace/ethereum/tests/sanity_checks.rs +++ b/hyperspace/ethereum/tests/sanity_checks.rs @@ -20,7 +20,7 @@ use hyperspace_ethereum::{ client::{EthRpcClient, EthereumClient}, config::EthereumClientConfig, contract::{IbcHandler, UnwrapContractError}, - mock::{utils, utils::USE_GETH}, + mock::{utils, utils::{USE_GETH, hyperspace_ethereum_client_fixture}}, utils::{DeployYuiIbc, ProviderImpl}, yui_types::IntoToken, }; @@ -208,9 +208,9 @@ async fn deploy_mock_client_fixture(deploy: &DeployYuiIbcMockClient) -> ClientId .yui_ibc .create_client(utils::mock::create_client_msg("mock-client")) .await; - println!("client id: {}", string); + println!("client id: {}", string.0); println!("Diamond contract addr: {:?}", deploy.yui_ibc.diamond.address()); - ClientId(string) + ClientId(string.0) } #[track_caller] From 7088210a919783000a950f3b27edd18a493b5a89 Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Mon, 11 Sep 2023 18:09:34 -0300 Subject: [PATCH 21/43] "Add dynamic handling of client consensus state and improve logging" This commit adds dynamic handling of client consensus state in ibc_provider.rs and improves logging across different modules. Previously, for certain IBC events the provider was not returning if the Ethereum IBC event was not found, leading to undesired behaviors. Now, after each IBC event processing, an appropriate response is always returned, improving the robustness. Additionally, incorrect log entries have been amended, while superfluous log entries have been streamlined, enhancing debugging capabilities. Finally, erroneous static client consensus handling has been replaced by dynamic queries, increasing flexibility and correctness. --- hyperspace/core/src/macros.rs | 2 +- hyperspace/core/src/packets.rs | 4 +- hyperspace/ethereum/src/chain.rs | 200 +++++++++++------- hyperspace/ethereum/src/client.rs | 2 +- hyperspace/ethereum/src/ibc_provider.rs | 208 ++++++++++++++++--- hyperspace/ethereum/src/prove.rs | 67 ++++-- ibc/modules/src/core/ics04_channel/packet.rs | 3 +- 7 files changed, 360 insertions(+), 126 deletions(-) diff --git a/hyperspace/core/src/macros.rs b/hyperspace/core/src/macros.rs index ce1d5a40b..4920a4297 100644 --- a/hyperspace/core/src/macros.rs +++ b/hyperspace/core/src/macros.rs @@ -45,7 +45,7 @@ macro_rules! chains { )* } - #[derive(Clone)] + #[derive(Clone, Debug)] pub enum AnyAssetId { $( $(#[$($meta)*])* diff --git a/hyperspace/core/src/packets.rs b/hyperspace/core/src/packets.rs index f402d60b1..f9c98d47c 100644 --- a/hyperspace/core/src/packets.rs +++ b/hyperspace/core/src/packets.rs @@ -324,7 +324,7 @@ pub async fn query_ready_and_timed_out_packets( // creation height on source chain if packet_height > latest_source_height_on_sink.revision_height { // Sink does not have client update required to prove recv packet message - log::debug!(target: "hyperspace", "Skipping packet {:?} as sink does not have client update required to prove recv packet message", packet); + log::debug!(target: "hyperspace", "Skipping packet as sink does not have client update required to prove recv packet message: {:?}", packet); recv_packets_count.fetch_add(1, Ordering::SeqCst); return Ok(None) } @@ -342,7 +342,7 @@ pub async fn query_ready_and_timed_out_packets( { proof_height } else { - log::trace!(target: "hyperspace", "Skipping packet {:?} as no proof height could be found", packet); + log::trace!(target: "hyperspace", "Skipping packet as no proof height could be found: {:?}", packet); return Ok(None) }; diff --git a/hyperspace/ethereum/src/chain.rs b/hyperspace/ethereum/src/chain.rs index 496b544b6..b5d6da178 100644 --- a/hyperspace/ethereum/src/chain.rs +++ b/hyperspace/ethereum/src/chain.rs @@ -253,16 +253,17 @@ pub(crate) fn client_state_from_abi_token(token: Token) -> Result Token { use ethers::abi::{encode as ethers_encode, Token as EthersToken}; - let time = consensus_state - .timestamp - .duration_since(Timestamp { seconds: 0, nanos: 0 }.try_into().unwrap()) - .unwrap(); + let timestamp = Timestamp::from(consensus_state.timestamp); + let consensus_state_data = EthersToken::Tuple( [ //timestamp EthersToken::Tuple( - [EthersToken::Int(time.as_secs().into()), EthersToken::Int(time.as_nanos().into())] - .to_vec(), + [ + EthersToken::Int(timestamp.seconds.into()), + EthersToken::Int(timestamp.nanos.into()), + ] + .to_vec(), ), //root EthersToken::Tuple([EthersToken::Bytes(consensus_state.root.bytes.clone())].to_vec()), @@ -274,7 +275,7 @@ fn consensus_state_abi_token(consensus_state: &ConsensusState) -> Token { consensus_state_data } -fn consensus_state_from_abi_token(token: Token) -> Result { +pub(crate) fn consensus_state_from_abi_token(token: Token) -> Result { use ethers::abi::Token as EthersToken; let Token::Bytes(bytes) = token else { @@ -318,10 +319,10 @@ fn consensus_state_from_abi_token(token: Token) -> Result Result { // TODO: convert to u128 (nanoseconds) let timestamp = Timestamp::from(block_header.time); - let last_block_id = block_header.last_block_id.ok_or(ClientError::Other( - "last_block_id not found".to_string(), - ))?; + let last_block_id = block_header + .last_block_id + .ok_or(ClientError::Other("last_block_id not found".to_string()))?; let signed_header_header = EthersToken::Tuple( [ @@ -368,12 +369,8 @@ fn tm_header_abi_token(header: &Header) -> Result { //part_set_header EthersToken::Tuple( [ - EthersToken::Uint( - last_block_id.part_set_header.total.into(), - ), - EthersToken::Bytes( - last_block_id.part_set_header.hash.into(), - ), + EthersToken::Uint(last_block_id.part_set_header.total.into()), + EthersToken::Bytes(last_block_id.part_set_header.hash.into()), ] .to_vec(), ), @@ -381,13 +378,19 @@ fn tm_header_abi_token(header: &Header) -> Result { .to_vec(), ), //last_commit_hash - EthersToken::Bytes(block_header.last_commit_hash.ok_or(ClientError::Other( - "last_commit_hash not found".to_string(), - ))?.into()), + EthersToken::Bytes( + block_header + .last_commit_hash + .ok_or(ClientError::Other("last_commit_hash not found".to_string()))? + .into(), + ), //data_hash - EthersToken::Bytes(block_header.data_hash.ok_or(ClientError::Other( - "data_hash not found".to_string(), - ))?.into()), + EthersToken::Bytes( + block_header + .data_hash + .ok_or(ClientError::Other("data_hash not found".to_string()))? + .into(), + ), //validators_hash EthersToken::Bytes(block_header.validators_hash.into()), //next_validators_hash @@ -397,13 +400,19 @@ fn tm_header_abi_token(header: &Header) -> Result { //app_hash EthersToken::Bytes(block_header.app_hash.into()), //last_results_hash - EthersToken::Bytes(block_header.last_results_hash.ok_or(ClientError::Other( - "last_results_hash not found".to_string(), - ))?.into()), + EthersToken::Bytes( + block_header + .last_results_hash + .ok_or(ClientError::Other("last_results_hash not found".to_string()))? + .into(), + ), //evidence_hash - EthersToken::Bytes(block_header.evidence_hash.ok_or(ClientError::Other( - "evidence_hash not found".to_string(), - ))?.into()), + EthersToken::Bytes( + block_header + .evidence_hash + .ok_or(ClientError::Other("evidence_hash not found".to_string()))? + .into(), + ), //proposer_address EthersToken::Bytes(block_header.proposer_address.into()), ] @@ -445,7 +454,6 @@ fn tm_header_abi_token(header: &Header) -> Result { .to_vec(), ); Ok(ret) - } pub(crate) fn tm_header_from_abi_token(token: Token) -> Result { @@ -835,15 +843,21 @@ pub fn msg_connection_open_ack_token( [ //revisionNumber EthersToken::Uint( - msg.proofs.consensus_proof().ok_or( - ClientError::Other("consensus_proof not found".to_string()), - )?.height().revision_number.into(), + msg.proofs + .consensus_proof() + .ok_or(ClientError::Other("consensus_proof not found".to_string()))? + .height() + .revision_number + .into(), ), //revisionHeight EthersToken::Uint( - msg.proofs.consensus_proof().ok_or( - ClientError::Other("consensus_proof not found".to_string()), - )?.height().revision_number.into(), + msg.proofs + .consensus_proof() + .ok_or(ClientError::Other("consensus_proof not found".to_string()))? + .height() + .revision_number + .into(), ), ] .to_vec(), @@ -878,9 +892,12 @@ fn msg_connection_open_try_token( .consensus_proof() .map_or_else(Vec::new, |v| v.proof().clone().into()), proof_height: msg.proofs.height().into(), - consensus_height: msg.proofs.consensus_proof().ok_or( - ClientError::Other("consensus_proof not found".to_string()), - )?.height().into(), + consensus_height: msg + .proofs + .consensus_proof() + .ok_or(ClientError::Other("consensus_proof not found".to_string()))? + .height() + .into(), }; let conn_open_try_token = conn_open_try.into_token(); Ok(conn_open_try_token) @@ -967,7 +984,9 @@ impl Chain for EthereumClient { for msg in messages { if msg.type_url == ibc::core::ics02_client::msgs::create_client::TYPE_URL { dbg!(&msg.value.len()); - let msg = MsgCreateAnyClient::::decode_vec(&msg.value).map_err(|_| ClientError::Other("create_client: unsupported client state".into()))?;; + let msg = MsgCreateAnyClient::::decode_vec(&msg.value).map_err( + |_| ClientError::Other("create_client: unsupported client state".into()), + )?; let AnyClientState::Tendermint(client_state) = msg.client_state.unpack_recursive() else { //TODO return error support only tendermint client state @@ -977,7 +996,9 @@ impl Chain for EthereumClient { msg.consensus_state.unpack_recursive() else { //TODO return error support only tendermint consensus state - return Err(ClientError::Other("create_client: unsupported consensus state".into())) + return Err(ClientError::Other( + "create_client: unsupported consensus state".into(), + )) }; let client_state_abi_token = client_state_abi_token(client_state); let consensus_state_abi_token = consensus_state_abi_token(client_consensus); @@ -1030,24 +1051,31 @@ impl Chain for EthereumClient { *update_mutex = (client_state_data_vec.clone(), consensus_state_data_vec.clone()); calls.push(bytes); } else if msg.type_url == ibc::core::ics02_client::msgs::update_client::TYPE_URL { - let msg = MsgUpdateAnyClient::::decode_vec(&msg.value).map_err(|_| ClientError::Other("update_client: failed to decode_vec".into()))?;; + let msg = MsgUpdateAnyClient::::decode_vec(&msg.value).map_err( + |_| ClientError::Other("update_client: failed to decode_vec".into()), + )?; let AnyClientMessage::Tendermint(client_state) = msg.client_message.unpack_recursive() else { return Err(ClientError::Other(format!("update_client: unsupported client_state. Should be AnyClientMessage::Tendermint"))) }; - let ClientMessage::Header(header) = client_state else { + let ClientMessage::Header(header) = client_state else { return Err(ClientError::Other("update_client: unsupported Client Message. Should be ClientMessage::Header".into())) - }; + }; //get abi token to update client let tm_header_abi_token = tm_header_abi_token(header)?; let tm_header_bytes = ethers_encode(&[tm_header_abi_token]); //todo replace empty vec for prev state clint with an actual client state - let client_state = self.prev_state.lock().map_err(|_| { - ClientError::Other("update_client: can't lock prev_state mutex".into()) - })?.0.clone(); + let client_state = self + .prev_state + .lock() + .map_err(|_| { + ClientError::Other("update_client: can't lock prev_state mutex".into()) + })? + .0 + .clone(); //TODO replace client id. it was genereated when we created the client. use 0 for // testing @@ -1065,11 +1093,16 @@ impl Chain for EthereumClient { calls.push(self.yui.update_client_calldata(token).await); } else if msg.type_url == ibc::core::ics03_connection::msgs::conn_open_init::TYPE_URL { - let msg = MsgConnectionOpenInit::decode_vec(&msg.value).map_err(|_| ClientError::Other("conn_open_init: failed to decode_vec".into()))?;; + let msg = MsgConnectionOpenInit::decode_vec(&msg.value).map_err(|_| { + ClientError::Other("conn_open_init: failed to decode_vec".into()) + })?; let token = msg_connection_open_init_token(msg); calls.push(self.yui.connection_open_init_calldata(token).await); } else if msg.type_url == ibc::core::ics03_connection::msgs::conn_open_ack::TYPE_URL { - let msg = MsgConnectionOpenAck::::decode_vec(&msg.value).map_err(|_| ClientError::Other("conn_open_ack: failed to decode_vec".into()))?; + let msg = MsgConnectionOpenAck::::decode_vec(&msg.value) + .map_err(|_| { + ClientError::Other("conn_open_ack: failed to decode_vec".into()) + })?; let client_state = match msg.client_state.clone() { Some(m) => { @@ -1078,15 +1111,19 @@ impl Chain for EthereumClient { }; client_state.clone() }, - None => { - return Err(ClientError::Other(format!("conn_open_ack: client_state can't be None"))) - }, + None => + return Err(ClientError::Other(format!( + "conn_open_ack: client_state can't be None" + ))), }; let token = msg_connection_open_ack_token(msg, &client_state)?; calls.push(self.yui.connection_open_ack_calldata(token).await); } else if msg.type_url == ibc::core::ics03_connection::msgs::conn_open_try::TYPE_URL { - let msg = MsgConnectionOpenTry::::decode_vec(&msg.value).map_err(|_| ClientError::Other("conn_open_try: failed to decode_vec".into()))?;; + let msg = MsgConnectionOpenTry::::decode_vec(&msg.value) + .map_err(|_| { + ClientError::Other("conn_open_try: failed to decode_vec".into()) + })?; let client_state = match msg.client_state.clone() { Some(m) => { let AnyClientState::Tendermint(client_state) = m.unpack_recursive() else { @@ -1096,7 +1133,9 @@ impl Chain for EthereumClient { }, None => { //TODO return error support only tendermint client state - return Err(ClientError::Other(format!("conn_open_try: client_state can't be None"))) + return Err(ClientError::Other(format!( + "conn_open_try: client_state can't be None" + ))) }, }; @@ -1104,48 +1143,68 @@ impl Chain for EthereumClient { calls.push(self.yui.connection_open_try_calldata(token).await); } else if msg.type_url == ibc::core::ics03_connection::msgs::conn_open_confirm::TYPE_URL { - let msg = MsgConnectionOpenConfirm::decode_vec(&msg.value).map_err(|_| ClientError::Other("conn_open_confirm: failed to decode_vec".into()))?;; + let msg = MsgConnectionOpenConfirm::decode_vec(&msg.value).map_err(|_| { + ClientError::Other("conn_open_confirm: failed to decode_vec".into()) + })?; let token = msg_connection_open_confirm_token(msg); calls.push(self.yui.connection_open_confirm_calldata(token).await); } else if msg.type_url == channel_msgs::chan_open_init::TYPE_URL { - let msg = MsgChannelOpenInit::decode_vec(&msg.value).map_err(|_| ClientError::Other("chan_open_init: failed to decode_vec".into()))?;; + let msg = MsgChannelOpenInit::decode_vec(&msg.value).map_err(|_| { + ClientError::Other("chan_open_init: failed to decode_vec".into()) + })?; log::info!("msg.channel.ordering = {}", msg.channel.ordering); let token = msg.into_token(); calls.push(self.yui.channel_open_init_calldata(token).await); } else if msg.type_url == channel_msgs::chan_open_try::TYPE_URL { - let msg = MsgChannelOpenTry::decode_vec(&msg.value).map_err(|_| ClientError::Other("chan_open_try: failed to decode_vec".into()))?; + let msg = MsgChannelOpenTry::decode_vec(&msg.value).map_err(|_| { + ClientError::Other("chan_open_try: failed to decode_vec".into()) + })?; let token = msg.into_token(); calls.push(self.yui.channel_open_try_calldata(token).await); } else if msg.type_url == channel_msgs::chan_open_ack::TYPE_URL { - let msg = MsgChannelOpenAck::decode_vec(&msg.value).map_err(|_| ClientError::Other("chan_open_ack: failed to decode_vec".into()))?; + let msg = MsgChannelOpenAck::decode_vec(&msg.value).map_err(|_| { + ClientError::Other("chan_open_ack: failed to decode_vec".into()) + })?; log::info!("msg = {msg:#?}"); let token = msg.into_token(); calls.push(self.yui.send_and_get_tuple_calldata(token, "channelOpenAck").await); } else if msg.type_url == channel_msgs::chan_open_confirm::TYPE_URL { - let msg = MsgChannelOpenConfirm::decode_vec(&msg.value).map_err(|_| ClientError::Other("chann_open_confirm: failed to decode_vec".into()))?; + let msg = MsgChannelOpenConfirm::decode_vec(&msg.value).map_err(|_| { + ClientError::Other("chann_open_confirm: failed to decode_vec".into()) + })?; let token = msg.into_token(); calls.push(self.yui.send_and_get_tuple_calldata(token, "channelOpenConfirm").await); } else if msg.type_url == channel_msgs::chan_close_init::TYPE_URL { - let msg = MsgChannelCloseInit::decode_vec(&msg.value).map_err(|_| ClientError::Other("chann_close_init: failed to decode_vec".into()))?; + let msg = MsgChannelCloseInit::decode_vec(&msg.value).map_err(|_| { + ClientError::Other("chann_close_init: failed to decode_vec".into()) + })?; let token = msg.into_token(); calls.push(self.yui.send_and_get_tuple_calldata(token, "channelCloseInit").await); } else if msg.type_url == channel_msgs::chan_close_confirm::TYPE_URL { - let msg = MsgChannelCloseConfirm::decode_vec(&msg.value).map_err(|_| ClientError::Other("chann_close_confirm: failed to decode_vec".into()))?; + let msg = MsgChannelCloseConfirm::decode_vec(&msg.value).map_err(|_| { + ClientError::Other("chann_close_confirm: failed to decode_vec".into()) + })?; let token = msg.into_token(); calls .push(self.yui.send_and_get_tuple_calldata(token, "channelCloseConfirm").await); } else if msg.type_url == channel_msgs::timeout_on_close::TYPE_URL { - let msg = MsgTimeoutOnClose::decode_vec(&msg.value).map_err(|_| ClientError::Other("timeout_on_close: failed to decode_vec".into()))?; + let msg = MsgTimeoutOnClose::decode_vec(&msg.value).map_err(|_| { + ClientError::Other("timeout_on_close: failed to decode_vec".into()) + })?; return Err(ClientError::Other("timeout not supported".into())) } else if msg.type_url == channel_msgs::timeout::TYPE_URL { - let msg = MsgTimeout::decode_vec(&msg.value).map_err(|_| ClientError::Other("timeout: failed to decode_vec".into()))?; + let msg = MsgTimeout::decode_vec(&msg.value) + .map_err(|_| ClientError::Other("timeout: failed to decode_vec".into()))?; return Err(ClientError::Other("timeout not supported".into())) } else if msg.type_url == channel_msgs::acknowledgement::TYPE_URL { - let msg = MsgAcknowledgement::decode_vec(&msg.value).map_err(|_| ClientError::Other("acknowledgement: failed to decode_vec".into()))?; + let msg = MsgAcknowledgement::decode_vec(&msg.value).map_err(|_| { + ClientError::Other("acknowledgement: failed to decode_vec".into()) + })?; let token = msg.into_token(); calls.push(self.yui.send_and_get_tuple_calldata(token, "acknowledgePacket").await); } else if msg.type_url == channel_msgs::recv_packet::TYPE_URL { - let msg = MsgRecvPacket::decode_vec(&msg.value).map_err(|_| ClientError::Other("recv_packet: failed to decode_vec".into()))?; + let msg = MsgRecvPacket::decode_vec(&msg.value) + .map_err(|_| ClientError::Other("recv_packet: failed to decode_vec".into()))?; let token = msg.into_token(); calls.push(self.yui.send_and_get_tuple_calldata(token, "recvPacket").await); } else { @@ -1156,7 +1215,7 @@ impl Chain for EthereumClient { } } - let method = self.yui.method::<_, (Vec, Vec>)>("call_batch", calls)?; + let method = self.yui.method::<_, (Vec, Vec>)>("callBatch", calls)?; let data = method.call().await?; let receipt = method .send() @@ -1177,7 +1236,8 @@ impl Chain for EthereumClient { thread::sleep(Duration::from_secs(5)); - let block_hash = receipt.block_hash.ok_or(ClientError::Other("Block hash is missing".into()))?; + let block_hash = + receipt.block_hash.ok_or(ClientError::Other("Block hash is missing".into()))?; Ok((block_hash, receipt.transaction_hash)) } diff --git a/hyperspace/ethereum/src/client.rs b/hyperspace/ethereum/src/client.rs index fcf0506bf..14328bbd2 100644 --- a/hyperspace/ethereum/src/client.rs +++ b/hyperspace/ethereum/src/client.rs @@ -614,7 +614,7 @@ impl primitives::TestProvider for EthereumClient { async fn send_transfer(&self, params: MsgTransfer) -> Result<(), Self::Error> { let params = ( params.token.denom.to_string(), - params.token.amount.as_u256().as_u64(), + params.token.amount.as_u256(), params.receiver.to_string(), params.source_port.to_string(), params.source_channel.to_string(), diff --git a/hyperspace/ethereum/src/ibc_provider.rs b/hyperspace/ethereum/src/ibc_provider.rs index 03bf7efce..a8b167ce1 100644 --- a/hyperspace/ethereum/src/ibc_provider.rs +++ b/hyperspace/ethereum/src/ibc_provider.rs @@ -69,7 +69,9 @@ use ssz_rs::Merkleized; use thiserror::Error; use crate::{ - chain::{client_state_from_abi_token, tm_header_from_abi_token}, + chain::{ + client_state_from_abi_token, consensus_state_from_abi_token, tm_header_from_abi_token, + }, prove::prove_fast, }; use ibc::{ @@ -95,6 +97,7 @@ use ibc_proto::{ }, }; use ibc_rpc::{IbcApiClient, PacketInfo}; +use ics07_tendermint::consensus_state::ConsensusState as TmConsensusState; use icsxx_ethereum::{ client_message::ClientMessage, client_state::ClientState, consensus_state::ConsensusState, }; @@ -332,13 +335,13 @@ impl IbcProvider for EthereumClient { // TODO: this function is mostly used in tests and in 'fishing' mode. async fn ibc_events(&self) -> Pin + Send + 'static>> { - let ibc_address = self.config.ibc_handler_address; + let ibc_address = self.yui.diamond.address(); let client = self.clone(); let ws = self.websocket_provider().await.unwrap(); (async_stream::stream! { let mut events_stream = ws.subscribe_logs( - &Filter::new().from_block(BlockNumber::Latest).address(ibc_address), + &Filter::new().from_block(BlockNumber::Earliest).address(ibc_address), ) .await .unwrap() @@ -347,24 +350,19 @@ impl IbcProvider for EthereumClient { let height = Height::new(0, log.block_number.unwrap().as_u64()); let topic0 = log.topics[0]; - // let mut maybe_ibc_event = if topic0 == CreateClientFilter::signature() { - // let event = CreateClientFilter::decode_log(&raw_log).expect("decode event"); - // IbcEvent::try_from_event(&client, event, log, height).await - // } else { + let mut maybe_ibc_event = if topic0 == UpdateClientHeightFilter::signature() { + let event = UpdateClientHeightFilter::decode_log(&raw_log).expect("decode event"); + let topic1 = H256::from_slice(&encode(&[Token::FixedBytes( + keccak256("07-tendermint-0".to_string().into_bytes()).to_vec(), + )])); + } else { log::error!(target: "hyperspace_ethereum", "unknown event: {}", log.log_type.unwrap_or(format!("{topic0:?}")) ); - return None - // }; - - // match maybe_ibc_event { - // Ok(ev) => Some(ev), - // Err(err) => { - // log::error!(target: "hyperspace_ethereum", "failed to decode event: {err}"); - // None - // }, - // } + }; + + Some(IbcEvent::Empty("".into())) }).boxed(); while let Some(ev) = events_stream.next().await { @@ -380,6 +378,9 @@ impl IbcProvider for EthereumClient { client_id: ClientId, consensus_height: Height, ) -> Result { + log::info!(target: "hyperspace_ethereum", "query_client_consensus: {client_id:?}, {consensus_height:?}"); + + /* let binding = self .yui .method( @@ -405,9 +406,150 @@ impl IbcProvider for EthereumClient { .unwrap(); let proof_height = Some(at.into()); - let consensus_state = google::protobuf::Any::decode(&*client_cons).ok(); + let mut cs = client_state_from_abi_token::(client_state_token)?; + */ + + // First, we try to find an `UpdateClient` event at the given height... + let mut consensus_state = None; + let mut event_filter = self + .yui + .event_for_name::("UpdateClientHeight") + .expect("contract is missing UpdateClient event") + .to_block(at.revision_height) + .from_block(at.revision_height); + // .from_block(BlockNumber::Earliest) + // .to_block(BlockNumber::Latest); + event_filter.filter = event_filter + .filter + .topic1({ + let hash = H256::from_slice(&encode(&[Token::FixedBytes( + keccak256(client_id.to_string().into_bytes()).to_vec(), + )])); + ValueOrArray::Value(hash) + }) + .topic2({ + let height_bytes = encode(&[Token::Tuple(vec![ + Token::Uint(consensus_height.revision_number.into()), + Token::Uint(consensus_height.revision_height.into()), + ])]); + ValueOrArray::Value(H256::from_slice(&encode(&[Token::FixedBytes( + keccak256(&height_bytes).to_vec(), + )]))) + }); + let maybe_log = self + .yui + .diamond + .client() + .get_logs(&event_filter.filter) + .await + .unwrap() + .pop() // get only the last event + ; + let batch_func = self.yui.function("callBatch")?; + match maybe_log { + Some(log) => { + let tx_hash = log.transaction_hash.expect("tx hash should exist"); + let func = self.yui.function("updateClient")?; + let tx = + self.client().get_transaction(tx_hash).await.unwrap().ok_or_else(|| { + ClientError::Other(format!("transaction not found: {}", tx_hash)) + })?; + let Token::Array(batch_calldata) = + batch_func.decode_input(&tx.input[4..])?.pop().unwrap() + else { + return Err(ClientError::Other("batch calldata not found".to_string())) + }; - Ok(QueryConsensusStateResponse { consensus_state, proof: vec![0], proof_height }) + for input_tok in batch_calldata.into_iter().rev() { + let Token::Bytes(input) = input_tok else { panic!() }; + if input[..4] == func.short_signature() { + let calldata = func.decode_input(&input[4..])?.pop().unwrap(); + let Token::Tuple(toks) = calldata else { panic!() }; + let header = tm_header_from_abi_token(toks[1].clone())?; + consensus_state = Some(TmConsensusState { + timestamp: header.signed_header.header.time, + root: CommitmentRoot { + bytes: header.signed_header.header.app_hash.as_bytes().to_owned(), + }, + next_validators_hash: header.signed_header.header.next_validators_hash, + }); + // TODO: figure out how to distinguish between the same function calls + log::info!(target: "hyperspace_ethereum", "query_client_consensus FOUND"); + + let proof_height = Some(at.into()); + return Ok(QueryConsensusStateResponse { + consensus_state: Some( + consensus_state.expect("should always be initialized").to_any(), + ), + proof: vec![0], + proof_height, + }) + } + } + // TODO: handle frozen height + }, + None => {}, + } + + log::trace!(target: "hyperspace_ethereum", "no update client event found for blocks ..{at}, looking for a create client event..."); + + // ...otherwise, try to get the `CreateClient` event + log::info!(target: "hyperspace_ethereum", "qconss {}", line!()); + let mut event_filter = self + .yui + .event_for_name::("CreateClient") + .expect("contract is missing CreateClient event") + .from_block(BlockNumber::Earliest) + .to_block(at.revision_height); + event_filter.filter = event_filter.filter.topic1({ + let hash = H256::from_slice(&encode(&[Token::FixedBytes( + keccak256(client_id.to_string().into_bytes()).to_vec(), + )])); + ValueOrArray::Value(hash) + }); + log::info!(target: "hyperspace_ethereum", "qconss {}", line!()); + let log = self + .yui + .diamond + .client() + .get_logs(&event_filter.filter) + .await + .unwrap() + .pop() // get only the last event + .ok_or_else(|| ClientError::Other("no events found".to_string()))?; + log::info!(target: "hyperspace_ethereum", "qconss {}", line!()); + + let tx_hash = log.transaction_hash.expect("tx hash should exist"); + let func = self.yui.function("createClient")?; + let tx = self + .client() + .get_transaction(tx_hash) + .await + .unwrap() + .ok_or_else(|| ClientError::Other(format!("transaction not found: {}", tx_hash)))?; + + let Token::Array(batch_calldata) = batch_func.decode_input(&tx.input[4..])?.pop().unwrap() + else { + return Err(ClientError::Other("batch calldata not found".to_string())) + }; + + for input_tok in batch_calldata.into_iter().rev() { + let Token::Bytes(input) = input_tok else { panic!() }; + log::info!("sig = {:?}", func.short_signature()); + if input[..4] == func.short_signature() { + let calldata = func.decode_input(&input[4..])?.pop().unwrap(); + let Token::Tuple(toks) = calldata else { panic!() }; + let consensus_state_token = toks[2].clone(); + consensus_state = Some(consensus_state_from_abi_token(consensus_state_token)?); + break + } + } + + let proof_height = Some(at.into()); + let any = consensus_state.expect("should always be initialized").to_any(); + log::info!(target: "hyperspace_ethereum", "query_client_consensus FOUND"); + + Ok(QueryConsensusStateResponse { consensus_state: Some(any), proof: vec![0], proof_height }) } async fn query_client_state( @@ -976,7 +1118,8 @@ impl IbcProvider for EthereumClient { .from_block(BlockNumber::Earliest) // TODO: use contract creation height .to_block(BlockNumber::Latest) .topic1(ValueOrArray::Array( - seqs.into_iter() + seqs.clone() + .into_iter() .map(|seq| { let bytes = encode(&[Token::Uint(seq.into())]); H256::from_slice(bytes.as_slice()) @@ -1024,9 +1167,12 @@ impl IbcProvider for EthereumClient { let counterparty = channel.counterparty.expect("counterparty is none"); Ok(logs .into_iter() - .map(move |log| { + .filter_map(move |log| { let value = SendPacketFilter::decode_log(&log.clone().into()).unwrap(); - PacketInfo { + if !seqs.contains(&value.sequence) { + return None + } + Some(PacketInfo { height: Some(log.block_number.unwrap().as_u64().into()), source_port: source_port.clone(), source_channel: source_channel.clone(), @@ -1041,7 +1187,7 @@ impl IbcProvider for EthereumClient { .unwrap() .to_string(), ack: None, - } + }) }) .collect()) } @@ -1092,7 +1238,8 @@ impl IbcProvider for EthereumClient { .from_block(BlockNumber::Earliest) // TODO: use contract creation height .to_block(BlockNumber::Latest) .topic3(ValueOrArray::Array( - seqs.into_iter() + seqs.clone() + .into_iter() .map(|seq| { let bytes = encode(&[Token::Uint(seq.into())]); H256::from_slice(bytes.as_slice()) @@ -1120,9 +1267,13 @@ impl IbcProvider for EthereumClient { Ok(logs .into_iter() - .map(move |log| { + .filter_map(move |log| { let value = RecvPacketFilter::decode_log(&log.clone().into()).unwrap(); - PacketInfo { + if !seqs.contains(&value.sequence) { + return None + } + + Some(PacketInfo { height: Some(log.block_number.unwrap().as_u64().into()), source_port: value.source_port.clone(), source_channel: value.source_channel.clone(), @@ -1137,7 +1288,7 @@ impl IbcProvider for EthereumClient { .unwrap() .to_string(), ack: acks_map.get(&value.sequence).cloned(), - } + }) }) .collect()) } @@ -1151,6 +1302,7 @@ impl IbcProvider for EthereumClient { client_id: ClientId, client_height: Height, ) -> Result<(Height, Timestamp), Self::Error> { + log::info!(target: "hyperspace_ethereum", "query_client_update_time_and_height: {client_id:?}, {client_height:?}"); let event_filter = self .yui .event_for_name::("UpdateClientHeight") @@ -1180,7 +1332,7 @@ impl IbcProvider for EthereumClient { .await .unwrap() .pop() - .unwrap(); + .ok_or_else(|| Self::Error::Other("no logs found".to_owned()))?; let height = Height::new(0, log.block_number.expect("block number is none").as_u64()); diff --git a/hyperspace/ethereum/src/prove.rs b/hyperspace/ethereum/src/prove.rs index f3df95e94..4c6077254 100644 --- a/hyperspace/ethereum/src/prove.rs +++ b/hyperspace/ethereum/src/prove.rs @@ -1,5 +1,6 @@ // use base2::Base2; use crate::client::{ClientError, EthereumClient}; +use anyhow::anyhow; use ethereum_consensus::{ altair::mainnet::SYNC_COMMITTEE_SIZE, bellatrix::compute_domain, @@ -8,7 +9,10 @@ use ethereum_consensus::{ signing::compute_signing_root, state_transition::Context, }; -use ethers::prelude::{EthCall, H256}; +use ethers::{ + core::{rand, rand::Rng}, + prelude::{EthCall, H256}, +}; use icsxx_ethereum::client_state::ClientState; use pallet_ibc::light_clients::HostFunctionsManager; use primitives::mock::LocalClientTypes; @@ -29,7 +33,7 @@ use sync_committee_prover::{ prove_sync_committee_update, SyncCommitteeProver, }; use sync_committee_verifier::{verify_sync_committee_attestation, SignatureVerifier}; -use tokio::time; +use tokio::{task::JoinSet, time, time::sleep}; // use tokio_stream::{wrappers::IntervalStream, StreamExt}; pub async fn prove( @@ -243,29 +247,48 @@ pub async fn prove_fast( let block = sync_committee_prover.fetch_block(&block_header.slot.to_string()).await?; let state = sync_committee_prover.fetch_beacon_state(&block_header.slot.to_string()).await?; + let from = client_state.finalized_header.slot + 1; + let to = block_header.slot; + let mut join_set: JoinSet> = JoinSet::new(); + let range = (from..to).collect::>(); + let delay = 5000; let mut ancestor_blocks = vec![]; - for i in (client_state.finalized_header.slot + 1)..block_header.slot { - if let Ok(ancestor_header) = - sync_committee_prover.fetch_header(i.to_string().as_str()).await - { - // let ancestry_proof = - // prove_block_roots_proof(finalized_state.clone(), ancestor_header.clone())?; - let header_state = - sync_committee_prover.fetch_beacon_state(i.to_string().as_str()).await?; - let execution_payload_proof = prove_execution_payload(header_state)?; - ancestor_blocks.push(AncestorBlock { - header: ancestor_header, - execution_payload: execution_payload_proof, - ancestry_proof: AncestryProof::BlockRoots { - block_roots_proof: BlockRootsProof { - block_header_index: 0, - block_header_branch: vec![], - }, - block_roots_branch: vec![], - }, - }) + for heights in range.chunks(100) { + for i in heights.iter().copied() { + let duration = Duration::from_millis(rand::thread_rng().gen_range(1..delay) as u64); + let sync_committee_prover = sync_committee_prover.clone(); + join_set.spawn(async move { + sleep(duration).await; + + if let Ok(ancestor_header) = + sync_committee_prover.fetch_header(i.to_string().as_str()).await + { + // let ancestry_proof = + // prove_block_roots_proof(finalized_state.clone(), ancestor_header.clone())?; + let header_state = + sync_committee_prover.fetch_beacon_state(i.to_string().as_str()).await?; + let execution_payload_proof = prove_execution_payload(header_state)?; + return Ok(AncestorBlock { + header: ancestor_header, + execution_payload: execution_payload_proof, + ancestry_proof: AncestryProof::BlockRoots { + block_roots_proof: BlockRootsProof { + block_header_index: 0, + block_header_branch: vec![], + }, + block_roots_branch: vec![], + }, + }) + } + Err(anyhow::anyhow!("Could not fetch ancestor block")) + }); + } + while let Some(res) = join_set.join_next().await { + let out = res.map_err(|e| anyhow!("{e}"))??; + ancestor_blocks.push(out); } } + ancestor_blocks.sort_by_key(|ancestor_block| ancestor_block.header.slot); let ep = block.body.execution_payload; let execution_payload_proof = ExecutionPayloadProof { diff --git a/ibc/modules/src/core/ics04_channel/packet.rs b/ibc/modules/src/core/ics04_channel/packet.rs index e776be705..61e9636e8 100644 --- a/ibc/modules/src/core/ics04_channel/packet.rs +++ b/ibc/modules/src/core/ics04_channel/packet.rs @@ -143,8 +143,7 @@ impl<'a> core::fmt::Debug for PacketData<'a> { impl core::fmt::Debug for Packet { fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> { // Remember: if you alter the definition of `Packet`, - // 1. update the formatter debug struct builder calls (return object of - // this function) + // 1. update the formatter debug struct builder calls (return object of this function) // 2. update this destructuring assignment accordingly let Packet { sequence: _, From d4dab9fe0a762007a37fa4791b71b902632da35f Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Tue, 12 Sep 2023 13:43:42 -0300 Subject: [PATCH 22/43] fix the test --- Cargo.lock | 1 + hyperspace/ethereum/src/ibc_provider.rs | 49 +------------------------ hyperspace/ethereum/src/mock/utils.rs | 2 +- light-clients/common/Cargo.toml | 1 + 4 files changed, 4 insertions(+), 49 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fe173cf6f..c38f130ff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6466,6 +6466,7 @@ dependencies = [ "async-trait", "derive_more", "hash-db 0.15.2", + "hex", "ibc", "ibc-proto", "parity-scale-codec", diff --git a/hyperspace/ethereum/src/ibc_provider.rs b/hyperspace/ethereum/src/ibc_provider.rs index a8b167ce1..f8b8db933 100644 --- a/hyperspace/ethereum/src/ibc_provider.rs +++ b/hyperspace/ethereum/src/ibc_provider.rs @@ -417,8 +417,6 @@ impl IbcProvider for EthereumClient { .expect("contract is missing UpdateClient event") .to_block(at.revision_height) .from_block(at.revision_height); - // .from_block(BlockNumber::Earliest) - // .to_block(BlockNumber::Latest); event_filter.filter = event_filter .filter .topic1({ @@ -583,7 +581,7 @@ impl IbcProvider for EthereumClient { .pop() // get only the last event ; log::info!(target: "hyperspace_ethereum", "qcs {}", line!()); - let batch_func = self.yui.function("call_batch")?; + let batch_func = self.yui.function("callBatch")?; match maybe_log { Some(log) => { let tx_hash = log.transaction_hash.expect("tx hash should exist"); @@ -672,58 +670,13 @@ impl IbcProvider for EthereumClient { }, } - // let decoded_log = UpdateClientFilter::decode_log(&log.clone().into()).unwrap(); - // decoded_log. - // let block_number = self - // .client() - // .get_block(BlockId::Hash(block_hash)) - // .await - // .unwrap() - // .unwrap() - // .number - // .unwrap(); - // let event_filter = self - // .yui - // .event_for_name::("GeneratedClientIdentifier") - // .expect("contract is missing GeneratedClientIdentifier event") - // .from_block(block_number) - // .to_block(block_number); - // let log = self - // .yui - // .diamond - // .client() - // .get_logs(&event_filter.filter) - // .await - // .unwrap() - // .into_iter() - // .find(|log| log.transaction_hash.expect("tx hash should exist") == tx_hash) - // .unwrap(); - - // let decoded_log = - // GeneratedClientIdentifierFilter::decode_log(&log.clone().into()).unwrap(); - - // emit CreateClient(clientId, msg_.clientType); - // emit UpdateClient(msg_.clientId, keccak256(msg_.clientMessage)); - // let (client_state, _): (Vec, bool) = self - // .yui - // .method("getClientState", (client_id.to_string(),)) - // .expect("contract is missing getClientState") - // .block(BlockId::Number(BlockNumber::Number(at.revision_height.into()))) - // .call() - // .await - // .map_err(|err| todo!("query-client-state: error: {err:?}")) - // .unwrap(); - let proof_height = Some(at.into()); - // let client_state = google::protobuf::Any::decode(&*client_state).ok(); Ok(QueryClientStateResponse { client_state: Some(client_state.expect("should always be initialized").to_any()), proof_height, proof: vec![0], }) - // log::error!(target: "hyperspace_ethereum", "TODO: implement query_client_state"); - // todo!() } async fn query_connection_end( diff --git a/hyperspace/ethereum/src/mock/utils.rs b/hyperspace/ethereum/src/mock/utils.rs index 968ffa11a..8e4725bbd 100644 --- a/hyperspace/ethereum/src/mock/utils.rs +++ b/hyperspace/ethereum/src/mock/utils.rs @@ -101,7 +101,7 @@ pub fn compile_solc(project_paths: ProjectPathsConfig) -> ProjectCompileOutput { stop_after: None, remappings: vec![], optimizer: Optimizer { - enabled: Some(true), + enabled: Some(false), runs: Some(5), details: Some(OptimizerDetails { peephole: Some(true), diff --git a/light-clients/common/Cargo.toml b/light-clients/common/Cargo.toml index fd4b5fc6e..978147135 100644 --- a/light-clients/common/Cargo.toml +++ b/light-clients/common/Cargo.toml @@ -12,6 +12,7 @@ serde = { version = "1.0.144", default-features = false, features = ["derive"] } derive_more = { version = "0.99.17", default-features = false, features = ["from"] } hash-db = { version = "0.15.2", default-features = false } async-trait = { version = "0.1.53", default-features = false } +hex = "0.4.3" # ibc ibc = { path = "../../ibc/modules", default-features = false } From 6f3feb8955e7df78c116ec3bd31e278de8f6b77c Mon Sep 17 00:00:00 2001 From: "rust.dev" <102041955+RustNinja@users.noreply.github.com> Date: Tue, 12 Sep 2023 17:45:29 +0100 Subject: [PATCH 23/43] Use client error instead of unwrap and expect in ibc provider (#49) * use client error in ibc provider * more replacement of unwrap to ClientError * replace in query_client_update_time_and_height * remove few unwrap and use ClientError * update 1 more fn query_client_id_from_tx_hash to replace unwrap * more changes to return ClientError instead of unwrap or expect * update ibc provider * remove all panic, unwrap and expect and return ClientError ibc provider --- hyperspace/ethereum/src/ibc_provider.rs | 440 +++++++++++++++++------- 1 file changed, 309 insertions(+), 131 deletions(-) diff --git a/hyperspace/ethereum/src/ibc_provider.rs b/hyperspace/ethereum/src/ibc_provider.rs index 03bf7efce..35ceebfa1 100644 --- a/hyperspace/ethereum/src/ibc_provider.rs +++ b/hyperspace/ethereum/src/ibc_provider.rs @@ -172,7 +172,9 @@ pub async fn parse_ethereum_events( for log in logs { let raw_log = RawLog::from(log.clone()); - let height = Height::new(0, log.block_number.unwrap().as_u64()); + let height = Height::new(0, log.block_number.ok_or( + ClientError::Other("block number not found".to_string()) + )?.as_u64()); let topic0 = log.topics[0]; macro_rules! handle_events { @@ -270,12 +272,18 @@ impl IbcProvider for EthereumClient { log::info!(target: "hyperspace_ethereum", "Getting blocks {}..{}", from, to); let filter = Filter::new().from_block(from).to_block(to).address(self.yui.diamond.address()); - let mut logs = self.client().get_logs(&filter).await.unwrap(); + let mut logs = self.client().get_logs(&filter).await.map_err(|e| { + ClientError::Other(format!("failed to get logs: {}", e)) + })?; let filter = Filter::new() .from_block(from) .to_block(to) - .address(self.yui.bank.as_ref().unwrap().address()); - let logs2 = self.client().get_logs(&filter).await.unwrap(); + .address(self.yui.bank.as_ref().ok_or( + ClientError::Other("bank contract not found".to_string()) + )?.address()); + let logs2 = self.client().get_logs(&filter).await.map_err( + |e| ClientError::Other(format!("failed to get logs: {}", e)), + )?; logs.extend(logs2); let maybe_proof = prove_fast(self, &client_state, block.slot).await; @@ -392,7 +400,9 @@ impl IbcProvider for EthereumClient { ]), ), ) - .expect("contract is missing getConsensusState"); + .map_err( + |err| ClientError::Other(format!("contract is missing getConsensusState {}", err)), + )?; let (client_cons, _): (Vec, bool) = binding .block(BlockId::Number(BlockNumber::Number(at.revision_height.into()))) @@ -402,7 +412,7 @@ impl IbcProvider for EthereumClient { log::error!(target: "hyperspace_ethereum", "error: {err}"); err }) - .unwrap(); + .map_err(|err| ClientError::Other(format!("failed to query client consensus: {}", err)))?; let proof_height = Some(at.into()); let consensus_state = google::protobuf::Any::decode(&*client_cons).ok(); @@ -421,7 +431,9 @@ impl IbcProvider for EthereumClient { let mut event_filter = self .yui .event_for_name::("UpdateClient") - .expect("contract is missing UpdateClient event") + .map_err( + |err| ClientError::Other(format!("contract is missing UpdateClient event: {}", err)), + )? .from_block(BlockNumber::Earliest) .to_block(at.revision_height); event_filter.filter = event_filter.filter.topic1({ @@ -437,30 +449,44 @@ impl IbcProvider for EthereumClient { .client() .get_logs(&event_filter.filter) .await - .unwrap() + .map_err( + |err| ClientError::Other(format!("failed to get logs: {}", err)), + )? .pop() // get only the last event ; log::info!(target: "hyperspace_ethereum", "qcs {}", line!()); let batch_func = self.yui.function("call_batch")?; match maybe_log { Some(log) => { - let tx_hash = log.transaction_hash.expect("tx hash should exist"); + let tx_hash = log.transaction_hash.ok_or( + ClientError::Other("tx hash not found".to_string()), + )?; let func = self.yui.function("updateClient")?; let tx = - self.client().get_transaction(tx_hash).await.unwrap().ok_or_else(|| { + self.client().get_transaction(tx_hash).await.map_err( + |err| ClientError::Other(format!("failed to get transaction: {}", err)), + )?.ok_or_else(|| { ClientError::Other(format!("transaction not found: {}", tx_hash)) })?; let Token::Array(batch_calldata) = - batch_func.decode_input(&tx.input[4..])?.pop().unwrap() + batch_func.decode_input(&tx.input[4..])?.pop().ok_or( + ClientError::Other("batch calldata not found".to_string()), + )? else { return Err(ClientError::Other("batch calldata not found".to_string())) }; for input_tok in batch_calldata.into_iter().rev() { - let Token::Bytes(input) = input_tok else { panic!() }; + let Token::Bytes(input) = input_tok else { + return Err(ClientError::Other("input token should be bytes".to_string())) + }; if input[..4] == func.short_signature() { - let calldata = func.decode_input(&input[4..])?.pop().unwrap(); - let Token::Tuple(toks) = calldata else { panic!() }; + let calldata = func.decode_input(&input[4..])?.pop().ok_or( + ClientError::Other("calldata not found".to_string()), + )?; + let Token::Tuple(toks) = calldata else { + return Err(ClientError::Other("calldata should be bytes".to_string())) + }; let header = tm_header_from_abi_token(toks[1].clone())?; let client_state_token = toks[2].clone(); let mut cs = @@ -483,7 +509,9 @@ impl IbcProvider for EthereumClient { let mut event_filter = self .yui .event_for_name::("CreateClient") - .expect("contract is missing CreateClient event") + .map_err( + |err| ClientError::Other(format!("contract is missing CreateClient event: {}", err)), + )? .from_block(BlockNumber::Earliest) .to_block(at.revision_height); event_filter.filter = event_filter.filter.topic1({ @@ -498,28 +526,40 @@ impl IbcProvider for EthereumClient { .client() .get_logs(&event_filter.filter) .await - .unwrap() + .map_err( + |err| ClientError::Other(format!("failed to get logs: {}", err)), + )? .pop() // get only the last event .ok_or_else(|| ClientError::Other("no events found".to_string()))?; - let tx_hash = log.transaction_hash.expect("tx hash should exist"); + let tx_hash = log.transaction_hash.ok_or( + ClientError::Other("tx hash not found".to_string()), + )?; let func = self.yui.function("createClient")?; let tx = - self.client().get_transaction(tx_hash).await.unwrap().ok_or_else(|| { + self.client().get_transaction(tx_hash).await. + map_err(|err| ClientError::Other(format!("failed to get transaction: {}", err)))? + .ok_or_else(|| { ClientError::Other(format!("transaction not found: {}", tx_hash)) })?; let Token::Array(batch_calldata) = - batch_func.decode_input(&tx.input[4..])?.pop().unwrap() + batch_func.decode_input(&tx.input[4..])?.pop(). + ok_or(ClientError::Other("batch calldata not found".to_string()))? else { return Err(ClientError::Other("batch calldata not found".to_string())) }; for input_tok in batch_calldata.into_iter().rev() { - let Token::Bytes(input) = input_tok else { panic!() }; + let Token::Bytes(input) = input_tok else { + return Err(ClientError::Other("input token should be bytes".to_string())) + }; if input[..4] == func.short_signature() { - let calldata = func.decode_input(&input[4..])?.pop().unwrap(); - let Token::Tuple(toks) = calldata else { panic!() }; + let calldata = func.decode_input(&input[4..])?.pop(). + ok_or(ClientError::Other("calldata not found".to_string()))?; + let Token::Tuple(toks) = calldata else { + return Err(ClientError::Other("calldata should be bytes".to_string())) + }; let client_state_token = toks[1].clone(); client_state = Some(client_state_from_abi_token::( client_state_token, @@ -576,7 +616,9 @@ impl IbcProvider for EthereumClient { // let client_state = google::protobuf::Any::decode(&*client_state).ok(); Ok(QueryClientStateResponse { - client_state: Some(client_state.expect("should always be initialized").to_any()), + client_state: Some(client_state.ok_or( + ClientError::Other("client state not found".to_string()) + )?.to_any()), proof_height, proof: vec![0], }) @@ -592,7 +634,9 @@ impl IbcProvider for EthereumClient { let (connection_end, exists): (ConnectionEndData, bool) = self .yui .method("getConnection", (connection_id.to_string(),)) - .expect("contract is missing getConnectionEnd") + .map_err( + |err| ClientError::Other(format!("contract is missing getConnectionEnd {}", err)), + )? .block(BlockId::Number(BlockNumber::Number(at.revision_height.into()))) .call() .await @@ -642,15 +686,21 @@ impl IbcProvider for EthereumClient { "getChannel", (port_id.as_str().to_owned(), channel_id.to_string()), ) - .expect("contract is missing getChannel"); + .map_err( + |err| ClientError::Other(format!("contract is missing getChannel {}", err)), + )?; let channel_data = binding .block(BlockId::Number(BlockNumber::Number(at.revision_height.into()))) .call() .await - .unwrap(); + .map_err( + |err| ClientError::Other(format!("failed to query channel: {}", err)), + )?; - let _state = State::from_i32(channel_data.state as _).expect("invalid channel state"); + let _state = State::from_i32(channel_data.state as _).map_err( + |err| ClientError::Other(format!("invalid channel state: {}", err)), + )?; let counterparty = Some(ChannelCounterparty { port_id: channel_data.counterparty.port_id, channel_id: channel_data.counterparty.channel_id, @@ -705,7 +755,9 @@ impl IbcProvider for EthereumClient { let proof = self .eth_query_proof(&path, Some(at.revision_height), COMMITMENTS_STORAGE_INDEX) .await?; - let storage = proof.storage_proof.first().unwrap(); + let storage = proof.storage_proof.first().ok_or( + ClientError::Other("storage proof not found".to_string()), + )?; let bytes = u256_to_bytes(&storage.value); Ok(QueryPacketCommitmentResponse { @@ -735,7 +787,9 @@ impl IbcProvider for EthereumClient { let proof = self .eth_query_proof(&path, Some(at.revision_height), COMMITMENTS_STORAGE_INDEX) .await?; - let storage = proof.storage_proof.first().unwrap(); + let storage = proof.storage_proof.first().ok_or( + ClientError::Other("storage proof not found".to_string()), + )?; let bytes = u256_to_bytes(&storage.value); @@ -760,13 +814,17 @@ impl IbcProvider for EthereumClient { "getNextSequenceRecv", (channel_id.to_string(), port_id.as_str().to_owned()), ) - .expect("contract is missing getNextSequenceRecv"); + .map_err( + |err| ClientError::Other(format!("contract is missing getNextSequenceRecv {}", err)), + )?; let channel_data = binding .block(BlockId::Number(BlockNumber::Number(at.revision_height.into()))) .call() .await - .unwrap(); + .map_err( + |err| ClientError::Other(format!("failed to query channel_data: {}", err)), + )?; Ok(QueryNextSequenceReceiveResponse { next_sequence_receive: todo!(), @@ -792,7 +850,9 @@ impl IbcProvider for EthereumClient { let proof = self .eth_query_proof(&path, Some(at.revision_height), COMMITMENTS_STORAGE_INDEX) .await?; - let storage = proof.storage_proof.first().unwrap(); + let storage = proof.storage_proof.first().ok_or( + ClientError::Other("storage proof not found".to_string()), + )?; let received = self .has_packet_receipt(at, port_id.as_str().to_owned(), format!("{channel_id}"), sequence) @@ -821,7 +881,9 @@ impl IbcProvider for EthereumClient { .ok_or_else(|| ClientError::MiddlewareError(todo!()))?; let nanoseconds = Duration::from_secs(block.timestamp.as_u64()).as_nanos() as u64; - let timestamp = Timestamp::from_nanoseconds(nanoseconds).expect("timestamp error"); + let timestamp = Timestamp::from_nanoseconds(nanoseconds).map_err( + |e| ClientError::Other(format!("failed to parse timestamp : {nanoseconds}, err: {e}")), + )?; log::info!(target: "hyperspace_ethereum", "latest_height_and_timestamp: {height:?}, {timestamp:?}"); @@ -842,13 +904,17 @@ impl IbcProvider for EthereumClient { "hasCommitments", (port_id.as_str().to_owned(), channel_id.to_string(), start_seq, end_seq), ) - .expect("contract is missing getConnectionEnd"); + .map_err( + |err| ClientError::Other(format!("contract is missing hasCommitments {}", err)), + )?; let bitmap: U256 = binding .block(BlockId::Number(BlockNumber::Number(at.revision_height.into()))) .call() .await - .unwrap(); + .map_err( + |err| ClientError::Other(format!("failed to query_packet_commitments: {}", err)), + )?; let mut seqs = vec![]; for i in 0..256u64 { if bitmap.bit(i as _).into() { @@ -880,13 +946,17 @@ impl IbcProvider for EthereumClient { "hasAcknowledgements", (port_id.as_str().to_owned(), channel_id.to_string(), start_seq, end_seq), ) - .expect("contract is missing getConnectionEnd"); + .map_err( + |err| ClientError::Other(format!("contract is missing hasAcknowledgements {}", err)), + )?; let bitmap: U256 = binding .block(BlockId::Number(BlockNumber::Number(at.revision_height.into()))) .call() .await - .unwrap(); + .map_err( + |err| ClientError::Other(format!("failed to query_packet_acknowledgements: {}", err)), + )?; let mut seqs = vec![]; for i in 0..256u64 { if bitmap.bit(i as _).into() { @@ -972,7 +1042,9 @@ impl IbcProvider for EthereumClient { let event_filter = self .yui .event_for_name::("SendPacket") - .expect("contract is missing SendPacket event") + .map_err( + |err| ClientError::ContractAbiError(err), + )? .from_block(BlockNumber::Earliest) // TODO: use contract creation height .to_block(BlockNumber::Latest) .topic1(ValueOrArray::Array( @@ -1007,43 +1079,61 @@ impl IbcProvider for EthereumClient { data.into_iter().map(hex::encode).collect::>().join(", ") ); } - let mut logs = self.yui.diamond.client().get_logs(&event_filter.filter).await.unwrap(); + let mut logs = self.yui.diamond.client().get_logs(&event_filter.filter).await.map_err( + |err| ClientError::Other(format!("failed to get logs: {}", err)), + )?; let logs2 = self .yui .bank .as_ref() - .unwrap() + .ok_or( + ClientError::Other("bank contract not found".to_string()), + )? .client() .get_logs(&event_filter.filter) .await - .unwrap(); + .map_err( + |err| ClientError::Other(format!("failed to get logs: {}", err)), + )?; logs.extend(logs2); let channel = self.query_channel_end(at, channel_id, port_id).await?; - let channel = channel.channel.expect("channel is none"); - let counterparty = channel.counterparty.expect("counterparty is none"); - Ok(logs - .into_iter() - .map(move |log| { - let value = SendPacketFilter::decode_log(&log.clone().into()).unwrap(); - PacketInfo { - height: Some(log.block_number.unwrap().as_u64().into()), - source_port: source_port.clone(), - source_channel: source_channel.clone(), - destination_port: counterparty.port_id.clone(), - destination_channel: counterparty.channel_id.clone(), - sequence: value.sequence, - timeout_height: value.timeout_height.into(), - timeout_timestamp: value.timeout_timestamp, - data: value.data.to_vec(), - channel_order: Order::from_i32(channel.ordering) - .map_err(|_| Self::Error::Other("invalid channel order".to_owned())) - .unwrap() - .to_string(), - ack: None, - } - }) - .collect()) + let channel = channel.channel.ok_or( + ClientError::Other("channel is none".to_string()), + )?; + let counterparty = channel.counterparty.ok_or( + ClientError::Other("counterparty is none".to_string()), + )?; + + let mut ret = vec![]; + + for log in logs.into_iter() { + log::debug!(target: "hyperspace_ethereum", "log: {:?}", log); + let value = SendPacketFilter::decode_log(&log.clone().into()).map_err( + |err| ClientError::Other(format!("failed to decode log: {}", err)), + )?; + let packet_info = PacketInfo { + height: Some(log.block_number.ok_or( + ClientError::Other("block number not found".to_string()), + )?.as_u64().into()), + source_port: source_port.clone(), + source_channel: source_channel.clone(), + destination_port: counterparty.port_id.clone(), + destination_channel: counterparty.channel_id.clone(), + sequence: value.sequence, + timeout_height: value.timeout_height.into(), + timeout_timestamp: value.timeout_timestamp, + data: value.data.to_vec(), + channel_order: Order::from_i32(channel.ordering) + .map_err(|_| + ClientError::Other("invalid channel order".to_string()) + )? + .to_string(), + ack: None, + }; + ret.push(packet_info); + } + Ok(ret) } async fn query_received_packets( @@ -1058,7 +1148,9 @@ impl IbcProvider for EthereumClient { let event_filter = self .yui .event_for_name::("RecvPacket") - .expect("contract is missing RecvPacket event") + .map_err( + |err| ClientError::ContractAbiError(err), + )? .from_block(BlockNumber::Earliest) // TODO: use contract creation height .to_block(BlockNumber::Latest) .topic1(ValueOrArray::Array( @@ -1081,14 +1173,20 @@ impl IbcProvider for EthereumClient { )]))) }); - let logs = self.yui.diamond.client().get_logs(&event_filter.filter).await.unwrap(); + let logs = self.yui.diamond.client().get_logs(&event_filter.filter).await.map_err( + |err| ClientError::Other(format!("failed to get logs in query_received_packets: {}", err)), + )?; let channel = self.query_channel_end(at, channel_id, port_id).await?; - let channel = channel.channel.expect("channel is none"); + let channel = channel.channel.ok_or( + ClientError::Other("channel is none".to_string()), + )?; let acks_filter = self .yui .event_for_name::("WriteAcknowledgement") - .expect("contract is missing WriteAcknowledgement event") + .map_err( + |err| ClientError::ContractAbiError(err), + )? .from_block(BlockNumber::Earliest) // TODO: use contract creation height .to_block(BlockNumber::Latest) .topic3(ValueOrArray::Array( @@ -1113,33 +1211,40 @@ impl IbcProvider for EthereumClient { let mut acks_map = acks_filter .query() .await - .unwrap() + .map_err( + |err| ClientError::Other(format!("failed to get acks_map in query_received_packets: {}", err)), + )? .into_iter() .map(|ack| (ack.sequence, ack.acknowledgement.to_vec())) .collect::>(); - Ok(logs - .into_iter() - .map(move |log| { - let value = RecvPacketFilter::decode_log(&log.clone().into()).unwrap(); - PacketInfo { - height: Some(log.block_number.unwrap().as_u64().into()), - source_port: value.source_port.clone(), - source_channel: value.source_channel.clone(), - destination_port: destination_port.clone(), - destination_channel: destination_channel.clone(), - sequence: value.sequence, - timeout_height: value.timeout_height.into(), - timeout_timestamp: value.timeout_timestamp, - data: value.data.to_vec(), - channel_order: Order::from_i32(channel.ordering) - .map_err(|_| Self::Error::Other("invalid channel order".to_owned())) - .unwrap() - .to_string(), - ack: acks_map.get(&value.sequence).cloned(), - } - }) - .collect()) + let mut ret = vec![]; + + for log in logs.into_iter() { + let value = RecvPacketFilter::decode_log(&log.clone().into()).map_err( + |err| ClientError::Other(format!("failed to decode log in query_send_packets: {}", err)), + )?; + let packet_info = PacketInfo { + height: Some(log.block_number.ok_or( + ClientError::Other("block number not found".to_string()), + )?.as_u64().into()), + source_port: value.source_port.clone(), + source_channel: value.source_channel.clone(), + destination_port: destination_port.clone(), + destination_channel: destination_channel.clone(), + sequence: value.sequence, + timeout_height: value.timeout_height.into(), + timeout_timestamp: value.timeout_timestamp, + data: value.data.to_vec(), + channel_order: Order::from_i32(channel.ordering) + .map_err(|_| Self::Error::Other("invalid channel order in query_send_packets".to_owned()))? + .to_string(), + ack: acks_map.get(&value.sequence).cloned(), + }; + ret.push(packet_info); + } + + Ok(ret) } fn expected_block_time(&self) -> Duration { @@ -1154,7 +1259,9 @@ impl IbcProvider for EthereumClient { let event_filter = self .yui .event_for_name::("UpdateClientHeight") - .expect("contract is missing UpdateClientHeight event") + .map_err( + |err| ClientError::ContractAbiError(err), + )? .from_block(BlockNumber::Earliest) // TODO: use contract creation height .to_block(BlockNumber::Latest) .topic1({ @@ -1178,15 +1285,23 @@ impl IbcProvider for EthereumClient { .client() .get_logs(&event_filter.filter) .await - .unwrap() + .map_err( + |err| ClientError::Other(format!("failed to get logs in query_client_update_time_and_height: {}", err)), + )? .pop() - .unwrap(); + .ok_or( + ClientError::Other("no logs found".to_string()), + )?; - let height = Height::new(0, log.block_number.expect("block number is none").as_u64()); + let height = Height::new(0, log.block_number.ok_or( + ClientError::Other("block number not found in query_client_update_time_and_height".to_string()), + )?.as_u64()); let timestamp = Timestamp::from_nanoseconds(self.query_timestamp_at(height.revision_height).await?) - .unwrap(); + .map_err( + |err| ClientError::Other(format!("failed to get timestamp in query_client_update_time_and_height: {}", err)), + )?; Ok((height, timestamp)) } @@ -1206,10 +1321,14 @@ impl IbcProvider for EthereumClient { .yui .bank .as_ref() - .expect("bank is none") + .ok_or( + ClientError::Other("bank contract not found".to_string()), + )? .method::<_, U256>( "balanceOf", - (H160::from_str(&self.account_id().to_string()).unwrap(), asset_id.clone()), + (H160::from_str(&self.account_id().to_string()).map_err( + |_| ClientError::Other("failed get bytes from account id".to_string()), + )?, asset_id.clone()), )? .call() .await?; @@ -1307,9 +1426,13 @@ impl IbcProvider for EthereumClient { ) -> Result<(AnyClientState, AnyConsensusState), Self::Error> { let sync_committee_prover = self.prover(); let block_id = "head"; - let block_header = sync_committee_prover.fetch_header(&block_id).await.unwrap(); + let block_header = sync_committee_prover.fetch_header(&block_id).await.map_err( + |err| ClientError::Other(format!("failed to fetch header in initialize_client_state: {}", err)), + )?; - let state = sync_committee_prover.fetch_beacon_state(block_id).await.unwrap(); + let state = sync_committee_prover.fetch_beacon_state(block_id).await.map_err( + |err| ClientError::Other(format!("failed to fetch beacon state in initialize_client_state: {}", err)), + )?; // TODO: query `at` block // let finality_checkpoint = @@ -1329,11 +1452,15 @@ impl IbcProvider for EthereumClient { .client() .get_block(BlockId::Number(BlockNumber::Number(execution_header.block_number.into()))) .await - .unwrap() - .unwrap(); + .map_err( + |err| ClientError::MiddlewareError(err), + )? + .ok_or( + ClientError::Other(format!("not able to find a block : {}", execution_header.block_number.to_string())), + )?; dbg!(&block.state_root); - dbg!(&block.hash.unwrap()); + dbg!(&block.hash.unwrap_or_default()); dbg!(&state.state_roots.iter().take(10).collect::>()); dbg!(&state.block_roots.iter().take(10).collect::>()); dbg!(&block_header.state_root); @@ -1354,7 +1481,9 @@ impl IbcProvider for EthereumClient { // block.timestamp.as_u64() as i64, 0, ) - .unwrap(), + .map_err( + |err| ClientError::Other(format!("failed to get timestamp in initialize_client_state: {}, timestamp{}", err, execution_header.timestamp)), + )?.into(), root: CommitmentRoot { bytes: execution_header.state_root.to_vec() }, // root: CommitmentRoot { bytes: block.state_root.0.to_vec() }, }); @@ -1370,14 +1499,22 @@ impl IbcProvider for EthereumClient { .client() .get_block(BlockId::Hash(block_hash)) .await - .unwrap() - .unwrap() + .map_err( + |err| ClientError::MiddlewareError(err) + )? + .ok_or( + ClientError::Other(format!("not able to find a block : {}", block_hash.to_string())) + )? .number - .unwrap(); + .ok_or( + ClientError::Other(format!("not able to find a block number with hash: {}", block_hash.to_string())) + )?; let event_filter = self .yui .event_for_name::("GeneratedClientIdentifier") - .expect("contract is missing GeneratedClientIdentifier event") + .map_err( + |err| ClientError::ContractAbiError(err) + )? .from_block(block_number) .to_block(block_number); let log = self @@ -1386,12 +1523,18 @@ impl IbcProvider for EthereumClient { .client() .get_logs(&event_filter.filter) .await - .unwrap() + .map_err( + |err| ClientError::MiddlewareError(err) + )? .into_iter() - .find(|log| log.transaction_hash.expect("tx hash should exist") == tx_hash) - .unwrap(); - - let decoded_log = GeneratedClientIdentifierFilter::decode_log(&log.clone().into()).unwrap(); + .find(|log| log.transaction_hash == Some(tx_hash)) + .ok_or( + ClientError::Other(format!("not able to find a log with tx hash: {}", tx_hash.to_string())) + )?; + + let decoded_log = GeneratedClientIdentifierFilter::decode_log(&log.clone().into()).map_err( + |err| ClientError::Other(format!("failed to decode log in query_client_id_from_tx_hash: {}", err)) + )?; Ok(decoded_log.0.parse()?) } @@ -1403,14 +1546,22 @@ impl IbcProvider for EthereumClient { .client() .get_block(BlockId::Hash(block_hash)) .await - .unwrap() - .unwrap() + .map_err( + |err| ClientError::MiddlewareError(err), + )? + .ok_or( + ClientError::Other(format!("not able to find a block with hash: {}", block_hash.to_string())), + )? .number - .unwrap(); + .ok_or( + ClientError::Other(format!("not able to find a block number with hash: {}", block_hash.to_string())), + )?; let event_filter = self .yui .event_for_name::("OpenInitConnection") - .expect("contract is missing OpenInitConnection event") + .map_err( + |err| ClientError::ContractAbiError(err), + )? .from_block(block_number) .to_block(block_number); let log = self @@ -1419,12 +1570,18 @@ impl IbcProvider for EthereumClient { .client() .get_logs(&event_filter.filter) .await - .unwrap() + .map_err( + |err| ClientError::MiddlewareError(err), + )? .into_iter() - .find(|log| log.transaction_hash.expect("tx hash should exist") == tx_hash) - .unwrap(); - - let decoded_log = OpenInitConnectionFilter::decode_log(&log.clone().into()).unwrap(); + .find(|log| log.transaction_hash == Some(tx_hash)) + .ok_or( + ClientError::Other(format!("not able to find a log with tx hash: {}", tx_hash.to_string())), + )?; + + let decoded_log = OpenInitConnectionFilter::decode_log(&log.clone().into()).map_err( + |err| ClientError::Other(format!("failed to decode OpenInitConnectionFilter in query_connection_id_from_tx_hash: {}", err)), + )?; Ok(decoded_log.connection_id.parse()?) } @@ -1436,14 +1593,22 @@ impl IbcProvider for EthereumClient { .client() .get_block(BlockId::Hash(block_hash)) .await - .unwrap() - .unwrap() + .map_err( + |err| ClientError::MiddlewareError(err), + )? + .ok_or( + ClientError::Other(format!("not able to find a block with hash: {}", block_hash.to_string())), + )? .number - .unwrap(); + .ok_or( + ClientError::Other(format!("not able to find a block number with hash: {}", block_hash.to_string())), + )?; let event_filter = self .yui .event_for_name::("OpenInitChannel") - .expect("contract is missing OpenInitChannel event") + .map_err( + |err| ClientError::ContractAbiError(err), + )? .from_block(block_number) .to_block(block_number); let log = self @@ -1452,12 +1617,25 @@ impl IbcProvider for EthereumClient { .client() .get_logs(&event_filter.filter) .await - .unwrap() + .map_err( + |err| ClientError::MiddlewareError(err), + )? .into_iter() - .find(|log| log.transaction_hash.expect("tx hash should exist") == tx_hash) - .unwrap(); + .find(|log| + if let Some(transaction_hash) = &log.transaction_hash { + *transaction_hash == tx_hash + } else { + log::error!(target: "hyperspace_ethereum", "tx hash should exist: {tx_hash}"); + return false; + } + ) + .ok_or( + ClientError::Other(format!("not able to find a log with tx hash: {}", tx_hash.to_string())), + )?; - let decoded_log = OpenInitChannelFilter::decode_log(&log.clone().into()).unwrap(); + let decoded_log = OpenInitChannelFilter::decode_log(&log.clone().into()).map_err( + |err| ClientError::Other(format!("failed to decode OpenInitChannelFilter in query_channel_id_from_tx_hash: {}", err)), + )?; Ok((decoded_log.channel_id.parse()?, decoded_log.port_id.parse()?)) } From bd7ecaea92840a3a8caa051cbe506ea028f08077 Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Thu, 14 Sep 2023 02:31:56 -0300 Subject: [PATCH 24/43] Improve Ethereum provider functionality and update dependencies This update includes several changes to improve the functionality of the Ethereum provider, as well as an update of dependencies. Specific changes include the removal of unnecessary log info calls and the addition of debug level logging to capture events. Additionally, the calculation of the 'from' and 'to' values for block processing has been streamlined. Dependencies for the Ethereum provider, such as 'anyhow', have also been updated to the latest versions. The update also includes a fix to ensure that the mock Ethereum client has the correct commitment sequences. This was necessary to ensure the Ethereum provider operates optimally, with relevant debug info being captured. The dependency updates ensure compatibility and security, and the mock client fix ensures accurate testing results. --- algorithms/beefy/prover/Cargo.toml | 2 +- contracts/pallet-ibc/src/light_clients.rs | 15 +- hyperspace/ethereum/Cargo.toml | 7 +- hyperspace/ethereum/src/chain.rs | 2 - hyperspace/ethereum/src/client.rs | 25 +++ hyperspace/ethereum/src/ibc_provider.rs | 31 +-- hyperspace/ethereum/src/prove.rs | 221 ++-------------------- hyperspace/ethereum/src/utils.rs | 1 - hyperspace/testsuite/src/lib.rs | 8 +- 9 files changed, 54 insertions(+), 258 deletions(-) diff --git a/algorithms/beefy/prover/Cargo.toml b/algorithms/beefy/prover/Cargo.toml index e04faaf65..dff74ee27 100644 --- a/algorithms/beefy/prover/Cargo.toml +++ b/algorithms/beefy/prover/Cargo.toml @@ -8,7 +8,7 @@ authors = ["Seun Lanlege ", "David Salami Result<(), EthereumError> { - unimplemented!() - } -} - #[derive(Clone, Debug, PartialEq, Eq, ClientDef)] pub enum AnyClient { Grandpa(ics10_grandpa::client_def::GrandpaClient), @@ -397,7 +384,7 @@ impl AnyClientMessage { #[cfg(feature = "ethereum")] Self::Ethereum(m) => match m { icsxx_ethereum::client_message::ClientMessage::Header(h) => - Some(Height::new(0, h.execution_payload.block_number)), + Some(Height::new(0, h.inner.execution_payload.block_number)), icsxx_ethereum::client_message::ClientMessage::Misbehaviour(_) => None, }, #[cfg(test)] diff --git a/hyperspace/ethereum/Cargo.toml b/hyperspace/ethereum/Cargo.toml index 5ef8aeed4..f50a375b9 100644 --- a/hyperspace/ethereum/Cargo.toml +++ b/hyperspace/ethereum/Cargo.toml @@ -19,11 +19,10 @@ icsxx-ethereum = { path = "../../light-clients/icsxx-ethereum" } pallet-ibc = { path = "../../contracts/pallet-ibc" } hyperspace-cosmos = { path = "../cosmos" } -sync-committee-primitives = { git = "https://github.com/polytope-labs/sync-committee-rs.git", rev = "c5afca4fbb92cb60dde29c3a89454c288b022d97", features = ["testing"] } -sync-committee-verifier = { git = "https://github.com/polytope-labs/sync-committee-rs.git", rev = "c5afca4fbb92cb60dde29c3a89454c288b022d97", features = ["testing"] } -sync-committee-prover = { git = "https://github.com/polytope-labs/sync-committee-rs.git", rev = "c5afca4fbb92cb60dde29c3a89454c288b022d97" } +sync-committee-primitives = { git = "https://github.com/polytope-labs/sync-committee-rs.git", rev = "106f53e045cc85c4a8d984c8e295800cebaa2475" } +sync-committee-verifier = { git = "https://github.com/polytope-labs/sync-committee-rs.git", rev = "106f53e045cc85c4a8d984c8e295800cebaa2475" } +sync-committee-prover = { git = "https://github.com/polytope-labs/sync-committee-rs.git", rev = "106f53e045cc85c4a8d984c8e295800cebaa2475" } #light-client-common = { path = "../common" } -ethereum-consensus = { git = "https://github.com/polytope-labs/ethereum-consensus", branch = "main" } ssz-rs = { git = "https://github.com/polytope-labs/ssz-rs", branch = "main" } cast = { git = "https://github.com/foundry-rs/foundry", version = "0.2.0" } diff --git a/hyperspace/ethereum/src/chain.rs b/hyperspace/ethereum/src/chain.rs index b5d6da178..7a3ad8d36 100644 --- a/hyperspace/ethereum/src/chain.rs +++ b/hyperspace/ethereum/src/chain.rs @@ -1234,8 +1234,6 @@ impl Chain for EthereumClient { } } - thread::sleep(Duration::from_secs(5)); - let block_hash = receipt.block_hash.ok_or(ClientError::Other("Block hash is missing".into()))?; Ok((block_hash, receipt.transaction_hash)) diff --git a/hyperspace/ethereum/src/client.rs b/hyperspace/ethereum/src/client.rs index 14328bbd2..7265e86f9 100644 --- a/hyperspace/ethereum/src/client.rs +++ b/hyperspace/ethereum/src/client.rs @@ -581,6 +581,31 @@ impl EthereumClient { } } + #[track_caller] + pub fn has_commitment( + &self, + at: Height, + port_id: String, + channel_id: String, + sequence: u64, + ) -> impl Future> + '_ { + async move { + let binding = self + .yui + .method("hasCommitment", (port_id, channel_id, sequence)) + .expect("contract is missing hasCommitment"); + + let receipt: bool = binding + .block(BlockId::Number(BlockNumber::Number(at.revision_height.into()))) + .call() + .await + .map_err(|err| todo!()) + .unwrap(); + + Ok(receipt) + } + } + #[track_caller] pub fn has_acknowledgement( &self, diff --git a/hyperspace/ethereum/src/ibc_provider.rs b/hyperspace/ethereum/src/ibc_provider.rs index 18e82555a..18740a113 100644 --- a/hyperspace/ethereum/src/ibc_provider.rs +++ b/hyperspace/ethereum/src/ibc_provider.rs @@ -62,7 +62,6 @@ use crate::{ COMMITMENTS_STORAGE_INDEX, CONNECTIONS_STORAGE_INDEX, }, events::TryFromEvent, - prove::prove, }; use futures::{FutureExt, Stream, StreamExt}; use ssz_rs::Merkleized; @@ -171,8 +170,6 @@ pub async fn parse_ethereum_events( logs: Vec, ) -> Result, ClientError> { let mut events = vec![]; - log::info!("SendPacketFilter.topic0 = {}", hex::encode(&SendPacketFilter::signature())); - for log in logs { let raw_log = RawLog::from(log.clone()); let height = Height::new( @@ -187,7 +184,9 @@ pub async fn parse_ethereum_events( ($topic0:ident, $events:ident, $log:ident, $raw_log:ident, $height:ident, $($ty:ty),+) => { $(if $topic0 == <$ty>::signature() { let event = <$ty>::decode_log(&$raw_log).expect("decode event"); - $events.push(IbcEvent::try_from_event(client, event, $log, $height).await?) + let ev = IbcEvent::try_from_event(client, event, $log, $height).await?; + log::debug!(target: "hyperspace_ethereum", "encountered event: {:?} at {}", ev.event_type(), ev.height()); + $events.push(ev); } else )+ { log::error!( target: "hyperspace_ethereum", "unknown event: {}", @@ -256,18 +255,12 @@ impl IbcProvider for EthereumClient { let latest_height = self.latest_height_and_timestamp().await?.0; let latest_revision = latest_height.revision_number; - // 1 slot = 1 block - // 1 epoch = 32 slot - // 1 block = 12 sec - // finalisation ~= 2.5 epoch - // 32 * 12 * 2.5 = 960 sec = 16 min - let prover = self.prover(); let block = prover.fetch_block("head").await?; let number = block.body.execution_payload.block_number; let height = Height::new(0, number.into()); - let from = latest_cp_client_height; + let from = latest_cp_client_height + 1; let to = number.min(latest_cp_client_height + NUMBER_OF_BLOCKS_TO_PROCESS_PER_ITER); // let to = finality_event // .number @@ -298,17 +291,14 @@ impl IbcProvider for EthereumClient { logs.extend(logs2); let maybe_proof = prove_fast(self, &client_state, block.slot).await; - // let Ok(update) = else { - // log::error!(target: "hyperspace_ethereum", "failed to prove"); - // return Ok(vec![]) - // }; - let update = match maybe_proof { + let header = match maybe_proof { Ok(x) => x, Err(e) => { log::error!(target: "hyperspace_ethereum", "failed to prove {e}"); return Ok(vec![]) }, }; + let update = &header.inner; // let update = prove(self, finality_event.number.unwrap().as_u64()).await?; log::info!(target: "hyperspace_ethereum", @@ -335,7 +325,7 @@ impl IbcProvider for EthereumClient { ); let msg = MsgUpdateAnyClient:: { client_id: client_id.clone(), - client_message: AnyClientMessage::Ethereum(ClientMessage::Header(update)), + client_message: AnyClientMessage::Ethereum(ClientMessage::Header(header)), signer: counterparty.account_id(), }; let value = msg.encode_vec().map_err(|e| { @@ -574,7 +564,6 @@ impl IbcProvider for EthereumClient { client_id: ClientId, ) -> Result { // First, we try to find an `UpdateClient` event at the given height... - log::info!(target: "hyperspace_ethereum", "qcs {}", line!()); let mut client_state = None; let mut event_filter = self .yui @@ -590,7 +579,6 @@ impl IbcProvider for EthereumClient { )])); ValueOrArray::Value(hash) }); - log::info!(target: "hyperspace_ethereum", "qcs {}", line!()); let maybe_log = self .yui .diamond @@ -602,7 +590,6 @@ impl IbcProvider for EthereumClient { )? .pop() // get only the last event ; - log::info!(target: "hyperspace_ethereum", "qcs {}", line!()); let batch_func = self.yui.function("callBatch")?; match maybe_log { Some(log) => { @@ -1122,8 +1109,8 @@ impl IbcProvider for EthereumClient { let mut pending = vec![]; for seq in seqs { - let received = self - .has_acknowledgement(at, port_id.as_str().to_owned(), format!("{channel_id}"), seq) + let received = !self + .has_commitment(at, port_id.as_str().to_owned(), format!("{channel_id}"), seq) .await?; if !received { diff --git a/hyperspace/ethereum/src/prove.rs b/hyperspace/ethereum/src/prove.rs index 4c6077254..c431742f9 100644 --- a/hyperspace/ethereum/src/prove.rs +++ b/hyperspace/ethereum/src/prove.rs @@ -1,14 +1,6 @@ // use base2::Base2; use crate::client::{ClientError, EthereumClient}; use anyhow::anyhow; -use ethereum_consensus::{ - altair::mainnet::SYNC_COMMITTEE_SIZE, - bellatrix::compute_domain, - phase0::mainnet::SLOTS_PER_EPOCH, - primitives::{Bytes32, Root}, - signing::compute_signing_root, - state_transition::Context, -}; use ethers::{ core::{rand, rand::Rng}, prelude::{EthCall, H256}, @@ -21,10 +13,10 @@ use ssz_rs::{ }; use std::time::Duration; use sync_committee_primitives::{ + constants::{Bytes32, SLOTS_PER_EPOCH}, types::{ AncestorBlock, AncestryProof, BlockRootsProof, ExecutionPayloadProof, FinalityProof, - LightClientState, LightClientUpdate, SyncCommitteeUpdate, DOMAIN_SYNC_COMMITTEE, - GENESIS_VALIDATORS_ROOT, + LightClientState, LightClientUpdate, SyncCommitteeUpdate, }, util::{compute_fork_version, compute_sync_committee_period_at_slot}, }; @@ -32,208 +24,17 @@ use sync_committee_prover::{ prove_block_roots_proof, prove_execution_payload, prove_finalized_header, prove_sync_committee_update, SyncCommitteeProver, }; -use sync_committee_verifier::{verify_sync_committee_attestation, SignatureVerifier}; +use sync_committee_verifier::verify_sync_committee_attestation; use tokio::{task::JoinSet, time, time::sleep}; // use tokio_stream::{wrappers::IntervalStream, StreamExt}; - -pub async fn prove( - client: &EthereumClient, - eth_client_state: &ClientState, - block_number: u64, -) -> Result, ClientError> { - let sync_committee_prover = client.prover(); - let client_state = ð_client_state.inner; - - let block_id = format!("{block_number:?}"); - let block_id = "head"; - - let finality_checkpoint = sync_committee_prover.fetch_finalized_checkpoint().await?; - if finality_checkpoint.finalized.root == Node::default() || - finality_checkpoint.finalized.epoch <= client_state.latest_finalized_epoch || - finality_checkpoint.finalized.root == - client_state.finalized_header.clone().hash_tree_root()? - { - return Err(ClientError::Other("No new finalized checkpoint found".into())) - } - - log::debug!(target: "hyperspace_ethereum", "A new epoch has been finalized {}", finality_checkpoint.finalized.epoch); - - let block_id = { - let mut block_id = hex::encode(finality_checkpoint.finalized.root.as_bytes()); - block_id.insert_str(0, "0x"); - block_id - }; - - let finalized_header = sync_committee_prover.fetch_header(&block_id).await?; - let finalized_state = sync_committee_prover - .fetch_beacon_state(finalized_header.slot.to_string().as_str()) - .await?; - let execution_payload_proof = prove_execution_payload(finalized_state.clone())?; - - let mut attested_epoch = finality_checkpoint.finalized.epoch + 2; - // Get attested header and the signature slot - - let mut attested_slot = attested_epoch * SLOTS_PER_EPOCH; - // Due to the fact that all slots in an epoch can be missed we are going to try and fetch - // the attested block from four possible epochs. - let mut attested_epoch_loop_count = 0; - let (attested_block_header, signature_block) = loop { - if attested_epoch_loop_count >= 4 { - panic!("Could not fetch any block from the attested epoch after going through four epochs, your Eth devnet is fucked") - } - // If we have maxed out the slots in the current epoch and still didn't find any block, - // we move to the next epoch - if (attested_epoch * SLOTS_PER_EPOCH).saturating_add(SLOTS_PER_EPOCH - 1) == attested_slot { - // No block was found in attested epoch we move to the next possible attested epoch - log::debug!(target: "hyperspace_ethereum", - "No slots found in epoch {attested_epoch} Moving to the next possible epoch {}", - attested_epoch + 1 - ); - std::thread::sleep(Duration::from_secs(24)); - attested_epoch += 1; - attested_slot = attested_epoch * SLOTS_PER_EPOCH; - attested_epoch_loop_count += 1; - } - - if let Ok(header) = - sync_committee_prover.fetch_header(attested_slot.to_string().as_str()).await - { - let mut signature_slot = header.slot + 1; - let mut loop_count = 0; - let signature_block = loop { - if loop_count == 2 { - break None - } - if (attested_epoch * SLOTS_PER_EPOCH).saturating_add(SLOTS_PER_EPOCH - 1) == - signature_slot - { - log::debug!(target: "hyperspace_ethereum", "Waiting for signature block for attested header"); - std::thread::sleep(Duration::from_secs(24)); - signature_slot = header.slot + 1; - loop_count += 1; - } - if let Ok(signature_block) = - sync_committee_prover.fetch_block(signature_slot.to_string().as_str()).await - { - break Some(signature_block) - } - signature_slot += 1; - }; - // If the next block does not have sufficient sync committee participants - if let Some(signature_block) = signature_block { - if signature_block - .body - .sync_aggregate - .sync_committee_bits - .as_bitslice() - .count_ones() < (2 * SYNC_COMMITTEE_SIZE) / 3 - { - attested_slot += 1; - log::debug!(target: "hyperspace_ethereum", "Signature block does not have sufficient sync committee participants -> participants {}", signature_block.body.sync_aggregate.sync_committee_bits.as_bitslice().count_ones()); - continue - } - break (header, signature_block) - } else { - log::debug!(target: "hyperspace_ethereum", "No signature block found in {attested_epoch} Moving to the next possible epoch {}", attested_epoch + 1); - std::thread::sleep(Duration::from_secs(24)); - attested_epoch += 1; - attested_slot = attested_epoch * SLOTS_PER_EPOCH; - attested_epoch_loop_count += 1; - continue - } - } - attested_slot += 1 - }; - - let attested_state = sync_committee_prover - .fetch_beacon_state(attested_block_header.slot.to_string().as_str()) - .await?; - - let finalized_hash_tree_root = finalized_header.clone().hash_tree_root()?; - log::debug!(target: "hyperspace_ethereum", "{:?}, {}", attested_state.finalized_checkpoint, attested_state.slot); - log::debug!(target: "hyperspace_ethereum", "{:?}, {}", finalized_hash_tree_root, finalized_header.slot); - - assert_eq!(finalized_hash_tree_root, attested_state.finalized_checkpoint.root); - - let finality_proof = FinalityProof { - epoch: finality_checkpoint.finalized.epoch, - finality_branch: prove_finalized_header(attested_state.clone())?, - }; - - let state_period = compute_sync_committee_period_at_slot(finalized_header.slot); - - let update_attested_period = compute_sync_committee_period_at_slot(attested_block_header.slot); - - let sync_committee_update = if state_period == update_attested_period { - let sync_committee_proof = prove_sync_committee_update(attested_state.clone())?; - - let sync_committee_proof = sync_committee_proof - .into_iter() - .map(|node| Bytes32::try_from(node.as_bytes()).expect("Node is always 32 byte slice")) - .collect::>(); - - Some(SyncCommitteeUpdate { - next_sync_committee: attested_state.next_sync_committee, - next_sync_committee_branch: sync_committee_proof, - }) - } else { - None - }; - - let mut i = finalized_header.slot - 1; - let mut ancestor_blocks = vec![]; - while ancestor_blocks.len() < 5 { - if (finalized_header.slot - i) > 100 { - break - } - if let Ok(ancestor_header) = - sync_committee_prover.fetch_header(i.to_string().as_str()).await - { - let ancestry_proof = - prove_block_roots_proof(finalized_state.clone(), ancestor_header.clone())?; - let header_state = - sync_committee_prover.fetch_beacon_state(i.to_string().as_str()).await?; - let execution_payload_proof = prove_execution_payload(header_state)?; - ancestor_blocks.push(AncestorBlock { - header: ancestor_header, - execution_payload: execution_payload_proof, - ancestry_proof, - }) - } - i -= 1; - } - - log::debug!(target: "hyperspace_ethereum", "\nAncestor blocks count: \n {:?} \n", ancestor_blocks.len()); - - // construct light client - let light_client_update = LightClientUpdate { - attested_header: attested_block_header, - sync_committee_update, - finalized_header, - execution_payload: execution_payload_proof, - finality_proof, - sync_aggregate: signature_block.body.sync_aggregate, - signature_slot: signature_block.slot, - ancestor_blocks: vec![], // TODO: add ancestor blocks? - }; - - // client_state = verify_sync_committee_attestation::( - // client_state.clone(), - // light_client_update, - // ) - // .unwrap(); - // println!( - // "Sucessfully verified Ethereum block at slot {:?}", - // client_state.finalized_header.slot - // ); - Ok(light_client_update) -} +use icsxx_ethereum::client_message::Header; +use sync_committee_primitives::constants::SYNC_COMMITTEE_SIZE; pub async fn prove_fast( client: &EthereumClient, eth_client_state: &ClientState, block_number: u64, -) -> Result, ClientError> { +) -> Result { let sync_committee_prover = client.prover(); let block_id = format!("{block_number:?}"); @@ -265,9 +66,10 @@ pub async fn prove_fast( { // let ancestry_proof = // prove_block_roots_proof(finalized_state.clone(), ancestor_header.clone())?; - let header_state = + let mut header_state = sync_committee_prover.fetch_beacon_state(i.to_string().as_str()).await?; - let execution_payload_proof = prove_execution_payload(header_state)?; + let execution_payload_proof = prove_execution_payload(&mut header_state)?; + let _header_state = header_state; return Ok(AncestorBlock { header: ancestor_header, execution_payload: execution_payload_proof, @@ -292,7 +94,7 @@ pub async fn prove_fast( let ep = block.body.execution_payload; let execution_payload_proof = ExecutionPayloadProof { - state_root: ep.state_root, + state_root: H256::from_slice(&ep.state_root.to_vec()), block_number: ep.block_number, multi_proof: vec![], execution_payload_branch: vec![], @@ -306,10 +108,9 @@ pub async fn prove_fast( finality_proof: Default::default(), sync_aggregate: Default::default(), signature_slot: Default::default(), - ancestor_blocks, }; light_client_update.attested_header.slot = block_header.slot; light_client_update.finalized_header.slot = block_header.slot; - Ok(light_client_update) + Ok(Header { inner: light_client_update, ancestor_blocks }) } diff --git a/hyperspace/ethereum/src/utils.rs b/hyperspace/ethereum/src/utils.rs index 509ba06ef..0592eb365 100644 --- a/hyperspace/ethereum/src/utils.rs +++ b/hyperspace/ethereum/src/utils.rs @@ -393,7 +393,6 @@ where let mut func = None; for faucet in self.deployed_facets.iter().chain(iter::once(&self.diamond)) { if let Ok(f) = faucet.abi().function(name) { - log::info!(target: "hyperspace_ethereum", "found function: {name}, {}, {}, {}", f.signature(), f.abi_signature(), hex::encode(&f.short_signature())); if func.is_some() { log::error!(target: "hyperspace_ethereum", "ambiguous function name: {}", name); //panic!("ambiguous function name: {}", name); diff --git a/hyperspace/testsuite/src/lib.rs b/hyperspace/testsuite/src/lib.rs index 95f040141..d4fef001a 100644 --- a/hyperspace/testsuite/src/lib.rs +++ b/hyperspace/testsuite/src/lib.rs @@ -376,10 +376,10 @@ async fn send_packet_with_connection_delay( let (previous_balance, ..) = send_transfer(chain_a, chain_b, asset_a.clone(), channel_id_a, None).await; assert_send_transfer(chain_a, asset_a, previous_balance, 120).await; - // log::info!(target: "hyperspace", "Sending transfer from {}", chain_b.name()); - // let (previous_balance, ..) = - // send_transfer(chain_b, chain_a, asset_b.clone(), channel_id_b, None).await; - // assert_send_transfer(chain_b, asset_b, previous_balance, 120).await; + log::info!(target: "hyperspace", "Sending transfer from {}", chain_b.name()); + let (previous_balance, ..) = + send_transfer(chain_b, chain_a, asset_b.clone(), channel_id_b, None).await; + assert_send_transfer(chain_b, asset_b, previous_balance, 120).await; // now send from chain b. log::info!(target: "hyperspace", "🚀🚀 Token Transfer successful with connection delay"); } From c78b42fda2f1aa37f5465a5d53d669fd87f16030 Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Thu, 14 Sep 2023 02:32:11 -0300 Subject: [PATCH 25/43] update sync-committee deps --- Cargo.lock | 303 ++++++++++-------- hyperspace/ethereum/src/ibc_provider.rs | 8 - light-clients/icsxx-ethereum-cw/Cargo.toml | 5 +- light-clients/icsxx-ethereum-cw/src/client.rs | 7 +- .../icsxx-ethereum-cw/src/context.rs | 6 +- .../icsxx-ethereum-cw/src/contract.rs | 17 +- light-clients/icsxx-ethereum/Cargo.toml | 15 +- .../icsxx-ethereum/src/client_def.rs | 18 +- .../icsxx-ethereum/src/client_message.rs | 39 ++- .../icsxx-ethereum/src/client_state.rs | 5 +- .../icsxx-ethereum/src/consensus_state.rs | 6 +- light-clients/icsxx-ethereum/src/error.rs | 1 - light-clients/icsxx-ethereum/src/lib.rs | 5 +- light-clients/icsxx-ethereum/src/proto.rs | 46 +-- .../icsxx-ethereum/src/proto/ethereum.proto | 20 +- light-clients/icsxx-ethereum/src/tests.rs | 5 - 16 files changed, 252 insertions(+), 254 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c38f130ff..061a3484f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -209,11 +209,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "amcl" -version = "0.3.0" -source = "git+https://github.com/sigp/milagro_bls#d3fc0a40cfe8b72ccda46ba050ee6786a59ce753" - [[package]] name = "android_system_properties" version = "0.1.5" @@ -234,9 +229,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.69" +version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" [[package]] name = "approx" @@ -263,6 +258,124 @@ dependencies = [ "yansi 0.5.1", ] +[[package]] +name = "ark-bls12-381" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c775f0d12169cba7aae4caeb547bb6a50781c7449a8aa53793827c9ec4abf488" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-serialize", + "ark-std", +] + +[[package]] +name = "ark-ec" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defd9a439d56ac24968cca0571f598a61bc8c55f71d50a89cda591cb750670ba" +dependencies = [ + "ark-ff", + "ark-poly", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", + "itertools", + "num-traits", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm", + "ark-ff-macros", + "ark-serialize", + "ark-std", + "derivative", + "digest 0.10.6", + "itertools", + "num-bigint", + "num-traits", + "paste", + "rustc_version", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-poly" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d320bfc44ee185d899ccbadfa8bc31aab923ce1558716e1997a1e74057fe86bf" +dependencies = [ + "ark-ff", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-serialize-derive", + "ark-std", + "digest 0.10.6", + "num-bigint", +] + +[[package]] +name = "ark-serialize-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae3281bc6d0fd7e549af32b52511e1302185bd688fd3359fa36423346ff682ea" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand 0.8.5", +] + [[package]] name = "array-bytes" version = "4.2.0" @@ -975,6 +1088,23 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" +[[package]] +name = "bls_on_arkworks" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffc35f5286b3fa350a0a77df5166c034c5a12dc4a3ee13bf2126ac9e9109ef8e" +dependencies = [ + "ark-bls12-381", + "ark-ec", + "ark-ff", + "ark-serialize", + "ark-std", + "hkdf", + "hmac 0.12.1", + "libm 0.2.7", + "sha2 0.10.6", +] + [[package]] name = "bnum" version = "0.7.0" @@ -2631,25 +2761,6 @@ dependencies = [ "cfg-if 1.0.0", ] -[[package]] -name = "enr" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26fa0a0be8915790626d5759eb51fe47435a8eac92c2f212bd2da9aa7f30ea56" -dependencies = [ - "base64 0.13.1", - "bs58", - "bytes", - "hex", - "k256 0.11.6", - "log", - "rand 0.8.5", - "rlp", - "serde", - "sha3", - "zeroize", -] - [[package]] name = "enr" version = "0.8.1" @@ -2780,16 +2891,6 @@ dependencies = [ "libc", ] -[[package]] -name = "error-chain" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc" -dependencies = [ - "backtrace", - "version_check", -] - [[package]] name = "eth-keystore" version = "0.5.0" @@ -2844,31 +2945,6 @@ dependencies = [ "tiny-keccak", ] -[[package]] -name = "ethereum-consensus" -version = "0.1.1" -source = "git+https://github.com/polytope-labs/ethereum-consensus?branch=main#48335b5c8074d63553ee4681993e294eba947f88" -dependencies = [ - "async-stream", - "bs58", - "enr 0.6.2", - "error-chain", - "hashbrown 0.13.2", - "hex", - "integer-sqrt", - "milagro_bls", - "multiaddr 0.14.0", - "multihash", - "rand 0.8.5", - "serde", - "serde_json", - "serde_yaml", - "sha2 0.9.9", - "ssz-rs", - "tokio", - "tokio-stream", -] - [[package]] name = "ethereum-types" version = "0.14.1" @@ -4852,7 +4928,6 @@ dependencies = [ "ecdsa 0.16.7", "elliptic-curve 0.13.5", "env_logger 0.10.0", - "ethereum-consensus", "ethers 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "ethers-providers 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "ethers-solc 2.0.9", @@ -5331,7 +5406,6 @@ dependencies = [ "anyhow", "derive_more", "env_logger 0.9.3", - "ethereum-consensus", "futures", "hex", "ibc", @@ -5339,6 +5413,7 @@ dependencies = [ "ibc-proto", "jsonrpsee-ws-client", "log", + "primitive-types", "prost 0.11.6", "prost-build", "prost-types", @@ -5368,7 +5443,6 @@ dependencies = [ "derive_more", "digest 0.10.6", "ed25519-zebra", - "ethereum-consensus", "hex", "hyperspace-primitives", "ibc", @@ -5962,9 +6036,9 @@ checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a" [[package]] name = "libm" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" +checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" [[package]] name = "libp2p" @@ -5994,7 +6068,7 @@ dependencies = [ "libp2p-webrtc", "libp2p-websocket", "libp2p-yamux", - "multiaddr 0.16.0", + "multiaddr", "parking_lot 0.12.1", "pin-project", "smallvec 1.10.0", @@ -6015,7 +6089,7 @@ dependencies = [ "futures-timer", "instant", "log", - "multiaddr 0.16.0", + "multiaddr", "multihash", "multistream-select", "once_cell", @@ -6729,18 +6803,6 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39617bc909d64b068dcffd0e3e31679195b5576d0c83fadc52690268cc2b2b55" -[[package]] -name = "milagro_bls" -version = "1.5.1" -source = "git+https://github.com/sigp/milagro_bls#d3fc0a40cfe8b72ccda46ba050ee6786a59ce753" -dependencies = [ - "amcl", - "hex", - "lazy_static", - "rand 0.8.5", - "zeroize", -] - [[package]] name = "mime" version = "0.3.16" @@ -6861,24 +6923,6 @@ dependencies = [ "ureq", ] -[[package]] -name = "multiaddr" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c580bfdd8803cce319b047d239559a22f809094aaea4ac13902a1fdcfcd4261" -dependencies = [ - "arrayref", - "bs58", - "byteorder", - "data-encoding", - "multihash", - "percent-encoding", - "serde", - "static_assertions", - "unsigned-varint", - "url", -] - [[package]] name = "multiaddr" version = "0.16.0" @@ -7240,7 +7284,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ "autocfg", - "libm 0.2.6", + "libm 0.2.7", ] [[package]] @@ -10551,18 +10595,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_yaml" -version = "0.8.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" -dependencies = [ - "indexmap 1.9.2", - "ryu", - "serde", - "yaml-rust", -] - [[package]] name = "sha-1" version = "0.9.8" @@ -10735,7 +10767,7 @@ dependencies = [ "bytes", "ics23 0.10.0", "proptest", - "rand 0.8.5", + "rand 0.7.3", "sha2 0.10.6", "tendermint", ] @@ -11891,13 +11923,14 @@ dependencies = [ [[package]] name = "ssz-rs" version = "0.8.0" -source = "git+https://github.com/polytope-labs/ssz-rs?branch=main#be360ab4849fefc82cfb9f3f5d6a09352ddd6eee" +source = "git+https://github.com/polytope-labs/ssz-rs?branch=main#6f5d37b7f92875b5cbb6ef60e8c498ca013943cb" dependencies = [ "as-any", "bitvec 1.0.1", "hex", "itertools", "num-bigint", + "parity-scale-codec", "serde", "sha2 0.9.9", "ssz-rs-derive", @@ -11906,7 +11939,7 @@ dependencies = [ [[package]] name = "ssz-rs-derive" version = "0.8.0" -source = "git+https://github.com/polytope-labs/ssz-rs?branch=main#be360ab4849fefc82cfb9f3f5d6a09352ddd6eee" +source = "git+https://github.com/polytope-labs/ssz-rs?branch=main#6f5d37b7f92875b5cbb6ef60e8c498ca013943cb" dependencies = [ "proc-macro2", "quote", @@ -12231,25 +12264,35 @@ dependencies = [ [[package]] name = "sync-committee-primitives" version = "0.1.0" -source = "git+https://github.com/polytope-labs/sync-committee-rs.git?rev=c5afca4fbb92cb60dde29c3a89454c288b022d97#c5afca4fbb92cb60dde29c3a89454c288b022d97" +source = "git+https://github.com/polytope-labs/sync-committee-rs.git?rev=106f53e045cc85c4a8d984c8e295800cebaa2475#106f53e045cc85c4a8d984c8e295800cebaa2475" dependencies = [ - "ethereum-consensus", + "anyhow", + "ark-bls12-381", + "ark-ec", + "bls_on_arkworks", + "hex", "hex-literal 0.4.1", "parity-scale-codec", + "primitive-types", + "serde", "ssz-rs", ] [[package]] name = "sync-committee-prover" version = "0.1.0" -source = "git+https://github.com/polytope-labs/sync-committee-rs.git?rev=c5afca4fbb92cb60dde29c3a89454c288b022d97#c5afca4fbb92cb60dde29c3a89454c288b022d97" +source = "git+https://github.com/polytope-labs/sync-committee-rs.git?rev=106f53e045cc85c4a8d984c8e295800cebaa2475#106f53e045cc85c4a8d984c8e295800cebaa2475" dependencies = [ - "actix-rt", "anyhow", + "ark-bls12-381", + "ark-ec", "async-stream", "base2", + "bls_on_arkworks", "env_logger 0.10.0", - "ethereum-consensus", + "hex", + "log", + "primitive-types", "reqwest", "serde", "serde_json", @@ -12263,9 +12306,12 @@ dependencies = [ [[package]] name = "sync-committee-verifier" version = "0.1.0" -source = "git+https://github.com/polytope-labs/sync-committee-rs.git?rev=c5afca4fbb92cb60dde29c3a89454c288b022d97#c5afca4fbb92cb60dde29c3a89454c288b022d97" +source = "git+https://github.com/polytope-labs/sync-committee-rs.git?rev=106f53e045cc85c4a8d984c8e295800cebaa2475#106f53e045cc85c4a8d984c8e295800cebaa2475" dependencies = [ - "ethereum-consensus", + "anyhow", + "ark-bls12-381", + "ark-ec", + "bls_on_arkworks", "log", "ssz-rs", "sync-committee-primitives", @@ -13222,9 +13268,9 @@ version = "1.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ - "cfg-if 1.0.0", + "cfg-if 0.1.10", "digest 0.10.6", - "rand 0.8.5", + "rand 0.7.3", "static_assertions", ] @@ -13637,7 +13683,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57d20cb3c59b788653d99541c646c561c9dd26506f25c0cebfe810659c54c6d7" dependencies = [ "downcast-rs", - "libm 0.2.6", + "libm 0.2.7", "memory_units", "num-rational", "num-traits", @@ -14497,15 +14543,6 @@ version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47430998a7b5d499ccee752b41567bc3afc57e1327dc855b1a2aa44ce29b5fa1" -[[package]] -name = "yaml-rust" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" -dependencies = [ - "linked-hash-map", -] - [[package]] name = "yamux" version = "0.10.2" diff --git a/hyperspace/ethereum/src/ibc_provider.rs b/hyperspace/ethereum/src/ibc_provider.rs index 18740a113..25c36f485 100644 --- a/hyperspace/ethereum/src/ibc_provider.rs +++ b/hyperspace/ethereum/src/ibc_provider.rs @@ -258,15 +258,9 @@ impl IbcProvider for EthereumClient { let prover = self.prover(); let block = prover.fetch_block("head").await?; let number = block.body.execution_payload.block_number; - let height = Height::new(0, number.into()); let from = latest_cp_client_height + 1; let to = number.min(latest_cp_client_height + NUMBER_OF_BLOCKS_TO_PROCESS_PER_ITER); - // let to = finality_event - // .number - // .unwrap() - // .as_u64() - // .min(latest_cp_client_height + NUMBER_OF_BLOCKS_TO_PROCESS_PER_ITER); log::info!(target: "hyperspace_ethereum", "Getting blocks {}..{}", from, to); let filter = @@ -331,8 +325,6 @@ impl IbcProvider for EthereumClient { let value = msg.encode_vec().map_err(|e| { ClientError::from(format!("Failed to encode MsgUpdateClient {msg:?}: {e:?}")) })?; - // log::info!(target: "hyperspace_ethereum", "update client header: {value:?}", value = - // hex::encode(&value)); Any { value, type_url: msg.type_url() } }; diff --git a/light-clients/icsxx-ethereum-cw/Cargo.toml b/light-clients/icsxx-ethereum-cw/Cargo.toml index d0356fb17..e51007727 100644 --- a/light-clients/icsxx-ethereum-cw/Cargo.toml +++ b/light-clients/icsxx-ethereum-cw/Cargo.toml @@ -62,9 +62,8 @@ tendermint-proto = { git = "https://github.com/informalsystems/tendermint-rs", r sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39", default-features = false } sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39", default-features = false, features = ["disable_panic_handler", "disable_oom", "disable_allocator"] } -ethereum-consensus = { git = "https://github.com/polytope-labs/ethereum-consensus", branch = "main", default-features = false } -sync-committee-verifier = { git = "https://github.com/polytope-labs/sync-committee-rs.git", rev = "c5afca4fbb92cb60dde29c3a89454c288b022d97", default-features = false } -sync-committee-primitives = { git = "https://github.com/polytope-labs/sync-committee-rs.git", rev = "c5afca4fbb92cb60dde29c3a89454c288b022d97", default-features = false } +sync-committee-verifier = { git = "https://github.com/polytope-labs/sync-committee-rs.git", rev = "106f53e045cc85c4a8d984c8e295800cebaa2475", default-features = false } +sync-committee-primitives = { git = "https://github.com/polytope-labs/sync-committee-rs.git", rev = "106f53e045cc85c4a8d984c8e295800cebaa2475", default-features = false } ssz-rs = { git = "https://github.com/polytope-labs/ssz-rs", branch = "main" , default-features = false } [dev-dependencies] diff --git a/light-clients/icsxx-ethereum-cw/src/client.rs b/light-clients/icsxx-ethereum-cw/src/client.rs index fe416d74d..515084c5e 100644 --- a/light-clients/icsxx-ethereum-cw/src/client.rs +++ b/light-clients/icsxx-ethereum-cw/src/client.rs @@ -44,11 +44,10 @@ use icsxx_ethereum::{ }; use prost::Message; use std::str::FromStr; -use sync_committee_verifier::BlsVerify; impl<'a, H> ClientTypes for Context<'a, H> where - H: Clone + Eq + Send + Sync + Debug + Default + BlsVerify + 'static, + H: Clone + Eq + Send + Sync + Debug + Default + 'static, { type AnyClientMessage = ClientMessage; type AnyClientState = ClientState; @@ -58,7 +57,7 @@ where impl<'a, H> ClientReader for Context<'a, H> where - H: Clone + Eq + Send + Sync + Debug + Default + BlsVerify + 'static, + H: Clone + Eq + Send + Sync + Debug + Default + 'static, { fn client_type(&self, client_id: &ClientId) -> Result { log!(self, "in client : [client_type] >> client_id = {:?}", client_id); @@ -191,7 +190,7 @@ where impl<'a, H> ClientKeeper for Context<'a, H> where - H: Clone + Eq + Send + Sync + Debug + Default + BlsVerify + 'static, + H: Clone + Eq + Send + Sync + Debug + Default + 'static, { fn store_client_type( &mut self, diff --git a/light-clients/icsxx-ethereum-cw/src/context.rs b/light-clients/icsxx-ethereum-cw/src/context.rs index 1f1279aa1..5b2f80e55 100644 --- a/light-clients/icsxx-ethereum-cw/src/context.rs +++ b/light-clients/icsxx-ethereum-cw/src/context.rs @@ -21,7 +21,6 @@ use cosmwasm_std::{DepsMut, Env, Storage}; use ibc::{core::ics26_routing::context::ReaderContext, Height}; use icsxx_ethereum::{client_state::ClientState, consensus_state::ConsensusState}; use std::{fmt, fmt::Debug, marker::PhantomData}; -use sync_committee_verifier::BlsVerify; pub struct Context<'a, H> { pub deps: DepsMut<'a>, @@ -124,7 +123,4 @@ where } } -impl<'a, H: Clone + Eq + Send + Sync + Debug + Default + BlsVerify + 'static> ReaderContext - for Context<'a, H> -{ -} +impl<'a, H: Clone + Eq + Send + Sync + Debug + Default + 'static> ReaderContext for Context<'a, H> {} diff --git a/light-clients/icsxx-ethereum-cw/src/contract.rs b/light-clients/icsxx-ethereum-cw/src/contract.rs index a34e4e84b..6d4db65c0 100644 --- a/light-clients/icsxx-ethereum-cw/src/contract.rs +++ b/light-clients/icsxx-ethereum-cw/src/contract.rs @@ -48,7 +48,7 @@ use icsxx_ethereum::{ }; // use light_client_common::{verify_membership, verify_non_membership}; use std::{collections::BTreeSet, str::FromStr}; -use sync_committee_verifier::{BlsVerify, LightClientState}; +use sync_committee_verifier::LightClientState; /* // version info for migration info const CONTRACT_NAME: &str = "crates.io:ics10-grandpa-cw"; @@ -184,7 +184,7 @@ fn process_message( ExecuteMsg::CheckSubstituteAndUpdateState(msg) => { let _msg = CheckSubstituteAndUpdateStateMsg::try_from(msg)?; // manually load both states from the combined storage using the appropriate prefixes - let mut old_client_state = ctx + let old_client_state = ctx .client_state_prefixed(SUBJECT_PREFIX) .map_err(|e| ContractError::Client(e.to_string()))?; let substitute_client_state = ctx @@ -280,7 +280,7 @@ fn store_client_and_consensus_states( consensus_update: ConsensusUpdateResult>, ) -> Result, ContractError> where - H: Clone + Eq + Send + Sync + Debug + Default + BlsVerify + 'static, + H: Clone + Eq + Send + Sync + Debug + Default + 'static, { let height = client_state.latest_height(); match consensus_update { @@ -301,14 +301,3 @@ where .map_err(|e| ContractError::Client(e.to_string()))?; Ok(to_binary(&ContractResult::success())) } - -impl BlsVerify for HostFunctions { - fn verify( - public_keys: &[ðereum_consensus::crypto::PublicKey], - msg: &[u8], - signature: ðereum_consensus::crypto::Signature, - ) -> Result<(), sync_committee_verifier::error::Error> { - // TODO: bls - Ok(()) - } -} diff --git a/light-clients/icsxx-ethereum/Cargo.toml b/light-clients/icsxx-ethereum/Cargo.toml index 639e5c7d1..8597ecd45 100644 --- a/light-clients/icsxx-ethereum/Cargo.toml +++ b/light-clients/icsxx-ethereum/Cargo.toml @@ -13,10 +13,10 @@ ibc = { path = "../../ibc/modules", default-features = false } ibc-proto = { path = "../../ibc/proto", default-features = false } # local deps -ethereum-consensus = { git = "https://github.com/polytope-labs/ethereum-consensus", branch = "main", default-features = false } -sync-committee-verifier = { git = "https://github.com/polytope-labs/sync-committee-rs.git", rev = "c5afca4fbb92cb60dde29c3a89454c288b022d97", default-features = false } -sync-committee-primitives = { git = "https://github.com/polytope-labs/sync-committee-rs.git", rev = "c5afca4fbb92cb60dde29c3a89454c288b022d97", default-features = false } +sync-committee-verifier = { git = "https://github.com/polytope-labs/sync-committee-rs.git", rev = "106f53e045cc85c4a8d984c8e295800cebaa2475", default-features = false } +sync-committee-primitives = { git = "https://github.com/polytope-labs/sync-committee-rs.git", rev = "106f53e045cc85c4a8d984c8e295800cebaa2475", default-features = false } ssz-rs = { git = "https://github.com/polytope-labs/ssz-rs", branch = "main" , default-features = false } +primitive-types = { version = "0.12.0", default-features = false, features = [] } # crates.io prost = { version = "0.11", default-features = false } @@ -42,9 +42,9 @@ tokio = { version = "1.21.1", features = ["macros"] } json = { package = "serde_json", version = "1.0.85" } jsonrpsee-ws-client = "0.16.2" actix-rt = "2.3.0" -sync-committee-primitives = { git = "https://github.com/polytope-labs/sync-committee-rs.git", rev = "c5afca4fbb92cb60dde29c3a89454c288b022d97", features = ["testing"] } -sync-committee-verifier = { git = "https://github.com/polytope-labs/sync-committee-rs.git", rev = "c5afca4fbb92cb60dde29c3a89454c288b022d97", features = ["testing"] } -sync-committee-prover = { git = "https://github.com/polytope-labs/sync-committee-rs.git", rev = "c5afca4fbb92cb60dde29c3a89454c288b022d97" } +sync-committee-primitives = { git = "https://github.com/polytope-labs/sync-committee-rs.git", rev = "106f53e045cc85c4a8d984c8e295800cebaa2475" } +sync-committee-verifier = { git = "https://github.com/polytope-labs/sync-committee-rs.git", rev = "106f53e045cc85c4a8d984c8e295800cebaa2475" } +sync-committee-prover = { git = "https://github.com/polytope-labs/sync-committee-rs.git", rev = "106f53e045cc85c4a8d984c8e295800cebaa2475" } [features] default = ["std"] @@ -57,9 +57,6 @@ std = [ "serde/std", "sync-committee-verifier/std", "sync-committee-primitives/std", - "ethereum-consensus/std", - "ethereum-consensus/async", - "ethereum-consensus/async-stream", "ssz-rs/std", "tendermint/std", ] diff --git a/light-clients/icsxx-ethereum/src/client_def.rs b/light-clients/icsxx-ethereum/src/client_def.rs index de9e0cc80..dab418897 100644 --- a/light-clients/icsxx-ethereum/src/client_def.rs +++ b/light-clients/icsxx-ethereum/src/client_def.rs @@ -22,7 +22,6 @@ use crate::client_message::{ClientMessage, Misbehaviour}; use alloc::{format, string::ToString, vec, vec::Vec}; use anyhow::anyhow; use core::{fmt::Debug, marker::PhantomData}; -use ethereum_consensus::crypto::{PublicKey, Signature}; use ibc::{ core::{ ics02_client::{ @@ -47,7 +46,7 @@ use ibc::{ }, Height, }; -use sync_committee_verifier::{verify_sync_committee_attestation, BlsVerify, LightClientState}; +use sync_committee_verifier::{verify_sync_committee_attestation, LightClientState}; use tendermint_proto::Protobuf; // TODO: move this function in a separate crate and remove the one from `light_client_common` crate @@ -96,7 +95,7 @@ pub struct EthereumClient(PhantomData); impl ClientDef for EthereumClient where - H: Clone + Eq + Send + Sync + Debug + Default + BlsVerify, + H: Clone + Eq + Send + Sync + Debug + Default, { type ClientMessage = ClientMessage; type ClientState = ClientState; @@ -111,7 +110,7 @@ where ) -> Result<(), Ics02Error> { match client_message { ClientMessage::Header(header) => { - let _ = verify_sync_committee_attestation::(client_state.inner, header) + let _ = verify_sync_committee_attestation(client_state.inner, header.inner) .map_err(|e| Ics02Error::implementation_specific(e.to_string()))?; }, ClientMessage::Misbehaviour(Misbehaviour { never }) => match never {}, @@ -150,6 +149,7 @@ where (height, cs) }) .collect::>(); + let header = header.inner; let height = Height::new( 0, // TODO: check this header.execution_payload.block_number as u64, @@ -436,13 +436,3 @@ where Ok(()) } } - -impl BlsVerify for EthereumClient { - fn verify( - public_keys: &[&PublicKey], - msg: &[u8], - signature: &Signature, - ) -> Result<(), sync_committee_verifier::error::Error> { - todo!() - } -} diff --git a/light-clients/icsxx-ethereum/src/client_message.rs b/light-clients/icsxx-ethereum/src/client_message.rs index 6eed4f963..ccf4b247f 100644 --- a/light-clients/icsxx-ethereum/src/client_message.rs +++ b/light-clients/icsxx-ethereum/src/client_message.rs @@ -26,6 +26,7 @@ use alloc::{collections::BTreeMap, string::ToString, vec::Vec}; use anyhow::anyhow; use core::convert::Infallible; use ibc::Height; +use sync_committee_primitives::types::AncestorBlock; use sync_committee_verifier::LightClientUpdate; use tendermint_proto::Protobuf; @@ -34,7 +35,12 @@ pub const ETHEREUM_CLIENT_MESSAGE_TYPE_URL: &str = "/ibc.lightclients.ethereum.v pub const ETHEREUM_HEADER_TYPE_URL: &str = "/ibc.lightclients.ethereum.v1.Header"; pub const ETHEREUM_MISBEHAVIOUR_TYPE_URL: &str = "/ibc.lightclients.ethereum.v1.Misbehaviour"; -pub type Header = LightClientUpdate; +#[derive(Clone, Debug)] +pub struct Header { + pub inner: LightClientUpdate, + // ancestors of the finalized block to be verified, may be empty. + pub ancestor_blocks: Vec, +} /// Misbehaviour type for GRANDPA. If both first and second proofs are valid /// (that is, form a valid canonical chain of blocks where on of the chain is a fork of @@ -95,13 +101,15 @@ impl TryFrom for Header { .collect::, _>>()?; let header = Header { - attested_header, - sync_committee_update, - finalized_header, - execution_payload, - finality_proof, - sync_aggregate, - signature_slot, + inner: LightClientUpdate { + attested_header, + sync_committee_update, + finalized_header, + execution_payload, + finality_proof, + sync_aggregate, + signature_slot, + }, ancestor_blocks, }; Ok(header) @@ -110,13 +118,14 @@ impl TryFrom for Header { impl From
for RawHeader { fn from(header: Header) -> Self { - let attested_header = Some(header.attested_header.into()); - let sync_committee_update = header.sync_committee_update.map(Into::into); - let finalized_header = Some(header.finalized_header.into()); - let execution_payload = Some(header.execution_payload.into()); - let finality_proof = Some(header.finality_proof.into()); - let sync_aggregate = Some(header.sync_aggregate.into()); - let signature_slot = header.signature_slot; + let inner = header.inner; + let attested_header = Some(inner.attested_header.into()); + let sync_committee_update = inner.sync_committee_update.map(Into::into); + let finalized_header = Some(inner.finalized_header.into()); + let execution_payload = Some(inner.execution_payload.into()); + let finality_proof = Some(inner.finality_proof.into()); + let sync_aggregate = Some(inner.sync_aggregate.into()); + let signature_slot = inner.signature_slot; let ancestor_blocks = header.ancestor_blocks.into_iter().map(Into::into).collect::>(); diff --git a/light-clients/icsxx-ethereum/src/client_state.rs b/light-clients/icsxx-ethereum/src/client_state.rs index 29402668b..65eb4a4ab 100644 --- a/light-clients/icsxx-ethereum/src/client_state.rs +++ b/light-clients/icsxx-ethereum/src/client_state.rs @@ -21,14 +21,13 @@ use crate::{ use alloc::{format, string::ToString, vec::Vec}; use anyhow::anyhow; use core::{fmt::Debug, marker::PhantomData, time::Duration}; -use ethereum_consensus::primitives::Hash32; use ibc::{ core::{ics02_client::client_state::ClientType, ics24_host::identifier::ChainId}, Height, }; use ibc_proto::google::protobuf::Any; use serde::{Deserialize, Serialize}; -use sync_committee_verifier::{BlsVerify, LightClientState}; +use sync_committee_verifier::LightClientState; use tendermint_proto::Protobuf; /// Protobuf type url for GRANDPA ClientState @@ -125,7 +124,7 @@ impl ClientState { impl ibc::core::ics02_client::client_state::ClientState for ClientState where - H: Send + Sync + Clone + Debug + Default + Eq + BlsVerify, + H: Send + Sync + Clone + Debug + Default + Eq, { type UpgradeOptions = UpgradeOptions; type ClientDef = EthereumClient; diff --git a/light-clients/icsxx-ethereum/src/consensus_state.rs b/light-clients/icsxx-ethereum/src/consensus_state.rs index 1cd522382..095bbb67d 100644 --- a/light-clients/icsxx-ethereum/src/consensus_state.rs +++ b/light-clients/icsxx-ethereum/src/consensus_state.rs @@ -17,9 +17,9 @@ use crate::{alloc::string::ToString, error::Error, proto::ConsensusState as RawC use alloc::{format, vec, vec::Vec}; use anyhow::anyhow; use core::{convert::Infallible, fmt::Debug}; -use ethereum_consensus::primitives::Hash32; use ibc::{core::ics23_commitment::commitment::CommitmentRoot, timestamp::Timestamp, Height}; use ibc_proto::google::protobuf::Any; +use primitive_types::H256; use serde::{Deserialize, Serialize}; use tendermint::time::Time; use tendermint_proto::{google::protobuf as tpb, Protobuf}; @@ -34,8 +34,8 @@ pub struct ConsensusState { } impl ConsensusState { - pub fn new(root: Hash32, timestamp: u64) -> Self { - let root_bytes: Vec = root.to_vec(); + pub fn new(root: H256, timestamp: u64) -> Self { + let root_bytes: Vec = root.0.to_vec(); Self { timestamp: Time::from_unix_timestamp(timestamp as i64, 0) .expect("timestamp should be valid"), diff --git a/light-clients/icsxx-ethereum/src/error.rs b/light-clients/icsxx-ethereum/src/error.rs index 24df1476d..6ec97070f 100644 --- a/light-clients/icsxx-ethereum/src/error.rs +++ b/light-clients/icsxx-ethereum/src/error.rs @@ -34,7 +34,6 @@ pub enum Error { Anyhow(anyhow::Error), Deserialize(ssz_rs::DeserializeError), Serialize(SimpleSerializeError), - Ethereum(ethereum_consensus::crypto::Error), Custom(String), } diff --git a/light-clients/icsxx-ethereum/src/lib.rs b/light-clients/icsxx-ethereum/src/lib.rs index 69b519457..5f5e1d438 100644 --- a/light-clients/icsxx-ethereum/src/lib.rs +++ b/light-clients/icsxx-ethereum/src/lib.rs @@ -34,9 +34,6 @@ pub mod verify; #[cfg(test)] mod tests; -pub use ethereum_consensus::crypto::{ - PublicKey as EthereumPublicKey, Signature as EthereumSignature, -}; -pub use sync_committee_verifier::{error::Error as EthereumError, BlsVerify}; +pub use sync_committee_verifier::error::Error as EthereumError; pub trait HostFunctions: Sized + Send + Sync {} diff --git a/light-clients/icsxx-ethereum/src/proto.rs b/light-clients/icsxx-ethereum/src/proto.rs index c8edd7279..72605dfe6 100644 --- a/light-clients/icsxx-ethereum/src/proto.rs +++ b/light-clients/icsxx-ethereum/src/proto.rs @@ -26,15 +26,15 @@ mod convert { }; use crate::{alloc::string::ToString, error::Error}; use alloc::vec::Vec; - use ethereum_consensus::{ - altair::{mainnet::SYNC_COMMITTEE_SIZE, SyncAggregate, SyncCommittee}, - phase0::BeaconBlockHeader, - primitives::Root, - }; + use primitive_types::H256; use ssz_rs::{Bitvector, Deserialize, Serialize}; - use sync_committee_primitives::types::{ - AncestorBlock, AncestryProof, BlockRootsProof, ExecutionPayloadProof, FinalityProof, - SyncCommitteeUpdate, + use sync_committee_primitives::{ + consensus_types::{BeaconBlockHeader, SyncAggregate, SyncCommittee}, + constants::SYNC_COMMITTEE_SIZE, + types::{ + AncestorBlock, AncestryProof, BlockRootsProof, ExecutionPayloadProof, FinalityProof, + SyncCommitteeUpdate, + }, }; use sync_committee_verifier::LightClientState; @@ -43,7 +43,7 @@ mod convert { fn try_from(raw: RawBeaconBlockHeader) -> Result { let slot = raw.slot; - let proposer_index = raw.proposer_index.try_into()?; + let proposer_index = raw.proposer_index; let parent_root = raw.parent_root.as_slice().try_into()?; let state_root = raw.state_root.as_slice().try_into()?; let body_root = raw.body_root.as_slice().try_into()?; @@ -63,7 +63,7 @@ mod convert { } } - impl TryFrom for SyncCommitteeUpdate { + impl TryFrom for SyncCommitteeUpdate { type Error = Error; fn try_from(raw: RawSyncCommitteeUpdate) -> Result { @@ -82,14 +82,14 @@ mod convert { } } - impl From> for RawSyncCommitteeUpdate { - fn from(update: SyncCommitteeUpdate) -> Self { + impl From for RawSyncCommitteeUpdate { + fn from(update: SyncCommitteeUpdate) -> Self { Self { next_sync_committee: Some(update.next_sync_committee.into()), next_sync_committee_branch: update .next_sync_committee_branch .into_iter() - .map(|root| root.to_vec()) + .map(|root| root.0.to_vec()) .collect(), } } @@ -125,7 +125,7 @@ mod convert { type Error = Error; fn try_from(raw: RawExecutionPayloadProof) -> Result { - let state_root = raw.state_root.as_slice().try_into()?; + let state_root = H256::from_slice(&raw.state_root); let block_number = raw.block_number; let multi_proof = raw .multi_proof @@ -145,13 +145,13 @@ mod convert { impl From for RawExecutionPayloadProof { fn from(proof: ExecutionPayloadProof) -> Self { Self { - state_root: proof.state_root.to_vec(), + state_root: proof.state_root.0.to_vec(), block_number: proof.block_number, - multi_proof: proof.multi_proof.iter().map(|root| root.to_vec()).collect(), + multi_proof: proof.multi_proof.iter().map(|root| root.0.to_vec()).collect(), execution_payload_branch: proof .execution_payload_branch .iter() - .map(|root| root.to_vec()) + .map(|root| root.0.to_vec()) .collect(), timestamp: proof.timestamp, } @@ -176,7 +176,7 @@ mod convert { fn from(proof: FinalityProof) -> Self { Self { epoch: proof.epoch, - finality_branch: proof.finality_branch.iter().map(|root| root.to_vec()).collect(), + finality_branch: proof.finality_branch.iter().map(|root| root.0.to_vec()).collect(), } } } @@ -301,7 +301,7 @@ mod convert { match proof { AncestryProof::BlockRoots { block_roots_proof, block_roots_branch } => { let block_roots_branch = - block_roots_branch.into_iter().map(|root| root.to_vec()).collect(); + block_roots_branch.into_iter().map(|root| root.0.to_vec()).collect(); Self { message: Some(ancestry_proof::Message::BlockRoots(RawBlockRoots { block_roots_proof: Some(block_roots_proof.into()), @@ -317,11 +317,11 @@ mod convert { historical_roots_branch, } => { let historical_batch_proof = - historical_batch_proof.into_iter().map(|root| root.to_vec()).collect(); + historical_batch_proof.into_iter().map(|root| root.0.to_vec()).collect(); let historical_roots_proof = - historical_roots_proof.into_iter().map(|root| root.to_vec()).collect(); + historical_roots_proof.into_iter().map(|root| root.0.to_vec()).collect(); let historical_roots_branch = - historical_roots_branch.into_iter().map(|root| root.to_vec()).collect(); + historical_roots_branch.into_iter().map(|root| root.0.to_vec()).collect(); Self { message: Some(ancestry_proof::Message::HistoricalRoots( RawHistoricalRoots { @@ -355,7 +355,7 @@ mod convert { impl From for RawBlockRootsProof { fn from(proof: BlockRootsProof) -> Self { let block_header_branch = - proof.block_header_branch.into_iter().map(|root| root.to_vec()).collect(); + proof.block_header_branch.into_iter().map(|root| root.0.to_vec()).collect(); Self { block_header_index: proof.block_header_index, block_header_branch } } } diff --git a/light-clients/icsxx-ethereum/src/proto/ethereum.proto b/light-clients/icsxx-ethereum/src/proto/ethereum.proto index 26632a0f6..86b95c8dc 100644 --- a/light-clients/icsxx-ethereum/src/proto/ethereum.proto +++ b/light-clients/icsxx-ethereum/src/proto/ethereum.proto @@ -82,7 +82,7 @@ pub struct SyncCommitteeUpdate { // actual sync committee pub next_sync_committee: SyncCommittee, // sync committee, ssz merkle proof. - pub next_sync_committee_branch: Vec, + pub next_sync_committee_branch: Vec, } */ @@ -108,13 +108,13 @@ message SyncCommittee { pub struct ExecutionPayloadProof { /// The state root in the `ExecutionPayload` which represents the commitment to /// the ethereum world state in the yellow paper. - pub state_root: Hash32, + pub state_root: H256, /// the block number of the execution header. pub block_number: u64, /// merkle mutli proof for the state_root & block_number in the [`ExecutionPayload`]. - pub multi_proof: Vec, + pub multi_proof: Vec, /// merkle proof for the `ExecutionPayload` in the [`BeaconBlockBody`]. - pub execution_payload_branch: Vec, + pub execution_payload_branch: Vec, /// timestamp pub timestamp: u64, } @@ -133,7 +133,7 @@ pub struct FinalityProof { /// The latest finalized epoch pub epoch: u64, /// Finalized header proof - pub finality_branch: Vec, + pub finality_branch: Vec, } */ @@ -165,7 +165,7 @@ pub enum AncestryProof { /// Proof for the header in `state.block_roots` block_roots_proof: BlockRootsProof, /// The proof for the reconstructed `hash_tree_root(state.block_roots)` in [`BeaconState`] - block_roots_branch: Vec, + block_roots_branch: Vec, }, /// This variant defines the neccessary proofs for a beacon chain header in the /// `state.historical_roots`. @@ -174,14 +174,14 @@ pub enum AncestryProof { block_roots_proof: BlockRootsProof, /// The proof for the `historical_batch.block_roots`, needed to reconstruct /// `hash_tree_root(historical_batch)` - historical_batch_proof: Vec, + historical_batch_proof: Vec, /// The proof for the `hash_tree_root(historical_batch)` in `state.historical_roots` - historical_roots_proof: Vec, + historical_roots_proof: Vec, /// The generalized index for the historical_batch in `state.historical_roots`. historical_roots_index: u64, /// The proof for the reconstructed `hash_tree_root(state.historical_roots)` in /// [`BeaconState`] - historical_roots_branch: Vec, + historical_roots_branch: Vec, }, } */ @@ -242,7 +242,7 @@ pub struct BlockRootsProof { /// Generalized index of the header in the `block_roots` list. pub block_header_index: u64, /// The proof for the header, needed to reconstruct `hash_tree_root(state.block_roots)` - pub block_header_branch: Vec, + pub block_header_branch: Vec, } */ diff --git a/light-clients/icsxx-ethereum/src/tests.rs b/light-clients/icsxx-ethereum/src/tests.rs index 5e3294704..98ec32a8f 100644 --- a/light-clients/icsxx-ethereum/src/tests.rs +++ b/light-clients/icsxx-ethereum/src/tests.rs @@ -1,15 +1,10 @@ use super::*; // use base2::Base2; -use ethereum_consensus::{ - bellatrix::compute_domain, primitives::Root, signing::compute_signing_root, - state_transition::Context, -}; use ssz_rs::{calculate_multi_merkle_root, is_valid_merkle_branch, GeneralizedIndex, Merkleized}; use std::time::Duration; use sync_committee_primitives::{ types::{ AncestorBlock, FinalityProof, LightClientState, LightClientUpdate, SyncCommitteeUpdate, - DOMAIN_SYNC_COMMITTEE, GENESIS_VALIDATORS_ROOT, }, util::{compute_fork_version, compute_sync_committee_period_at_slot}, }; From 65949846fd7fd554786e986b505434991a93dcc8 Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Thu, 14 Sep 2023 16:07:14 -0300 Subject: [PATCH 26/43] add script for generating ABI and update ABI --- hyperspace/ethereum/scripts/generate_abi.sh | 21 + hyperspace/ethereum/src/abi/diamond-abi.json | 248 +++ .../src/abi/diamond-cut-facet-abi.json | 253 ++++ .../src/abi/diamond-loupe-facet-abi.json | 97 ++ hyperspace/ethereum/src/abi/ibc-host-abi.json | 1334 ----------------- .../ethereum/src/abi/ibc-querier-abi.json | 511 +++++++ .../src/abi/ics20-transfer-bank-abi.json | 430 ++++++ .../ethereum/src/abi/ownership-facet-abi.json | 63 + ...nt-abi.json => tendermint-client-abi.json} | 64 +- hyperspace/ethereum/src/config.rs | 1 + hyperspace/ethereum/src/contract.rs | 12 - hyperspace/ethereum/src/ibc_provider.rs | 21 + hyperspace/ethereum/src/utils.rs | 15 +- 13 files changed, 1696 insertions(+), 1374 deletions(-) create mode 100644 hyperspace/ethereum/scripts/generate_abi.sh create mode 100644 hyperspace/ethereum/src/abi/diamond-abi.json create mode 100644 hyperspace/ethereum/src/abi/diamond-cut-facet-abi.json create mode 100644 hyperspace/ethereum/src/abi/diamond-loupe-facet-abi.json delete mode 100644 hyperspace/ethereum/src/abi/ibc-host-abi.json create mode 100644 hyperspace/ethereum/src/abi/ibc-querier-abi.json create mode 100644 hyperspace/ethereum/src/abi/ics20-transfer-bank-abi.json create mode 100644 hyperspace/ethereum/src/abi/ownership-facet-abi.json rename hyperspace/ethereum/src/abi/{light-client-abi.json => tendermint-client-abi.json} (86%) diff --git a/hyperspace/ethereum/scripts/generate_abi.sh b/hyperspace/ethereum/scripts/generate_abi.sh new file mode 100644 index 000000000..2cf365341 --- /dev/null +++ b/hyperspace/ethereum/scripts/generate_abi.sh @@ -0,0 +1,21 @@ +SCRIPT=$(realpath "$0") +SCRIPTPATH=$(dirname "$SCRIPT") + +cd $SCRIPTPATH/../yui-ibc-solidity/node_modules || (echo "Error: yui-ibc-solidity/node_modules does not exist" && exit 1) + +forge inspect ../contracts/diamond/Diamond.sol:Diamond abi > ../../src/abi/diamond-abi.json +forge inspect ../contracts/diamond/facets/DiamondCutFacet.sol:DiamondCutFacet abi > ../../src/abi/diamond-cut-facet-abi.json +forge inspect ../contracts/diamond/facets/DiamondLoupeFacet.sol:DiamondLoupeFacet abi > ../../src/abi/diamond-loupe-facet-abi.json +forge inspect ../contracts/diamond/facets/OwnershipFacet.sol:OwnershipFacet abi > ../../src/abi/ownership-facet-abi.json + +forge inspect ../contracts/core/02-client/IBCClient.sol:IBCClient abi > ../../src/abi/ibc-client-abi.json +forge inspect ../contracts/core/03-connection/IBCConnection.sol:IBCConnection abi > ../../src/abi/ibc-connection-abi.json +forge inspect ../contracts/core/04-channel/IBCPacket.sol:IBCPacket abi > ../../src/abi/ibc-packet-abi.json +forge inspect ../contracts/core/04-channel/IBCChannelHandshake.sol:IBCChannelHandshake abi > ../../src/abi/ibc-channel-abi.json +forge inspect ../contracts/core/25-handler/IBCQuerier.sol:IBCQuerier abi > ../../src/abi/ibc-querier-abi.json + +forge inspect ../contracts/apps/20-transfer/ICS20TransferBank.sol:ICS20TransferBank abi > ../../src/abi/ics20-transfer-bank-abi.json +forge inspect ../contracts/clients/TendermintLightClientSimple.sol:TendermintLightClientSimple abi > ../../src/abi/tendermint-client-abi.json + +# remove all "."s inside the abi files to make them compatible with the derive macro +sed -i 's/\.//g' ../../src/abi/*.json \ No newline at end of file diff --git a/hyperspace/ethereum/src/abi/diamond-abi.json b/hyperspace/ethereum/src/abi/diamond-abi.json new file mode 100644 index 000000000..d4b457cf7 --- /dev/null +++ b/hyperspace/ethereum/src/abi/diamond-abi.json @@ -0,0 +1,248 @@ +[ + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "facetAddress", + "type": "address" + }, + { + "internalType": "enum IDiamondFacetCutAction", + "name": "action", + "type": "uint8" + }, + { + "internalType": "bytes4[]", + "name": "functionSelectors", + "type": "bytes4[]" + } + ], + "internalType": "struct IDiamondFacetCut[]", + "name": "_diamondCut", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "init", + "type": "address" + }, + { + "internalType": "bytes", + "name": "initCalldata", + "type": "bytes" + } + ], + "internalType": "struct DiamondArgs", + "name": "_args", + "type": "tuple" + } + ], + "stateMutability": "payable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_selector", + "type": "bytes4" + } + ], + "name": "CannotAddFunctionToDiamondThatAlreadyExists", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes4[]", + "name": "_selectors", + "type": "bytes4[]" + } + ], + "name": "CannotAddSelectorsToZeroAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_selector", + "type": "bytes4" + } + ], + "name": "CannotRemoveFunctionThatDoesNotExist", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_selector", + "type": "bytes4" + } + ], + "name": "CannotRemoveImmutableFunction", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_selector", + "type": "bytes4" + } + ], + "name": "CannotReplaceFunctionThatDoesNotExists", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_selector", + "type": "bytes4" + } + ], + "name": "CannotReplaceFunctionWithTheSameFunctionFromTheSameFacet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes4[]", + "name": "_selectors", + "type": "bytes4[]" + } + ], + "name": "CannotReplaceFunctionsFromFacetWithZeroAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_selector", + "type": "bytes4" + } + ], + "name": "CannotReplaceImmutableFunction", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_functionSelector", + "type": "bytes4" + } + ], + "name": "FunctionNotFound", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "_action", + "type": "uint8" + } + ], + "name": "IncorrectFacetCutAction", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_initializationContractAddress", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_calldata", + "type": "bytes" + } + ], + "name": "InitializationFunctionReverted", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_contractAddress", + "type": "address" + }, + { + "internalType": "string", + "name": "_message", + "type": "string" + } + ], + "name": "NoBytecodeAtAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_facetAddress", + "type": "address" + } + ], + "name": "NoSelectorsProvidedForFacetForCut", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_facetAddress", + "type": "address" + } + ], + "name": "RemoveFacetAddressMustBeZeroAddress", + "type": "error" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "calls", + "type": "bytes[]" + } + ], + "name": "callBatch", + "outputs": [ + { + "internalType": "bool[]", + "name": "", + "type": "bool[]" + }, + { + "internalType": "bytes[]", + "name": "", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/hyperspace/ethereum/src/abi/diamond-cut-facet-abi.json b/hyperspace/ethereum/src/abi/diamond-cut-facet-abi.json new file mode 100644 index 000000000..fe1b32175 --- /dev/null +++ b/hyperspace/ethereum/src/abi/diamond-cut-facet-abi.json @@ -0,0 +1,253 @@ +[ + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_selector", + "type": "bytes4" + } + ], + "name": "CannotAddFunctionToDiamondThatAlreadyExists", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes4[]", + "name": "_selectors", + "type": "bytes4[]" + } + ], + "name": "CannotAddSelectorsToZeroAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_selector", + "type": "bytes4" + } + ], + "name": "CannotRemoveFunctionThatDoesNotExist", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_selector", + "type": "bytes4" + } + ], + "name": "CannotRemoveImmutableFunction", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_selector", + "type": "bytes4" + } + ], + "name": "CannotReplaceFunctionThatDoesNotExists", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_selector", + "type": "bytes4" + } + ], + "name": "CannotReplaceFunctionWithTheSameFunctionFromTheSameFacet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes4[]", + "name": "_selectors", + "type": "bytes4[]" + } + ], + "name": "CannotReplaceFunctionsFromFacetWithZeroAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_selector", + "type": "bytes4" + } + ], + "name": "CannotReplaceImmutableFunction", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "_action", + "type": "uint8" + } + ], + "name": "IncorrectFacetCutAction", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_initializationContractAddress", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_calldata", + "type": "bytes" + } + ], + "name": "InitializationFunctionReverted", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_contractAddress", + "type": "address" + }, + { + "internalType": "string", + "name": "_message", + "type": "string" + } + ], + "name": "NoBytecodeAtAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_facetAddress", + "type": "address" + } + ], + "name": "NoSelectorsProvidedForFacetForCut", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + }, + { + "internalType": "address", + "name": "_contractOwner", + "type": "address" + } + ], + "name": "NotContractOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_facetAddress", + "type": "address" + } + ], + "name": "RemoveFacetAddressMustBeZeroAddress", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "facetAddress", + "type": "address" + }, + { + "internalType": "enum IDiamondFacetCutAction", + "name": "action", + "type": "uint8" + }, + { + "internalType": "bytes4[]", + "name": "functionSelectors", + "type": "bytes4[]" + } + ], + "indexed": false, + "internalType": "struct IDiamondFacetCut[]", + "name": "_diamondCut", + "type": "tuple[]" + }, + { + "indexed": false, + "internalType": "address", + "name": "_init", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "_calldata", + "type": "bytes" + } + ], + "name": "DiamondCut", + "type": "event" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "facetAddress", + "type": "address" + }, + { + "internalType": "enum IDiamondFacetCutAction", + "name": "action", + "type": "uint8" + }, + { + "internalType": "bytes4[]", + "name": "functionSelectors", + "type": "bytes4[]" + } + ], + "internalType": "struct IDiamondFacetCut[]", + "name": "_diamondCut", + "type": "tuple[]" + }, + { + "internalType": "address", + "name": "_init", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_calldata", + "type": "bytes" + } + ], + "name": "diamondCut", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/hyperspace/ethereum/src/abi/diamond-loupe-facet-abi.json b/hyperspace/ethereum/src/abi/diamond-loupe-facet-abi.json new file mode 100644 index 000000000..9e55b210e --- /dev/null +++ b/hyperspace/ethereum/src/abi/diamond-loupe-facet-abi.json @@ -0,0 +1,97 @@ +[ + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_functionSelector", + "type": "bytes4" + } + ], + "name": "facetAddress", + "outputs": [ + { + "internalType": "address", + "name": "facetAddress_", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "facetAddresses", + "outputs": [ + { + "internalType": "address[]", + "name": "facetAddresses_", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_facet", + "type": "address" + } + ], + "name": "facetFunctionSelectors", + "outputs": [ + { + "internalType": "bytes4[]", + "name": "_facetFunctionSelectors", + "type": "bytes4[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "facets", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "facetAddress", + "type": "address" + }, + { + "internalType": "bytes4[]", + "name": "functionSelectors", + "type": "bytes4[]" + } + ], + "internalType": "struct IDiamondLoupeFacet[]", + "name": "facets_", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/hyperspace/ethereum/src/abi/ibc-host-abi.json b/hyperspace/ethereum/src/abi/ibc-host-abi.json deleted file mode 100644 index c0541973d..000000000 --- a/hyperspace/ethereum/src/abi/ibc-host-abi.json +++ /dev/null @@ -1,1334 +0,0 @@ -[ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "", - "type": "string" - } - ], - "name": "GeneratedChannelIdentifier", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "", - "type": "string" - } - ], - "name": "GeneratedClientIdentifier", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "", - "type": "string" - } - ], - "name": "GeneratedConnectionIdentifier", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "name", - "type": "bytes" - }, - { - "internalType": "address", - "name": "addr", - "type": "address" - } - ], - "name": "authenticateCapability", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "name", - "type": "bytes" - }, - { - "internalType": "address", - "name": "addr", - "type": "address" - } - ], - "name": "claimCapability", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "portId", - "type": "string" - }, - { - "internalType": "string", - "name": "channelId", - "type": "string" - }, - { - "internalType": "uint64", - "name": "sequence", - "type": "uint64" - } - ], - "name": "deletePacketCommitment", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "generateChannelIdentifier", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "clientType", - "type": "string" - } - ], - "name": "generateClientIdentifier", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "generateConnectionIdentifier", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "portId", - "type": "string" - }, - { - "internalType": "string", - "name": "channelId", - "type": "string" - } - ], - "name": "getChannel", - "outputs": [ - { - "components": [ - { - "internalType": "enum Channel.State", - "name": "state", - "type": "uint8" - }, - { - "internalType": "enum Channel.Order", - "name": "ordering", - "type": "uint8" - }, - { - "components": [ - { - "internalType": "string", - "name": "port_id", - "type": "string" - }, - { - "internalType": "string", - "name": "channel_id", - "type": "string" - } - ], - "internalType": "struct ChannelCounterparty.Data", - "name": "counterparty", - "type": "tuple" - }, - { - "internalType": "string[]", - "name": "connection_hops", - "type": "string[]" - }, - { - "internalType": "string", - "name": "version", - "type": "string" - } - ], - "internalType": "struct Channel.Data", - "name": "channel", - "type": "tuple" - }, - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "clientType", - "type": "string" - } - ], - "name": "getClientImpl", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "clientId", - "type": "string" - } - ], - "name": "getClientState", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - }, - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "clientId", - "type": "string" - } - ], - "name": "getClientType", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "connectionId", - "type": "string" - } - ], - "name": "getConnection", - "outputs": [ - { - "components": [ - { - "internalType": "string", - "name": "client_id", - "type": "string" - }, - { - "components": [ - { - "internalType": "string", - "name": "identifier", - "type": "string" - }, - { - "internalType": "string[]", - "name": "features", - "type": "string[]" - } - ], - "internalType": "struct Version.Data[]", - "name": "versions", - "type": "tuple[]" - }, - { - "internalType": "enum ConnectionEnd.State", - "name": "state", - "type": "uint8" - }, - { - "components": [ - { - "internalType": "string", - "name": "client_id", - "type": "string" - }, - { - "internalType": "string", - "name": "connection_id", - "type": "string" - }, - { - "components": [ - { - "internalType": "bytes", - "name": "key_prefix", - "type": "bytes" - } - ], - "internalType": "struct MerklePrefix.Data", - "name": "prefix", - "type": "tuple" - } - ], - "internalType": "struct Counterparty.Data", - "name": "counterparty", - "type": "tuple" - }, - { - "internalType": "uint64", - "name": "delay_period", - "type": "uint64" - } - ], - "internalType": "struct ConnectionEnd.Data", - "name": "connection", - "type": "tuple" - }, - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "clientId", - "type": "string" - }, - { - "internalType": "uint64", - "name": "height", - "type": "uint64" - } - ], - "name": "getConsensusState", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - }, - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getExpectedTimePerBlock", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "name", - "type": "bytes" - } - ], - "name": "getModuleOwner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "portId", - "type": "string" - }, - { - "internalType": "string", - "name": "channelId", - "type": "string" - } - ], - "name": "getNextSequenceAck", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "portId", - "type": "string" - }, - { - "internalType": "string", - "name": "channelId", - "type": "string" - } - ], - "name": "getNextSequenceRecv", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "portId", - "type": "string" - }, - { - "internalType": "string", - "name": "channelId", - "type": "string" - } - ], - "name": "getNextSequenceSend", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "portId", - "type": "string" - }, - { - "internalType": "string", - "name": "channelId", - "type": "string" - }, - { - "internalType": "uint64", - "name": "sequence", - "type": "uint64" - } - ], - "name": "getPacketAcknowledgementCommitment", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - }, - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "portId", - "type": "string" - }, - { - "internalType": "string", - "name": "channelId", - "type": "string" - }, - { - "internalType": "uint64", - "name": "sequence", - "type": "uint64" - } - ], - "name": "getPacketCommitment", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - }, - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "clientId", - "type": "string" - }, - { - "internalType": "uint64", - "name": "height", - "type": "uint64" - } - ], - "name": "getProcessedHeight", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "clientId", - "type": "string" - }, - { - "internalType": "uint64", - "name": "height", - "type": "uint64" - } - ], - "name": "getProcessedTime", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "portId", - "type": "string" - }, - { - "internalType": "string", - "name": "channelId", - "type": "string" - }, - { - "internalType": "uint64", - "name": "sequence", - "type": "uint64" - } - ], - "name": "hasAcknowledgement", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "portId", - "type": "string" - }, - { - "internalType": "string", - "name": "channelId", - "type": "string" - }, - { - "internalType": "uint64", - "name": "fromSequence", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "toSequence", - "type": "uint64" - } - ], - "name": "hasAcknowledgements", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "portId", - "type": "string" - }, - { - "internalType": "string", - "name": "channelId", - "type": "string" - }, - { - "internalType": "uint64", - "name": "sequence", - "type": "uint64" - } - ], - "name": "hasPacketReceipt", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "acknowledgement", - "type": "bytes" - } - ], - "name": "makePacketAcknowledgementCommitment", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint64", - "name": "sequence", - "type": "uint64" - }, - { - "internalType": "string", - "name": "source_port", - "type": "string" - }, - { - "internalType": "string", - "name": "source_channel", - "type": "string" - }, - { - "internalType": "string", - "name": "destination_port", - "type": "string" - }, - { - "internalType": "string", - "name": "destination_channel", - "type": "string" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "uint64", - "name": "revision_number", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "revision_height", - "type": "uint64" - } - ], - "internalType": "struct Height.Data", - "name": "timeout_height", - "type": "tuple" - }, - { - "internalType": "uint64", - "name": "timeout_timestamp", - "type": "uint64" - } - ], - "internalType": "struct Packet.Data", - "name": "packet", - "type": "tuple" - } - ], - "name": "makePacketCommitment", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "onlyIBCModule", - "outputs": [], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "setAboba", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "portId", - "type": "string" - }, - { - "internalType": "string", - "name": "channelId", - "type": "string" - }, - { - "components": [ - { - "internalType": "enum Channel.State", - "name": "state", - "type": "uint8" - }, - { - "internalType": "enum Channel.Order", - "name": "ordering", - "type": "uint8" - }, - { - "components": [ - { - "internalType": "string", - "name": "port_id", - "type": "string" - }, - { - "internalType": "string", - "name": "channel_id", - "type": "string" - } - ], - "internalType": "struct ChannelCounterparty.Data", - "name": "counterparty", - "type": "tuple" - }, - { - "internalType": "string[]", - "name": "connection_hops", - "type": "string[]" - }, - { - "internalType": "string", - "name": "version", - "type": "string" - } - ], - "internalType": "struct Channel.Data", - "name": "channel", - "type": "tuple" - } - ], - "name": "setChannel", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "clientType", - "type": "string" - }, - { - "internalType": "address", - "name": "clientImpl", - "type": "address" - } - ], - "name": "setClientImpl", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "clientId", - "type": "string" - }, - { - "internalType": "bytes", - "name": "clientStateBytes", - "type": "bytes" - } - ], - "name": "setClientState", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "clientId", - "type": "string" - }, - { - "internalType": "string", - "name": "clientType", - "type": "string" - } - ], - "name": "setClientType", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "connectionId", - "type": "string" - }, - { - "components": [ - { - "internalType": "string", - "name": "client_id", - "type": "string" - }, - { - "components": [ - { - "internalType": "string", - "name": "identifier", - "type": "string" - }, - { - "internalType": "string[]", - "name": "features", - "type": "string[]" - } - ], - "internalType": "struct Version.Data[]", - "name": "versions", - "type": "tuple[]" - }, - { - "internalType": "enum ConnectionEnd.State", - "name": "state", - "type": "uint8" - }, - { - "components": [ - { - "internalType": "string", - "name": "client_id", - "type": "string" - }, - { - "internalType": "string", - "name": "connection_id", - "type": "string" - }, - { - "components": [ - { - "internalType": "bytes", - "name": "key_prefix", - "type": "bytes" - } - ], - "internalType": "struct MerklePrefix.Data", - "name": "prefix", - "type": "tuple" - } - ], - "internalType": "struct Counterparty.Data", - "name": "counterparty", - "type": "tuple" - }, - { - "internalType": "uint64", - "name": "delay_period", - "type": "uint64" - } - ], - "internalType": "struct ConnectionEnd.Data", - "name": "connection", - "type": "tuple" - } - ], - "name": "setConnection", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "clientId", - "type": "string" - }, - { - "internalType": "uint64", - "name": "height", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "consensusStateBytes", - "type": "bytes" - } - ], - "name": "setConsensusState", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "expectedTimePerBlock_", - "type": "uint64" - } - ], - "name": "setExpectedTimePerBlock", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "ibcModule_", - "type": "address" - } - ], - "name": "setIBCModule", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "portId", - "type": "string" - }, - { - "internalType": "string", - "name": "channelId", - "type": "string" - }, - { - "internalType": "uint64", - "name": "sequence", - "type": "uint64" - } - ], - "name": "setNextSequenceAck", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "portId", - "type": "string" - }, - { - "internalType": "string", - "name": "channelId", - "type": "string" - }, - { - "internalType": "uint64", - "name": "sequence", - "type": "uint64" - } - ], - "name": "setNextSequenceRecv", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "portId", - "type": "string" - }, - { - "internalType": "string", - "name": "channelId", - "type": "string" - }, - { - "internalType": "uint64", - "name": "sequence", - "type": "uint64" - } - ], - "name": "setNextSequenceSend", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "portId", - "type": "string" - }, - { - "internalType": "string", - "name": "channelId", - "type": "string" - }, - { - "internalType": "uint64", - "name": "sequence", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "acknowledgement", - "type": "bytes" - } - ], - "name": "setPacketAcknowledgementCommitment", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "portId", - "type": "string" - }, - { - "internalType": "string", - "name": "channelId", - "type": "string" - }, - { - "internalType": "uint64", - "name": "sequence", - "type": "uint64" - }, - { - "components": [ - { - "internalType": "uint64", - "name": "sequence", - "type": "uint64" - }, - { - "internalType": "string", - "name": "source_port", - "type": "string" - }, - { - "internalType": "string", - "name": "source_channel", - "type": "string" - }, - { - "internalType": "string", - "name": "destination_port", - "type": "string" - }, - { - "internalType": "string", - "name": "destination_channel", - "type": "string" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "uint64", - "name": "revision_number", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "revision_height", - "type": "uint64" - } - ], - "internalType": "struct Height.Data", - "name": "timeout_height", - "type": "tuple" - }, - { - "internalType": "uint64", - "name": "timeout_timestamp", - "type": "uint64" - } - ], - "internalType": "struct Packet.Data", - "name": "packet", - "type": "tuple" - } - ], - "name": "setPacketCommitment", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "portId", - "type": "string" - }, - { - "internalType": "string", - "name": "channelId", - "type": "string" - }, - { - "internalType": "uint64", - "name": "sequence", - "type": "uint64" - } - ], - "name": "setPacketReceipt", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "clientId", - "type": "string" - }, - { - "internalType": "uint64", - "name": "height", - "type": "uint64" - }, - { - "internalType": "uint256", - "name": "processedHeight", - "type": "uint256" - } - ], - "name": "setProcessedHeight", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "clientId", - "type": "string" - }, - { - "internalType": "uint64", - "name": "height", - "type": "uint64" - }, - { - "internalType": "uint256", - "name": "processedTime", - "type": "uint256" - } - ], - "name": "setProcessedTime", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/hyperspace/ethereum/src/abi/ibc-querier-abi.json b/hyperspace/ethereum/src/abi/ibc-querier-abi.json new file mode 100644 index 000000000..54720553e --- /dev/null +++ b/hyperspace/ethereum/src/abi/ibc-querier-abi.json @@ -0,0 +1,511 @@ +[ + { + "inputs": [ + { + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "internalType": "string", + "name": "channelId", + "type": "string" + } + ], + "name": "getChannel", + "outputs": [ + { + "components": [ + { + "internalType": "enum ChannelState", + "name": "state", + "type": "uint8" + }, + { + "internalType": "enum ChannelOrder", + "name": "ordering", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "string", + "name": "port_id", + "type": "string" + }, + { + "internalType": "string", + "name": "channel_id", + "type": "string" + } + ], + "internalType": "struct ChannelCounterpartyData", + "name": "counterparty", + "type": "tuple" + }, + { + "internalType": "string[]", + "name": "connection_hops", + "type": "string[]" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + } + ], + "internalType": "struct ChannelData", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "clientId", + "type": "string" + } + ], + "name": "getClientState", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + }, + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "connectionId", + "type": "string" + } + ], + "name": "getConnection", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "client_id", + "type": "string" + }, + { + "components": [ + { + "internalType": "string", + "name": "identifier", + "type": "string" + }, + { + "internalType": "string[]", + "name": "features", + "type": "string[]" + } + ], + "internalType": "struct VersionData[]", + "name": "versions", + "type": "tuple[]" + }, + { + "internalType": "enum ConnectionEndState", + "name": "state", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "string", + "name": "client_id", + "type": "string" + }, + { + "internalType": "string", + "name": "connection_id", + "type": "string" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "key_prefix", + "type": "bytes" + } + ], + "internalType": "struct MerklePrefixData", + "name": "prefix", + "type": "tuple" + } + ], + "internalType": "struct CounterpartyData", + "name": "counterparty", + "type": "tuple" + }, + { + "internalType": "uint64", + "name": "delay_period", + "type": "uint64" + } + ], + "internalType": "struct ConnectionEndData", + "name": "", + "type": "tuple" + }, + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "clientId", + "type": "string" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "revision_number", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "revision_height", + "type": "uint64" + } + ], + "internalType": "struct HeightData", + "name": "height", + "type": "tuple" + } + ], + "name": "getConsensusState", + "outputs": [ + { + "internalType": "bytes", + "name": "consensusStateBytes", + "type": "bytes" + }, + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getExpectedTimePerBlock", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "internalType": "string", + "name": "channelId", + "type": "string" + }, + { + "internalType": "uint64", + "name": "sequence", + "type": "uint64" + } + ], + "name": "getHashedPacketAcknowledgementCommitment", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "internalType": "string", + "name": "channelId", + "type": "string" + }, + { + "internalType": "uint64", + "name": "sequence", + "type": "uint64" + } + ], + "name": "getHashedPacketCommitment", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "internalType": "string", + "name": "channelId", + "type": "string" + } + ], + "name": "getNextSequenceSend", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "internalType": "string", + "name": "channelId", + "type": "string" + }, + { + "internalType": "uint64", + "name": "sequence", + "type": "uint64" + } + ], + "name": "getPacketAcknowledgementCommitment", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "internalType": "string", + "name": "channelId", + "type": "string" + }, + { + "internalType": "uint64", + "name": "sequence", + "type": "uint64" + } + ], + "name": "hasAcknowledgement", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "internalType": "string", + "name": "channelId", + "type": "string" + }, + { + "internalType": "uint64", + "name": "fromSequence", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "toSequence", + "type": "uint64" + } + ], + "name": "hasAcknowledgements", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "internalType": "string", + "name": "channelId", + "type": "string" + }, + { + "internalType": "uint64", + "name": "sequence", + "type": "uint64" + } + ], + "name": "hasCommitment", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "internalType": "string", + "name": "channelId", + "type": "string" + }, + { + "internalType": "uint64", + "name": "fromSequence", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "toSequence", + "type": "uint64" + } + ], + "name": "hasCommitments", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "internalType": "string", + "name": "channelId", + "type": "string" + }, + { + "internalType": "uint64", + "name": "sequence", + "type": "uint64" + } + ], + "name": "hasPacketReceipt", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/hyperspace/ethereum/src/abi/ics20-transfer-bank-abi.json b/hyperspace/ethereum/src/abi/ics20-transfer-bank-abi.json new file mode 100644 index 000000000..e9d73c246 --- /dev/null +++ b/hyperspace/ethereum/src/abi/ics20-transfer-bank-abi.json @@ -0,0 +1,430 @@ +[ + { + "inputs": [ + { + "internalType": "contract IDiamond", + "name": "ibcHandler_", + "type": "address" + }, + { + "internalType": "contract IICS20Bank", + "name": "bank_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "string", + "name": "id", + "type": "string" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ibcAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint64", + "name": "sequence", + "type": "uint64" + }, + { + "internalType": "string", + "name": "source_port", + "type": "string" + }, + { + "internalType": "string", + "name": "source_channel", + "type": "string" + }, + { + "internalType": "string", + "name": "destination_port", + "type": "string" + }, + { + "internalType": "string", + "name": "destination_channel", + "type": "string" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "revision_number", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "revision_height", + "type": "uint64" + } + ], + "internalType": "struct HeightData", + "name": "timeout_height", + "type": "tuple" + }, + { + "internalType": "uint64", + "name": "timeout_timestamp", + "type": "uint64" + } + ], + "internalType": "struct PacketData", + "name": "packet", + "type": "tuple" + }, + { + "internalType": "bytes", + "name": "acknowledgement", + "type": "bytes" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "onAcknowledgementPacket", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "internalType": "string", + "name": "channelId", + "type": "string" + } + ], + "name": "onChanCloseConfirm", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "internalType": "string", + "name": "channelId", + "type": "string" + } + ], + "name": "onChanCloseInit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "internalType": "string", + "name": "channelId", + "type": "string" + }, + { + "internalType": "string", + "name": "counterpartyVersion", + "type": "string" + } + ], + "name": "onChanOpenAck", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "portId", + "type": "string" + }, + { + "internalType": "string", + "name": "channelId", + "type": "string" + } + ], + "name": "onChanOpenConfirm", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum ChannelOrder", + "name": "", + "type": "uint8" + }, + { + "internalType": "string[]", + "name": "", + "type": "string[]" + }, + { + "internalType": "string", + "name": "", + "type": "string" + }, + { + "internalType": "string", + "name": "channelId", + "type": "string" + }, + { + "components": [ + { + "internalType": "string", + "name": "port_id", + "type": "string" + }, + { + "internalType": "string", + "name": "channel_id", + "type": "string" + } + ], + "internalType": "struct ChannelCounterpartyData", + "name": "", + "type": "tuple" + }, + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "name": "onChanOpenInit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum ChannelOrder", + "name": "", + "type": "uint8" + }, + { + "internalType": "string[]", + "name": "", + "type": "string[]" + }, + { + "internalType": "string", + "name": "", + "type": "string" + }, + { + "internalType": "string", + "name": "channelId", + "type": "string" + }, + { + "components": [ + { + "internalType": "string", + "name": "port_id", + "type": "string" + }, + { + "internalType": "string", + "name": "channel_id", + "type": "string" + } + ], + "internalType": "struct ChannelCounterpartyData", + "name": "", + "type": "tuple" + }, + { + "internalType": "string", + "name": "", + "type": "string" + }, + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "name": "onChanOpenTry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint64", + "name": "sequence", + "type": "uint64" + }, + { + "internalType": "string", + "name": "source_port", + "type": "string" + }, + { + "internalType": "string", + "name": "source_channel", + "type": "string" + }, + { + "internalType": "string", + "name": "destination_port", + "type": "string" + }, + { + "internalType": "string", + "name": "destination_channel", + "type": "string" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "revision_number", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "revision_height", + "type": "uint64" + } + ], + "internalType": "struct HeightData", + "name": "timeout_height", + "type": "tuple" + }, + { + "internalType": "uint64", + "name": "timeout_timestamp", + "type": "uint64" + } + ], + "internalType": "struct PacketData", + "name": "packet", + "type": "tuple" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "onRecvPacket", + "outputs": [ + { + "internalType": "bytes", + "name": "acknowledgement", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "string", + "name": "receiver", + "type": "string" + }, + { + "internalType": "string", + "name": "sourcePort", + "type": "string" + }, + { + "internalType": "string", + "name": "sourceChannel", + "type": "string" + }, + { + "internalType": "uint64", + "name": "timeoutHeight", + "type": "uint64" + } + ], + "name": "sendTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/hyperspace/ethereum/src/abi/ownership-facet-abi.json b/hyperspace/ethereum/src/abi/ownership-facet-abi.json new file mode 100644 index 000000000..20ab56a94 --- /dev/null +++ b/hyperspace/ethereum/src/abi/ownership-facet-abi.json @@ -0,0 +1,63 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + }, + { + "internalType": "address", + "name": "_contractOwner", + "type": "address" + } + ], + "name": "NotContractOwner", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "owner_", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/hyperspace/ethereum/src/abi/light-client-abi.json b/hyperspace/ethereum/src/abi/tendermint-client-abi.json similarity index 86% rename from hyperspace/ethereum/src/abi/light-client-abi.json rename to hyperspace/ethereum/src/abi/tendermint-client-abi.json index 07c0469a3..c5da66240 100644 --- a/hyperspace/ethereum/src/abi/light-client-abi.json +++ b/hyperspace/ethereum/src/abi/tendermint-client-abi.json @@ -1,4 +1,20 @@ [ + { + "inputs": [ + { + "internalType": "address", + "name": "ibcHandler_", + "type": "address" + }, + { + "internalType": "address", + "name": "delegateTendermintUpdate", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, { "inputs": [ { @@ -44,7 +60,7 @@ "type": "uint64" } ], - "internalType": "struct Height.Data", + "internalType": "struct HeightData", "name": "height", "type": "tuple" } @@ -106,7 +122,7 @@ "type": "uint64" } ], - "internalType": "struct Height.Data", + "internalType": "struct HeightData", "name": "height", "type": "tuple" } @@ -150,7 +166,7 @@ "type": "uint64" } ], - "internalType": "struct Height.Data", + "internalType": "struct HeightData", "name": "", "type": "tuple" }, @@ -183,7 +199,7 @@ "type": "uint64" } ], - "internalType": "struct Height.Data", + "internalType": "struct HeightData", "name": "height", "type": "tuple" } @@ -207,14 +223,26 @@ { "inputs": [ { - "internalType": "string", - "name": "clientId", - "type": "string" - }, - { - "internalType": "bytes", - "name": "clientMessageBytes", - "type": "bytes" + "components": [ + { + "internalType": "string", + "name": "clientId", + "type": "string" + }, + { + "internalType": "bytes", + "name": "clientMessage", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "prevClientState", + "type": "bytes" + } + ], + "internalType": "struct IBCMsgsMsgUpdateClient", + "name": "msg_", + "type": "tuple" } ], "name": "updateClient", @@ -244,7 +272,7 @@ "type": "uint64" } ], - "internalType": "struct Height.Data", + "internalType": "struct HeightData", "name": "height", "type": "tuple" } @@ -282,7 +310,7 @@ "type": "uint64" } ], - "internalType": "struct Height.Data", + "internalType": "struct HeightData", "name": "height", "type": "tuple" }, @@ -314,7 +342,7 @@ "type": "bytes" } ], - "internalType": "struct Height.VerifyMembershipBytes", + "internalType": "struct HeightVerifyMembershipBytes", "name": "membershipBytes", "type": "tuple" }, @@ -332,7 +360,7 @@ "type": "bool" } ], - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { @@ -355,7 +383,7 @@ "type": "uint64" } ], - "internalType": "struct Height.Data", + "internalType": "struct HeightData", "name": "height", "type": "tuple" }, @@ -387,7 +415,7 @@ "type": "bytes" } ], - "internalType": "struct Height.VerifyMembershipBytes", + "internalType": "struct HeightVerifyMembershipBytes", "name": "membershipBytes", "type": "tuple" } diff --git a/hyperspace/ethereum/src/config.rs b/hyperspace/ethereum/src/config.rs index c6fa60d64..3a87b5382 100644 --- a/hyperspace/ethereum/src/config.rs +++ b/hyperspace/ethereum/src/config.rs @@ -83,6 +83,7 @@ pub struct EthereumClientConfig { pub mnemonic: Option, /// private key for the wallet pub private_key: Option, + /// private key path for the wallet pub private_key_path: Option, /// maximum block weight pub max_block_weight: u64, diff --git a/hyperspace/ethereum/src/contract.rs b/hyperspace/ethereum/src/contract.rs index edb348ea3..32ea11191 100644 --- a/hyperspace/ethereum/src/contract.rs +++ b/hyperspace/ethereum/src/contract.rs @@ -379,15 +379,3 @@ impl Detokenize for ConnectionEnd { }) } } - -pub const LIGHT_CLIENT_ABI_JSON: &str = include_str!("./abi/light-client-abi.json"); - -/// Create a new contract instance from the given address and ABI. -#[track_caller] -pub fn light_client_contract(address: Address, client: Arc) -> Contract -where - M: Middleware, -{ - let abi: Abi = serde_json::from_str(LIGHT_CLIENT_ABI_JSON).unwrap(); - Contract::new(address, abi, client) -} diff --git a/hyperspace/ethereum/src/ibc_provider.rs b/hyperspace/ethereum/src/ibc_provider.rs index 25c36f485..5912bd320 100644 --- a/hyperspace/ethereum/src/ibc_provider.rs +++ b/hyperspace/ethereum/src/ibc_provider.rs @@ -120,6 +120,27 @@ abigen!( IbcPacketAbi, "hyperspace/ethereum/src/abi/ibc-packet-abi.json"; + + IbcQuerierAbi, + "hyperspace/ethereum/src/abi/ibc-querier-abi.json"; + + Ics20TransferBankAbi, + "hyperspace/ethereum/src/abi/ics20-transfer-bank-abi.json"; + + TendermintClientAbi, + "hyperspace/ethereum/src/abi/tendermint-client-abi.json"; + + DiamondAbi, + "hyperspace/ethereum/src/abi/diamond-abi.json"; + + DiamondCutFacetAbi, + "hyperspace/ethereum/src/abi/diamond-cut-facet-abi.json"; + + DiamondLoupeFacetAbi, + "hyperspace/ethereum/src/abi/diamond-loupe-facet-abi.json"; + + OwnershipFacetAbi, + "hyperspace/ethereum/src/abi/ownership-facet-abi.json"; ); impl From for Height { diff --git a/hyperspace/ethereum/src/utils.rs b/hyperspace/ethereum/src/utils.rs index 0592eb365..d32392506 100644 --- a/hyperspace/ethereum/src/utils.rs +++ b/hyperspace/ethereum/src/utils.rs @@ -42,15 +42,10 @@ impl FacetCut { #[derive(Debug)] pub struct DeployYuiIbc { - // pub ibc_client: ContractInstance, - // pub ibc_connection: ContractInstance, - // pub ibc_channel_handshake: ContractInstance, - // pub ibc_packet: ContractInstance, - // pub ibc_handler: ContractInstance, pub facet_cuts: Vec, pub deployed_facets: Vec>, pub diamond: ContractInstance, - pub storage_layout: StorageLayout, + // pub storage_layout: StorageLayout, pub tendermint: ContractInstance, pub bank: Option>, } @@ -475,9 +470,9 @@ where assert_eq!(receipt.status, Some(1.into())); } - pub fn find_storage(&self, name: &str) -> &Storage { - self.storage_layout.storage.iter().find(|x| x.contract == name).unwrap() - } + // pub fn find_storage(&self, name: &str) -> &Storage { + // self.storage_layout.storage.iter().find(|x| x.contract == name).unwrap() + // } } impl Clone for DeployYuiIbc @@ -489,7 +484,7 @@ where facet_cuts: self.facet_cuts.clone(), deployed_facets: self.deployed_facets.clone(), diamond: self.diamond.clone(), - storage_layout: self.storage_layout.clone(), + // storage_layout: self.storage_layout.clone(), tendermint: self.tendermint.clone(), bank: self.bank.clone(), } From 6cd6630efd18a5ac9aaf92c5d7f49ef224778608 Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Fri, 15 Sep 2023 00:52:06 -0300 Subject: [PATCH 27/43] Add commands for ethereum client --- Cargo.lock | 104 ++++- config/ethereum.toml | 1 + hyperspace/Cargo.toml | 2 +- hyperspace/core/Cargo.toml | 2 +- hyperspace/core/src/chain.rs | 3 +- hyperspace/core/src/command.rs | 9 +- hyperspace/core/src/macros.rs | 13 +- hyperspace/ethereum/Cargo.toml | 2 + hyperspace/ethereum/src/bin/launch-yui-ibc.rs | 14 +- hyperspace/ethereum/src/client.rs | 56 +-- hyperspace/ethereum/src/cmd.rs | 134 ++++++ hyperspace/ethereum/src/config.rs | 152 +++++- hyperspace/ethereum/src/lib.rs | 8 +- hyperspace/ethereum/src/mock/utils.rs | 325 +------------ hyperspace/ethereum/src/utils.rs | 436 +++++++++++++++++- hyperspace/ethereum/tests/sanity_checks.rs | 55 ++- hyperspace/parachain/Cargo.toml | 2 +- hyperspace/src/main.rs | 15 +- utils/parachain-node/Cargo.toml | 2 +- utils/subxt/codegen/Cargo.toml | 2 +- 20 files changed, 905 insertions(+), 432 deletions(-) create mode 100644 config/ethereum.toml create mode 100644 hyperspace/ethereum/src/cmd.rs diff --git a/Cargo.lock b/Cargo.lock index 061a3484f..e52e2a67e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -227,6 +227,54 @@ dependencies = [ "winapi", ] +[[package]] +name = "anstream" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f58811cfac344940f1a400b6e6231ce35171f614f26439e80f8c1465c5cc0c" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b84bf0a05bbb2a83e5eb6fa36bb6e87baa08193c35ff52bbf6b38d8af2890e46" + +[[package]] +name = "anstyle-parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +dependencies = [ + "windows-sys 0.48.0", +] + +[[package]] +name = "anstyle-wincon" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58f54d10c6dfa51283a066ceab3ec1ab78d13fae00aa49243a45e4571fb79dfd" +dependencies = [ + "anstyle", + "windows-sys 0.48.0", +] + [[package]] name = "anyhow" version = "1.0.75" @@ -1414,26 +1462,24 @@ dependencies = [ [[package]] name = "clap" -version = "4.1.14" +version = "4.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "906f7fe1da4185b7a282b2bc90172a496f9def1aca4545fe7526810741591e14" +checksum = "84ed82781cea27b43c9b106a979fe450a13a31aab0500595fb3fc06616de08e6" dependencies = [ "clap_builder", - "clap_derive 4.1.14", - "once_cell", + "clap_derive 4.4.2", ] [[package]] name = "clap_builder" -version = "4.1.14" +version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "351f9ad9688141ed83dfd8f5fb998a06225ef444b48ff4dc43de6d409b7fd10b" +checksum = "2bb9faaa7c2ef94b2743a21f5a29e6f0010dff4caa69ac8e9d6cf8b6fa74da08" dependencies = [ - "bitflags 1.3.2", - "clap_lex 0.4.1", - "is-terminal", + "anstream", + "anstyle", + "clap_lex 0.5.1", "strsim", - "termcolor", "terminal_size", "unicase", "unicode-width", @@ -1463,9 +1509,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.1.14" +version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81d7dc0031c3a59a04fc2ba395c8e2dd463cba1859275f065d225f6122221b45" +checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873" dependencies = [ "heck", "proc-macro2", @@ -1484,16 +1530,16 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.4.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1" +checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" [[package]] name = "codegen" version = "0.1.0" dependencies = [ "anyhow", - "clap 3.2.23", + "clap 4.4.3", "frame-metadata", "hex", "http", @@ -1598,6 +1644,12 @@ dependencies = [ "wasm-bindgen-futures", ] +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + [[package]] name = "comfy-table" version = "6.1.4" @@ -3702,7 +3754,7 @@ version = "0.1.0" source = "git+https://github.com/foundry-rs/foundry#d4f626bb7f96d46358997d4b27f79358cb2b3401" dependencies = [ "auto_impl", - "clap 4.1.14", + "clap 4.4.3", "comfy-table", "dunce", "ethers-core 2.0.8", @@ -4811,7 +4863,7 @@ name = "hyperspace" version = "0.1.0" dependencies = [ "anyhow", - "clap 3.2.23", + "clap 4.4.3", "hyperspace-core", "tokio", "toml 0.7.6", @@ -4823,7 +4875,7 @@ version = "0.1.0" dependencies = [ "anyhow", "async-trait", - "clap 3.2.23", + "clap 4.4.3", "codegen", "derive_more", "env_logger 0.9.3", @@ -4925,6 +4977,7 @@ dependencies = [ "async-stream", "async-trait", "cast", + "clap 4.4.3", "ecdsa 0.16.7", "elliptic-curve 0.13.5", "env_logger 0.10.0", @@ -4952,6 +5005,7 @@ dependencies = [ "serde", "serde_json", "ssz-rs", + "strum 0.25.0", "sync-committee-primitives", "sync-committee-prover", "sync-committee-verifier", @@ -4990,7 +5044,7 @@ dependencies = [ "beefy-light-client", "beefy-light-client-primitives", "beefy-prover", - "clap 3.2.23", + "clap 4.4.3", "derive_more", "finality-grandpa", "frame-support", @@ -10767,7 +10821,7 @@ dependencies = [ "bytes", "ics23 0.10.0", "proptest", - "rand 0.7.3", + "rand 0.8.5", "sha2 0.10.6", "tendermint", ] @@ -13268,9 +13322,9 @@ version = "1.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "digest 0.10.6", - "rand 0.7.3", + "rand 0.8.5", "static_assertions", ] @@ -13426,6 +13480,12 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + [[package]] name = "uuid" version = "0.8.2" diff --git a/config/ethereum.toml b/config/ethereum.toml new file mode 100644 index 000000000..23050eb88 --- /dev/null +++ b/config/ethereum.toml @@ -0,0 +1 @@ +type = "ethereum" diff --git a/hyperspace/Cargo.toml b/hyperspace/Cargo.toml index 3fe79a4e5..5ccd214bc 100644 --- a/hyperspace/Cargo.toml +++ b/hyperspace/Cargo.toml @@ -6,7 +6,7 @@ authors = ["Seun Lanlege ", "David Salami ), #[cfg(feature = "ethereum")] - Ethereum(EthereumClientConfig, EthereumClient), + Ethereum(EthereumClientConfig, EthereumClient, EthereumCmd), } fn wrap_any_msg_into_wasm(msg: Any, code_id: Bytes) -> Result { diff --git a/hyperspace/core/src/command.rs b/hyperspace/core/src/command.rs index f7cfe14c1..a98547e46 100644 --- a/hyperspace/core/src/command.rs +++ b/hyperspace/core/src/command.rs @@ -13,7 +13,7 @@ // limitations under the License. use crate::{ - chain::{AnyConfig, Config, CoreConfig}, + chain::{AnyCmd, AnyConfig, Config, CoreConfig}, fish, relay, Mode, }; use anyhow::{anyhow, Result}; @@ -51,6 +51,13 @@ pub enum Subcommand { CreateConnection(Cmd), #[clap(name = "create-channel", about = "Creates a channel on the specified port")] CreateChannel(Cmd), + #[clap(name = "client", about = "Client commands")] + Client { + #[command(subcommand)] + client: AnyCmd, + #[command(flatten)] + cmd: Cmd, + }, } #[derive(Debug, Clone, Parser)] diff --git a/hyperspace/core/src/macros.rs b/hyperspace/core/src/macros.rs index 4920a4297..c72b93603 100644 --- a/hyperspace/core/src/macros.rs +++ b/hyperspace/core/src/macros.rs @@ -16,7 +16,7 @@ macro_rules! chains { ($( $(#[$($meta:meta)*])* - $name:ident($config:path, $client:path), + $name:ident($config:path, $client:path$(, $cmd:path)?), )*) => { #[derive(Debug, Serialize, Deserialize, Clone)] #[serde(tag = "type", rename_all = "snake_case")] @@ -72,6 +72,17 @@ macro_rules! chains { Other(String), } + #[derive(Debug, Clone, clap::Parser)] + pub enum AnyCmd { + $( + $(#[$($meta)*])* + $( + #[command(subcommand)] + $name($cmd), + )? + )* + } + impl From for AnyError { fn from(e: anyhow::Error) -> Self { Self::Other(e.to_string()) diff --git a/hyperspace/ethereum/Cargo.toml b/hyperspace/ethereum/Cargo.toml index f50a375b9..9dbf3807e 100644 --- a/hyperspace/ethereum/Cargo.toml +++ b/hyperspace/ethereum/Cargo.toml @@ -52,6 +52,8 @@ once_cell = "1.18.0" ecdsa = "0.16.7" log = "0.4.20" reqwest = "0.11.18" +clap = { version = "4.4.2", features = ["derive"] } +strum = "0.25.0" [dev-dependencies] toml = "0.7.3" diff --git a/hyperspace/ethereum/src/bin/launch-yui-ibc.rs b/hyperspace/ethereum/src/bin/launch-yui-ibc.rs index 7108aafc3..188cbed93 100644 --- a/hyperspace/ethereum/src/bin/launch-yui-ibc.rs +++ b/hyperspace/ethereum/src/bin/launch-yui-ibc.rs @@ -5,14 +5,20 @@ async fn main() { tracing_subscriber::fmt::init(); let path = utils::yui_ibc_solidity_path(); - let project_output = utils::compile_yui(&path, "contracts/core"); - let diamond_project_output = utils::compile_yui(&path, "contracts/diamond"); - let (anvil, client) = utils::spawn_anvil(); + let project_output = hyperspace_ethereum::utils::compile_yui(&path, "contracts/core"); + let diamond_project_output = + hyperspace_ethereum::utils::compile_yui(&path, "contracts/diamond"); + let (anvil, client) = utils::spawn_anvil().await; println!("address: {:?}", anvil.endpoint()); println!("chain-id: {:?}", anvil.chain_id()); - let yui_ibc = utils::deploy_yui_ibc(&project_output, &diamond_project_output, client).await; + let yui_ibc = hyperspace_ethereum::utils::deploy_yui_ibc( + &project_output, + &diamond_project_output, + client, + ) + .await; println!("diamond address: {:?}", yui_ibc.diamond.address()); diff --git a/hyperspace/ethereum/src/client.rs b/hyperspace/ethereum/src/client.rs index 7265e86f9..696ecaef4 100644 --- a/hyperspace/ethereum/src/client.rs +++ b/hyperspace/ethereum/src/client.rs @@ -44,10 +44,7 @@ use std::{ use sync_committee_prover::SyncCommitteeProver; use thiserror::Error; -pub type EthRpcClient = ethers::prelude::SignerMiddleware< - ethers::providers::Provider, - ethers::signers::Wallet, ->; +pub type EthRpcClient = SignerMiddleware, Wallet>; pub(crate) type WsEth = Provider; pub static IBC_STORAGE_SLOT: Lazy = @@ -159,43 +156,30 @@ pub struct AckPacket { impl EthereumClient { pub async fn new(mut config: EthereumClientConfig) -> Result { - let client = Provider::::try_from(config.http_rpc_url.to_string()) - .map_err(|_| ClientError::UriParseError(config.http_rpc_url.clone()))?; - - let chain_id = client.get_chainid().await.unwrap(); - - let wallet: LocalWallet = if let Some(mnemonic) = &config.mnemonic { - MnemonicBuilder::::default() - .phrase(mnemonic.as_str()) - .build() - .unwrap() - .with_chain_id(chain_id.as_u64()) - } else if let Some(path) = config.private_key_path.take() { - LocalWallet::decrypt_keystore( - path, - option_env!("KEY_PASS").expect("KEY_PASS is not set"), - ) - .unwrap() - .into() - } else if let Some(private_key) = config.private_key.take() { - let key = elliptic_curve::SecretKey::::from_sec1_pem( - private_key.as_str(), - ) - .unwrap(); - key.into() - } else { - panic!("no private key or mnemonic provided") + let client = config.client().await?; + + let yui = match config.yui.take() { + None => DeployYuiIbc::<_, _>::from_addresses( + client.clone(), + config.diamond_address.clone().ok_or_else(|| { + ClientError::Other("diamond address must be provided".to_string()) + })?, + Some(config.tendermint_address.clone().ok_or_else(|| { + ClientError::Other("tendermint address must be provided".to_string()) + })?), + Some(config.bank_address.clone().ok_or_else(|| { + ClientError::Other("bank address must be provided".to_string()) + })?), + config.diamond_facets.clone(), + )?, + Some(yui) => yui, }; - - let client = ethers::middleware::SignerMiddleware::new(client, wallet); - - let yui = config.yui.take().unwrap(); Ok(Self { - http_rpc: Arc::new(client), + http_rpc: client, ws_uri: config.ws_rpc_url.clone(), common_state: Default::default(), yui, - prev_state: Arc::new(std::sync::Mutex::new((vec![], vec![]))), + prev_state: Arc::new(Mutex::new((vec![], vec![]))), client_id: Arc::new(Mutex::new(config.client_id.clone())), connection_id: Arc::new(Mutex::new(config.connection_id.clone())), channel_whitelist: Arc::new(Mutex::new( diff --git a/hyperspace/ethereum/src/cmd.rs b/hyperspace/ethereum/src/cmd.rs new file mode 100644 index 000000000..fc9e7fb7c --- /dev/null +++ b/hyperspace/ethereum/src/cmd.rs @@ -0,0 +1,134 @@ +use crate::{ + client::{ClientError, EthRpcClient}, + config::EthereumClientConfig, + utils::{deploy_client, deploy_ibc, deploy_module, DeployYuiIbc}, +}; +use anyhow::{anyhow, bail}; +use clap::{Args, Parser, Subcommand}; +use std::path::PathBuf; + +#[derive(Debug, Clone, Parser)] +pub enum EthereumCmd { + /// Deploy contracts + #[command(subcommand)] + Deploy(DeployCmd), +} + +#[derive(Debug, Clone, Subcommand)] +pub enum DeployCmd { + /// Deploy core contracts + Core(DeployCoreCmd), + /// Deploy module contracts + Module(DeployModuleCmd), + /// Deploy client contracts + Client(DeployClientCmd), +} + +#[derive(Debug, Clone, Args)] +pub struct DeployCoreCmd { + #[clap(long)] + pub yui_solidity_path: PathBuf, +} + +impl DeployCoreCmd { + pub async fn run( + &self, + mut config: EthereumClientConfig, + ) -> anyhow::Result { + let client = config.client().await?; + let path = &self.yui_solidity_path; + let yui_ibc = deploy_ibc::(path, client).await?; + config.diamond_address = Some(yui_ibc.diamond.address()); + config.diamond_facets = yui_ibc + .deployed_facets + .iter() + .map(|x| (x.abi_name(), x.contract().address())) + .collect(); + Ok(config) + } +} + +#[derive(Debug, Clone, Parser)] +pub struct DeployClientCmd { + /// Path to yui-solidity source code + #[clap(long)] + pub yui_solidity_path: PathBuf, + /// Client type (e.g. '07-tendermint') + #[clap(long)] + pub client_type: String, + /// Name of the delegate update contract + #[clap(long)] + pub delegate_update_name: String, + /// Name of the client contract + #[clap(long)] + pub client_name: String, +} + +impl DeployClientCmd { + pub async fn run( + &self, + mut config: EthereumClientConfig, + ) -> anyhow::Result { + let client = config.client().await?; + let path = &self.yui_solidity_path; + let diamond_addr = config.diamond_address.ok_or_else(|| { + anyhow!("Diamond contract should be deployed first (use 'deploy core' subcommand)") + })?; + let facets = config.diamond_facets.clone(); + if facets.is_empty() { + bail!("Diamond facets are empty. Make sure to deploy the core first ('deploy core')") + }; + let yui_ibc = DeployYuiIbc::<_, EthRpcClient>::from_addresses( + client.clone(), + diamond_addr, + None, + None, + facets, + )?; + let contract = deploy_client( + path, + yui_ibc.clone(), + self.client_type.clone(), + &self.delegate_update_name, + &self.client_name, + client, + ) + .await?; + config.tendermint_address = Some(contract.address()); + Ok(config) + } +} + +#[derive(Debug, Clone, Parser)] +pub struct DeployModuleCmd { + #[clap(long)] + pub yui_solidity_path: PathBuf, +} + +impl DeployModuleCmd { + pub async fn run( + &self, + mut config: EthereumClientConfig, + ) -> anyhow::Result { + let client = config.client().await?; + let path = &self.yui_solidity_path; + let diamond_addr = config.diamond_address.ok_or_else(|| { + anyhow!("Diamond contract should be deployed first (use 'deploy core' subcommand)") + })?; + let contract = deploy_module::(path, diamond_addr, client).await?; + config.bank_address = Some(contract.address()); + Ok(config) + } +} + +impl EthereumCmd { + pub async fn run(&self, config: EthereumClientConfig) -> anyhow::Result { + match self { + EthereumCmd::Deploy(cmd) => match cmd { + DeployCmd::Core(cmd) => cmd.run(config).await, + DeployCmd::Client(cmd) => cmd.run(config).await, + DeployCmd::Module(cmd) => cmd.run(config).await, + }, + } + } +} diff --git a/hyperspace/ethereum/src/config.rs b/hyperspace/ethereum/src/config.rs index 3a87b5382..7b4e0ac43 100644 --- a/hyperspace/ethereum/src/config.rs +++ b/hyperspace/ethereum/src/config.rs @@ -1,8 +1,26 @@ -use ethers::signers::LocalWallet; -use std::{str::FromStr, sync::Arc}; +use ethers::{ + abi::Abi, + core::k256, + middleware::SignerMiddleware, + prelude::{coins_bip39::English, LocalWallet, MnemonicBuilder, Signer}, +}; +use std::{ + fmt::{Display, Formatter}, + str::FromStr, + sync::Arc, +}; -use crate::utils::{DeployYuiIbc, ProviderImpl}; +use crate::{ + client::{ClientError, EthRpcClient}, + ibc_provider::{ + DIAMONDABI_ABI, DIAMONDCUTFACETABI_ABI, DIAMONDLOUPEFACETABI_ABI, IBCCHANNELABI_ABI, + IBCCLIENTABI_ABI, IBCCONNECTIONABI_ABI, IBCPACKETABI_ABI, IBCQUERIERABI_ABI, + ICS20TRANSFERBANKABI_ABI, OWNERSHIPFACETABI_ABI, TENDERMINTCLIENTABI_ABI, + }, + utils::{DeployYuiIbc, ProviderImpl}, +}; use ethers::types::Address; +use ethers_providers::{Http, Middleware, Provider}; use ibc::core::ics24_host::identifier::{ChannelId, ClientId, ConnectionId, PortId}; use serde::{de::Visitor, Deserialize, Deserializer, Serialize, Serializer}; @@ -37,28 +55,35 @@ where ser.serialize_str(&format!("{uri}")) } -fn address_de<'de, D>(de: D) -> Result -where - D: Deserializer<'de>, -{ - struct FromStr; +struct AddressFromStr; - impl Visitor<'_> for FromStr { - type Value = Address; +impl Visitor<'_> for AddressFromStr { + type Value = Address; - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(formatter, "a string that can parse into an address") - } + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(formatter, "a string that can parse into an address") + } - fn visit_string(self, v: String) -> Result - where - E: serde::de::Error, - { - Address::from_str(&v).map_err(serde::de::Error::custom) - } + fn visit_string(self, v: String) -> Result + where + E: serde::de::Error, + { + Address::from_str(&v).map_err(serde::de::Error::custom) } +} - de.deserialize_str(FromStr) +fn address_de<'de, D>(de: D) -> Result +where + D: Deserializer<'de>, +{ + de.deserialize_str(AddressFromStr) +} + +fn address_de_opt<'de, D>(de: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + de.deserialize_str(AddressFromStr).map(Some) } #[derive(Debug, Clone, Deserialize, Serialize)] @@ -76,9 +101,6 @@ pub struct EthereumClientConfig { #[serde(deserialize_with = "address_de")] // TODO: remove and use `yui.diamond.address()` instead pub ibc_handler_address: Address, - /// address of the IBCChannelHandshake contract. - #[serde(deserialize_with = "address_de")] - pub tendermint_client_address: Address, /// mnemonic for the wallet pub mnemonic: Option, /// private key for the wallet @@ -100,18 +122,102 @@ pub struct EthereumClientConfig { /// All the client states and headers will be wrapped in WASM ones using the WASM code ID. #[serde(default)] pub wasm_code_id: Option, + /// Diamond contract address + #[serde(deserialize_with = "address_de_opt")] + #[serde(default)] + pub diamond_address: Option
, + /// ICS-07 Tendermint light-client contract address + #[serde(deserialize_with = "address_de_opt")] + #[serde(default)] + pub tendermint_address: Option
, + /// ICS-20 Bank address + #[serde(deserialize_with = "address_de_opt")] + #[serde(default)] + pub bank_address: Option
, + /// Diamond facets (ABI file name, contract address) + pub diamond_facets: Vec<(ContractName, Address)>, #[serde(skip)] pub yui: Option, ProviderImpl>>, pub client_type: String, pub jwt_secret_path: Option, } +#[derive(Debug, Clone, Copy, Deserialize, Serialize, strum::EnumString)] +pub enum ContractName { + Diamond, + DiamondCutFacet, + DiamondLoupeFacet, + IBCChannelHandshake, + IBCClient, + IBCConnection, + IBCPacket, + IBCQuerier, + ICS20TransferBank, + OwnershipFacet, + TendermintLightClientSimple, +} + +impl Display for ContractName { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{self:?}") + } +} + +impl ContractName { + pub fn to_abi(&self) -> Abi { + match self { + ContractName::Diamond => DIAMONDABI_ABI.clone(), + ContractName::DiamondCutFacet => DIAMONDCUTFACETABI_ABI.clone(), + ContractName::DiamondLoupeFacet => DIAMONDLOUPEFACETABI_ABI.clone(), + ContractName::IBCChannelHandshake => IBCCHANNELABI_ABI.clone(), + ContractName::IBCClient => IBCCLIENTABI_ABI.clone(), + ContractName::IBCConnection => IBCCONNECTIONABI_ABI.clone(), + ContractName::IBCPacket => IBCPACKETABI_ABI.clone(), + ContractName::IBCQuerier => IBCQUERIERABI_ABI.clone(), + ContractName::ICS20TransferBank => ICS20TRANSFERBANKABI_ABI.clone(), + ContractName::OwnershipFacet => OWNERSHIPFACETABI_ABI.clone(), + ContractName::TendermintLightClientSimple => TENDERMINTCLIENTABI_ABI.clone(), + } + } +} + impl EthereumClientConfig { /// ICS-23 compatible commitment prefix #[track_caller] pub fn commitment_prefix(&self) -> Vec { hex::decode(self.commitment_prefix.clone()).expect("bad commitment prefix hex") } + + pub async fn client(&self) -> Result, ClientError> { + let client = Provider::::try_from(self.http_rpc_url.to_string()) + .map_err(|_| ClientError::UriParseError(self.http_rpc_url.clone()))?; + + let chain_id = client.get_chainid().await.unwrap(); + + let wallet: LocalWallet = if let Some(mnemonic) = &self.mnemonic { + MnemonicBuilder::::default() + .phrase(mnemonic.as_str()) + .build() + .unwrap() + .with_chain_id(chain_id.as_u64()) + } else if let Some(path) = self.private_key_path.clone() { + LocalWallet::decrypt_keystore( + path, + option_env!("KEY_PASS").expect("KEY_PASS is not set"), + ) + .unwrap() + .into() + } else if let Some(private_key) = self.private_key.clone() { + let key = + elliptic_curve::SecretKey::::from_sec1_pem(private_key.as_str()) + .unwrap(); + key.into() + } else { + panic!("no private key or mnemonic provided") + }; + + Ok(Arc::new(SignerMiddleware::new(client, wallet))) + } } #[cfg(test)] diff --git a/hyperspace/ethereum/src/lib.rs b/hyperspace/ethereum/src/lib.rs index 63cf62fa0..8d5fba0ba 100644 --- a/hyperspace/ethereum/src/lib.rs +++ b/hyperspace/ethereum/src/lib.rs @@ -1,12 +1,10 @@ #![allow(warnings)] -pub mod config; - +pub mod chain; pub mod client; - +pub mod cmd; +pub mod config; pub mod contract; - -pub mod chain; pub mod events; pub mod ibc_provider; pub mod jwt; diff --git a/hyperspace/ethereum/src/mock/utils.rs b/hyperspace/ethereum/src/mock/utils.rs index 8e4725bbd..933029562 100644 --- a/hyperspace/ethereum/src/mock/utils.rs +++ b/hyperspace/ethereum/src/mock/utils.rs @@ -1,52 +1,32 @@ #![allow(dead_code)] -use cast::hashbrown::HashSet; use elliptic_curve::pkcs8::der::pem; -use std::{ - collections::HashMap, - fs::File, - iter::once, - path::{Path, PathBuf}, - sync::Arc, - time::Duration, -}; +use std::{path::PathBuf, sync::Arc, time::Duration}; use crate::{ config::EthereumClientConfig, contract::UnwrapContractError, - utils::{DeployYuiIbc, FacetCut, FacetCutAction, ProviderImpl}, + utils::{DeployYuiIbc, ProviderImpl}, }; use ethers::{ - abi::{Detokenize, Token, Tokenize}, - contract::ContractFactory, - core::{rand::rngs::ThreadRng, utils::Anvil}, + abi::{Detokenize, Tokenize}, + core::utils::Anvil, middleware::SignerMiddleware, - prelude::{ContractInstance, *}, + prelude::*, providers::{Http, Middleware, Provider}, signers::{LocalWallet, Signer}, utils::AnvilInstance, }; -use ethers_solc::{ - artifacts::{ - output_selection::OutputSelection, DebuggingSettings, Libraries, Optimizer, - OptimizerDetails, RevertStrings, Settings, SettingsMetadata, StorageLayout, - }, - Artifact, ConfigurableContractArtifact, EvmVersion, Project, ProjectCompileOutput, - ProjectPathsConfig, SolcConfig, -}; +use ethers_solc::Artifact; use futures::SinkExt; -use ibc::{ - core::{ - ics04_channel::packet::Packet, - ics24_host::identifier::{ChannelId, PortId}, - }, - timestamp::Timestamp, - Height, -}; -use tracing::log; +use ibc::core::ics24_host::identifier::ClientId; pub const USE_GETH: bool = true; +pub const ETH_NODE_PORT: u16 = 8545; +pub const ETH_NODE_PORT_WS: u16 = 8546; +pub const BEACON_NODE_PORT: u16 = 3500; + #[track_caller] pub fn yui_ibc_solidity_path() -> PathBuf { let base = env!("CARGO_MANIFEST_DIR"); @@ -60,7 +40,7 @@ pub fn yui_ibc_solidity_path() -> PathBuf { } #[track_caller] -pub fn spawn_anvil() -> (AnvilInstance, Arc, LocalWallet>>) { +pub async fn spawn_anvil() -> (AnvilInstance, Arc, LocalWallet>>) { let anvil = Anvil::new().spawn(); println!("{:?}", std::env::current_dir().unwrap()); let wallet: LocalWallet = if USE_GETH { @@ -74,125 +54,19 @@ pub fn spawn_anvil() -> (AnvilInstance, Arc, Loc anvil.keys()[0].clone().into() }; - let endpoint = if USE_GETH { "http://localhost:6001".to_string() } else { anvil.endpoint() }; + let endpoint = + if USE_GETH { format!("http://localhost:{}", ETH_NODE_PORT) } else { anvil.endpoint() }; let provider = Provider::::try_from(endpoint) .unwrap() .interval(Duration::from_millis(10u64)); - let chain_id = if USE_GETH { 4242u64 } else { anvil.chain_id() }; + let chain_id = + if USE_GETH { provider.get_chainid().await.unwrap().as_u64() } else { anvil.chain_id() }; let client = SignerMiddleware::new(provider, wallet.with_chain_id(chain_id)); let client = Arc::new(client); (anvil, client) } -#[track_caller] -pub fn compile_solc(project_paths: ProjectPathsConfig) -> ProjectCompileOutput { - // custom solc config to solve Yul-relatated compilation errors - let mut selection = OutputSelection::default_output_selection(); - // selection - // .0 - // .get_mut("*") - // .unwrap() - // .get_mut("*") - // .unwrap() - // .push("storageLayout".to_string()); - let solc_config = SolcConfig { - settings: Settings { - stop_after: None, - remappings: vec![], - optimizer: Optimizer { - enabled: Some(false), - runs: Some(5), - details: Some(OptimizerDetails { - peephole: Some(true), - inliner: Some(true), - jumpdest_remover: Some(true), - order_literals: Some(true), - deduplicate: Some(true), - cse: Some(true), - constant_optimizer: Some(true), - yul: Some(false), - yul_details: None, - }), - }, - model_checker: None, - metadata: None, - output_selection: selection, - evm_version: Some(EvmVersion::Paris), - via_ir: Some(true), // TODO: this flag is unstable - // debug: Some(DebuggingSettings { - // revert_strings: Some(RevertStrings::Debug), - // debug_info: vec!["location".to_string()], - // }), - debug: None, - libraries: Libraries { libs: Default::default() }, - }, - }; - - let mut project = Project::builder() - .paths(project_paths) - .ephemeral() - .no_artifacts() - .solc_config(solc_config) - .build() - .expect("project build failed"); - - // TODO: figure out how to enable it in the config - // project.artifacts.additional_values.storage_layout = true; - // project.artifacts.additional_files.abi = true; - // project.solc.args.push("--storage-layout".to_string()); - - let project_output = project.compile().expect("compilation failed"); - - if project_output.has_compiler_errors() { - for err in project_output.output().errors { - eprintln!("error: {}", err); - } - panic!("compiler errors"); - } - - return project_output -} - -/// Uses solc to compile the yui-ibc-solidity contracts. -/// -/// first argument is the path to the yui-ibc-solidity repo. -/// the second argument is the path to the solidity sources, relative to the first argument. -/// -/// so if you have the yui-ibc-solidity as the path to yui then sources should be "contracts/core" -/// for IBCHandler or "contracts/clients" for the clients. -#[track_caller] -pub fn compile_yui(path_to_yui: &Path, sources: &str) -> ProjectCompileOutput { - assert!( - path_to_yui.exists(), - "path to yui-ibc-solidity does not exist: {}", - path_to_yui.display() - ); - - let project_paths = ProjectPathsConfig::builder() - .root(&path_to_yui) - .sources(path_to_yui.join(sources)) - .build() - .unwrap(); - - compile_solc(project_paths) -} - -#[allow(dead_code)] -pub async fn deploy_contract( - contract: &ConfigurableContractArtifact, - constructor_args: T, - client: Arc, -) -> ContractInstance, M> -where - M: Middleware, - T: abi::Tokenize, -{ - let (abi, bytecode, _) = contract.clone().into_parts(); - let mut factory = ContractFactory::new(abi.unwrap(), bytecode.unwrap(), client.clone()); - factory.deploy(constructor_args).unwrap().send().await.unwrap() -} - pub mod mock { use ethers::abi::Token; use prost::Message; @@ -240,162 +114,12 @@ pub mod mock { } } -fn get_selectors(contract: &ContractInstance, M>) -> Vec<(String, [u8; 4])> -where - M: Middleware, -{ - let signatures = contract.abi().functions.keys().cloned().collect::>(); - signatures - .into_iter() - .filter(|val| val != "init(bytes)") - .map(|val| (val.clone(), contract.abi().function(&val).unwrap().short_signature())) - .collect() -} - -pub async fn deploy_yui_ibc( - project_output: &ProjectCompileOutput, - diamond_project_output: &ProjectCompileOutput, - client: Arc, -) -> DeployYuiIbc, M> -where - M: Middleware, -{ - let facet_names = [ - "IBCClient", - "IBCConnection", - "IBCChannelHandshake", - "IBCPacket", - "IBCQuerier", - "DiamondCutFacet", - "DiamondLoupeFacet", - "OwnershipFacet", - ]; - - project_output.artifacts().for_each(|(name, artifact)| { - let size = artifact.bytecode.as_ref().unwrap().object.as_bytes().unwrap().len(); - let max = 24 * 1024; - if size > max { - panic!("{} size is too big: {}/{}", name, size, max); - } - log::info!("{} size: {}/{}", name, size, max); - }); - diamond_project_output.artifacts().for_each(|(name, artifact)| { - let size = artifact.bytecode.as_ref().unwrap().object.as_bytes().unwrap().len(); - let max = 24 * 1024; - if size > max { - panic!("{} size is too big: {}/{}", name, size, max); - } - log::info!("{} size: {}/{}", name, size, max); - }); - - let acc = client.default_sender().unwrap(); - - println!("Sender account: {acc:?}"); - - let contract = diamond_project_output.find_first("DiamondInit").unwrap(); - let (abi, bytecode, _) = contract.clone().into_parts(); - let factory = ContractFactory::new(abi.unwrap(), bytecode.unwrap(), client.clone()); - let diamond_init = factory.deploy(()).unwrap().send().await.unwrap(); - println!("Diamond init address: {:?}", diamond_init.address()); - - let mut sigs = HashMap::<[u8; 4], (String, String)>::new(); - let mut facet_cuts = vec![]; - let mut deployed_facets = vec![]; - for facet_name in facet_names { - let contract = project_output - .find_first(facet_name) - .or_else(|| diamond_project_output.find_first(facet_name)) - .unwrap(); - let (abi, bytecode, _) = contract.clone().into_parts(); - let factory = ContractFactory::new(abi.unwrap(), bytecode.unwrap(), client.clone()); - let facet = factory.deploy(()).unwrap().send().await.unwrap(); - let facet_address = facet.address(); - println!("Deployed {facet_name} on {facet_address:?}"); - deployed_facets.push(facet.clone()); - let selectors = get_selectors(&facet); - - for (name, selector) in &selectors { - if sigs.contains_key(selector) { - let (contract_name, fn_name) = &sigs[selector]; - panic!( - "duplicate selector: {}:{} and {}:{}", - contract_name, fn_name, facet_name, name - ); - } - sigs.insert(*selector, (facet_name.to_owned(), name.clone())); - } - - let facet_cut = FacetCut { address: facet_address, action: FacetCutAction::Add, selectors }; - facet_cuts.push(facet_cut); - } - let init_calldata = diamond_init.method::<_, ()>("init", ()).unwrap().calldata().unwrap(); - - let contract = diamond_project_output.find_first("Diamond").unwrap(); - let (abi, bytecode, _) = contract.clone().into_parts(); - let factory = ContractFactory::new(abi.unwrap(), bytecode.unwrap(), client.clone()); - let diamond = factory - .deploy(Token::Tuple(vec![ - Token::Array(facet_cuts.clone().into_iter().map(|x| x.into_token()).collect()), - Token::Tuple(vec![ - Token::Address(acc), - Token::Address(diamond_init.address()), - Token::Bytes(init_calldata.0.into()), - ]), - ])) - .unwrap() - .send() - .await - .unwrap(); - - // std::fs::ReadDir::new(). - let predefined_layout = serde_json::from_reader::<_, StorageLayout>( - File::open("/Users/vmark/work/centauri-private/hyperspace/ethereum/src/storage_layout/ibc_storage.json").unwrap(), - ) - .expect("failed to read predefined storage layout"); - - let storage_layout = project_output - .compiled_artifacts() - .iter() - .chain(diamond_project_output.compiled_artifacts()) - .flat_map(|(_, artifact)| { - artifact.into_iter().flat_map(|(an, artifact)| { - println!("artifact name {an}"); - artifact - }) - }) - .filter_map(|ar| ar.artifact.storage_layout.clone()) - .chain(once(predefined_layout)) - .fold(StorageLayout { storage: vec![], types: Default::default() }, |mut acc, layout| { - // let mut len0 = acc.storage.len(); - // let mut len1 = layout.storage.len(); - acc.storage.extend(layout.storage); - // assert_eq!(acc.storage.len(), len0 + len1, "duplicated storage"); - - let len0 = acc.types.len(); - let len1 = layout.types.len(); - acc.types.extend(layout.types); - assert_eq!(acc.types.len(), len0 + len1, "duplicated type"); - acc - }); - - // dbg!(&storage_layout); - let tendermint_client = diamond.clone(); - - DeployYuiIbc { - diamond, - facet_cuts, - deployed_facets, - storage_layout, - tendermint: tendermint_client, - bank: None, - } -} - pub async fn hyperspace_ethereum_client_fixture( anvil: &AnvilInstance, yui_ibc: DeployYuiIbc, ProviderImpl>, ) -> EthereumClientConfig { - let endpoint = if USE_GETH { "http://localhost:6001".to_string() } else { anvil.endpoint() }; + let endpoint = + if USE_GETH { format!("http://localhost:{}", ETH_NODE_PORT) } else { anvil.endpoint() }; let wallet_path = if USE_GETH { Some("keys/0x73db010c3275eb7a92e5c38770316248f4c644ee".to_string()) } else { @@ -424,22 +148,23 @@ pub async fn hyperspace_ethereum_client_fixture( EthereumClientConfig { http_rpc_url: endpoint.parse().unwrap(), - ws_rpc_url: "ws://localhost:5001".parse().unwrap(), - beacon_rpc_url: "http://localhost:8001".parse().unwrap(), + ws_rpc_url: format!("ws://127.0.0.1:{}", ETH_NODE_PORT_WS).parse().unwrap(), + beacon_rpc_url: format!("http://localhost:{}", BEACON_NODE_PORT).parse().unwrap(), ibc_handler_address: yui_ibc.diamond.address(), - tendermint_client_address: yui_ibc.tendermint.address(), mnemonic: None, max_block_weight: 1, private_key: wallet, private_key_path: wallet_path, name: "ethereum-client".into(), - client_id: Some( - ibc::core::ics24_host::identifier::ClientId::new("07-tendermint", 0).unwrap(), - ), + client_id: Some(ClientId::new("07-tendermint", 0).unwrap()), connection_id: None, channel_whitelist: vec![], commitment_prefix: "424242".into(), wasm_code_id: None, + bank_address: yui_ibc.bank.clone().map(|b| b.address()), + diamond_address: Some(yui_ibc.diamond.address()), + tendermint_address: yui_ibc.tendermint.clone().map(|x| x.address()), + diamond_facets: vec![], yui: Some(yui_ibc), client_type: "07-tendermint".into(), jwt_secret_path, diff --git a/hyperspace/ethereum/src/utils.rs b/hyperspace/ethereum/src/utils.rs index d32392506..a28fa59be 100644 --- a/hyperspace/ethereum/src/utils.rs +++ b/hyperspace/ethereum/src/utils.rs @@ -1,15 +1,34 @@ -use crate::contract::UnwrapContractError; +use crate::{ + client::ClientError, + config::{ContractName, EthereumClientConfig}, + contract::UnwrapContractError, + ibc_provider::{DIAMONDABI_ABI, ICS20TRANSFERBANKABI_ABI, TENDERMINTCLIENTABI_ABI}, +}; use ethers::{ - abi::{AbiError, Address, Detokenize, EventExt, Function, FunctionExt, Token, Tokenize}, - contract::{ContractInstance, FunctionCall}, + abi::{AbiError, Address, Detokenize, EventExt, Function, Token, Tokenize}, + contract::{ContractFactory, ContractInstance, FunctionCall}, core::types::Bytes, prelude::{ EthEvent, Event, Filter, Http, LocalWallet, Middleware, Provider, TransactionReceipt, H256, }, }; -use ethers_solc::artifacts::{Storage, StorageLayout}; -use ibc::core::ics04_channel::packet::Packet; -use std::iter; +use ethers_solc::{ + artifacts::{ + output_selection::OutputSelection, Libraries, Optimizer, OptimizerDetails, Settings, + StorageLayout, + }, + Artifact, ConfigurableContractArtifact, EvmVersion, Project, ProjectCompileOutput, + ProjectPathsConfig, SolcConfig, +}; +use ibc::core::{ics02_client::client_state::ClientType, ics04_channel::packet::Packet}; +use std::{ + borrow::Borrow, + collections::HashMap, + fs::File, + iter::once, + path::{Path, PathBuf}, + sync::Arc, +}; pub type ProviderImpl = ethers::prelude::SignerMiddleware, LocalWallet>; @@ -40,19 +59,91 @@ impl FacetCut { } } +#[derive(Debug)] +pub struct Facet { + contract: ContractInstance, + abi_name: ContractName, +} + +impl, M> Clone for Facet { + fn clone(&self) -> Self { + Self { contract: self.contract.clone(), abi_name: self.abi_name } + } +} + +impl Facet +where + B: Borrow + Clone, + M: Middleware, +{ + pub fn new(contract: ContractInstance, abi_name: ContractName) -> Self { + Self { contract, abi_name } + } + + pub fn from_address(address: Address, abi_name: ContractName, client: B) -> Self { + Self { + contract: ContractInstance::::new(address, abi_name.to_abi(), client), + abi_name, + } + } + + pub fn contract(&self) -> &ContractInstance { + &self.contract + } + + pub fn abi_name(&self) -> ContractName { + self.abi_name + } +} + #[derive(Debug)] pub struct DeployYuiIbc { - pub facet_cuts: Vec, - pub deployed_facets: Vec>, + pub deployed_facets: Vec>, pub diamond: ContractInstance, // pub storage_layout: StorageLayout, - pub tendermint: ContractInstance, + pub tendermint: Option>, pub bank: Option>, } impl DeployYuiIbc where - B: Clone + std::borrow::Borrow, + B: Borrow + Clone, + M: Middleware, +{ + pub fn from_addresses( + client: B, + diamond_address: Address, + tendermint_address: Option
, + bank_address: Option
, + diamond_facets: Vec<(ContractName, Address)>, + ) -> Result { + Ok(Self { + diamond: ContractInstance::::new( + diamond_address, + DIAMONDABI_ABI.clone(), + client.clone(), + ), + tendermint: tendermint_address.map(|addr| { + ContractInstance::::new(addr, TENDERMINTCLIENTABI_ABI.clone(), client.clone()) + }), + bank: bank_address.map(|addr| { + ContractInstance::::new( + addr, + ICS20TRANSFERBANKABI_ABI.clone(), + client.clone(), + ) + }), + deployed_facets: diamond_facets + .into_iter() + .map(|(abi, addr)| Facet::from_address(addr, abi, client.clone())) + .collect(), + }) + } +} + +impl DeployYuiIbc +where + B: Clone + Borrow, M: Middleware, { pub async fn bind_port(&self, port_id: &str, address: Address) { @@ -386,7 +477,7 @@ where pub fn function(&self, name: &str) -> ethers::abi::Result<&Function> { let mut func = None; - for faucet in self.deployed_facets.iter().chain(iter::once(&self.diamond)) { + for faucet in self.deployed_facets.iter().map(|x| x.contract()).chain(once(&self.diamond)) { if let Ok(f) = faucet.abi().function(name) { if func.is_some() { log::error!(target: "hyperspace_ethereum", "ambiguous function name: {}", name); @@ -413,7 +504,8 @@ where ) -> Result, AbiError> { let mut contract: Option<&ContractInstance> = None; - let lookup_contracts = self.deployed_facets.iter().chain(std::iter::once(&self.diamond)); + let lookup_contracts = + self.deployed_facets.iter().map(|x| x.contract()).chain(once(&self.diamond)); for lookup_contract in lookup_contracts { if lookup_contract.abi().function(name).is_ok() { @@ -436,7 +528,8 @@ where pub fn event_for_name(&self, name: &str) -> Result, AbiError> { let mut contract: Option<&ContractInstance> = None; - let lookup_contracts = self.deployed_facets.iter().chain(std::iter::once(&self.diamond)); + let lookup_contracts = + self.deployed_facets.iter().map(|x| x.contract()).chain(once(&self.diamond)); for lookup_contract in lookup_contracts { if lookup_contract.abi().event(name).is_ok() { @@ -481,7 +574,6 @@ where { fn clone(&self) -> Self { Self { - facet_cuts: self.facet_cuts.clone(), deployed_facets: self.deployed_facets.clone(), diamond: self.diamond.clone(), // storage_layout: self.storage_layout.clone(), @@ -490,3 +582,319 @@ where } } } + +pub async fn deploy_contract( + contract: &ConfigurableContractArtifact, + constructor_args: T, + client: Arc, +) -> ContractInstance, M> +where + M: Middleware, + T: Tokenize, +{ + let (abi, bytecode, _) = contract.clone().into_parts(); + let mut factory = ContractFactory::new(abi.unwrap(), bytecode.unwrap(), client); + factory.deploy(constructor_args).unwrap().send().await.unwrap() +} + +#[track_caller] +pub fn compile_solc(project_paths: ProjectPathsConfig) -> ProjectCompileOutput { + // custom solc config to solve Yul-relatated compilation errors + let mut selection = OutputSelection::default_output_selection(); + // selection + // .0 + // .get_mut("*") + // .unwrap() + // .get_mut("*") + // .unwrap() + // .push("storageLayout".to_string()); + let solc_config = SolcConfig { + settings: Settings { + stop_after: None, + remappings: vec![], + optimizer: Optimizer { + enabled: Some(false), + runs: Some(5), + details: Some(OptimizerDetails { + peephole: Some(true), + inliner: Some(true), + jumpdest_remover: Some(true), + order_literals: Some(true), + deduplicate: Some(true), + cse: Some(true), + constant_optimizer: Some(true), + yul: Some(false), + yul_details: None, + }), + }, + model_checker: None, + metadata: None, + output_selection: selection, + evm_version: Some(EvmVersion::Paris), + via_ir: Some(true), // TODO: this flag is unstable + // debug: Some(DebuggingSettings { + // revert_strings: Some(RevertStrings::Debug), + // debug_info: vec!["location".to_string()], + // }), + debug: None, + libraries: Libraries { libs: Default::default() }, + }, + }; + + let mut project = Project::builder() + .paths(project_paths) + .ephemeral() + .no_artifacts() + .solc_config(solc_config) + .build() + .expect("project build failed"); + + // TODO: figure out how to enable it in the config + // project.artifacts.additional_values.storage_layout = true; + // project.artifacts.additional_files.abi = true; + // project.solc.args.push("--storage-layout".to_string()); + + let project_output = project.compile().expect("compilation failed"); + + if project_output.has_compiler_errors() { + for err in project_output.output().errors { + eprintln!("error: {}", err); + } + panic!("compiler errors"); + } + + return project_output +} + +/// Uses solc to compile the yui-ibc-solidity contracts. +/// +/// first argument is the path to the yui-ibc-solidity repo. +/// the second argument is the path to the solidity sources, relative to the first argument. +/// +/// so if you have the yui-ibc-solidity as the path to yui then sources should be "contracts/core" +/// for IBCHandler or "contracts/clients" for the clients. +#[track_caller] +pub fn compile_yui(path_to_yui: &Path, sources: &str) -> ProjectCompileOutput { + assert!( + path_to_yui.exists(), + "path to yui-ibc-solidity does not exist: {}", + path_to_yui.display() + ); + + let project_paths = ProjectPathsConfig::builder() + .root(&path_to_yui) + .sources(path_to_yui.join(sources)) + .build() + .unwrap(); + + compile_solc(project_paths) +} + +fn get_selectors(contract: &ContractInstance, M>) -> Vec<(String, [u8; 4])> +where + M: Middleware, +{ + let signatures = contract.abi().functions.keys().cloned().collect::>(); + signatures + .into_iter() + .filter(|val| val != "init(bytes)") + .map(|val| (val.clone(), contract.abi().function(&val).unwrap().short_signature())) + .collect() +} + +pub async fn deploy_yui_ibc( + project_output: &ProjectCompileOutput, + diamond_project_output: &ProjectCompileOutput, + client: Arc, +) -> DeployYuiIbc, M> +where + M: Middleware, +{ + use ContractName::*; + let facet_names = [ + IBCClient, + IBCConnection, + IBCChannelHandshake, + IBCPacket, + IBCQuerier, + DiamondCutFacet, + DiamondLoupeFacet, + OwnershipFacet, + ]; + + project_output.artifacts().for_each(|(name, artifact)| { + let size = artifact.bytecode.as_ref().unwrap().object.as_bytes().unwrap().len(); + let max = 24 * 1024; + if size > max { + panic!("{} size is too big: {}/{}", name, size, max); + } + log::info!("{} size: {}/{}", name, size, max); + }); + diamond_project_output.artifacts().for_each(|(name, artifact)| { + let size = artifact.bytecode.as_ref().unwrap().object.as_bytes().unwrap().len(); + let max = 24 * 1024; + if size > max { + panic!("{} size is too big: {}/{}", name, size, max); + } + log::info!("{} size: {}/{}", name, size, max); + }); + + let acc = client.default_sender().unwrap(); + + println!("Sender account: {acc:?}"); + + let contract = diamond_project_output.find_first("DiamondInit").unwrap(); + let (abi, bytecode, _) = contract.clone().into_parts(); + let factory = ContractFactory::new(abi.unwrap(), bytecode.unwrap(), client.clone()); + let diamond_init = factory.deploy(()).unwrap().send().await.unwrap(); + println!("Diamond init address: {:?}", diamond_init.address()); + + let mut sigs = HashMap::<[u8; 4], (ContractName, String)>::new(); + let mut facet_cuts = vec![]; + let mut deployed_facets = vec![]; + for facet_name in facet_names { + let facet_name_str = facet_name.to_string(); + dbg!(&facet_name_str); + let contract = project_output + .find_first(&facet_name_str) + .or_else(|| diamond_project_output.find_first(&facet_name_str)) + .unwrap(); + let (abi, bytecode, _) = contract.clone().into_parts(); + let factory = ContractFactory::new(abi.unwrap(), bytecode.unwrap(), client.clone()); + let facet = factory.deploy(()).unwrap().send().await.unwrap(); + let facet_address = facet.address(); + println!("Deployed {facet_name} on {facet_address:?}"); + let selectors = get_selectors(&facet); + deployed_facets.push(Facet::new(facet, facet_name)); + + for (name, selector) in &selectors { + if sigs.contains_key(selector) { + let (contract_name, fn_name) = &sigs[selector]; + panic!( + "duplicate selector: {}:{} and {}:{}", + contract_name, fn_name, facet_name_str, name + ); + } + sigs.insert(*selector, (facet_name, name.clone())); + } + + let facet_cut = FacetCut { address: facet_address, action: FacetCutAction::Add, selectors }; + facet_cuts.push(facet_cut); + } + let init_calldata = diamond_init.method::<_, ()>("init", ()).unwrap().calldata().unwrap(); + + let contract = diamond_project_output.find_first("Diamond").unwrap(); + let (abi, bytecode, _) = contract.clone().into_parts(); + let factory = ContractFactory::new(abi.unwrap(), bytecode.unwrap(), client.clone()); + let diamond = factory + .deploy(Token::Tuple(vec![ + Token::Array(facet_cuts.clone().into_iter().map(|x| x.into_token()).collect()), + Token::Tuple(vec![ + Token::Address(acc), + Token::Address(diamond_init.address()), + Token::Bytes(init_calldata.0.into()), + ]), + ])) + .unwrap() + .send() + .await + .unwrap(); + + let predefined_layout = serde_json::from_reader::<_, StorageLayout>( + File::open("/Users/vmark/work/centauri-private/hyperspace/ethereum/src/storage_layout/ibc_storage.json").unwrap(), + ) + .expect("failed to read predefined storage layout"); + + let _storage_layout = project_output + .compiled_artifacts() + .iter() + .chain(diamond_project_output.compiled_artifacts()) + .flat_map(|(_, artifact)| { + artifact.into_iter().flat_map(|(an, artifact)| { + println!("artifact name {an}"); + artifact + }) + }) + .filter_map(|ar| ar.artifact.storage_layout.clone()) + .chain(once(predefined_layout)) + .fold(StorageLayout { storage: vec![], types: Default::default() }, |mut acc, layout| { + acc.storage.extend(layout.storage); + + let len0 = acc.types.len(); + let len1 = layout.types.len(); + acc.types.extend(layout.types); + assert_eq!(acc.types.len(), len0 + len1, "duplicated type"); + acc + }); + + DeployYuiIbc { + diamond, + deployed_facets, + // storage_layout, + tendermint: None, + bank: None, + } +} + +pub async fn deploy_client( + yui_solidity_path: &PathBuf, + yui_ibc: DeployYuiIbc, M>, + client_type: ClientType, + delegate_update_name: &str, + client_name: &str, + client: Arc, +) -> Result, M>, ClientError> { + let project_output1 = compile_yui(yui_solidity_path, "contracts/clients"); + let upd = project_output1.find_first(delegate_update_name).unwrap(); + + let (abi, bytecode, _) = upd.clone().into_parts(); + let factory = ContractFactory::new(abi.unwrap(), bytecode.unwrap(), client.clone()); + let update_client_delegate_contract = factory.deploy(()).unwrap().send().await.unwrap(); + + let contract = project_output1.find_first(client_name).unwrap(); + let r = contract.clone(); + let (abi, bytecode, _) = r.into_parts(); + + let factory = ContractFactory::new(abi.unwrap(), bytecode.unwrap(), client); + let tendermint_light_client = factory + .deploy(( + Token::Address(yui_ibc.diamond.address()), + Token::Address(update_client_delegate_contract.address()), + )) + .unwrap() + .send() + .await + .unwrap(); + + let _ = yui_ibc.register_client(&client_type, tendermint_light_client.address()).await; + Ok(tendermint_light_client) +} + +pub async fn deploy_ibc( + yui_solidity_path: &PathBuf, + client: Arc, +) -> Result, M>, ClientError> { + let project_output = compile_yui(&yui_solidity_path, "contracts/core"); + let diamond_project_output = compile_yui(&yui_solidity_path, "contracts/diamond"); + let yui_ibc = deploy_yui_ibc(&project_output, &diamond_project_output, client).await; + Ok(yui_ibc) +} + +pub async fn deploy_module( + yui_solidity_path: &PathBuf, + diamond_address: Address, + client: Arc, +) -> Result, M>, ClientError> { + let project_output = compile_yui(&yui_solidity_path, "contracts/apps/20-transfer"); + + let artifact = project_output.find_first("ICS20Bank").expect("no ICS20Bank in project output"); + let bank_contract = deploy_contract::(artifact, (), client.clone()).await; + println!("Bank module address: {:?}", bank_contract.address()); + let artifact = project_output + .find_first("ICS20TransferBank") + .expect("no ICS20TransferBank in project output"); + let constructor_args = + (Token::Address(diamond_address), Token::Address(bank_contract.address())); + let module_contract = deploy_contract(artifact, constructor_args, client.clone()).await; + Ok(module_contract) +} diff --git a/hyperspace/ethereum/tests/sanity_checks.rs b/hyperspace/ethereum/tests/sanity_checks.rs index 57209224d..0a3793646 100644 --- a/hyperspace/ethereum/tests/sanity_checks.rs +++ b/hyperspace/ethereum/tests/sanity_checks.rs @@ -20,7 +20,10 @@ use hyperspace_ethereum::{ client::{EthRpcClient, EthereumClient}, config::EthereumClientConfig, contract::{IbcHandler, UnwrapContractError}, - mock::{utils, utils::{USE_GETH, hyperspace_ethereum_client_fixture}}, + mock::{ + utils, + utils::{hyperspace_ethereum_client_fixture, USE_GETH}, + }, utils::{DeployYuiIbc, ProviderImpl}, yui_types::IntoToken, }; @@ -137,14 +140,19 @@ impl DeployYuiIbcMockClient { pub async fn deploy_yui_ibc_and_mock_client_fixture() -> DeployYuiIbcMockClient { let path = utils::yui_ibc_solidity_path(); - let project_output = utils::compile_yui(&path, "contracts/core"); - let diamond_project_output = utils::compile_yui(&path, "contracts/diamond"); - let (anvil, client) = utils::spawn_anvil(); + let project_output = hyperspace_ethereum::utils::compile_yui(&path, "contracts/core"); + let diamond_project_output = + hyperspace_ethereum::utils::compile_yui(&path, "contracts/diamond"); + let (anvil, client) = utils::spawn_anvil().await; log::warn!("{}", anvil.endpoint()); - let yui_ibc = - utils::deploy_yui_ibc(&project_output, &diamond_project_output, client.clone()).await; + let yui_ibc = hyperspace_ethereum::utils::deploy_yui_ibc( + &project_output, + &diamond_project_output, + client.clone(), + ) + .await; - let ibc_mock_client = utils::compile_solc({ + let ibc_mock_client = hyperspace_ethereum::utils::compile_solc({ let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); ProjectPathsConfig::builder() @@ -154,7 +162,7 @@ pub async fn deploy_yui_ibc_and_mock_client_fixture() -> DeployYuiIbcMockClient .unwrap() }); - let ibc_mock_client = utils::deploy_contract( + let ibc_mock_client = hyperspace_ethereum::utils::deploy_contract( ibc_mock_client.find_first("MockClient").unwrap(), (Token::Address(yui_ibc.diamond.address()),), client.clone(), @@ -218,7 +226,7 @@ fn deploy_mock_module_fixture( deploy: &DeployYuiIbcMockClient, ) -> impl Future, ProviderImpl>> + '_ { async move { - let clients = utils::compile_solc({ + let clients = hyperspace_ethereum::utils::compile_solc({ let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); ProjectPathsConfig::builder() @@ -230,8 +238,12 @@ fn deploy_mock_module_fixture( let contract = clients.find_first("MockModule").expect("no MockModule in project output"); let constructor_args = (Token::Address(deploy.yui_ibc.diamond.address()),); - let contract = - utils::deploy_contract(contract, constructor_args, deploy.client.clone()).await; + let contract = hyperspace_ethereum::utils::deploy_contract( + contract, + constructor_args, + deploy.client.clone(), + ) + .await; println!("Mock module address: {:?}", contract.address()); contract } @@ -248,14 +260,19 @@ async fn test_deploy_yui_ibc_and_create_eth_client() { /* ______________________________________________________________________________ */ //compile and deploy yui ibc contracts - let project_output = utils::compile_yui(&path, "contracts/core"); - let project_output1 = utils::compile_yui(&path, "contracts/clients"); - let diamond_project_output = utils::compile_yui(&path, "contracts/diamond"); + let project_output = hyperspace_ethereum::utils::compile_yui(&path, "contracts/core"); + let project_output1 = hyperspace_ethereum::utils::compile_yui(&path, "contracts/clients"); + let diamond_project_output = + hyperspace_ethereum::utils::compile_yui(&path, "contracts/diamond"); - let (anvil, client) = utils::spawn_anvil(); + let (anvil, client) = utils::spawn_anvil().await; - let mut yui_ibc = - utils::deploy_yui_ibc(&project_output, &diamond_project_output, client.clone()).await; + let mut yui_ibc = hyperspace_ethereum::utils::deploy_yui_ibc( + &project_output, + &diamond_project_output, + client.clone(), + ) + .await; /* ______________________________________________________________________________ */ @@ -494,8 +511,8 @@ async fn test_deploy_yui_ibc_and_create_eth_client() { async fn relayer_channel_tests() { let path = utils::yui_ibc_solidity_path(); - let project_output1 = utils::compile_yui(&path, "contracts/clients"); - let (anvil, client) = utils::spawn_anvil(); + let project_output1 = hyperspace_ethereum::utils::compile_yui(&path, "contracts/clients"); + let (anvil, client) = utils::spawn_anvil().await; let signer = Signer::from_str("0CDA3F47EF3C4906693B170EF650EB968C5F4B2C").unwrap(); /* ______________________________________________________________________________ */ diff --git a/hyperspace/parachain/Cargo.toml b/hyperspace/parachain/Cargo.toml index 69c380cec..fc6d6e6ae 100644 --- a/hyperspace/parachain/Cargo.toml +++ b/hyperspace/parachain/Cargo.toml @@ -77,7 +77,7 @@ sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch [dev-dependencies] derive_more = "0.99.17" -clap = {version = "3.2.0", features = ["derive"]} +clap = { version = "4.4.2", features = ["derive"] } state-machine = { package = "sp-state-machine", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } prost = "0.11" primitives = { path = "../primitives", package = "hyperspace-primitives", features = ["testing"] } diff --git a/hyperspace/src/main.rs b/hyperspace/src/main.rs index e09b143e8..a48d44350 100644 --- a/hyperspace/src/main.rs +++ b/hyperspace/src/main.rs @@ -11,9 +11,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -use anyhow::Result; +use anyhow::{bail, Result}; use clap::Parser; use hyperspace_core::{ + chain::{AnyCmd, AnyConfig}, command::{Cli, Subcommand}, logging, }; @@ -42,5 +43,17 @@ async fn main() -> Result<()> { cmd.save_config(&new_config).await }, Subcommand::Fish(cmd) => cmd.fish().await, + Subcommand::Client { cmd, client } => { + let mut config = cmd.parse_config().await?; + match (client, config.chain_a) { + (AnyCmd::Ethereum(client_cmd), AnyConfig::Ethereum(client_cfg)) => { + let new_config = client_cmd.run(client_cfg).await?; + config.chain_a = AnyConfig::Ethereum(new_config); + cmd.save_config(&config).await + }, + (cmd, cfg) => + bail!("Client command {:?} is not supported for chain {:?}", cmd, cfg), + } + }, } } diff --git a/utils/parachain-node/Cargo.toml b/utils/parachain-node/Cargo.toml index a42398598..e1d257234 100644 --- a/utils/parachain-node/Cargo.toml +++ b/utils/parachain-node/Cargo.toml @@ -10,7 +10,7 @@ edition = "2021" build = "build.rs" [dependencies] -clap = { version = "4.0.22", features = ["derive"] } +clap = { version = "4.4.2", features = ["derive"] } derive_more = "0.99.2" log = "0.4.17" codec = { package = "parity-scale-codec", version = "3.0.0" } diff --git a/utils/subxt/codegen/Cargo.toml b/utils/subxt/codegen/Cargo.toml index 9a22f8705..6f28bc957 100644 --- a/utils/subxt/codegen/Cargo.toml +++ b/utils/subxt/codegen/Cargo.toml @@ -11,7 +11,7 @@ path = "bin/main.rs" [dependencies] tokio = { version = "1.21.2", features = ["full"] } anyhow = "1.0.66" -clap = { version = "3.2.22", features = ["derive", "env"] } +clap = { version = "4.4.2", features = ["derive", "env"] } serde_json = "1.0.91" http = "0.2.9" subxt-codegen = { git = "https://github.com/paritytech/subxt", rev = "2a4da618a033bb82f768e4ef67b093b371f8b492" } From 52a339d749aa1677712edee22f56257c18c50095 Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Fri, 15 Sep 2023 01:04:56 -0300 Subject: [PATCH 28/43] update integration test --- hyperspace/testsuite/tests/ethereum_cosmos.rs | 93 +++++++++++-------- 1 file changed, 53 insertions(+), 40 deletions(-) diff --git a/hyperspace/testsuite/tests/ethereum_cosmos.rs b/hyperspace/testsuite/tests/ethereum_cosmos.rs index 852540839..73a51d2cc 100644 --- a/hyperspace/testsuite/tests/ethereum_cosmos.rs +++ b/hyperspace/testsuite/tests/ethereum_cosmos.rs @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +use crate::utils::ETH_NODE_PORT_WS; use core::time::Duration; use ethers::{ abi::Token, @@ -19,7 +20,7 @@ use ethers::{ utils::AnvilInstance, }; use ethers_solc::{Artifact, ProjectCompileOutput, ProjectPathsConfig}; -use futures::StreamExt; +use futures::{StreamExt, TryFutureExt, TryStreamExt}; use hyperspace_core::{ chain::{AnyAssetId, AnyChain, AnyConfig}, logging, @@ -28,7 +29,10 @@ use hyperspace_core::{ use hyperspace_cosmos::client::{CosmosClient, CosmosClientConfig}; use hyperspace_ethereum::{ config::EthereumClientConfig, - mock::{utils, utils::hyperspace_ethereum_client_fixture}, + mock::{ + utils, + utils::{hyperspace_ethereum_client_fixture, ETH_NODE_PORT}, + }, utils::{DeployYuiIbc, ProviderImpl}, }; use hyperspace_parachain::{finality_protocol::FinalityProtocol, ParachainClientConfig}; @@ -66,13 +70,13 @@ impl Default for Args { }); Args { - chain_a: format!("ws://{eth}:5001"), + chain_a: format!("ws://{eth}:{ETH_NODE_PORT_WS}"), chain_b: format!("http://{cosmos}:26657"), connection_prefix_a: "ibc/".to_string(), connection_prefix_b: "ibc".to_string(), cosmos_grpc: format!("http://{cosmos}:9090"), cosmos_ws: format!("ws://{cosmos}:26657/websocket"), - ethereum_rpc: format!("http://{eth}:6001"), + ethereum_rpc: format!("http://{eth}:{}", ETH_NODE_PORT), wasm_path, } } @@ -90,13 +94,28 @@ pub struct DeployYuiIbcTendermintClient { pub async fn deploy_yui_ibc_and_tendermint_client_fixture() -> DeployYuiIbcTendermintClient { let path = utils::yui_ibc_solidity_path(); - let project_output = utils::compile_yui(&path, "contracts/core"); - let diamond_project_output = utils::compile_yui(&path, "contracts/diamond"); - let project_output1 = utils::compile_yui(&path, "contracts/clients"); - let (anvil, client) = utils::spawn_anvil(); + let project_output = hyperspace_ethereum::utils::compile_yui(&path, "contracts/core"); + let diamond_project_output = + hyperspace_ethereum::utils::compile_yui(&path, "contracts/diamond"); + let project_output1 = hyperspace_ethereum::utils::compile_yui(&path, "contracts/clients"); + let (anvil, client) = utils::spawn_anvil().await; log::warn!("{}", anvil.endpoint()); - let yui_ibc = - utils::deploy_yui_ibc(&project_output, &diamond_project_output, client.clone()).await; + let yui_ibc = hyperspace_ethereum::utils::deploy_yui_ibc( + &project_output, + &diamond_project_output, + client.clone(), + ) + .await; + + project_output1.artifacts().for_each(|(name, artifact)| { + if let Some(size) = artifact.bytecode.as_ref().unwrap().object.as_bytes().map(|x| x.len()) { + let max = 24 * 1024; + if size > max { + log::warn!("{} size is too big: {}/{}", name, size, max); + } + log::info!("{} size: {}/{}", name, size, max); + } + }); let upd = project_output1.find_first("DelegateTendermintUpdate").unwrap(); let (abi, bytecode, _) = upd.clone().into_parts(); @@ -139,11 +158,13 @@ fn deploy_transfer_module_fixture( ) -> impl Future, ProviderImpl>> + '_ { async move { let path = utils::yui_ibc_solidity_path(); - let project_output = utils::compile_yui(&path, "contracts/apps/20-transfer"); + let project_output = + hyperspace_ethereum::utils::compile_yui(&path, "contracts/apps/20-transfer"); let artifact = project_output.find_first("ICS20Bank").expect("no ICS20Bank in project output"); - let bank_contract = utils::deploy_contract(artifact, (), deploy.client.clone()).await; + let bank_contract = + hyperspace_ethereum::utils::deploy_contract(artifact, (), deploy.client.clone()).await; println!("Bank module address: {:?}", bank_contract.address()); let artifact = project_output .find_first("ICS20TransferBank") @@ -152,8 +173,12 @@ fn deploy_transfer_module_fixture( Token::Address(deploy.yui_ibc.diamond.address()), Token::Address(bank_contract.address()), ); - let module_contract = - utils::deploy_contract(artifact, constructor_args, deploy.client.clone()).await; + let module_contract = hyperspace_ethereum::utils::deploy_contract( + artifact, + constructor_args, + deploy.client.clone(), + ) + .await; module_contract } } @@ -173,31 +198,11 @@ async fn setup_clients() -> (AnyChain, AnyChain) { yui_ibc.bind_port("transfer", bank.address()).await; yui_ibc.bank = Some(bank); - // Overrides - // yui_ibc.diamond = ContractInstance::new( - // H160::from_str("0xf02f5476535c0eea1e501d2c155c1e1f3055e752").unwrap(), - // yui_ibc.diamond.abi().clone(), - // yui_ibc.diamond.client(), - // ); - // yui_ibc.tendermint = ContractInstance::new( - // H160::from_str("0x5d2d6b3fd375fd77dc627d1ae955c441ec157847").unwrap(), - // yui_ibc.tendermint.abi().clone(), - // yui_ibc.tendermint.client(), - // ); - // { - // let bank = yui_ibc.bank.as_mut().unwrap(); - // *bank = ContractInstance::new( - // H160::from_str("0xa4373e6da07ad62d43c3a74f5edb3d3aa6674c14").unwrap(), - // bank.abi().clone(), - // bank.client(), - // ); - // } - //replace the tendermint client address in hyperspace config with a real one let diamond_address = yui_ibc.diamond.address(); - let tendermint_address = yui_ibc.tendermint.address(); + let tendermint_address = yui_ibc.tendermint.as_ref().map(|x| x.address()); let mut config_a = hyperspace_ethereum_client_fixture(&anvil, yui_ibc).await; - config_a.tendermint_client_address = tendermint_address; + config_a.tendermint_address = tendermint_address; config_a.ibc_handler_address = diamond_address; let mut config_b = CosmosClientConfig { @@ -269,10 +274,8 @@ async fn setup_clients() -> (AnyChain, AnyChain) { async fn ethereum_to_cosmos_ibc_messaging_full_integration_test() { logging::setup_logging(); - let asset_id_a = AnyAssetId::Ethereum("pica".to_string()); - let asset_id_b = AnyAssetId::Cosmos( - "ibc/47B97D8FF01DA03FCB2F4B1FFEC931645F254E21EF465FA95CBA6888CB964DC4".to_string(), - ); + let asset_str = "pica".to_string(); + let asset_id_a = AnyAssetId::Ethereum(asset_str.clone()); let (mut chain_a, mut chain_b) = setup_clients().await; let (handle, channel_a, channel_b, connection_id_a, connection_id_b) = setup_connection_and_channel(&mut chain_a, &mut chain_b, Duration::from_secs(60 * 2)).await; @@ -286,6 +289,16 @@ async fn ethereum_to_cosmos_ibc_messaging_full_integration_test() { log::info!(target: "hyperspace", "Conn A: {connection_id_a:?} B: {connection_id_b:?}"); log::info!(target: "hyperspace", "Chann A: {channel_a:?} B: {channel_b:?}"); + let asset_id_b = AnyAssetId::Cosmos(format!( + "ibc/{}", + hex::encode(&sha2_256( + format!("{}/{channel_b}/{asset_str}", PortId::transfer()).as_bytes() + )) + .to_uppercase() + )); + + log::info!(target: "hyperspace", "Asset A: {asset_id_a:?} B: {asset_id_b:?}"); + // Set connections and channel whitelist chain_a.set_connection_id(connection_id_a); chain_b.set_connection_id(connection_id_b); From 4960d4ff9dd19aad66f377f8bed943b3af290f45 Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Fri, 15 Sep 2023 01:30:10 -0300 Subject: [PATCH 29/43] add a default config --- config/centauri-local.toml | 16 ++++++++++++++++ config/ethereum-local.toml | 14 ++++++++++++++ config/ethereum.toml | 1 - hyperspace/ethereum/src/client.rs | 16 ++++++++-------- hyperspace/ethereum/src/config.rs | 15 ++++----------- hyperspace/ethereum/src/mock/utils.rs | 2 +- hyperspace/ethereum/src/utils.rs | 1 - hyperspace/testsuite/tests/ethereum_cosmos.rs | 2 -- 8 files changed, 43 insertions(+), 24 deletions(-) create mode 100644 config/centauri-local.toml create mode 100644 config/ethereum-local.toml delete mode 100644 config/ethereum.toml diff --git a/config/centauri-local.toml b/config/centauri-local.toml new file mode 100644 index 000000000..9f1eaf330 --- /dev/null +++ b/config/centauri-local.toml @@ -0,0 +1,16 @@ +type = "cosmos" +name = "centauri" +rpc_url = "http://127.0.0.1:26657/" +grpc_url = "http://127.0.0.1:9090/" +websocket_url = "ws://127.0.0.1:26657/websocket" +chain_id = "centauri-testnet-1" +account_prefix = "centauri" +fee_denom = "stake" +fee_amount = "4000" +gas_limit = 9223372036854775806 +store_prefix = "ibc" +max_tx_size = 200000 +channel_whitelist = [] +mnemonic = "sense state fringe stool behind explain area quit ugly affair develop thumb clinic weasel choice atom gesture spare sea renew penalty second upon peace" +skip_optional_client_updates = true +max_packets_to_process = 200 diff --git a/config/ethereum-local.toml b/config/ethereum-local.toml new file mode 100644 index 000000000..0d6a81f03 --- /dev/null +++ b/config/ethereum-local.toml @@ -0,0 +1,14 @@ +type = "ethereum" +http_rpc_url = "http://localhost:8545/" +ws_rpc_url = "ws://127.0.0.1:8546/" +beacon_rpc_url = "http://localhost:3500/" +ibc_handler_address = "0x0000000000000000000000000000000000000000" +private_key_path = "hyperspace/ethereum/keys/0x73db010c3275eb7a92e5c38770316248f4c644ee" +max_block_weight = 1 +name = "ethereum-client" +channel_whitelist = [] +commitment_prefix = "0x6962632f" +diamond_address = "0x2a1bcb20cfdbd43addfd2477f477cf818ec31de8" +diamond_facets = [["IBCClient", "0x8cb9f283077e85b8b0a032696391af056ffd412e"], ["IBCConnection", "0xbd6d4ddd95a4bce95482abf285d7d529e11dc38d"], ["IBCChannelHandshake", "0x0e10190b3287e3be51b1c24a8a6a3b985966fd9c"], ["IBCPacket", "0x598cfa9aa58de691b6084b53bc058cc165bf70b4"], ["IBCQuerier", "0xedb8dfa5612637a14416d8f89f4db56ad2eed7c7"], ["DiamondCutFacet", "0x263c273bd66f4fbbff91f1f58db344b9cac36d20"], ["DiamondLoupeFacet", "0x18940f61ab52ec134500312ddb9d55f2ef450b6f"], ["OwnershipFacet", "0x91bf53ea9aed6d7901f785878f248748089319f1"]] +client_type = "07-tendermint" +jwt_secret_path = "/Users/vmark/work/eth-pos-devnet/execution/jwtsecret" diff --git a/config/ethereum.toml b/config/ethereum.toml deleted file mode 100644 index 23050eb88..000000000 --- a/config/ethereum.toml +++ /dev/null @@ -1 +0,0 @@ -type = "ethereum" diff --git a/hyperspace/ethereum/src/client.rs b/hyperspace/ethereum/src/client.rs index 696ecaef4..f75377926 100644 --- a/hyperspace/ethereum/src/client.rs +++ b/hyperspace/ethereum/src/client.rs @@ -227,7 +227,7 @@ impl EthereumClient { .from_block(BlockNumber::Earliest) // .from_block(from_block) .to_block(BlockNumber::Latest) - .address(self.config.ibc_handler_address) + .address(self.yui.diamond.address()) .event("OpenInitChannel(string,string)"); let logs = self.client().get_logs(&filter).await.unwrap(); @@ -249,7 +249,7 @@ impl EthereumClient { let filter = Filter::new() .from_block(from_block) .to_block(BlockNumber::Latest) - .address(self.config.ibc_handler_address) + .address(self.yui.diamond.address()) .event("GeneratedClientIdentifier(string)"); let logs = self.client().get_logs(&filter).await.unwrap(); @@ -270,7 +270,7 @@ impl EthereumClient { let filter = Filter::new() .from_block(from_block) .to_block(BlockNumber::Latest) - .address(self.config.ibc_handler_address) + .address(self.yui.diamond.address()) .event("GeneratedConnectionIdentifier(string)"); let logs = self.client().get_logs(&filter).await.unwrap(); @@ -291,7 +291,7 @@ impl EthereumClient { let filter = Filter::new() .from_block(from_block) .to_block(BlockNumber::Latest) - .address(self.config.ibc_handler_address) + .address(self.yui.diamond.address()) .event("AcknowledgePacket((uint64,string,string,string,string,bytes,(uint64,uint64),uint64),bytes)"); let logs = self.client().get_logs(&filter).await.unwrap(); @@ -392,7 +392,7 @@ impl EthereumClient { let filter = Filter::new() .from_block(from) .to_block(to) - .address(self.config.ibc_handler_address) + .address(self.yui.diamond.address()) .event(event_name); let client = self.client().clone(); @@ -421,7 +421,7 @@ impl EthereumClient { .unwrap(); let client = self.client().clone(); - let address = self.config.ibc_handler_address.clone(); + let address = self.yui.diamond.address().clone(); async move { Ok(client @@ -451,7 +451,7 @@ impl EthereumClient { cast::SimpleCast::index("bytes32", dbg!(&var_name), dbg!(&storage_index)).unwrap(); let client = self.client().clone(); - let address = self.config.ibc_handler_address.clone(); + let address = self.yui.diamond.address().clone(); dbg!(&address); dbg!(&H256::from_str(&index).unwrap()); @@ -491,7 +491,7 @@ impl EthereumClient { let index = cast::SimpleCast::index("bytes32", &key2_hashed_hex, &key2_hashed_hex).unwrap(); let client = self.client().clone(); - let address = self.config.ibc_handler_address.clone(); + let address = self.yui.diamond.address().clone(); async move { client diff --git a/hyperspace/ethereum/src/config.rs b/hyperspace/ethereum/src/config.rs index 7b4e0ac43..a901be351 100644 --- a/hyperspace/ethereum/src/config.rs +++ b/hyperspace/ethereum/src/config.rs @@ -97,10 +97,6 @@ pub struct EthereumClientConfig { /// HTTP URL for RPC (Beacon node) #[serde(deserialize_with = "uri_de", serialize_with = "uri_se")] pub beacon_rpc_url: http::uri::Uri, - /// address of the OwnableIBCHandler contract. - #[serde(deserialize_with = "address_de")] - // TODO: remove and use `yui.diamond.address()` instead - pub ibc_handler_address: Address, /// mnemonic for the wallet pub mnemonic: Option, /// private key for the wallet @@ -135,6 +131,7 @@ pub struct EthereumClientConfig { #[serde(default)] pub bank_address: Option
, /// Diamond facets (ABI file name, contract address) + #[serde(default)] pub diamond_facets: Vec<(ContractName, Address)>, #[serde(skip)] pub yui: Option, ProviderImpl>>, @@ -195,15 +192,11 @@ impl EthereumClientConfig { let chain_id = client.get_chainid().await.unwrap(); let wallet: LocalWallet = if let Some(mnemonic) = &self.mnemonic { - MnemonicBuilder::::default() - .phrase(mnemonic.as_str()) - .build() - .unwrap() - .with_chain_id(chain_id.as_u64()) + MnemonicBuilder::::default().phrase(mnemonic.as_str()).build().unwrap() } else if let Some(path) = self.private_key_path.clone() { LocalWallet::decrypt_keystore( path, - option_env!("KEY_PASS").expect("KEY_PASS is not set"), + std::env::var("KEY_PASS").expect("KEY_PASS is not set"), ) .unwrap() .into() @@ -216,7 +209,7 @@ impl EthereumClientConfig { panic!("no private key or mnemonic provided") }; - Ok(Arc::new(SignerMiddleware::new(client, wallet))) + Ok(Arc::new(SignerMiddleware::new(client, wallet.with_chain_id(chain_id.as_u64())))) } } diff --git a/hyperspace/ethereum/src/mock/utils.rs b/hyperspace/ethereum/src/mock/utils.rs index 933029562..9f55f2621 100644 --- a/hyperspace/ethereum/src/mock/utils.rs +++ b/hyperspace/ethereum/src/mock/utils.rs @@ -46,7 +46,7 @@ pub async fn spawn_anvil() -> (AnvilInstance, Arc (AnyChain, AnyChain) { yui_ibc.bank = Some(bank); //replace the tendermint client address in hyperspace config with a real one - let diamond_address = yui_ibc.diamond.address(); let tendermint_address = yui_ibc.tendermint.as_ref().map(|x| x.address()); let mut config_a = hyperspace_ethereum_client_fixture(&anvil, yui_ibc).await; config_a.tendermint_address = tendermint_address; - config_a.ibc_handler_address = diamond_address; let mut config_b = CosmosClientConfig { name: "centauri".to_string(), From c7b493d3d7f7a7d0ba5849a970ff2e9f4b3773d7 Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Fri, 15 Sep 2023 04:07:36 -0300 Subject: [PATCH 30/43] remove `prev_state` from client --- hyperspace/core/src/macros.rs | 2 +- hyperspace/cosmos/src/client.rs | 6 ++-- hyperspace/cosmos/src/provider.rs | 1 - hyperspace/ethereum/src/chain.rs | 47 +++++++++++++------------ hyperspace/ethereum/src/client.rs | 2 -- hyperspace/ethereum/src/cmd.rs | 30 ++++++++++++---- hyperspace/ethereum/src/ibc_provider.rs | 9 ++--- hyperspace/ethereum/src/mock/utils.rs | 7 ++-- hyperspace/ethereum/src/utils.rs | 29 +++++++++------ 9 files changed, 76 insertions(+), 57 deletions(-) diff --git a/hyperspace/core/src/macros.rs b/hyperspace/core/src/macros.rs index c72b93603..4a3b1c627 100644 --- a/hyperspace/core/src/macros.rs +++ b/hyperspace/core/src/macros.rs @@ -1013,7 +1013,7 @@ macro_rules! chains { AnyConfig::$name(config) => AnyChain::$name(<$client>::new(config).await?), )* }; - if let Some(code_id) = dbg!(maybe_wasm_code_id) { + if let Some(code_id) = maybe_wasm_code_id { Ok(AnyChain::Wasm(WasmChain { inner: Box::new(chain), code_id })) } else { Ok(chain) diff --git a/hyperspace/cosmos/src/client.rs b/hyperspace/cosmos/src/client.rs index acd2f67bb..5971339bb 100644 --- a/hyperspace/cosmos/src/client.rs +++ b/hyperspace/cosmos/src/client.rs @@ -401,12 +401,13 @@ where let mut xs = Vec::new(); let heightss = (from.value()..=to.value()).collect::>(); let client = Arc::new(self.clone()); - let to = self.rpc_call_delay().as_millis(); + let delay_to = self.rpc_call_delay().as_millis(); for heights in heightss.chunks(5) { let mut join_set = JoinSet::, Elapsed>>::new(); for height in heights.to_owned() { let client = client.clone(); - let duration = Duration::from_millis(rand::thread_rng().gen_range(0..to) as u64); + let duration = + Duration::from_millis(rand::thread_rng().gen_range(0..delay_to) as u64); let fut = async move { log::trace!(target: "hyperspace_cosmos", "Fetching header at height {:?}", height); let latest_light_block = @@ -430,7 +431,6 @@ where true => UpdateType::Optional, false => UpdateType::Mandatory, }; - Ok(( Header { signed_header: latest_light_block.signed_header, diff --git a/hyperspace/cosmos/src/provider.rs b/hyperspace/cosmos/src/provider.rs index 2f5886e4d..f0b5eef82 100644 --- a/hyperspace/cosmos/src/provider.rs +++ b/hyperspace/cosmos/src/provider.rs @@ -117,7 +117,6 @@ where let client_state_response = latest_cp_client_state .client_state .ok_or_else(|| Error::Custom("counterparty returned empty client state".to_string()))?; - log::info!(target: "hyperspace_cosmos", "cs len = {}", client_state_response.value.len()); let client_state = ClientState::::decode_vec(&client_state_response.value) .map_err(|_| Error::Custom("failed to decode client state response".to_string()))?; diff --git a/hyperspace/ethereum/src/chain.rs b/hyperspace/ethereum/src/chain.rs index 7a3ad8d36..6b60daddb 100644 --- a/hyperspace/ethereum/src/chain.rs +++ b/hyperspace/ethereum/src/chain.rs @@ -1,4 +1,4 @@ -use std::{fmt::Debug, sync::Arc, thread, time::Duration}; +use std::{fmt::Debug, str::FromStr, sync::Arc, thread, time::Duration}; use crate::{ client::{ClientError, EthereumClient}, @@ -33,6 +33,7 @@ use ibc::{ }, ics04_channel::msgs as channel_msgs, ics23_commitment::commitment::CommitmentRoot, + ics24_host::identifier::ClientId, }, protobuf::{ google::protobuf::Timestamp, @@ -75,8 +76,6 @@ impl MisbehaviourHandler for EthereumClient { fn client_state_abi_token(client: &ClientState) -> Token { use ethers::abi::{encode as ethers_encode, Token as EthersToken}; - log::info!("client: {:?}", client); - let client_state_data = EthersToken::Tuple( [ //chain_id @@ -153,8 +152,6 @@ pub(crate) fn client_state_from_abi_token(token: Token) -> Result chain_id, _ => return Err(ClientError::Other("chain_id not found".to_string())), @@ -1044,16 +1041,12 @@ impl Chain for EthereumClient { assert_eq!(tok, token); let bytes = self.yui.create_client_calldata(token).await; - //update mutex - let mut update_mutex = self.prev_state.lock().map_err(|_| { - ClientError::Other("create_client: can't lock prev_state mutex".into()) - })?; - *update_mutex = (client_state_data_vec.clone(), consensus_state_data_vec.clone()); calls.push(bytes); } else if msg.type_url == ibc::core::ics02_client::msgs::update_client::TYPE_URL { let msg = MsgUpdateAnyClient::::decode_vec(&msg.value).map_err( |_| ClientError::Other("update_client: failed to decode_vec".into()), )?; + let AnyClientMessage::Tendermint(client_state) = msg.client_message.unpack_recursive() else { @@ -1067,24 +1060,32 @@ impl Chain for EthereumClient { let tm_header_abi_token = tm_header_abi_token(header)?; let tm_header_bytes = ethers_encode(&[tm_header_abi_token]); - //todo replace empty vec for prev state clint with an actual client state - let client_state = self - .prev_state - .lock() - .map_err(|_| { - ClientError::Other("update_client: can't lock prev_state mutex".into()) - })? - .0 - .clone(); + let latest_height = self.latest_height_and_timestamp().await?.0; + let client_id = msg.client_id; + let latest_client_state = AnyClientState::try_from( + self.query_client_state(latest_height, client_id.clone()) + .await? + .client_state + .ok_or_else(|| { + ClientError::Other( + "update_client: can't get latest client state".to_string(), + ) + })?, + )?; + let AnyClientState::Tendermint(client_state) = + latest_client_state.unpack_recursive() + else { + //TODO return error support only tendermint client state + return Err(ClientError::Other("create_client: unsupported client state".into())) + }; - //TODO replace client id. it was genereated when we created the client. use 0 for - // testing - let client_id = format!("{}-0", self.config.client_type.clone()); + let client_state = client_state_abi_token(&client_state); + let client_state = ethers_encode(&[client_state]); let token = EthersToken::Tuple(vec![ //should be the same that we use to create client //client id - EthersToken::String(client_id), + EthersToken::String(client_id.to_string()), //tm header EthersToken::Bytes(tm_header_bytes), //tm header diff --git a/hyperspace/ethereum/src/client.rs b/hyperspace/ethereum/src/client.rs index f75377926..15f394738 100644 --- a/hyperspace/ethereum/src/client.rs +++ b/hyperspace/ethereum/src/client.rs @@ -64,7 +64,6 @@ pub struct EthereumClient { /// Common relayer data pub common_state: CommonClientState, pub yui: DeployYuiIbc, ProviderImpl>, - pub prev_state: Arc, Vec)>>, /// Light client id on counterparty chain pub client_id: Arc>>, /// Connection Id @@ -179,7 +178,6 @@ impl EthereumClient { ws_uri: config.ws_rpc_url.clone(), common_state: Default::default(), yui, - prev_state: Arc::new(Mutex::new((vec![], vec![]))), client_id: Arc::new(Mutex::new(config.client_id.clone())), connection_id: Arc::new(Mutex::new(config.connection_id.clone())), channel_whitelist: Arc::new(Mutex::new( diff --git a/hyperspace/ethereum/src/cmd.rs b/hyperspace/ethereum/src/cmd.rs index fc9e7fb7c..f2b60de61 100644 --- a/hyperspace/ethereum/src/cmd.rs +++ b/hyperspace/ethereum/src/cmd.rs @@ -1,7 +1,7 @@ use crate::{ client::{ClientError, EthRpcClient}, config::EthereumClientConfig, - utils::{deploy_client, deploy_ibc, deploy_module, DeployYuiIbc}, + utils::{deploy_client, deploy_ibc, deploy_transfer_module, DeployYuiIbc}, }; use anyhow::{anyhow, bail}; use clap::{Args, Parser, Subcommand}; @@ -18,8 +18,8 @@ pub enum EthereumCmd { pub enum DeployCmd { /// Deploy core contracts Core(DeployCoreCmd), - /// Deploy module contracts - Module(DeployModuleCmd), + /// Deploy ICS-20 Transfer module contracts + TransferModule(DeployTransferModuleCmd), /// Deploy client contracts Client(DeployClientCmd), } @@ -100,12 +100,12 @@ impl DeployClientCmd { } #[derive(Debug, Clone, Parser)] -pub struct DeployModuleCmd { +pub struct DeployTransferModuleCmd { #[clap(long)] pub yui_solidity_path: PathBuf, } -impl DeployModuleCmd { +impl DeployTransferModuleCmd { pub async fn run( &self, mut config: EthereumClientConfig, @@ -115,7 +115,23 @@ impl DeployModuleCmd { let diamond_addr = config.diamond_address.ok_or_else(|| { anyhow!("Diamond contract should be deployed first (use 'deploy core' subcommand)") })?; - let contract = deploy_module::(path, diamond_addr, client).await?; + let diamond_addr = config.diamond_address.ok_or_else(|| { + anyhow!("Diamond contract should be deployed first (use 'deploy core' subcommand)") + })?; + let facets = config.diamond_facets.clone(); + if facets.is_empty() { + bail!("Diamond facets are empty. Make sure to deploy the core first ('deploy core')") + }; + let yui_ibc = DeployYuiIbc::<_, EthRpcClient>::from_addresses( + client.clone(), + diamond_addr, + None, + None, + facets, + )?; + + let contract = + deploy_transfer_module::(path, yui_ibc, diamond_addr, client).await?; config.bank_address = Some(contract.address()); Ok(config) } @@ -127,7 +143,7 @@ impl EthereumCmd { EthereumCmd::Deploy(cmd) => match cmd { DeployCmd::Core(cmd) => cmd.run(config).await, DeployCmd::Client(cmd) => cmd.run(config).await, - DeployCmd::Module(cmd) => cmd.run(config).await, + DeployCmd::TransferModule(cmd) => cmd.run(config).await, }, } } diff --git a/hyperspace/ethereum/src/ibc_provider.rs b/hyperspace/ethereum/src/ibc_provider.rs index 5912bd320..ba043a8b0 100644 --- a/hyperspace/ethereum/src/ibc_provider.rs +++ b/hyperspace/ethereum/src/ibc_provider.rs @@ -209,7 +209,7 @@ pub async fn parse_ethereum_events( log::debug!(target: "hyperspace_ethereum", "encountered event: {:?} at {}", ev.event_type(), ev.height()); $events.push(ev); } else )+ { - log::error!( + log::warn!( target: "hyperspace_ethereum", "unknown event: {}", log.log_type.unwrap_or(format!("{:?}", $topic0)) ); @@ -375,7 +375,7 @@ impl IbcProvider for EthereumClient { keccak256("07-tendermint-0".to_string().into_bytes()).to_vec(), )])); } else { - log::error!(target: "hyperspace_ethereum", + log::warn!(target: "hyperspace_ethereum", "unknown event: {}", log.log_type.unwrap_or(format!("{topic0:?}")) ); @@ -493,7 +493,6 @@ impl IbcProvider for EthereumClient { next_validators_hash: header.signed_header.header.next_validators_hash, }); // TODO: figure out how to distinguish between the same function calls - log::info!(target: "hyperspace_ethereum", "query_client_consensus FOUND"); let proof_height = Some(at.into()); return Ok(QueryConsensusStateResponse { @@ -513,7 +512,6 @@ impl IbcProvider for EthereumClient { log::trace!(target: "hyperspace_ethereum", "no update client event found for blocks ..{at}, looking for a create client event..."); // ...otherwise, try to get the `CreateClient` event - log::info!(target: "hyperspace_ethereum", "qconss {}", line!()); let mut event_filter = self .yui .event_for_name::("CreateClient") @@ -526,7 +524,6 @@ impl IbcProvider for EthereumClient { )])); ValueOrArray::Value(hash) }); - log::info!(target: "hyperspace_ethereum", "qconss {}", line!()); let log = self .yui .diamond @@ -536,7 +533,6 @@ impl IbcProvider for EthereumClient { .unwrap() .pop() // get only the last event .ok_or_else(|| ClientError::Other("no events found".to_string()))?; - log::info!(target: "hyperspace_ethereum", "qconss {}", line!()); let tx_hash = log.transaction_hash.expect("tx hash should exist"); let func = self.yui.function("createClient")?; @@ -566,7 +562,6 @@ impl IbcProvider for EthereumClient { let proof_height = Some(at.into()); let any = consensus_state.expect("should always be initialized").to_any(); - log::info!(target: "hyperspace_ethereum", "query_client_consensus FOUND"); Ok(QueryConsensusStateResponse { consensus_state: Some(any), proof: vec![0], proof_height }) } diff --git a/hyperspace/ethereum/src/mock/utils.rs b/hyperspace/ethereum/src/mock/utils.rs index 9f55f2621..c5d72ab4d 100644 --- a/hyperspace/ethereum/src/mock/utils.rs +++ b/hyperspace/ethereum/src/mock/utils.rs @@ -150,7 +150,6 @@ pub async fn hyperspace_ethereum_client_fixture( http_rpc_url: endpoint.parse().unwrap(), ws_rpc_url: format!("ws://127.0.0.1:{}", ETH_NODE_PORT_WS).parse().unwrap(), beacon_rpc_url: format!("http://localhost:{}", BEACON_NODE_PORT).parse().unwrap(), - ibc_handler_address: yui_ibc.diamond.address(), mnemonic: None, max_block_weight: 1, private_key: wallet, @@ -164,7 +163,11 @@ pub async fn hyperspace_ethereum_client_fixture( bank_address: yui_ibc.bank.clone().map(|b| b.address()), diamond_address: Some(yui_ibc.diamond.address()), tendermint_address: yui_ibc.tendermint.clone().map(|x| x.address()), - diamond_facets: vec![], + diamond_facets: yui_ibc + .deployed_facets + .iter() + .map(|f| (f.abi_name(), f.contract().address())) + .collect(), yui: Some(yui_ibc), client_type: "07-tendermint".into(), jwt_secret_path, diff --git a/hyperspace/ethereum/src/utils.rs b/hyperspace/ethereum/src/utils.rs index c419adb81..4f4098cd1 100644 --- a/hyperspace/ethereum/src/utils.rs +++ b/hyperspace/ethereum/src/utils.rs @@ -808,12 +808,7 @@ where .compiled_artifacts() .iter() .chain(diamond_project_output.compiled_artifacts()) - .flat_map(|(_, artifact)| { - artifact.into_iter().flat_map(|(an, artifact)| { - println!("artifact name {an}"); - artifact - }) - }) + .flat_map(|(_, artifact)| artifact.into_iter().flat_map(|(an, artifact)| artifact)) .filter_map(|ar| ar.artifact.storage_layout.clone()) .chain(once(predefined_layout)) .fold(StorageLayout { storage: vec![], types: Default::default() }, |mut acc, layout| { @@ -850,12 +845,17 @@ pub async fn deploy_client( let factory = ContractFactory::new(abi.unwrap(), bytecode.unwrap(), client.clone()); let update_client_delegate_contract = factory.deploy(()).unwrap().send().await.unwrap(); + println!( + "Deployed update client delegate contract address: {:?}", + update_client_delegate_contract.address() + ); + let contract = project_output1.find_first(client_name).unwrap(); let r = contract.clone(); let (abi, bytecode, _) = r.into_parts(); let factory = ContractFactory::new(abi.unwrap(), bytecode.unwrap(), client); - let tendermint_light_client = factory + let light_client = factory .deploy(( Token::Address(yui_ibc.diamond.address()), Token::Address(update_client_delegate_contract.address()), @@ -865,8 +865,10 @@ pub async fn deploy_client( .await .unwrap(); - let _ = yui_ibc.register_client(&client_type, tendermint_light_client.address()).await; - Ok(tendermint_light_client) + println!("Deployed light client address: {:?}", light_client.address()); + + let _ = yui_ibc.register_client(&client_type, light_client.address()).await; + Ok(light_client) } pub async fn deploy_ibc( @@ -879,8 +881,9 @@ pub async fn deploy_ibc( Ok(yui_ibc) } -pub async fn deploy_module( +pub async fn deploy_transfer_module( yui_solidity_path: &PathBuf, + yui_ibc: DeployYuiIbc, M>, diamond_address: Address, client: Arc, ) -> Result, M>, ClientError> { @@ -888,12 +891,16 @@ pub async fn deploy_module( let artifact = project_output.find_first("ICS20Bank").expect("no ICS20Bank in project output"); let bank_contract = deploy_contract::(artifact, (), client.clone()).await; - println!("Bank module address: {:?}", bank_contract.address()); + println!("Deployed Bank module address: {:?}", bank_contract.address()); let artifact = project_output .find_first("ICS20TransferBank") .expect("no ICS20TransferBank in project output"); let constructor_args = (Token::Address(diamond_address), Token::Address(bank_contract.address())); let module_contract = deploy_contract(artifact, constructor_args, client.clone()).await; + println!("Deployed ICS-20 Transfer module address: {:?}", module_contract.address()); + + yui_ibc.bind_port("transfer", module_contract.address()).await; + Ok(module_contract) } From 9180cf77664c65d2fe2ff9af32c59dbec74626c6 Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Fri, 15 Sep 2023 04:17:49 -0300 Subject: [PATCH 31/43] update configs; clarify jwtsecret not found error --- config/centauri-local.toml | 5 ++++- config/ethereum-local.toml | 15 +++++++++------ hyperspace/ethereum/src/client.rs | 4 +++- hyperspace/ethereum/src/mock/utils.rs | 7 ++----- 4 files changed, 18 insertions(+), 13 deletions(-) diff --git a/config/centauri-local.toml b/config/centauri-local.toml index 9f1eaf330..67a5fc2e6 100644 --- a/config/centauri-local.toml +++ b/config/centauri-local.toml @@ -4,13 +4,16 @@ rpc_url = "http://127.0.0.1:26657/" grpc_url = "http://127.0.0.1:9090/" websocket_url = "ws://127.0.0.1:26657/websocket" chain_id = "centauri-testnet-1" +client_id = "07-tendermint-0" +connection_id = "connection-18" account_prefix = "centauri" fee_denom = "stake" fee_amount = "4000" gas_limit = 9223372036854775806 store_prefix = "ibc" max_tx_size = 200000 -channel_whitelist = [] +wasm_code_id = "4c7504846b7c35e1b7dfc62f9347fcb98fec95aecede9822a745ce14d6973ced" +channel_whitelist = [["channel-8", "transfer"]] mnemonic = "sense state fringe stool behind explain area quit ugly affair develop thumb clinic weasel choice atom gesture spare sea renew penalty second upon peace" skip_optional_client_updates = true max_packets_to_process = 200 diff --git a/config/ethereum-local.toml b/config/ethereum-local.toml index 0d6a81f03..5981cfa0c 100644 --- a/config/ethereum-local.toml +++ b/config/ethereum-local.toml @@ -2,13 +2,16 @@ type = "ethereum" http_rpc_url = "http://localhost:8545/" ws_rpc_url = "ws://127.0.0.1:8546/" beacon_rpc_url = "http://localhost:3500/" -ibc_handler_address = "0x0000000000000000000000000000000000000000" private_key_path = "hyperspace/ethereum/keys/0x73db010c3275eb7a92e5c38770316248f4c644ee" max_block_weight = 1 -name = "ethereum-client" -channel_whitelist = [] -commitment_prefix = "0x6962632f" -diamond_address = "0x2a1bcb20cfdbd43addfd2477f477cf818ec31de8" -diamond_facets = [["IBCClient", "0x8cb9f283077e85b8b0a032696391af056ffd412e"], ["IBCConnection", "0xbd6d4ddd95a4bce95482abf285d7d529e11dc38d"], ["IBCChannelHandshake", "0x0e10190b3287e3be51b1c24a8a6a3b985966fd9c"], ["IBCPacket", "0x598cfa9aa58de691b6084b53bc058cc165bf70b4"], ["IBCQuerier", "0xedb8dfa5612637a14416d8f89f4db56ad2eed7c7"], ["DiamondCutFacet", "0x263c273bd66f4fbbff91f1f58db344b9cac36d20"], ["DiamondLoupeFacet", "0x18940f61ab52ec134500312ddb9d55f2ef450b6f"], ["OwnershipFacet", "0x91bf53ea9aed6d7901f785878f248748089319f1"]] +name = "ethereum_client" +client_id = "08-wasm-22" +connection_id = "connection-0" +channel_whitelist = [["channel-0", "transfer"]] +commitment_prefix = "6962632f" +diamond_address = "0x4a976e25cde9d022007f7f02889901b382038237" +tendermint_address = "0xa6915519ec2cbc4e7eea7912673c885fc1f156ca" +bank_address = "0x87b47d11cdc84e3c3cb70b34dde1235c0862b68e" +diamond_facets = [["IBCClient", "0x10b57a97dad42b87185f39fc653939c89abda030"], ["IBCConnection", "0x163f4a54af24d13151f231fb74ef5cbc642d05a7"], ["IBCChannelHandshake", "0x5078d1a1240bcbca0f67ba25f07c66b85ab86d37"], ["IBCPacket", "0xc0a2f84324ddf94f4d5af8b507ffefb9016fcdaa"], ["IBCQuerier", "0x98f6789f22e1066dcd128ca99a859acf4821f834"], ["DiamondCutFacet", "0xc1e3b960d3db95ea5a4f2b7c91ba28b2222d5484"], ["DiamondLoupeFacet", "0x4dccf8ac3a04b9d7f294047ebc6481ed9d8fbab6"], ["OwnershipFacet", "0x0fce292ea5fbf749d8ef31412dbc8ac5841ba66d"]] client_type = "07-tendermint" jwt_secret_path = "/Users/vmark/work/eth-pos-devnet/execution/jwtsecret" diff --git a/hyperspace/ethereum/src/client.rs b/hyperspace/ethereum/src/client.rs index 15f394738..5658d1f8f 100644 --- a/hyperspace/ethereum/src/client.rs +++ b/hyperspace/ethereum/src/client.rs @@ -199,7 +199,9 @@ impl EthereumClient { pub async fn websocket_provider(&self) -> Result, ClientError> { if let Some(secret_path) = &self.config.jwt_secret_path { - let secret = std::fs::read_to_string(secret_path).unwrap(); + let secret = std::fs::read_to_string(secret_path).map_err(|e| { + ClientError::Other(format!("jwtsecret not found. Search for 'execution/jwtsecret' in the code and replace it with your local path. {e}")) + })?; let secret = JwtKey::from_slice(&hex::decode(&secret[2..]).unwrap()).expect("oops"); let jwt_auth = JwtAuth::new(secret, None, None); let token = jwt_auth.generate_token().unwrap(); diff --git a/hyperspace/ethereum/src/mock/utils.rs b/hyperspace/ethereum/src/mock/utils.rs index c5d72ab4d..965fda92a 100644 --- a/hyperspace/ethereum/src/mock/utils.rs +++ b/hyperspace/ethereum/src/mock/utils.rs @@ -140,11 +140,8 @@ pub async fn hyperspace_ethereum_client_fixture( None }; - let jwt_secret_path = if !USE_GETH { - None - } else { - Some(format!("{}/.lighthouse/local-testnet/geth_datadir1/geth/jwtsecret", env!("HOME"))) - }; + let jwt_secret_path = + if !USE_GETH { None } else { Some("../eth-pos-devnet/execution/jwtsecret".to_string()) }; EthereumClientConfig { http_rpc_url: endpoint.parse().unwrap(), From ec81853237c77e21705bcff1445017b983ea4fa2 Mon Sep 17 00:00:00 2001 From: "rust.dev" <102041955+RustNinja@users.noreply.github.com> Date: Fri, 15 Sep 2023 14:41:14 +0100 Subject: [PATCH 32/43] Client error across hyperspace eth (#50) * update chain.rs to provide more info into client error * update client_state_from_abi_token, replaced all unwrap * update consensus_state_from_abi_token * update tm_header_from_abi_token --------- Signed-off-by: Vladislav Co-authored-by: Vladislav --- hyperspace/ethereum/src/chain.rs | 328 ++++++++++++++++++++----------- 1 file changed, 209 insertions(+), 119 deletions(-) diff --git a/hyperspace/ethereum/src/chain.rs b/hyperspace/ethereum/src/chain.rs index 6b60daddb..ed2157271 100644 --- a/hyperspace/ethereum/src/chain.rs +++ b/hyperspace/ethereum/src/chain.rs @@ -148,22 +148,28 @@ pub(crate) fn client_state_from_abi_token(token: Token) -> Result chain_id, _ => return Err(ClientError::Other("chain_id not found".to_string())), }; - let (trust_level_numerator, trust_level_denominator) = match toks.get(1).cloned().unwrap() { + let (trust_level_numerator, trust_level_denominator) = match toks.get(1).cloned().ok_or( + ClientError::Other("failed to get index 1 and retrieve trust_level_numerator and trust_level_denominator".to_string()))? { EthersToken::Tuple(toks) => ( - match toks.get(0).cloned().unwrap() { + match toks.get(0).cloned().ok_or( + ClientError::Other("failed to get index 0 and retrieve numerator".to_string()))? { EthersToken::Uint(numerator) => numerator.as_u64(), _ => return Err(ClientError::Other("trust_level_numerator not found".to_string())), }, - match toks.get(1).cloned().unwrap() { + match toks.get(1).cloned().ok_or( + ClientError::Other("failed to get index 0 and retrieve denominator".to_string()))? { EthersToken::Uint(denominator) => denominator.as_u64(), _ => return Err(ClientError::Other("trust_level_denominator not found".to_string())), @@ -172,13 +178,16 @@ pub(crate) fn client_state_from_abi_token(token: Token) -> Result return Err(ClientError::Other("trust_level not found".to_string())), }; - let (trusting_period_secs, trusting_period_nanos) = match toks.get(2).cloned().unwrap() { + let (trusting_period_secs, trusting_period_nanos) = match toks.get(2).cloned().ok_or( + ClientError::Other("failed to get index 2 and retrieve trusting_period_secs and trusting_period_nanos".to_string()))? { EthersToken::Tuple(toks) => ( - match toks.get(0).cloned().unwrap() { + match toks.get(0).cloned().ok_or( + ClientError::Other("failed to get index 0 and retrieve numerator".to_string()))? { EthersToken::Int(numerator) => numerator.as_u64(), _ => return Err(ClientError::Other("trusting_period_secs not found".to_string())), }, - match toks.get(1).cloned().unwrap() { + match toks.get(1).cloned().ok_or( + ClientError::Other("failed to get index 1 and retrieve denominator".to_string()))? { EthersToken::Int(denominator) => denominator.as_u64(), _ => return Err(ClientError::Other("trusting_period_nanos not found".to_string())), }, @@ -186,13 +195,16 @@ pub(crate) fn client_state_from_abi_token(token: Token) -> Result return Err(ClientError::Other("trusting_period not found".to_string())), }; - let (unbonding_period_secs, unbonding_period_nanos) = match toks.get(3).cloned().unwrap() { + let (unbonding_period_secs, unbonding_period_nanos) = match toks.get(3).cloned().ok_or( + ClientError::Other("failed to get index 3 and retrieve unbonding_period_secs and unbonding_period_nanos".to_string()))? { EthersToken::Tuple(toks) => ( - match toks.get(0).cloned().unwrap() { + match toks.get(0).cloned().ok_or( + ClientError::Other("failed to get index 0 and retrieve numerator".to_string()))? { EthersToken::Int(numerator) => numerator.as_u64(), _ => return Err(ClientError::Other("unbonding_period_secs not found".to_string())), }, - match toks.get(1).cloned().unwrap() { + match toks.get(1).cloned().ok_or( + ClientError::Other("failed to get index 1 and retrieve denominator".to_string()))? { EthersToken::Int(denominator) => denominator.as_u64(), _ => return Err(ClientError::Other("unbonding_period_nanos not found".to_string())), }, @@ -200,13 +212,16 @@ pub(crate) fn client_state_from_abi_token(token: Token) -> Result return Err(ClientError::Other("unbonding_period not found".to_string())), }; - let (max_clock_drift_secs, max_clock_drift_nanos) = match toks.get(4).cloned().unwrap() { + let (max_clock_drift_secs, max_clock_drift_nanos) = match toks.get(4).cloned().ok_or( + ClientError::Other("failed to get index 4 and retrieve max_clock_drift_secs and max_clock_drift_nanos".to_string()))? { EthersToken::Tuple(toks) => ( - match toks.get(0).cloned().unwrap() { + match toks.get(0).cloned().ok_or( + ClientError::Other("failed to get index 0 and retrieve numerator".to_string()))? { EthersToken::Int(numerator) => numerator.as_u64(), _ => return Err(ClientError::Other("max_clock_drift_secs not found".to_string())), }, - match toks.get(1).cloned().unwrap() { + match toks.get(1).cloned().ok_or( + ClientError::Other("failed to get index 1 and retrieve denominator".to_string()))? { EthersToken::Int(denominator) => denominator.as_u64(), _ => return Err(ClientError::Other("max_clock_drift_nanos not found".to_string())), }, @@ -214,12 +229,14 @@ pub(crate) fn client_state_from_abi_token(token: Token) -> Result return Err(ClientError::Other("max_clock_drift not found".to_string())), }; - let frozen_height = match toks.get(5).cloned().unwrap() { + let frozen_height = match toks.get(5).cloned().ok_or( + ClientError::Other("failed to get index 5 and retrieve frozen_height".to_string()))? { EthersToken::Int(frozen_height) => frozen_height.as_u64(), _ => return Err(ClientError::Other("frozen_height not found".to_string())), }; - let latest_height = match toks.get(6).cloned().unwrap() { + let latest_height = match toks.get(6).cloned().ok_or( + ClientError::Other("failed to get index 6 and retrieve latest_height".to_string()))? { EthersToken::Int(latest_height) => latest_height.as_u64(), _ => return Err(ClientError::Other("latest_height not found".to_string())), }; @@ -284,17 +301,23 @@ pub(crate) fn consensus_state_from_abi_token(token: Token) -> Result ( - match toks.get(0).cloned().unwrap() { + match toks.get(0).cloned().ok_or( + ClientError::Other("failed to get index 0 and retrieve numerator".to_string()))? { EthersToken::Int(numerator) => numerator.as_u64(), _ => return Err(ClientError::Other("timestamp_secs not found".to_string())), }, - match toks.get(1).cloned().unwrap() { + match toks.get(1).cloned().ok_or( + ClientError::Other("failed to get index 1 and retrieve denominator".to_string()))? { EthersToken::Int(denominator) => denominator.as_u64(), _ => return Err(ClientError::Other("timestamp_nanos not found".to_string())), }, @@ -302,15 +325,18 @@ pub(crate) fn consensus_state_from_abi_token(token: Token) -> Result return Err(ClientError::Other("timestamp not found".to_string())), }; - let (root,) = match toks.get(1).cloned().unwrap() { - EthersToken::Tuple(toks) => (match toks.get(0).cloned().unwrap() { + let (root,) = match toks.get(1).cloned().ok_or( + ClientError::Other("failed to get index 1 and retrieve root".to_string()))? { + EthersToken::Tuple(toks) => (match toks.get(0).cloned().ok_or( + ClientError::Other("failed to get index 0 and retrieve root".to_string()))? { EthersToken::Bytes(root) => root, _ => return Err(ClientError::Other("root not found'".to_string())), },), _ => return Err(ClientError::Other("root not found".to_string())), }; - let next_validators_hash = match toks.get(2).cloned().unwrap() { + let next_validators_hash = match toks.get(2).cloned().ok_or( + ClientError::Other("failed to get index 2 and retrieve next_validators_hash".to_string()))? { EthersToken::Bytes(next_validators_hash) => next_validators_hash, _ => return Err(ClientError::Other("next_validators_hash not found".to_string())), }; @@ -321,7 +347,9 @@ pub(crate) fn consensus_state_from_abi_token(token: Token) -> Result Result match toks.get(0).cloned().unwrap() { + let signed_header_header = match toks.get(0).cloned().ok_or( + ClientError::Other("failed to get index 0 and retrieve signed_header_header".to_string()))? { + EthersToken::Tuple(toks) => match toks.get(0).cloned().ok_or( + ClientError::Other("failed to get index 0 and retrieve signed_header_header".to_string()))? { EthersToken::Tuple(toks) => toks, _ => return Err(ClientError::Other("signed_header_header' not found".to_string())), }, _ => return Err(ClientError::Other("signed_header_header not found".to_string())), }; - let version = match signed_header_header.get(0).cloned().unwrap() { + let version = match signed_header_header.get(0).cloned().ok_or( + ClientError::Other("failed to get index 0 and retrieve version".to_string()))? { EthersToken::Tuple(toks) => toks, _ => return Err(ClientError::Other("version not found".to_string())), }; - let chain_id = match signed_header_header.get(1).cloned().unwrap() { + let chain_id = match signed_header_header.get(1).cloned().ok_or( + ClientError::Other("failed to get index 1 and retrieve chain_id".to_string()))? { EthersToken::String(chain_id) => chain_id, _ => return Err(ClientError::Other("chain_id not found".to_string())), }; - let height = match signed_header_header.get(2).cloned().unwrap() { + let height = match signed_header_header.get(2).cloned().ok_or( + ClientError::Other("failed to get index 2 and retrieve height".to_string()))? { EthersToken::Int(height) => height, _ => return Err(ClientError::Other("height not found".to_string())), }; - let time = match signed_header_header.get(3).cloned().unwrap() { + let time = match signed_header_header.get(3).cloned().ok_or( + ClientError::Other("failed to get index 3 and retrieve time".to_string()))? { EthersToken::Tuple(toks) => toks, _ => return Err(ClientError::Other("time not found".to_string())), }; - let last_block_id = match signed_header_header.get(4).cloned().unwrap() { + let last_block_id = match signed_header_header.get(4).cloned().ok_or( + ClientError::Other("failed to get index 4 and retrieve last_block_id".to_string()))? { EthersToken::Tuple(toks) => toks, _ => return Err(ClientError::Other("last_block_id not found".to_string())), }; - let last_commit_hash = match signed_header_header.get(5).cloned().unwrap() { + let last_commit_hash = match signed_header_header.get(5).cloned().ok_or( + ClientError::Other("failed to get index 5 and retrieve last_commit_hash".to_string()))? { EthersToken::Bytes(last_commit_hash) => last_commit_hash, _ => return Err(ClientError::Other("last_commit_hash not found".to_string())), }; - let data_hash = match signed_header_header.get(6).cloned().unwrap() { + let data_hash = match signed_header_header.get(6).cloned().ok_or( + ClientError::Other("failed to get index 6 and retrieve data_hash".to_string()))? { EthersToken::Bytes(data_hash) => data_hash, _ => return Err(ClientError::Other("data_hash not found".to_string())), }; - let validators_hash = match signed_header_header.get(7).cloned().unwrap() { + let validators_hash = match signed_header_header.get(7).cloned().ok_or( + ClientError::Other("failed to get index 7 and retrieve validators_hash".to_string()))? { EthersToken::Bytes(validators_hash) => validators_hash, _ => return Err(ClientError::Other("validators_hash not found".to_string())), }; - let next_validators_hash = match signed_header_header.get(8).cloned().unwrap() { + let next_validators_hash = match signed_header_header.get(8).cloned().ok_or( + ClientError::Other("failed to get index 8 and retrieve next_validators_hash".to_string()))? { EthersToken::Bytes(next_validators_hash) => next_validators_hash, _ => return Err(ClientError::Other("next_validators_hash not found".to_string())), }; - let consensus_hash = match signed_header_header.get(9).cloned().unwrap() { + let consensus_hash = match signed_header_header.get(9).cloned().ok_or( + ClientError::Other("failed to get index 9 and retrieve consensus_hash".to_string()))? { EthersToken::Bytes(consensus_hash) => consensus_hash, _ => return Err(ClientError::Other("consensus_hash not found".to_string())), }; - let app_hash = match signed_header_header.get(10).cloned().unwrap() { + let app_hash = match signed_header_header.get(10).cloned().ok_or( + ClientError::Other("failed to get index 10 and retrieve app_hash".to_string()))? { EthersToken::Bytes(app_hash) => app_hash, _ => return Err(ClientError::Other("app_hash not found".to_string())), }; - let last_results_hash = match signed_header_header.get(11).cloned().unwrap() { + let last_results_hash = match signed_header_header.get(11).cloned().ok_or( + ClientError::Other("failed to get index 11 and retrieve last_results_hash".to_string()))? { EthersToken::Bytes(last_results_hash) => last_results_hash, _ => return Err(ClientError::Other("last_results_hash not found".to_string())), }; - let evidence_hash = match signed_header_header.get(12).cloned().unwrap() { + let evidence_hash = match signed_header_header.get(12).cloned().ok_or( + ClientError::Other("failed to get index 12 and retrieve evidence_hash".to_string()))? { EthersToken::Bytes(evidence_hash) => evidence_hash, _ => return Err(ClientError::Other("evidence_hash not found".to_string())), }; - let proposer_address = match signed_header_header.get(13).cloned().unwrap() { + let proposer_address = match signed_header_header.get(13).cloned().ok_or( + ClientError::Other("failed to get index 13 and retrieve proposer_address".to_string()))? { EthersToken::Bytes(proposer_address) => proposer_address, _ => return Err(ClientError::Other("proposer_address not found".to_string())), }; - let version_block = match version.get(0).cloned().unwrap() { + let version_block = match version.get(0).cloned().ok_or( + ClientError::Other("failed to get index 0 and retrieve version_block".to_string()))? { EthersToken::Uint(version_block) => version_block, _ => return Err(ClientError::Other("version_block not found".to_string())), }; - let version_app = match version.get(1).cloned().unwrap() { + let version_app = match version.get(1).cloned().ok_or( + ClientError::Other("failed to get index 1 and retrieve version_app".to_string()))? { EthersToken::Uint(version_app) => version_app, _ => return Err(ClientError::Other("version_app not found".to_string())), }; - let time_secs = match time.get(0).cloned().unwrap() { + let time_secs = match time.get(0).cloned().ok_or( + ClientError::Other("failed to get index 0 and retrieve time_secs".to_string()))? { EthersToken::Int(time_secs) => time_secs, _ => return Err(ClientError::Other("time_secs not found".to_string())), }; - let time_nanos = match time.get(1).cloned().unwrap() { + let time_nanos = match time.get(1).cloned().ok_or( + ClientError::Other("failed to get index 1 and retrieve time_nanos".to_string()))? { EthersToken::Int(time_nanos) => time_nanos, _ => return Err(ClientError::Other("time_nanos not found".to_string())), }; - let last_block_id_hash = match last_block_id.get(0).cloned().unwrap() { + let last_block_id_hash = match last_block_id.get(0).cloned().ok_or( + ClientError::Other("failed to get index 0 and retrieve last_block_id_hash".to_string()))? { EthersToken::Bytes(last_block_id_hash) => last_block_id_hash, _ => return Err(ClientError::Other("last_block_id_hash not found".to_string())), }; - let last_block_id_part_set_header = match last_block_id.get(1).cloned().unwrap() { + let last_block_id_part_set_header = match last_block_id.get(1).cloned().ok_or( + ClientError::Other("failed to get index 1 and retrieve last_block_id_part_set_header".to_string()))? { EthersToken::Tuple(toks) => toks, _ => return Err(ClientError::Other("last_block_id_part_set_header not found".to_string())), }; let last_block_id_part_set_header_total = - match last_block_id_part_set_header.get(0).cloned().unwrap() { + match last_block_id_part_set_header.get(0).cloned().ok_or( + ClientError::Other("failed to get index 0 and retrieve last_block_id_part_set_header_total".to_string()))? { EthersToken::Uint(last_block_id_part_set_header_total) => last_block_id_part_set_header_total, _ => @@ -615,7 +668,8 @@ pub(crate) fn tm_header_from_abi_token(token: Token) -> Result last_block_id_part_set_header_hash, _ => @@ -624,35 +678,42 @@ pub(crate) fn tm_header_from_abi_token(token: Token) -> Result match toks.get(1).cloned().unwrap() { + let signed_header_commit = match toks.get(0).cloned().ok_or( + ClientError::Other("failed to get index 0 and retrieve signed_header_commit".to_string()))? { + EthersToken::Tuple(toks) => match toks.get(1).cloned().ok_or( + ClientError::Other("failed to get index 1 and retrieve signed_header_commit".to_string()))? { EthersToken::Tuple(toks) => toks, _ => return Err(ClientError::Other("signed_header_commit' not found".to_string())), }, _ => return Err(ClientError::Other("signed_header_commit not found".to_string())), }; - let last_commit_height = match signed_header_commit.get(0).cloned().unwrap() { + let last_commit_height = match signed_header_commit.get(0).cloned().ok_or( + ClientError::Other("failed to get index 0 and retrieve last_commit_height".to_string()))? { EthersToken::Int(last_commit_height) => last_commit_height, _ => return Err(ClientError::Other("last_commit_height not found".to_string())), }; - let last_commit_round = match signed_header_commit.get(1).cloned().unwrap() { + let last_commit_round = match signed_header_commit.get(1).cloned().ok_or( + ClientError::Other("failed to get index 1 and retrieve last_commit_round".to_string()))? { EthersToken::Int(last_commit_round) => last_commit_round, _ => return Err(ClientError::Other("last_commit_round not found".to_string())), }; - let last_commit_block_id = match signed_header_commit.get(2).cloned().unwrap() { + let last_commit_block_id = match signed_header_commit.get(2).cloned().ok_or( + ClientError::Other("failed to get index 2 and retrieve last_commit_block_id".to_string()))? { EthersToken::Tuple(toks) => toks, _ => return Err(ClientError::Other("last_commit_block_id not found".to_string())), }; - let last_commit_block_id_hash = match last_commit_block_id.get(0).cloned().unwrap() { + let last_commit_block_id_hash = match last_commit_block_id.get(0).cloned().ok_or( + ClientError::Other("failed to get index 0 and retrieve last_commit_block_id_hash".to_string()))? { EthersToken::Bytes(last_commit_block_id_hash) => last_commit_block_id_hash, _ => return Err(ClientError::Other("last_commit_block_id_hash not found".to_string())), }; - let last_commit_block_id_part_set_header = match last_commit_block_id.get(1).cloned().unwrap() { + let last_commit_block_id_part_set_header = match last_commit_block_id.get(1).cloned().ok_or( + ClientError::Other("failed to get index 1 and retrieve last_commit_block_id_part_set_header".to_string()))? { EthersToken::Tuple(toks) => toks, _ => return Err(ClientError::Other( @@ -661,7 +722,8 @@ pub(crate) fn tm_header_from_abi_token(token: Token) -> Result last_commit_block_id_part_set_header_total, _ => @@ -671,7 +733,8 @@ pub(crate) fn tm_header_from_abi_token(token: Token) -> Result last_commit_block_id_part_set_header_hash, _ => @@ -680,7 +743,8 @@ pub(crate) fn tm_header_from_abi_token(token: Token) -> Result trusted_height, _ => return Err(ClientError::Other("trusted_height not found".to_string())), }; @@ -691,52 +755,91 @@ pub(crate) fn tm_header_from_abi_token(token: Token) -> Result { - //TODO return error support only tendermint client state return Err(ClientError::Other(format!( "conn_open_try: client_state can't be None" ))) @@ -1163,49 +1241,53 @@ impl Chain for EthereumClient { let token = msg.into_token(); calls.push(self.yui.channel_open_try_calldata(token).await); } else if msg.type_url == channel_msgs::chan_open_ack::TYPE_URL { - let msg = MsgChannelOpenAck::decode_vec(&msg.value).map_err(|_| { - ClientError::Other("chan_open_ack: failed to decode_vec".into()) + let msg = MsgChannelOpenAck::decode_vec(&msg.value).map_err(|e| { + ClientError::Other(format!("chan_open_ack: failed to decode_vec: {:?}", e)) })?; log::info!("msg = {msg:#?}"); let token = msg.into_token(); calls.push(self.yui.send_and_get_tuple_calldata(token, "channelOpenAck").await); } else if msg.type_url == channel_msgs::chan_open_confirm::TYPE_URL { - let msg = MsgChannelOpenConfirm::decode_vec(&msg.value).map_err(|_| { - ClientError::Other("chann_open_confirm: failed to decode_vec".into()) + let msg = MsgChannelOpenConfirm::decode_vec(&msg.value).map_err(|e| { + ClientError::Other(format!("chann_open_confirm: failed to decode_vec : {:?}", e)) })?; let token = msg.into_token(); calls.push(self.yui.send_and_get_tuple_calldata(token, "channelOpenConfirm").await); } else if msg.type_url == channel_msgs::chan_close_init::TYPE_URL { - let msg = MsgChannelCloseInit::decode_vec(&msg.value).map_err(|_| { - ClientError::Other("chann_close_init: failed to decode_vec".into()) + let msg = MsgChannelCloseInit::decode_vec(&msg.value).map_err(|e| { + ClientError::Other(format!("chan_close_init: failed to decode_vec : {:?}", e)) })?; let token = msg.into_token(); calls.push(self.yui.send_and_get_tuple_calldata(token, "channelCloseInit").await); } else if msg.type_url == channel_msgs::chan_close_confirm::TYPE_URL { - let msg = MsgChannelCloseConfirm::decode_vec(&msg.value).map_err(|_| { - ClientError::Other("chann_close_confirm: failed to decode_vec".into()) + let msg = MsgChannelCloseConfirm::decode_vec(&msg.value).map_err(|e| { + ClientError::Other(format!("chan_close_confirm: failed to decode_vec : {:?}", e)) })?; let token = msg.into_token(); calls .push(self.yui.send_and_get_tuple_calldata(token, "channelCloseConfirm").await); } else if msg.type_url == channel_msgs::timeout_on_close::TYPE_URL { - let msg = MsgTimeoutOnClose::decode_vec(&msg.value).map_err(|_| { - ClientError::Other("timeout_on_close: failed to decode_vec".into()) + let msg = MsgTimeoutOnClose::decode_vec(&msg.value).map_err(|e| { + ClientError::Other(format!("timeout_on_close: failed to decode_vec : {:?}", e)) })?; return Err(ClientError::Other("timeout not supported".into())) } else if msg.type_url == channel_msgs::timeout::TYPE_URL { let msg = MsgTimeout::decode_vec(&msg.value) - .map_err(|_| ClientError::Other("timeout: failed to decode_vec".into()))?; + .map_err(|e| { + ClientError::Other(format!("timeout: failed to decode_vec : {:?}", e)) + })?; return Err(ClientError::Other("timeout not supported".into())) } else if msg.type_url == channel_msgs::acknowledgement::TYPE_URL { - let msg = MsgAcknowledgement::decode_vec(&msg.value).map_err(|_| { - ClientError::Other("acknowledgement: failed to decode_vec".into()) + let msg = MsgAcknowledgement::decode_vec(&msg.value).map_err(|e| { + ClientError::Other(format!("acknowledgement: failed to decode_vec : {:?}", e)) })?; let token = msg.into_token(); calls.push(self.yui.send_and_get_tuple_calldata(token, "acknowledgePacket").await); } else if msg.type_url == channel_msgs::recv_packet::TYPE_URL { let msg = MsgRecvPacket::decode_vec(&msg.value) - .map_err(|_| ClientError::Other("recv_packet: failed to decode_vec".into()))?; + .map_err(|e| { + ClientError::Other(format!("recv_packet: failed to decode_vec : {:?}", e)) + })?; let token = msg.into_token(); calls.push(self.yui.send_and_get_tuple_calldata(token, "recvPacket").await); } else { @@ -1224,7 +1306,10 @@ impl Chain for EthereumClient { .await? .ok_or_else(|| ClientError::Other("tx failed".into()))?; if receipt.status != Some(1.into()) { - return Err(ClientError::Other("tx failed".into())) + return Err(ClientError::Other(format!( + "tx failed: {:?}", + receipt + ))) } for (i, (success, result)) in @@ -1236,7 +1321,12 @@ impl Chain for EthereumClient { } let block_hash = - receipt.block_hash.ok_or(ClientError::Other("Block hash is missing".into()))?; + receipt.block_hash.ok_or( + ClientError::Other(format!( + "Block hash is missing for tx hash: {:?}", + receipt.transaction_hash + )) + )?; Ok((block_hash, receipt.transaction_hash)) } From 0a714ea7f3858a502eb01a26ba547d5b3e9d150a Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Fri, 15 Sep 2023 15:55:07 -0300 Subject: [PATCH 33/43] disable parachain chains --- hyperspace/core/src/chain.rs | 17 ++++++----------- hyperspace/core/src/lib.rs | 2 +- hyperspace/core/src/macros.rs | 6 +----- hyperspace/core/src/packets.rs | 15 +++------------ 4 files changed, 11 insertions(+), 29 deletions(-) diff --git a/hyperspace/core/src/chain.rs b/hyperspace/core/src/chain.rs index f5179aad5..3c00ecdfc 100644 --- a/hyperspace/core/src/chain.rs +++ b/hyperspace/core/src/chain.rs @@ -14,12 +14,7 @@ #![allow(unreachable_patterns)] -use crate::{ - chains, - substrate::{ - default::DefaultConfig, ComposableConfig, PicassoKusamaConfig, PicassoRococoConfig, - }, -}; +use crate::chains; use async_trait::async_trait; #[cfg(feature = "cosmos")] use cosmos::client::{CosmosClient, CosmosClientConfig}; @@ -97,13 +92,13 @@ impl From for AnyError { } chains! { - Parachain(ParachainClientConfig, ParachainClient), + // Parachain(ParachainClientConfig, ParachainClient), // Dali(ParachainClientConfig, ParachainClient), - Composable(ParachainClientConfig, ParachainClient), - PicassoRococo(ParachainClientConfig, ParachainClient), - PicassoKusama(ParachainClientConfig, ParachainClient), + // Composable(ParachainClientConfig, ParachainClient), + // PicassoRococo(ParachainClientConfig, ParachainClient), + // PicassoKusama(ParachainClientConfig, ParachainClient), #[cfg(feature = "cosmos")] - Cosmos(CosmosClientConfig, CosmosClient), + Cosmos(CosmosClientConfig, CosmosClient<()>), #[cfg(feature = "ethereum")] Ethereum(EthereumClientConfig, EthereumClient, EthereumCmd), } diff --git a/hyperspace/core/src/lib.rs b/hyperspace/core/src/lib.rs index ff5adb5b6..214c3129f 100644 --- a/hyperspace/core/src/lib.rs +++ b/hyperspace/core/src/lib.rs @@ -21,7 +21,7 @@ pub mod logging; mod macros; pub mod packets; pub mod queue; -pub mod substrate; +// pub mod substrate; mod utils; use crate::utils::RecentStream; diff --git a/hyperspace/core/src/macros.rs b/hyperspace/core/src/macros.rs index 4a3b1c627..1dfe46cde 100644 --- a/hyperspace/core/src/macros.rs +++ b/hyperspace/core/src/macros.rs @@ -821,11 +821,7 @@ macro_rules! chains { Self::Wasm(chain) => { let messages = messages .into_iter() - .map(|msg| { - let any = wrap_any_msg_into_wasm(msg, chain.code_id.clone()); - // any.as_ref().map(|any| { log::info!("Submitting message: {}", hex::encode(&any.value)); }); - any - }) + .map(|msg| wrap_any_msg_into_wasm(msg, chain.code_id.clone())) .collect::, _>>()?; chain.inner.submit(messages).await.map_err(AnyError::into) }, diff --git a/hyperspace/core/src/packets.rs b/hyperspace/core/src/packets.rs index f9c98d47c..efacaedf5 100644 --- a/hyperspace/core/src/packets.rs +++ b/hyperspace/core/src/packets.rs @@ -133,6 +133,7 @@ pub async fn query_ready_and_timed_out_packets( }, }; + // TODO: query_next_sequence_recv // let next_sequence_recv = sink // .query_next_sequence_recv(sink_height, &sink_port_id, &sink_channel_id) // .await?; @@ -234,18 +235,8 @@ pub async fn query_ready_and_timed_out_packets( Error::Custom(format!("Packet height not found for packet {packet:?}")) })?; - // [2023-09-08T12:24:41Z TRACE hyperspace] get_timeout_proof_height: - // ethereum-client->centauri, - // - // timeout_variant=Height, - // source_height=0-26948, - // timeout_height: Height { revision: 0, height: 24102 }, - // timeout_timestamp: Timestamp { time: None } } - // - // sink_height=1-23940, - // sink_timestamp=Timestamp(2023-09-08T12:24:33.381673Z), latest_client_height_on_source=1-23926, packet_creation_height=26885, - - log::info!("sink_height = {sink_height:?}, timeout_height = {:?}", packet.timeout_height); + + log::info!("sink_height = {sink_height:?}, timeout_height = {:?}", packet.timeout_height); if packet.timed_out(&sink_timestamp, sink_height) { timeout_packets_count.fetch_add(1, Ordering::SeqCst); From f5365d112184627727003c3cd6dba97f273724bc Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Fri, 15 Sep 2023 16:52:55 -0300 Subject: [PATCH 34/43] disable storage layout --- Cargo.lock | 1 - hyperspace/core/Cargo.toml | 2 +- hyperspace/ethereum/src/utils.rs | 42 ++++++++++++++++---------------- 3 files changed, 22 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e52e2a67e..0afd51643 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4915,7 +4915,6 @@ dependencies = [ "sp-state-machine 0.13.0", "sp-trie 7.0.0", "subxt", - "subxt-generated", "tendermint-proto", "thiserror", "tokio", diff --git a/hyperspace/core/Cargo.toml b/hyperspace/core/Cargo.toml index b44ed6b1f..ef2243a89 100644 --- a/hyperspace/core/Cargo.toml +++ b/hyperspace/core/Cargo.toml @@ -57,7 +57,7 @@ sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polka sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } sp-beefy = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } subxt = { git = "https://github.com/paritytech/subxt", rev = "2a4da618a033bb82f768e4ef67b093b371f8b492", features = ["substrate-compat"] } -subxt-generated = { path = "../../utils/subxt/generated" } +#subxt-generated = { path = "../../utils/subxt/generated" } frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39", default-features = false } prost = { version = "0.11", default-features = false } diff --git a/hyperspace/ethereum/src/utils.rs b/hyperspace/ethereum/src/utils.rs index 4f4098cd1..00c8386c5 100644 --- a/hyperspace/ethereum/src/utils.rs +++ b/hyperspace/ethereum/src/utils.rs @@ -799,27 +799,27 @@ where .await .unwrap(); - let predefined_layout = serde_json::from_reader::<_, StorageLayout>( - File::open("/Users/vmark/work/centauri-private/hyperspace/ethereum/src/storage_layout/ibc_storage.json").unwrap(), - ) - .expect("failed to read predefined storage layout"); - - let _storage_layout = project_output - .compiled_artifacts() - .iter() - .chain(diamond_project_output.compiled_artifacts()) - .flat_map(|(_, artifact)| artifact.into_iter().flat_map(|(an, artifact)| artifact)) - .filter_map(|ar| ar.artifact.storage_layout.clone()) - .chain(once(predefined_layout)) - .fold(StorageLayout { storage: vec![], types: Default::default() }, |mut acc, layout| { - acc.storage.extend(layout.storage); - - let len0 = acc.types.len(); - let len1 = layout.types.len(); - acc.types.extend(layout.types); - assert_eq!(acc.types.len(), len0 + len1, "duplicated type"); - acc - }); + // let predefined_layout = serde_json::from_reader::<_, StorageLayout>( + // File::open("/Users/vmark/work/centauri-private/hyperspace/ethereum/src/storage_layout/ + // ibc_storage.json").unwrap(), ) + // .expect("failed to read predefined storage layout"); + // + // let _storage_layout = project_output + // .compiled_artifacts() + // .iter() + // .chain(diamond_project_output.compiled_artifacts()) + // .flat_map(|(_, artifact)| artifact.into_iter().flat_map(|(an, artifact)| artifact)) + // .filter_map(|ar| ar.artifact.storage_layout.clone()) + // .chain(once(predefined_layout)) + // .fold(StorageLayout { storage: vec![], types: Default::default() }, |mut acc, layout| { + // acc.storage.extend(layout.storage); + // + // let len0 = acc.types.len(); + // let len1 = layout.types.len(); + // acc.types.extend(layout.types); + // assert_eq!(acc.types.len(), len0 + len1, "duplicated type"); + // acc + // }); DeployYuiIbc { diamond, From 21396b671c8342174add5e6c7e1483f991446119 Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Tue, 19 Sep 2023 23:37:26 -0300 Subject: [PATCH 35/43] fix membership proofs --- .../ethereum_verification/ethereum_trie.rs | 333 ------------------ light-clients/icsxx-ethereum/Cargo.toml | 11 + .../icsxx-ethereum/src/client_def.rs | 24 +- light-clients/icsxx-ethereum/src/lib.rs | 2 + .../icsxx-ethereum/src/proof/ethereum_trie.rs | 322 +++++++++++++++++ .../src/proof}/mod.rs | 1 + .../src/proof}/node_codec.rs | 0 .../src/proof}/tests.rs | 63 ++-- light-clients/icsxx-ethereum/src/verify.rs | 49 +++ 9 files changed, 434 insertions(+), 371 deletions(-) delete mode 100644 light-clients/common/src/ethereum_verification/ethereum_trie.rs create mode 100644 light-clients/icsxx-ethereum/src/proof/ethereum_trie.rs rename light-clients/{common/src/ethereum_verification => icsxx-ethereum/src/proof}/mod.rs (98%) rename light-clients/{common/src/ethereum_verification => icsxx-ethereum/src/proof}/node_codec.rs (100%) rename light-clients/{common/src/ethereum_verification => icsxx-ethereum/src/proof}/tests.rs (72%) diff --git a/light-clients/common/src/ethereum_verification/ethereum_trie.rs b/light-clients/common/src/ethereum_verification/ethereum_trie.rs deleted file mode 100644 index cd707825b..000000000 --- a/light-clients/common/src/ethereum_verification/ethereum_trie.rs +++ /dev/null @@ -1,333 +0,0 @@ -extern crate alloc; - -use crate::ethereum_verification::node_codec; - -use std::marker::PhantomData; - -/// Taken from https://github.com/paritytech/trie/blob/aa3168d6de01793e71ebd906d3a82ae4b363db59/trie-eip1186/src/eip1186.rs -use hash_db::Hasher; -use primitive_types::H256; -use tiny_keccak::{Hasher as KeccakHasherTrait, Keccak}; -use trie_db::{ - node::{decode_hash, Node, NodeHandle, Value}, - CError, NibbleSlice, NodeCodec, TrieHash, TrieLayout, -}; - -/// Errors that may occur during proof verification. Most of the errors types simply indicate that -/// the proof is invalid with respect to the statement being verified, and the exact error type can -/// be used for debugging. -#[derive(PartialEq, Eq, Debug)] -pub enum VerifyError<'a, HO, CE> { - /// The proof does not contain any value for the given key - /// the error carries the nibbles left after traversing the trie - NonExistingValue(NibbleSlice<'a>), - /// The proof contains a value for the given key - /// while we were expecting to find a non-existence proof - ExistingValue(Vec), - /// The proof indicates that the trie contains a different value. - /// the error carries the value contained in the trie - ValueMismatch(Vec), - /// The proof is missing trie nodes required to verify. - IncompleteProof, - /// The node hash computed from the proof is not matching. - HashMismatch(HO), - /// One of the proof nodes could not be decoded. - DecodeError(CE), - /// Error in converting a plain hash into a HO - HashDecodeError(&'a [u8]), -} - -#[cfg(feature = "std")] -impl<'a, HO: std::fmt::Debug, CE: std::error::Error> std::fmt::Display for VerifyError<'a, HO, CE> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { - match self { - VerifyError::NonExistingValue(key) => { - write!(f, "Key does not exist in trie: reaming key={:?}", key) - }, - VerifyError::ExistingValue(value) => { - write!(f, "trie contains a value for given key value={:?}", value) - }, - VerifyError::ValueMismatch(key) => { - write!(f, "Expected value was not found in the trie: key={:?}", key) - }, - VerifyError::IncompleteProof => write!(f, "Proof is incomplete -- expected more nodes"), - VerifyError::HashMismatch(hash) => write!(f, "hash mismatch found: hash={:?}", hash), - VerifyError::DecodeError(err) => write!(f, "Unable to decode proof node: {}", err), - VerifyError::HashDecodeError(plain_hash) => { - write!(f, "Unable to decode hash value plain_hash: {:?}", plain_hash) - }, - } - } -} - -#[cfg(feature = "std")] -impl<'a, HO: std::fmt::Debug, CE: std::error::Error + 'static> std::error::Error - for VerifyError<'a, HO, CE> -{ - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match self { - VerifyError::DecodeError(err) => Some(err), - _ => None, - } - } -} - -/// Verify a compact proof for key-value pairs in a trie given a root hash. -pub fn verify_proof<'a, L>( - root: &::Out, - proof: &'a [Vec], - raw_key: &'a [u8], - expected_value: Option<&[u8]>, -) -> Result<(), VerifyError<'a, TrieHash, CError>> -where - L: TrieLayout, - ::Hash: hash_db::Hasher, -{ - if proof.is_empty() { - return Err(VerifyError::IncompleteProof) - } - let key = NibbleSlice::new(raw_key); - process_node::(Some(root), &proof[0], key, expected_value, &proof[1..]) -} - -fn process_node<'a, L>( - expected_node_hash: Option<&::Out>, - encoded_node: &'a [u8], - key: NibbleSlice<'a>, - expected_value: Option<&[u8]>, - proof: &'a [Vec], -) -> Result<(), VerifyError<'a, TrieHash, CError>> -where - L: TrieLayout, - ::Hash: hash_db::Hasher, -{ - if let Some(value) = expected_value { - if encoded_node == value { - return Ok(()) - } - } - if let Some(expected) = expected_node_hash { - let calculated_node_hash = ::hash(encoded_node); - if calculated_node_hash != *expected { - return Err(VerifyError::HashMismatch(calculated_node_hash)) - } - } - let node = ::decode(encoded_node).map_err(VerifyError::DecodeError)?; - match node { - Node::Empty => process_empty::(key, expected_value, proof), - Node::Leaf(nib, data) => process_leaf::(nib, data, key, expected_value, proof), - Node::Extension(nib, handle) => - process_extension::(&nib, handle, key, expected_value, proof), - Node::Branch(children, maybe_data) => - process_branch::(children, maybe_data, key, expected_value, proof), - Node::NibbledBranch(nib, children, maybe_data) => - process_nibbledbranch::(nib, children, maybe_data, key, expected_value, proof), - } -} - -fn process_empty<'a, L>( - key: NibbleSlice<'a>, - expected_value: Option<&[u8]>, - _: &[Vec], -) -> Result<(), VerifyError<'a, TrieHash, CError>> -where - L: TrieLayout, -{ - if expected_value.is_none() { - Ok(()) - } else { - Err(VerifyError::NonExistingValue(key)) - } -} - -fn process_leaf<'a, L>( - nib: NibbleSlice, - data: Value<'a>, - key: NibbleSlice<'a>, - expected_value: Option<&[u8]>, - proof: &'a [Vec], -) -> Result<(), VerifyError<'a, TrieHash, CError>> -where - L: TrieLayout, -{ - if key != nib && expected_value.is_none() { - return Ok(()) - } else if key != nib { - return Err(VerifyError::NonExistingValue(key)) - } - match_value::(Some(data), key, expected_value, proof) -} -fn process_extension<'a, L>( - nib: &NibbleSlice, - handle: NodeHandle<'a>, - mut key: NibbleSlice<'a>, - expected_value: Option<&[u8]>, - proof: &'a [Vec], -) -> Result<(), VerifyError<'a, TrieHash, CError>> -where - L: TrieLayout, -{ - if !key.starts_with(nib) && expected_value.is_none() { - return Ok(()) - } else if !key.starts_with(nib) { - return Err(VerifyError::NonExistingValue(key)) - } - key.advance(nib.len()); - - match handle { - NodeHandle::Inline(encoded_node) => - process_node::(None, encoded_node, key, expected_value, proof), - NodeHandle::Hash(plain_hash) => { - let new_root = decode_hash::(plain_hash) - .ok_or_else(|| VerifyError::HashDecodeError(plain_hash))?; - process_node::(Some(&new_root), &proof[0], key, expected_value, &proof[1..]) - }, - } -} - -fn process_nibbledbranch<'a, L>( - nib: NibbleSlice, - children: [Option>; 16], - maybe_data: Option>, - mut key: NibbleSlice<'a>, - expected_value: Option<&[u8]>, - proof: &'a [Vec], -) -> Result<(), VerifyError<'a, TrieHash, CError>> -where - L: TrieLayout, -{ - if !key.starts_with(&nib) && expected_value.is_none() { - return Ok(()) - } else if !key.starts_with(&nib) && expected_value.is_some() { - return Err(VerifyError::NonExistingValue(key)) - } - key.advance(nib.len()); - - if key.is_empty() { - match_value::(maybe_data, key, expected_value, proof) - } else { - match_children::(children, key, expected_value, proof) - } -} - -fn process_branch<'a, L>( - children: [Option>; 16], - maybe_data: Option>, - key: NibbleSlice<'a>, - expected_value: Option<&[u8]>, - proof: &'a [Vec], -) -> Result<(), VerifyError<'a, TrieHash, CError>> -where - L: TrieLayout, -{ - if key.is_empty() { - match_value::(maybe_data, key, expected_value, proof) - } else { - match_children::(children, key, expected_value, proof) - } -} -fn match_children<'a, L>( - children: [Option>; 16], - mut key: NibbleSlice<'a>, - expected_value: Option<&[u8]>, - proof: &'a [Vec], -) -> Result<(), VerifyError<'a, TrieHash, CError>> -where - L: TrieLayout, -{ - match children.get(key.at(0) as usize) { - Some(Some(NodeHandle::Hash(hash))) => - if proof.is_empty() { - Err(VerifyError::IncompleteProof) - } else { - key.advance(1); - let new_root = decode_hash::(hash) - .ok_or_else(|| VerifyError::HashDecodeError(hash))?; - process_node::(Some(&new_root), &proof[0], key, expected_value, &proof[1..]) - }, - Some(Some(NodeHandle::Inline(encoded_node))) => { - key.advance(1); - process_node::(None, encoded_node, key, expected_value, proof) - }, - Some(None) => - if expected_value.is_none() { - Ok(()) - } else { - Err(VerifyError::NonExistingValue(key)) - }, - None => panic!("key index is out of range in children array"), - } -} - -fn match_value<'a, L>( - maybe_data: Option>, - key: NibbleSlice<'a>, - expected_value: Option<&[u8]>, - proof: &'a [Vec], -) -> Result<(), VerifyError<'a, TrieHash, CError>> -where - L: TrieLayout, -{ - match (maybe_data, proof.first(), expected_value) { - (None, _, None) => Ok(()), - (None, _, Some(_)) => Err(VerifyError::NonExistingValue(key)), - (Some(Value::Inline(inline_data)), _, Some(value)) => - if inline_data == value { - Ok(()) - } else { - Err(VerifyError::ValueMismatch(inline_data.to_vec())) - }, - (Some(Value::Inline(inline_data)), _, None) => - Err(VerifyError::ExistingValue(inline_data.to_vec())), - (Some(Value::Node(plain_hash)), Some(next_proof_item), Some(value)) => { - let value_hash = L::Hash::hash(value); - let node_hash = decode_hash::(plain_hash) - .ok_or_else(|| VerifyError::HashDecodeError(plain_hash))?; - if node_hash != value_hash { - Err(VerifyError::HashMismatch(node_hash)) - } else if next_proof_item != value { - Err(VerifyError::ValueMismatch(next_proof_item.to_vec())) - } else { - Ok(()) - } - }, - (Some(Value::Node(_)), None, _) => Err(VerifyError::IncompleteProof), - (Some(Value::Node(_)), Some(proof_item), None) => - Err(VerifyError::ExistingValue(proof_item.to_vec())), - } -} - -pub fn keccak_256(input: &[u8]) -> [u8; 32] { - let mut out = [0u8; 32]; - let mut k = Keccak::v256(); - k.update(input); - k.finalize(&mut out); - out -} - -/// Trie layout for EIP-1186 state proof nodes. -#[derive(Default, Clone)] -pub struct EIP1186Layout(PhantomData); - -impl> TrieLayout for EIP1186Layout { - const USE_EXTENSION: bool = true; - const ALLOW_EMPTY: bool = false; - const MAX_INLINE_VALUE: Option = None; - type Hash = H; - type Codec = node_codec::RlpNodeCodec; -} - -use hash256_std_hasher::Hash256StdHasher; - -#[derive(Debug)] -pub struct KeccakHasher; - -impl hash_db::Hasher for KeccakHasher { - type Out = H256; - type StdHasher = Hash256StdHasher; - const LENGTH: usize = 32; - - fn hash(x: &[u8]) -> Self::Out { - keccak_256(x).into() - } -} diff --git a/light-clients/icsxx-ethereum/Cargo.toml b/light-clients/icsxx-ethereum/Cargo.toml index 8597ecd45..ac4fe9324 100644 --- a/light-clients/icsxx-ethereum/Cargo.toml +++ b/light-clients/icsxx-ethereum/Cargo.toml @@ -29,6 +29,16 @@ serde = { version = "1.0.144", default-features = false, features = ["derive"] } tendermint = { git = "https://github.com/informalsystems/tendermint-rs", rev = "e81f7bf23d63ffbcd242381d1ce5e35da3515ff1", default-features = false } tendermint-proto = { git = "https://github.com/informalsystems/tendermint-rs", rev = "e81f7bf23d63ffbcd242381d1ce5e35da3515ff1", default-features = false } +serde_cbor = "0.11.2" +ethers-core = { version = "2.0.10", default-features = false } +eth_merkle_tree = { version = "0.1.1", default-features = false } +rs_merkle = { version = "1.4.1", default-features = false } +#serde_json = { version = "1.0.105" , default-features = false } +hash-db = { version = "0.16.0", default-features = false } +trie-db = { version = "0.28.0", default-features = false } +rlp = { version = "0.5.2", default-features = false } +hex-literal = { version = "0.4.1", default-features = false } +hash256-std-hasher = { version = "0.15.2", default-features = false } [dev-dependencies] hex = "0.4.3" @@ -45,6 +55,7 @@ actix-rt = "2.3.0" sync-committee-primitives = { git = "https://github.com/polytope-labs/sync-committee-rs.git", rev = "106f53e045cc85c4a8d984c8e295800cebaa2475" } sync-committee-verifier = { git = "https://github.com/polytope-labs/sync-committee-rs.git", rev = "106f53e045cc85c4a8d984c8e295800cebaa2475" } sync-committee-prover = { git = "https://github.com/polytope-labs/sync-committee-rs.git", rev = "106f53e045cc85c4a8d984c8e295800cebaa2475" } +trie-db = { version = "0.28.0" } [features] default = ["std"] diff --git a/light-clients/icsxx-ethereum/src/client_def.rs b/light-clients/icsxx-ethereum/src/client_def.rs index dab418897..3974f1a0f 100644 --- a/light-clients/icsxx-ethereum/src/client_def.rs +++ b/light-clients/icsxx-ethereum/src/client_def.rs @@ -18,7 +18,10 @@ use ibc::core::ics02_client::{ client_consensus::ConsensusState as _, client_state::ClientState as _, }; -use crate::client_message::{ClientMessage, Misbehaviour}; +use crate::{ + client_message::{ClientMessage, Misbehaviour}, + verify::verify_ibc_proof, +}; use alloc::{format, string::ToString, vec, vec::Vec}; use anyhow::anyhow; use core::{fmt::Debug, marker::PhantomData}; @@ -246,16 +249,15 @@ where consensus_height: Height, expected_consensus_state: &Ctx::AnyConsensusState, ) -> Result<(), Ics02Error> { - // client_state.verify_height(height)?; - // let path = ClientConsensusStatePath { - // client_id: client_id.clone(), - // epoch: consensus_height.revision_number, - // height: consensus_height.revision_height, - // }; - // let value = expected_consensus_state.encode_to_vec().map_err(Ics02Error::encode)?; - // verify_membership::(prefix, proof, root, path, value) - // .map_err(Error::Anyhow)?; - unimplemented!() + client_state.verify_height(height)?; + let path = ClientConsensusStatePath { + client_id: client_id.clone(), + epoch: consensus_height.revision_number, + height: consensus_height.revision_height, + }; + let value = expected_consensus_state.encode_to_vec().map_err(Ics02Error::encode)?; + verify_ibc_proof(prefix, proof, root, path, Some(&value))?; + Ok(()) } fn verify_connection_state( diff --git a/light-clients/icsxx-ethereum/src/lib.rs b/light-clients/icsxx-ethereum/src/lib.rs index 5f5e1d438..9757371d3 100644 --- a/light-clients/icsxx-ethereum/src/lib.rs +++ b/light-clients/icsxx-ethereum/src/lib.rs @@ -19,12 +19,14 @@ //! ICS-10: Grandpa IBC light client protocol implementation extern crate alloc; +extern crate core; pub mod client_def; pub mod client_message; pub mod client_state; pub mod consensus_state; pub mod error; +pub mod proof; pub mod proto; pub mod verify; diff --git a/light-clients/icsxx-ethereum/src/proof/ethereum_trie.rs b/light-clients/icsxx-ethereum/src/proof/ethereum_trie.rs new file mode 100644 index 000000000..04f6aea35 --- /dev/null +++ b/light-clients/icsxx-ethereum/src/proof/ethereum_trie.rs @@ -0,0 +1,322 @@ +extern crate alloc; + +use crate::proof::node_codec; +use ethers_core::utils::keccak256; +use hash256_std_hasher::Hash256StdHasher; +use hash_db::Hasher; +/// Taken from https://github.com/paritytech/trie/blob/aa3168d6de01793e71ebd906d3a82ae4b363db59/trie-eip1186/src/eip1186.rs +use primitive_types::H256; +use std::marker::PhantomData; +use trie_db::{ + node::{decode_hash, Node, NodeHandle, Value}, + CError, NibbleSlice, NodeCodec, TrieHash, TrieLayout, +}; + +// /// Errors that may occur during proof verification. Most of the errors types simply indicate +// that /// the proof is invalid with respect to the statement being verified, and the exact error +// type can /// be used for debugging. +// #[derive(PartialEq, Eq, Debug)] +// pub enum VerifyError<'a, HO, CE> { +// /// The proof does not contain any value for the given key +// /// the error carries the nibbles left after traversing the trie +// NonExistingValue(NibbleSlice<'a>), +// /// The proof contains a value for the given key +// /// while we were expecting to find a non-existence proof +// ExistingValue(Vec), +// /// The proof indicates that the trie contains a different value. +// /// the error carries the value contained in the trie +// ValueMismatch(Vec), +// /// The proof is missing trie nodes required to verify. +// IncompleteProof, +// /// The node hash computed from the proof is not matching. +// HashMismatch(HO), +// /// One of the proof nodes could not be decoded. +// DecodeError(CE), +// /// Error in converting a plain hash into a HO +// HashDecodeError(&'a [u8]), +// } +// +// #[cfg(feature = "std")] +// impl<'a, HO: std::fmt::Debug, CE: std::error::Error> std::fmt::Display for VerifyError<'a, HO, +// CE> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { +// match self { +// VerifyError::NonExistingValue(key) => { +// write!(f, "Key does not exist in trie: reaming key") +// }, +// VerifyError::ExistingValue(value) => { +// write!(f, "trie contains a value for given key value={:?}", value) +// }, +// VerifyError::ValueMismatch(key) => { +// write!(f, "Expected value was not found in the trie: key={:?}", key) +// }, +// VerifyError::IncompleteProof => write!(f, "Proof is incomplete -- expected more nodes"), +// VerifyError::HashMismatch(hash) => write!(f, "hash mismatch found: hash={:?}", hash), +// VerifyError::DecodeError(err) => write!(f, "Unable to decode proof node: {}", err), +// VerifyError::HashDecodeError(plain_hash) => { +// write!(f, "Unable to decode hash value plain_hash: {:?}", plain_hash) +// }, +// } +// } +// } +// +// #[cfg(feature = "std")] +// impl<'a, HO: std::fmt::Debug, CE: std::error::Error + 'static> std::error::Error +// for VerifyError<'a, HO, CE> +// { +// fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { +// match self { +// VerifyError::DecodeError(err) => Some(err), +// _ => None, +// } +// } +// } +// +// /// Verify a compact proof for key-value pairs in a trie given a root hash. +// pub fn verify_proof<'a, L>( +// root: &::Out, +// proof: &'a [Vec], +// raw_key: &'a [u8], +// expected_value: Option<&[u8]>, +// ) -> Result<(), VerifyError<'a, TrieHash, CError>> +// where +// L: TrieLayout, +// ::Hash: hash_db::Hasher, +// { +// if proof.is_empty() { +// return Err(VerifyError::IncompleteProof) +// } +// let key = NibbleSlice::new(raw_key); +// process_node::(Some(root), &proof[0], key, expected_value, &proof[1..]) +// } +// +// fn process_node<'a, L>( +// expected_node_hash: Option<&::Out>, +// encoded_node: &'a [u8], +// key: NibbleSlice<'a>, +// expected_value: Option<&[u8]>, +// proof: &'a [Vec], +// ) -> Result<(), VerifyError<'a, TrieHash, CError>> +// where +// L: TrieLayout, +// ::Hash: hash_db::Hasher, +// { +// if let Some(value) = expected_value { +// if encoded_node == value { +// return Ok(()) +// } +// } +// if let Some(expected) = expected_node_hash { +// let calculated_node_hash = ::hash(encoded_node); +// if calculated_node_hash != *expected { +// return Err(VerifyError::HashMismatch(calculated_node_hash)) +// } +// } +// let node = ::decode(encoded_node).map_err(VerifyError::DecodeError)?; +// match node { +// Node::Empty => process_empty::(key, expected_value, proof), +// Node::Leaf(nib, data) => process_leaf::(nib, data, key, expected_value, proof), +// Node::Extension(nib, handle) => +// process_extension::(&nib, handle, key, expected_value, proof), +// Node::Branch(children, maybe_data) => +// process_branch::(children, maybe_data, key, expected_value, proof), +// Node::NibbledBranch(nib, children, maybe_data) => +// process_nibbledbranch::(nib, children, maybe_data, key, expected_value, proof), +// } +// } +// +// fn process_empty<'a, L>( +// key: NibbleSlice<'a>, +// expected_value: Option<&[u8]>, +// _: &[Vec], +// ) -> Result<(), VerifyError<'a, TrieHash, CError>> +// where +// L: TrieLayout, +// { +// if expected_value.is_none() { +// Ok(()) +// } else { +// Err(VerifyError::NonExistingValue(key)) +// } +// } +// +// fn process_leaf<'a, L>( +// nib: NibbleSlice, +// data: Value<'a>, +// key: NibbleSlice<'a>, +// expected_value: Option<&[u8]>, +// proof: &'a [Vec], +// ) -> Result<(), VerifyError<'a, TrieHash, CError>> +// where +// L: TrieLayout, +// { +// if key != nib && expected_value.is_none() { +// return Ok(()) +// } else if key != nib { +// return Err(VerifyError::NonExistingValue(key)) +// } +// match_value::(Some(data), key, expected_value, proof) +// } +// fn process_extension<'a, L>( +// nib: &NibbleSlice, +// handle: NodeHandle<'a>, +// mut key: NibbleSlice<'a>, +// expected_value: Option<&[u8]>, +// proof: &'a [Vec], +// ) -> Result<(), VerifyError<'a, TrieHash, CError>> +// where +// L: TrieLayout, +// { +// if !key.starts_with(nib) && expected_value.is_none() { +// return Ok(()) +// } else if !key.starts_with(nib) { +// return Err(VerifyError::NonExistingValue(key)) +// } +// key.advance(nib.len()); +// +// match handle { +// NodeHandle::Inline(encoded_node) => +// process_node::(None, encoded_node, key, expected_value, proof), +// NodeHandle::Hash(plain_hash) => { +// let new_root = decode_hash::(plain_hash) +// .ok_or_else(|| VerifyError::HashDecodeError(plain_hash))?; +// process_node::(Some(&new_root), &proof[0], key, expected_value, &proof[1..]) +// }, +// } +// } +// +// fn process_nibbledbranch<'a, L>( +// nib: NibbleSlice, +// children: [Option>; 16], +// maybe_data: Option>, +// mut key: NibbleSlice<'a>, +// expected_value: Option<&[u8]>, +// proof: &'a [Vec], +// ) -> Result<(), VerifyError<'a, TrieHash, CError>> +// where +// L: TrieLayout, +// { +// if !key.starts_with(&nib) && expected_value.is_none() { +// return Ok(()) +// } else if !key.starts_with(&nib) && expected_value.is_some() { +// return Err(VerifyError::NonExistingValue(key)) +// } +// key.advance(nib.len()); +// +// if key.is_empty() { +// match_value::(maybe_data, key, expected_value, proof) +// } else { +// match_children::(children, key, expected_value, proof) +// } +// } +// +// fn process_branch<'a, L>( +// children: [Option>; 16], +// maybe_data: Option>, +// key: NibbleSlice<'a>, +// expected_value: Option<&[u8]>, +// proof: &'a [Vec], +// ) -> Result<(), VerifyError<'a, TrieHash, CError>> +// where +// L: TrieLayout, +// { +// if key.is_empty() { +// match_value::(maybe_data, key, expected_value, proof) +// } else { +// match_children::(children, key, expected_value, proof) +// } +// } +// fn match_children<'a, L>( +// children: [Option>; 16], +// mut key: NibbleSlice<'a>, +// expected_value: Option<&[u8]>, +// proof: &'a [Vec], +// ) -> Result<(), VerifyError<'a, TrieHash, CError>> +// where +// L: TrieLayout, +// { +// match children.get(key.at(0) as usize) { +// Some(Some(NodeHandle::Hash(hash))) => +// if proof.is_empty() { +// Err(VerifyError::IncompleteProof) +// } else { +// key.advance(1); +// let new_root = decode_hash::(hash) +// .ok_or_else(|| VerifyError::HashDecodeError(hash))?; +// process_node::(Some(&new_root), &proof[0], key, expected_value, &proof[1..]) +// }, +// Some(Some(NodeHandle::Inline(encoded_node))) => { +// key.advance(1); +// process_node::(None, encoded_node, key, expected_value, proof) +// }, +// Some(None) => +// if expected_value.is_none() { +// Ok(()) +// } else { +// Err(VerifyError::NonExistingValue(key)) +// }, +// None => panic!("key index is out of range in children array"), +// } +// } +// +// fn match_value<'a, L>( +// maybe_data: Option>, +// key: NibbleSlice<'a>, +// expected_value: Option<&[u8]>, +// proof: &'a [Vec], +// ) -> Result<(), VerifyError<'a, TrieHash, CError>> +// where +// L: TrieLayout, +// { +// match (maybe_data, proof.first(), expected_value) { +// (None, _, None) => Ok(()), +// (None, _, Some(_)) => Err(VerifyError::NonExistingValue(key)), +// (Some(Value::Inline(inline_data)), _, Some(value)) => +// if inline_data == value { +// Ok(()) +// } else { +// Err(VerifyError::ValueMismatch(inline_data.to_vec())) +// }, +// (Some(Value::Inline(inline_data)), _, None) => +// Err(VerifyError::ExistingValue(inline_data.to_vec())), +// (Some(Value::Node(plain_hash)), Some(next_proof_item), Some(value)) => { +// let value_hash = L::Hash::hash(value); +// let node_hash = decode_hash::(plain_hash) +// .ok_or_else(|| VerifyError::HashDecodeError(plain_hash))?; +// if node_hash != value_hash { +// Err(VerifyError::HashMismatch(node_hash)) +// } else if next_proof_item != value { +// Err(VerifyError::ValueMismatch(next_proof_item.to_vec())) +// } else { +// Ok(()) +// } +// }, +// (Some(Value::Node(_)), None, _) => Err(VerifyError::IncompleteProof), +// (Some(Value::Node(_)), Some(proof_item), None) => +// Err(VerifyError::ExistingValue(proof_item.to_vec())), +// } +// } + +/// Trie layout for EIP-1186 state proof nodes. +#[derive(Default, Clone)] +pub struct EIP1186Layout(PhantomData); + +impl> TrieLayout for EIP1186Layout { + const USE_EXTENSION: bool = true; + const ALLOW_EMPTY: bool = false; + const MAX_INLINE_VALUE: Option = None; + type Hash = H; + type Codec = node_codec::RlpNodeCodec; +} + +#[derive(Debug)] +pub struct KeccakHasher; + +impl Hasher for KeccakHasher { + type Out = H256; + type StdHasher = Hash256StdHasher; + const LENGTH: usize = 32; + + fn hash(x: &[u8]) -> Self::Out { + keccak256(x).into() + } +} diff --git a/light-clients/common/src/ethereum_verification/mod.rs b/light-clients/icsxx-ethereum/src/proof/mod.rs similarity index 98% rename from light-clients/common/src/ethereum_verification/mod.rs rename to light-clients/icsxx-ethereum/src/proof/mod.rs index dce5498b1..1c2c8178c 100644 --- a/light-clients/common/src/ethereum_verification/mod.rs +++ b/light-clients/icsxx-ethereum/src/proof/mod.rs @@ -1,4 +1,5 @@ pub mod ethereum_trie; pub mod node_codec; + #[cfg(test)] mod tests; diff --git a/light-clients/common/src/ethereum_verification/node_codec.rs b/light-clients/icsxx-ethereum/src/proof/node_codec.rs similarity index 100% rename from light-clients/common/src/ethereum_verification/node_codec.rs rename to light-clients/icsxx-ethereum/src/proof/node_codec.rs diff --git a/light-clients/common/src/ethereum_verification/tests.rs b/light-clients/icsxx-ethereum/src/proof/tests.rs similarity index 72% rename from light-clients/common/src/ethereum_verification/tests.rs rename to light-clients/icsxx-ethereum/src/proof/tests.rs index 4c033a93d..aa85a284f 100644 --- a/light-clients/common/src/ethereum_verification/tests.rs +++ b/light-clients/icsxx-ethereum/src/proof/tests.rs @@ -1,8 +1,9 @@ -use crate::node_codec::RlpNodeCodec; - -use crate::*; - +use super::{node_codec::RlpNodeCodec, *}; +use crate::proof::ethereum_trie::{EIP1186Layout, KeccakHasher}; +use ethers_core::utils::keccak256; use hex_literal::hex; +use primitive_types::H256; +use trie_db::{node::Node, proof::verify_proof, NodeCodec}; #[test] fn test_verify_membership() { @@ -11,12 +12,20 @@ fn test_verify_membership() { hex!("f851808080a007c9a6fda8ffe9dbc9fb3ecc78460caef3c4659cfc8e4e865a6121d91375557d8080808080808080a03ce63212850c9a256f4cbb1a7ba7cb576549222339f2b4124621ea4a991fe6eb80808080").into(), hex!("f8709f20017a85544556ea847c203623a9c84efdb77fa4951a5b01296d9aacefc5f7b84ef84c01880de0b6b3a7640000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470").into(), ]; - - let key: Vec = keccak_256(&hex!("24264ae01b1abbc9a91e18926818ad5cbf39017b")).into(); - + let key: Vec = keccak256(&hex!("24264ae01b1abbc9a91e18926818ad5cbf39017b")).into(); let root = H256(hex!("7bac2ed96e9c1b0bf578c52fd6e86a2d74c555f8e74d5954aff57939f144299a")); - verify_proof::>(&root, &proof, &key, Some(&proof[2])).unwrap(); + /* + // pub fn verify_proof<'a, L>( + // root: &::Out, + // proof: &'a [Vec], + // raw_key: &'a [u8], + // expected_value: Option<&[u8]>, + // ) -> Result<(), VerifyError<'a, TrieHash, CError>> + + */ + verify_proof::, I, K, V>(&root, &proof, [&(&key, Some(&proof[2]))]) + .unwrap(); } #[test] @@ -28,9 +37,9 @@ fn test_verify_non_membership() { ]; let key_modified: Vec = - hex!("1eec017a85544556ea847c203623a9c84efdb77fa4951a5b01296d9aacefc5f7"); + hex!("1eec017a85544556ea847c203623a9c84efdb77fa4951a5b01296d9aacefc5f7").to_vec(); - let key: Vec = keccak_256(&hex!("24264ae01b1abbc9a91e18926818ad5cbf39017b")).into(); + let key: Vec = keccak256(&hex!("24264ae01b1abbc9a91e18926818ad5cbf39017b")).into(); let root = H256(hex!("7bac2ed96e9c1b0bf578c52fd6e86a2d74c555f8e74d5954aff57939f144299a")); @@ -50,7 +59,8 @@ fn test_verify_non_membership() { #[test] fn test_can_verify_eip_1186_proofs() { // source?: https://medium.com/@chiqing/eip-1186-explained-the-standard-for-getting-account-proof-444bc1e12e03 - let key = keccak_256(&hex!("b856af30b938b6f52e5bff365675f358cd52f91b")); + let root = H256(hex!("024c056bc5db60d71c7908c5fad6050646bd70fd772ff222702d577e2af2e56b")); + let key = keccak256(&hex!("b856af30b938b6f52e5bff365675f358cd52f91b")); let proof = vec![ hex!("f90211a021162657aa1e0af5eef47130ffc3362cb675ebbccfc99ee38ef9196144623507a073dec98f4943e2ab00f5751c23db67b65009bb3cb178d33f5aa93f0c08d583dda0d85b4e33773aaab742db880f8b64ea71f348c6eccb0a56854571bbd3db267f24a0bdcca489de03a49f109c1a2e7d3bd4e644d72de38b7b26dca2f8d3f112110c6fa05c7e8fdff6de07c4cb9ca6bea487a6e5be04af538c25480ce30761901b17e4bfa0d9891f4870e745509cfe17a31568f870b367a36329c892f1b2a37bf59e547183a0af08f747d2ea66efa5bcd03729a95f56297ef9b1e8533ac0d3c7546ebefd2418a0a107595919d4b102afaa0d9b91d9f554f83f0ad61a1e04487e5091543eb81db8a0a0725da6da3b62f88fc573a3fd0dd9dea9cba1750786021da836fd95b7295636a0fd7a768700af3caadaf52a08a23ab0b71ca52830f2b88b1a6b23a52f9ee05507a059434ae837706d7d317e4f7d03cd91f94ed0465fa8b99eaf18ca363bb318c7b3a09e9b831a5f59b781efd5dae8bea30bfd81b9fd5ea231d6b7e82da495c95dd35da0e72d02a01ed9bc928d94cad59ae0695f45120b7fbdbce43a2239a7e5bc81f731a0184bfb9a4051cbaa79917183d004c8d574d7ed5becaf9614c650ed40e8d123d9a0fa4797dc4a35af07f1cd6955318e3ff59578d4df32fd2174ed35f6c4db3471f9a0fec098d1fee8e975b5e78e19003699cf7cd746f47d03692d8e11c5fd58ba92a680").to_vec(), hex!("f90211a07fc5351578eb6ab7618a31e18c87b2b8b2703c682f2d4c1d01aaa8b53343036ea0e8871ae1828c54b9c9bbf7530890a2fe4e160fb62f72c740c7e79a756e07dbf3a04dd116a7d37146cd0ec730172fa97e84b1f13e687d56118e2d666a02a31a629fa08949d66b81ba98e5ca453ba1faf95c8476873d4c32ff6c9a2558b772c51c5768a028db2de6d80f3a06861d3acc082e3a6bb4a6948980a8e5527bd354a2da037779a09b01ba0fe0193c511161448c602bb9fff88b87ab0ded3255606a15f8bca9d348a0c1c1c6a89f2fdbee0840ff309b5cecd9764b5b5815b385576e75e235d1f04656a04e827215bb9511b3a288e33bb418132940a4d42d589b8db0f796ec917e8f9373a099398993d1d6fdd15d6082be370e4d2cc5d9870923d22770aaec9418f4b675d7a00cd1db5e131341b472af1bdf9a1bf1f1ca82bc5b280c8a50a20bcfff1ab0bdd4a09bbcc86c94be1aabf5c5ceced29f462f59103aa6dafe0fc60172bb2c549a8dbaa0902df0ba9eed7e8a6ebff2d06de8bcec5785bb98cba7606f7f40648408157ef4a0ba9dfd07c453e54504d41b7a44ea42e8220767d1e2a0e6e91ae8d5677ac70e50a0f02f2a5e26d7848f0e5a07de68cbbbd24253d545afb74aac81b35a70b6323f1ca0218b955deca7177f8f58c2da188611b333e5c7ef9212000f64ca92cd5bb6e5a0a049cd750f59e2d6f411d7b611b21b17c8eefe637ca01e1566c53f412308b34c6280").to_vec(), @@ -62,25 +72,24 @@ fn test_can_verify_eip_1186_proofs() { hex!("f86d9d3c3738deb88e49108e7a5bd83c14ad65b5ba598e2932551dc9b9ad1879b84df84b10874ef05b2fe9d8c8a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470").to_vec(), ]; - let root = H256(hex!("024c056bc5db60d71c7908c5fad6050646bd70fd772ff222702d577e2af2e56b")); assert!( verify_proof::>(&root, &proof, &key, Some(&proof[7])).is_ok() ); +} - assert!(matches!(RlpNodeCodec::::decode(&proof[7]).unwrap(), Node::Leaf(..))); - - let key_modified: Vec = - keccak_256(&hex!("b856af30b938b6f52e5bff365675f358cd52f91a")).into(); - - assert!(dbg!(verify_proof::>( - &root, - &proof, - &key_modified, - Some(&proof[7]) - )) - .is_err()); +#[test] +fn test_can_verify_eip_1186_non_existence_proofs() { + let root = H256(hex!("ab1020aa394b36082d49e7d6b98defcd3a1fad838e0cd4f3fff64990fd14b760")); + let key = hex!("bfa8b01fd8dc46bd81250474dd1a73ea76f021775d95be249c9a480fb17b8849"); + let proof = vec![ + hex!("f90211a0817776a79178c3ddd2aa41fb7f08f9f1c7f848e568ba0206148697562765df16a0b60879632cfa8aae2a8092c051d1bde9918938423fa836a5df9123305c92039da0b1380b7c699cb3f1bec8ca07de75ee5232c2b229e8f71a4efdccffa977c8198ea0f71700f8ab903ea191967e97c8d7862a1333c14ad1810ccae9a0dd7fa1fda9e5a032d5d2e30bf679141f1811829ad30b0eb688f16c5c3eb715bd593bd016f6fee1a0f322ec39ba01f262317ca0e3ef4baded11c3d0e5576507352f36fc8e97d39ad8a04f4a409bf1634599f0dac57a7568ad2d424c13ed8a74d8e84a327bbcf486af8ca0505b03ca809481fb0b0fd2ea1eef71f9c473d6487db932b9348f308dec7715e1a0d00912aaa2ecc35bf691537657354230085b5596b933faec0cb42cc60b78d39ba01035667dea728ce1bf4b0487d21925fe11145b2e8aa65bb850c2926175fc9372a0dab6eecc863a21b5727e0bd80f5921f400b3b3f596143abb662c5a7d5eae864fa0d5caead74f44b27992b5c6ffd281d64bcbb4a1bf307264f87b6c06562ac8c23da041b35c33db22d7fa88c7c53e2839d43a2c55228da57690abaeb74aae4c4c2950a08af8887847f3d19ef6e610116b5934cd3baac79238694cc5209febddbc7d50c2a0030f93c0c4fbd763d574d4f910b8cd5f90fb6e32275091cb5e474891ac3060a7a0baf638e937fb10836521cf7abfbdfebb48cbed23e1fb123928609e8f65509f4880").to_vec(), + hex!("f901f1a045d8ad73dc7ac79275f978e2bc962370db38d9177f72ac08b211197a9fb36981a0a6a828a04cb5a3fabb06350f360d2dd580f48d2b8b0cbe23f781edad99448670a0916a59f33c5f0652fae08b9d997080a9d76ff6b85a8c659d34099aeff7ef813aa070124e8e3929402ac2c38b1ecc44057344f40539585771cb64f4a0b3b0934798a0d6416e77f717a98804ce130f77904a7f389d4530bc4724a3227605d5fc29f1c4a0566268213759b2962394ac5e769bb91cfa4a2b15749dafdf7fb7a6696d6ea31aa03f7edc5b6fc507edced27e4097e3b98172e906884b2caeea231b03d1bf6dd2faa0cda3194a099eff475dfa80e5238a1e7d016ec0b49ca89d72a9e71e738c8d2b56a0e0cab6799aa23b4aaef24b66f618d03c58204f54c4fdb416c3b7e5dfd5683e2ca0b92006fb7e4596a99c1de6c3207321b6b8965ee28b7574bad18a880098ecfd28a085a0a0adfd229d54bb7c32ba7331224ad63d299b0bd3b4883dc897108ad7607ea08b4bddbd96d864c8b16950a268c7f4fa37200fe7305033e44d71f355600eefcea035b8c138ab8c579d91c8f5a2f5af9b8ed1e1e7b847d2ad7d0686a6edfbdd486280a033b4528aec1da956be6e93a5faebe948bd5c56858a17db1bb5daf94f2dc48522a08c5ecf11c47c7b89d88ee096c482f6351fffda0fd1dee14c7749025b34d2963b80").to_vec(), + hex!("f8518080808080808080a0326337efc729cf6e180a7920ae76745f631284ce3fbc5956015bea8ef9a1f27380a09c1130a1c746352c14e050db40ae97211ff41380acf38984aebf469ad3224cca808080808080").to_vec(), + hex!("f59f38b01fd8dc46bd81250474dd1a73ea76f021775d95be249c9a480fb17b88b6949cade252d10c01c0129e73a1f03f458e0109929d").to_vec(), + ]; - // TODO: understand why when passing None to verify_proof it panics - assert!(dbg!(verify_proof::>(&root, &proof, &key_modified, None)) - .is_ok()); + assert_eq!( + dbg!(verify_proof::>(&root, &proof, &key, None)), + Ok(()) + ); } diff --git a/light-clients/icsxx-ethereum/src/verify.rs b/light-clients/icsxx-ethereum/src/verify.rs index 8b1378917..d1cbc4407 100644 --- a/light-clients/icsxx-ethereum/src/verify.rs +++ b/light-clients/icsxx-ethereum/src/verify.rs @@ -1 +1,50 @@ +use crate::{ + error::Error, + proof::ethereum_trie::{verify_proof, EIP1186Layout, KeccakHasher, VerifyError}, +}; +use ethers_core::{ + abi, + types::EIP1186ProofResponse, + utils::{keccak256, rlp}, +}; +use ibc::core::{ + ics23_commitment::commitment::{CommitmentPrefix, CommitmentProofBytes, CommitmentRoot}, + ics24_host::Path, +}; +use primitive_types::H256; +use rlp::DecoderError; +use rs_merkle::Hasher; +pub fn verify_ibc_proof

( + prefix: &CommitmentPrefix, // TODO: use prefix + proof: &CommitmentProofBytes, + root: &CommitmentRoot, + path: P, + value: Option<&[u8]>, +) -> Result +where + P: Into, +{ + use VerifyError::*; + + let eth_proof = serde_cbor::from_slice::(proof.as_bytes()).unwrap(); + let key = keccak256(path.into().into_bytes()); + let value_hash = value.map(keccak256).map(|x| x.as_slice()); + let root = H256::from_slice(root.as_bytes()); + let res = verify_proof::>( + &root, + ð_proof.account_proof.into_iter().map(|x| x.to_vec()).collect::>(), + &key, + value_hash, + ); + + match res { + Ok(_) => Ok(true), + Err(err) => match err { + NonExistingValue(_) | ExistingValue(_) | ValueMismatch(_) | HashMismatch(_) => + Ok(false), + e @ IncompleteProof | e @ DecodeError(_) | e @ HashDecodeError(_) => + return Err(e.into()), + }, + } +} From c9da99d9b3a835fb9287889d77380ce98920f47e Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Fri, 22 Sep 2023 11:13:59 -0300 Subject: [PATCH 36/43] wip --- .gitignore | 2 +- Cargo.lock | 276 +++++++-- config/centauri-local.toml | 4 +- config/ethereum-local.toml | 12 +- hyperspace/ethereum/scripts/generate_abi.sh | 1 + hyperspace/ethereum/src/client.rs | 5 +- hyperspace/ethereum/src/ibc_provider.rs | 60 +- hyperspace/testsuite/tests/ethereum_cosmos.rs | 112 +++- light-clients/icsxx-ethereum/Cargo.toml | 3 +- light-clients/icsxx-ethereum/src/lib.rs | 1 - .../icsxx-ethereum/src/proof/ethereum_trie.rs | 568 +++++++++--------- .../icsxx-ethereum/src/proof/node_codec.rs | 9 +- .../icsxx-ethereum/src/proof/tests.rs | 16 +- light-clients/icsxx-ethereum/src/verify.rs | 39 +- utils/subxt/codegen/src/lib.rs | 2 +- 15 files changed, 703 insertions(+), 407 deletions(-) diff --git a/.gitignore b/.gitignore index d419360ca..5fd71d7c3 100644 --- a/.gitignore +++ b/.gitignore @@ -85,5 +85,5 @@ scripts/eth-bridge/consensus/genesis.ssz scripts/eth-bridge/consensus/beacondata scripts/eth-bridge/consensus/validatordata -hyperspace/ethereum/yui-ibc-solidity +#hyperspace/ethereum/yui-ibc-solidity hyperspace/ethereum/composable-centauri diff --git a/Cargo.lock b/Cargo.lock index 0afd51643..7074b98e2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1443,6 +1443,21 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "clap" +version = "2.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +dependencies = [ + "ansi_term", + "atty", + "bitflags 1.3.2", + "strsim 0.8.0", + "textwrap 0.11.0", + "unicode-width", + "vec_map", +] + [[package]] name = "clap" version = "3.2.23" @@ -1455,9 +1470,9 @@ dependencies = [ "clap_lex 0.2.4", "indexmap 1.9.2", "once_cell", - "strsim", + "strsim 0.10.0", "termcolor", - "textwrap", + "textwrap 0.16.0", ] [[package]] @@ -1479,7 +1494,7 @@ dependencies = [ "anstream", "anstyle", "clap_lex 0.5.1", - "strsim", + "strsim 0.10.0", "terminal_size", "unicase", "unicode-width", @@ -1500,7 +1515,7 @@ version = "3.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro-error", "proc-macro2", "quote", @@ -1513,7 +1528,7 @@ version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro2", "quote", "syn 2.0.28", @@ -1650,6 +1665,17 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +[[package]] +name = "colored" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2674ec482fbc38012cf31e6c42ba0177b431a0cb6f15fe40efa5aab1bda516f6" +dependencies = [ + "is-terminal", + "lazy_static", + "windows-sys 0.48.0", +] + [[package]] name = "comfy-table" version = "6.1.4" @@ -2119,6 +2145,27 @@ dependencies = [ "subtle", ] +[[package]] +name = "csv" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "626ae34994d3d8d668f4269922248239db4ae42d538b14c398b74a52208e8086" +dependencies = [ + "csv-core", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" +dependencies = [ + "memchr", +] + [[package]] name = "ct-logs" version = "0.8.0" @@ -2337,7 +2384,7 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim", + "strsim 0.10.0", "syn 1.0.109", ] @@ -2856,7 +2903,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9720bba047d567ffc8a3cba48bf19126600e249ab7f128e9233e6376976a116" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro2", "quote", "syn 1.0.109", @@ -2965,6 +3012,20 @@ dependencies = [ "uuid 0.8.2", ] +[[package]] +name = "eth_merkle_tree" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4e0a617d300b8c5e6bf8d87bacd3e8d0927bbe0c37ad01c6426f37c73a8f86d" +dependencies = [ + "colored", + "csv", + "hex", + "petgraph", + "rust-crypto", + "structopt", +] + [[package]] name = "ethabi" version = "18.0.0" @@ -3021,7 +3082,7 @@ checksum = "96b4026b97da8281276744741fac7eb385da905f6093c583331fa2953fdd4253" dependencies = [ "ethers-addressbook 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "ethers-contract 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "ethers-core 2.0.9", + "ethers-core 2.0.10", "ethers-etherscan 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "ethers-middleware 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "ethers-providers 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3050,7 +3111,7 @@ version = "2.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edcb6ffefc230d8c42874c51b28dc11dbb8de50b27a8fdf92648439d6baa68dc" dependencies = [ - "ethers-core 2.0.9", + "ethers-core 2.0.10", "once_cell", "serde", "serde_json", @@ -3075,7 +3136,7 @@ checksum = "0d4719a44c3d37ab07c6dea99ab174068d8c35e441b60b6c20ce4e48357273e8" dependencies = [ "ethers-contract-abigen 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "ethers-contract-derive 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "ethers-core 2.0.9", + "ethers-core 2.0.10", "ethers-providers 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "ethers-signers 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "futures-util", @@ -3114,7 +3175,7 @@ checksum = "155ea1b84d169d231317ed86e307af6f2bed6b40dd17e5e94bc84da21cadb21c" dependencies = [ "Inflector", "dunce", - "ethers-core 2.0.9", + "ethers-core 2.0.10", "ethers-etherscan 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "eyre", "hex", @@ -3159,7 +3220,7 @@ checksum = "8567ff196c4a37c1a8c90ec73bda0ad2062e191e4f0a6dc4d943e2ec4830fc88" dependencies = [ "Inflector", "ethers-contract-abigen 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "ethers-core 2.0.9", + "ethers-core 2.0.10", "hex", "proc-macro2", "quote", @@ -3213,9 +3274,9 @@ dependencies = [ [[package]] name = "ethers-core" -version = "2.0.9" +version = "2.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c29523f73c12753165781c6e5dc11c84d3e44c080a15f7c6cfbd70b514cb6f1" +checksum = "c0a17f0708692024db9956b31d7a20163607d2745953f5ae8125ab368ba280ad" dependencies = [ "arrayvec 0.7.2", "bytes", @@ -3247,7 +3308,7 @@ version = "2.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22b3a8269d3df0ed6364bc05b4735b95f4bf830ce3aef87d5e760fb0e93e5b91" dependencies = [ - "ethers-core 2.0.9", + "ethers-core 2.0.10", "reqwest", "semver", "serde", @@ -3280,7 +3341,7 @@ dependencies = [ "async-trait", "auto_impl", "ethers-contract 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "ethers-core 2.0.9", + "ethers-core 2.0.10", "ethers-etherscan 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "ethers-providers 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "ethers-signers 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3335,7 +3396,7 @@ dependencies = [ "base64 0.21.0", "bytes", "enr 0.8.1", - "ethers-core 2.0.9", + "ethers-core 2.0.10", "futures-channel", "futures-core", "futures-timer", @@ -3407,7 +3468,7 @@ dependencies = [ "coins-bip39", "elliptic-curve 0.13.5", "eth-keystore", - "ethers-core 2.0.9", + "ethers-core 2.0.10", "hex", "rand 0.8.5", "sha2 0.10.6", @@ -3486,7 +3547,7 @@ dependencies = [ "const-hex", "dirs", "dunce", - "ethers-core 2.0.9", + "ethers-core 2.0.10", "glob", "home", "md-5 0.10.5", @@ -4033,6 +4094,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" + [[package]] name = "funty" version = "2.0.0" @@ -4184,6 +4251,12 @@ dependencies = [ "byteorder", ] +[[package]] +name = "gcc" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" + [[package]] name = "generic-array" version = "0.12.4" @@ -4573,6 +4646,15 @@ dependencies = [ "http", ] +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "heck" version = "0.4.1" @@ -5459,8 +5541,13 @@ dependencies = [ "anyhow", "derive_more", "env_logger 0.9.3", + "eth_merkle_tree", + "ethers-core 2.0.10", "futures", + "hash-db 0.16.0", + "hash256-std-hasher", "hex", + "hex-literal 0.4.1", "ibc", "ibc-derive", "ibc-proto", @@ -5470,7 +5557,10 @@ dependencies = [ "prost 0.11.6", "prost-build", "prost-types", + "rlp", + "rs_merkle", "serde", + "serde_cbor", "serde_json", "ssz-rs", "sync-committee-primitives", @@ -5479,6 +5569,7 @@ dependencies = [ "tendermint", "tendermint-proto", "tokio", + "trie-db 0.28.0", ] [[package]] @@ -5899,7 +5990,7 @@ version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baa6da1e4199c10d7b1d0a6e5e8bd8e55f351163b6f4b3cbb044672a69bd4c1c" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro-crate", "proc-macro2", "quote", @@ -6382,7 +6473,7 @@ version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d527d5827582abd44a6d80c07ff8b50b4ee238a8979e05998474179e79dc400" dependencies = [ - "heck", + "heck 0.4.1", "quote", "syn 1.0.109", ] @@ -6850,12 +6941,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "micromath" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39617bc909d64b068dcffd0e3e31679195b5576d0c83fadc52690268cc2b2b55" - [[package]] name = "mime" version = "0.3.16" @@ -8631,7 +8716,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3f8ad728fb08fe212df3c05169e940fbb6d9d16a877ddde14644a983ba2012e" dependencies = [ "bytes", - "heck", + "heck 0.4.1", "itertools", "lazy_static", "log", @@ -8797,6 +8882,29 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" +[[package]] +name = "rand" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c" +dependencies = [ + "libc", + "rand 0.4.6", +] + +[[package]] +name = "rand" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +dependencies = [ + "fuchsia-cprng", + "libc", + "rand_core 0.3.1", + "rdrand", + "winapi", +] + [[package]] name = "rand" version = "0.7.3" @@ -8841,6 +8949,21 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +dependencies = [ + "rand_core 0.4.2", +] + +[[package]] +name = "rand_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" + [[package]] name = "rand_core" version = "0.5.1" @@ -8930,6 +9053,15 @@ dependencies = [ "yasna", ] +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +dependencies = [ + "rand_core 0.3.1", +] + [[package]] name = "redox_syscall" version = "0.2.16" @@ -9232,11 +9364,10 @@ dependencies = [ [[package]] name = "rs_merkle" -version = "1.2.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a632a43487c1332be8e183588079f89b6820fab24e04db49521eacd536837372" +checksum = "05225752ca6ede4cb1b73aa37ce3904affd042e98f28246f56f438ebfd47a810" dependencies = [ - "micromath", "sha2 0.10.6", ] @@ -9392,6 +9523,19 @@ dependencies = [ "tokio", ] +[[package]] +name = "rust-crypto" +version = "0.2.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a" +dependencies = [ + "gcc", + "libc", + "rand 0.3.23", + "rustc-serialize", + "time 0.1.45", +] + [[package]] name = "rustc-demangle" version = "0.1.21" @@ -9410,6 +9554,12 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" +[[package]] +name = "rustc-serialize" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" + [[package]] name = "rustc_version" version = "0.4.0" @@ -12024,12 +12174,42 @@ dependencies = [ "precomputed-hash", ] +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + [[package]] name = "strsim" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "structopt" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10" +dependencies = [ + "clap 2.34.0", + "lazy_static", + "structopt-derive", +] + +[[package]] +name = "structopt-derive" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" +dependencies = [ + "heck 0.3.3", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "strum" version = "0.24.1" @@ -12054,7 +12234,7 @@ version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro2", "quote", "rustversion", @@ -12067,7 +12247,7 @@ version = "0.25.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad8d03b598d3d0fff69bf533ee3ef19b8eeb342729596df84bcc7e1f96ec4059" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro2", "quote", "rustversion", @@ -12216,7 +12396,7 @@ source = "git+https://github.com/paritytech/subxt?rev=2a4da618a033bb82f768e4ef67 dependencies = [ "darling", "frame-metadata", - "heck", + "heck 0.4.1", "hex", "jsonrpsee", "parity-scale-codec", @@ -12622,6 +12802,15 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + [[package]] name = "textwrap" version = "0.16.0" @@ -13178,6 +13367,19 @@ dependencies = [ "smallvec 1.10.0", ] +[[package]] +name = "trie-db" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff28e0f815c2fea41ebddf148e008b077d2faddb026c9555b29696114d602642" +dependencies = [ + "hash-db 0.16.0", + "hashbrown 0.13.2", + "log", + "rustc-hex", + "smallvec 1.10.0", +] + [[package]] name = "trie-root" version = "0.17.0" @@ -13516,6 +13718,12 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + [[package]] name = "version_check" version = "0.9.4" diff --git a/config/centauri-local.toml b/config/centauri-local.toml index 67a5fc2e6..87ebc07f8 100644 --- a/config/centauri-local.toml +++ b/config/centauri-local.toml @@ -5,7 +5,7 @@ grpc_url = "http://127.0.0.1:9090/" websocket_url = "ws://127.0.0.1:26657/websocket" chain_id = "centauri-testnet-1" client_id = "07-tendermint-0" -connection_id = "connection-18" +connection_id = "connection-0" account_prefix = "centauri" fee_denom = "stake" fee_amount = "4000" @@ -13,7 +13,7 @@ gas_limit = 9223372036854775806 store_prefix = "ibc" max_tx_size = 200000 wasm_code_id = "4c7504846b7c35e1b7dfc62f9347fcb98fec95aecede9822a745ce14d6973ced" -channel_whitelist = [["channel-8", "transfer"]] +channel_whitelist = [["channel-8", "transfer"], ["channel-0", "transfer"]] mnemonic = "sense state fringe stool behind explain area quit ugly affair develop thumb clinic weasel choice atom gesture spare sea renew penalty second upon peace" skip_optional_client_updates = true max_packets_to_process = 200 diff --git a/config/ethereum-local.toml b/config/ethereum-local.toml index 5981cfa0c..43f9c37ae 100644 --- a/config/ethereum-local.toml +++ b/config/ethereum-local.toml @@ -5,13 +5,13 @@ beacon_rpc_url = "http://localhost:3500/" private_key_path = "hyperspace/ethereum/keys/0x73db010c3275eb7a92e5c38770316248f4c644ee" max_block_weight = 1 name = "ethereum_client" -client_id = "08-wasm-22" +client_id = "08-wasm-0" connection_id = "connection-0" -channel_whitelist = [["channel-0", "transfer"]] +channel_whitelist = [["channel-0", "transfer"], ["channel-0", "transfer"]] commitment_prefix = "6962632f" -diamond_address = "0x4a976e25cde9d022007f7f02889901b382038237" -tendermint_address = "0xa6915519ec2cbc4e7eea7912673c885fc1f156ca" -bank_address = "0x87b47d11cdc84e3c3cb70b34dde1235c0862b68e" -diamond_facets = [["IBCClient", "0x10b57a97dad42b87185f39fc653939c89abda030"], ["IBCConnection", "0x163f4a54af24d13151f231fb74ef5cbc642d05a7"], ["IBCChannelHandshake", "0x5078d1a1240bcbca0f67ba25f07c66b85ab86d37"], ["IBCPacket", "0xc0a2f84324ddf94f4d5af8b507ffefb9016fcdaa"], ["IBCQuerier", "0x98f6789f22e1066dcd128ca99a859acf4821f834"], ["DiamondCutFacet", "0xc1e3b960d3db95ea5a4f2b7c91ba28b2222d5484"], ["DiamondLoupeFacet", "0x4dccf8ac3a04b9d7f294047ebc6481ed9d8fbab6"], ["OwnershipFacet", "0x0fce292ea5fbf749d8ef31412dbc8ac5841ba66d"]] +diamond_address = "0xd0017ae5068faa14eaa547ba1c47fdc7afdf1230" +tendermint_address = "0x56378f9b88f341b1913a2fc6ac2bcbaa1b9a9f9f" +bank_address = "0x4976bb932815783f092dd0e3cca567d5502be46e" +diamond_facets = [["IBCClient", "0xb7198a3674e37433579be45aa9dd09f5ab4b314a"], ["IBCConnection", "0xb26397cfa7e111e844086bdd3da5080f9de65cb7"], ["IBCChannelHandshake", "0xfbf766071d0fdee42b78ab029b97194543b6d7a5"], ["IBCPacket", "0x844d2447e6c00cf6a5fbe9ad5eebebe31e40368e"], ["IBCQuerier", "0x992966599e81b9d4a3ef92172b9fa162d2e50d5b"], ["DiamondCutFacet", "0x3bf46cf159422e1791d20d45683b21f34ecae4be"], ["DiamondLoupeFacet", "0xb16af4cfc553ae0a8f43e812e22dc6caabdf5e63"], ["OwnershipFacet", "0x4f6e145fbaf72be9ea283f5793e70a1c594d5ceb"]] client_type = "07-tendermint" jwt_secret_path = "/Users/vmark/work/eth-pos-devnet/execution/jwtsecret" diff --git a/hyperspace/ethereum/scripts/generate_abi.sh b/hyperspace/ethereum/scripts/generate_abi.sh index 2cf365341..7846d8e24 100644 --- a/hyperspace/ethereum/scripts/generate_abi.sh +++ b/hyperspace/ethereum/scripts/generate_abi.sh @@ -15,6 +15,7 @@ forge inspect ../contracts/core/04-channel/IBCChannelHandshake.sol:IBCChannelHan forge inspect ../contracts/core/25-handler/IBCQuerier.sol:IBCQuerier abi > ../../src/abi/ibc-querier-abi.json forge inspect ../contracts/apps/20-transfer/ICS20TransferBank.sol:ICS20TransferBank abi > ../../src/abi/ics20-transfer-bank-abi.json +forge inspect ../contracts/apps/20-transfer/ICS20Bank.sol:ICS20Bank abi > ../../src/abi/ics20-bank-abi.json forge inspect ../contracts/clients/TendermintLightClientSimple.sol:TendermintLightClientSimple abi > ../../src/abi/tendermint-client-abi.json # remove all "."s inside the abi files to make them compatible with the derive macro diff --git a/hyperspace/ethereum/src/client.rs b/hyperspace/ethereum/src/client.rs index 5658d1f8f..15d26db3b 100644 --- a/hyperspace/ethereum/src/client.rs +++ b/hyperspace/ethereum/src/client.rs @@ -202,7 +202,8 @@ impl EthereumClient { let secret = std::fs::read_to_string(secret_path).map_err(|e| { ClientError::Other(format!("jwtsecret not found. Search for 'execution/jwtsecret' in the code and replace it with your local path. {e}")) })?; - let secret = JwtKey::from_slice(&hex::decode(&secret[2..]).unwrap()).expect("oops"); + let secret = + JwtKey::from_slice(&hex::decode(&secret[2..].trim()).unwrap()).expect("oops"); let jwt_auth = JwtAuth::new(secret, None, None); let token = jwt_auth.generate_token().unwrap(); @@ -428,7 +429,7 @@ impl EthereumClient { .get_proof( NameOrAddress::Address(address), vec![H256::from_str(&index).unwrap()], - block_height.map(|i| BlockId::from(i)), + block_height.map(BlockId::from), ) .await .unwrap()) diff --git a/hyperspace/ethereum/src/ibc_provider.rs b/hyperspace/ethereum/src/ibc_provider.rs index ba043a8b0..7dd462a15 100644 --- a/hyperspace/ethereum/src/ibc_provider.rs +++ b/hyperspace/ethereum/src/ibc_provider.rs @@ -1,4 +1,5 @@ use ethers::{ + abi, abi::{ encode, encode_packed, ethabi, Abi, AbiEncode, Detokenize, InvalidOutputType, ParamType, RawLog, Token, Tokenizable, @@ -110,37 +111,40 @@ use tracing::log; abigen!( IbcClientAbi, - "hyperspace/ethereum/src/abi/ibc-client-abi.json"; + "/Users/vmark/work/centauri-private/hyperspace/ethereum/src/abi/ibc-client-abi.json"; IbcConnectionAbi, - "hyperspace/ethereum/src/abi/ibc-connection-abi.json"; + "/Users/vmark/work/centauri-private/hyperspace/ethereum/src/abi/ibc-connection-abi.json"; IbcChannelAbi, - "hyperspace/ethereum/src/abi/ibc-channel-abi.json"; + "/Users/vmark/work/centauri-private/hyperspace/ethereum/src/abi/ibc-channel-abi.json"; IbcPacketAbi, - "hyperspace/ethereum/src/abi/ibc-packet-abi.json"; + "/Users/vmark/work/centauri-private/hyperspace/ethereum/src/abi/ibc-packet-abi.json"; IbcQuerierAbi, - "hyperspace/ethereum/src/abi/ibc-querier-abi.json"; + "/Users/vmark/work/centauri-private/hyperspace/ethereum/src/abi/ibc-querier-abi.json"; Ics20TransferBankAbi, - "hyperspace/ethereum/src/abi/ics20-transfer-bank-abi.json"; + "/Users/vmark/work/centauri-private/hyperspace/ethereum/src/abi/ics20-transfer-bank-abi.json"; + + Ics20BankAbi, + "/Users/vmark/work/centauri-private/hyperspace/ethereum/src/abi/ics20-bank-abi.json"; TendermintClientAbi, - "hyperspace/ethereum/src/abi/tendermint-client-abi.json"; + "/Users/vmark/work/centauri-private/hyperspace/ethereum/src/abi/tendermint-client-abi.json"; DiamondAbi, - "hyperspace/ethereum/src/abi/diamond-abi.json"; + "/Users/vmark/work/centauri-private/hyperspace/ethereum/src/abi/diamond-abi.json"; DiamondCutFacetAbi, - "hyperspace/ethereum/src/abi/diamond-cut-facet-abi.json"; + "/Users/vmark/work/centauri-private/hyperspace/ethereum/src/abi/diamond-cut-facet-abi.json"; DiamondLoupeFacetAbi, - "hyperspace/ethereum/src/abi/diamond-loupe-facet-abi.json"; + "/Users/vmark/work/centauri-private/hyperspace/ethereum/src/abi/diamond-loupe-facet-abi.json"; OwnershipFacetAbi, - "hyperspace/ethereum/src/abi/ownership-facet-abi.json"; + "/Users/vmark/work/centauri-private/hyperspace/ethereum/src/abi/ownership-facet-abi.json"; ); impl From for Height { @@ -829,23 +833,23 @@ impl IbcProvider for EthereumClient { } async fn query_proof(&self, at: Height, keys: Vec>) -> Result, Self::Error> { - // let key = String::from_utf8(keys[0].clone()).unwrap(); - // - // let proof_result = self - // .eth_query_proof(&key, Some(at.revision_height), COMMITMENTS_STORAGE_INDEX) - // .await?; - // - // let bytes = proof_result - // .storage_proof - // .first() - // .map(|p| p.proof.first()) - // .flatten() - // .map(|b| b.to_vec()) - // .unwrap_or_default(); - - // Ok(bytes) - // todo!("query-proof: redo") - Ok(vec![0]) + assert_eq!(keys.len(), 1); + let key = String::from_utf8(keys[0].clone()).unwrap(); + + let proof_result = self + .eth_query_proof(&key, Some(at.revision_height), COMMITMENTS_STORAGE_INDEX) + .await?; + + let bytes = proof_result + .storage_proof + .first() + .map(|p| { + let token = p.proof.clone().into_iter().map(|p| Token::Bytes(p.to_vec())).collect(); + encode(&[token]) + }) + .ok_or_else(|| ClientError::Other("storage proof not found".to_string()))?; + + Ok(bytes) } async fn query_packet_commitment( diff --git a/hyperspace/testsuite/tests/ethereum_cosmos.rs b/hyperspace/testsuite/tests/ethereum_cosmos.rs index a199fc059..61c64037f 100644 --- a/hyperspace/testsuite/tests/ethereum_cosmos.rs +++ b/hyperspace/testsuite/tests/ethereum_cosmos.rs @@ -15,8 +15,10 @@ use crate::utils::ETH_NODE_PORT_WS; use core::time::Duration; use ethers::{ - abi::Token, - prelude::{ContractFactory, ContractInstance}, + abi::{Abi, Token}, + prelude::{spoof::Account, ContractFactory, ContractInstance}, + providers::Middleware, + types::Address, utils::AnvilInstance, }; use ethers_solc::{Artifact, ProjectCompileOutput, ProjectPathsConfig}; @@ -24,11 +26,13 @@ use futures::{StreamExt, TryFutureExt, TryStreamExt}; use hyperspace_core::{ chain::{AnyAssetId, AnyChain, AnyConfig}, logging, - substrate::DefaultConfig, + // substrate::DefaultConfig, }; use hyperspace_cosmos::client::{CosmosClient, CosmosClientConfig}; use hyperspace_ethereum::{ + client::EthereumClient, config::EthereumClientConfig, + ibc_provider::Ics20BankAbi, mock::{ utils, utils::{hyperspace_ethereum_client_fixture, ETH_NODE_PORT}, @@ -45,8 +49,8 @@ use hyperspace_testsuite::{ setup_connection_and_channel, }; use ibc::core::ics24_host::identifier::{ClientId, PortId}; -use sp_core::hashing::sha2_256; -use std::{future::Future, path::PathBuf, str::FromStr, sync::Arc}; +use sp_core::{hashing::sha2_256, U256}; +use std::{fmt::Debug, future::Future, path::PathBuf, str::FromStr, sync::Arc}; use subxt::utils::H160; #[derive(Debug, Clone)] @@ -228,7 +232,7 @@ async fn setup_clients() -> (AnyChain, AnyChain) { }, }; - let chain_b = CosmosClient::::new(config_b.clone()).await.unwrap(); + let chain_b = CosmosClient::<()>::new(config_b.clone()).await.unwrap(); let wasm_data = tokio::fs::read(&args.wasm_path).await.expect("Failed to read wasm file"); let code_id = match chain_b.upload_wasm(wasm_data.clone()).await { @@ -244,6 +248,9 @@ async fn setup_clients() -> (AnyChain, AnyChain) { let code_id_str = hex::encode(code_id); config_b.wasm_code_id = Some(code_id_str); + println!("{}", toml::to_string_pretty(&config_a).unwrap()); + println!("\n{}", toml::to_string_pretty(&config_b).unwrap()); + let mut chain_a_wrapped = AnyConfig::Ethereum(config_a).into_client().await.unwrap(); let mut chain_b_wrapped = AnyConfig::Cosmos(config_b).into_client().await.unwrap(); @@ -259,7 +266,7 @@ async fn setup_clients() -> (AnyChain, AnyChain) { let (client_b, client_a) = create_clients(&mut chain_b_wrapped, &mut chain_a_wrapped).await.unwrap(); // let (client_a, client_b): (ClientId, ClientId) = - // ("08-wasm-136".parse().unwrap(), "07-tendermint-0".parse().unwrap()); + // ("08-wasm-150".parse().unwrap(), "07-tendermint-0".parse().unwrap()); log::info!(target: "hyperspace", "Client A: {client_a:?} B: {client_b:?}"); chain_a_wrapped.set_client_id(client_a); @@ -267,11 +274,10 @@ async fn setup_clients() -> (AnyChain, AnyChain) { (chain_a_wrapped, chain_b_wrapped) } -#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +#[tokio::test(flavor = "multi_thread", worker_threads = 10)] #[ignore] async fn ethereum_to_cosmos_ibc_messaging_full_integration_test() { logging::setup_logging(); - let asset_str = "pica".to_string(); let asset_id_a = AnyAssetId::Ethereum(asset_str.clone()); let (mut chain_a, mut chain_b) = setup_clients().await; @@ -280,10 +286,9 @@ async fn ethereum_to_cosmos_ibc_messaging_full_integration_test() { handle.abort(); // let connection_id_a = "connection-0".parse().unwrap(); - // let connection_id_b = "connection-35".parse().unwrap(); + // let connection_id_b = "connection-47".parse().unwrap(); // let channel_a = "channel-0".parse().unwrap(); - // let channel_b = "channel-10".parse().unwrap(); - + // let channel_b = "channel-24".parse().unwrap(); log::info!(target: "hyperspace", "Conn A: {connection_id_a:?} B: {connection_id_b:?}"); log::info!(target: "hyperspace", "Chann A: {channel_a:?} B: {channel_b:?}"); @@ -317,6 +322,44 @@ async fn ethereum_to_cosmos_ibc_messaging_full_integration_test() { ) .await; + // loop { + // let client_a_clone = chain_a.clone(); + // let client_b_clone = chain_b.clone(); + // let handle = tokio::task::spawn(async move { + // hyperspace_core::relay(client_a_clone, client_b_clone, None, None, None) + // .await + // .map_err(|e| { + // log::error!(target: "hyperspace", "Relayer loop failed: {:?}", e); + // e + // }) + // .unwrap() + // }); + // tokio::task::spawn(async move { + // let x = handle + // .map_err(|e| { + // log::error!(target: "hyperspace", "Relayer loop failed: {:?}", e); + // e + // }) + // .await; + // }) + // .await + // .map_err(|e| { + // log::error!(target: "hyperspace", "Relayer loop failed: {:?}", e); + // e + // }) + // .unwrap(); + // + // let balance = chain_a + // .query_ibc_balance(asset_id_a) + // .await + // .expect("Can't query ibc balance") + // .pop() + // .expect("No Ibc balances"); + // let amount = balance.amount.as_u256().as_u128(); + // + // log::info!("my balance = {amount}"); + // } + // // timeouts + connection delay // ibc_messaging_packet_height_timeout_with_connection_delay( // &mut chain_a, @@ -348,7 +391,7 @@ async fn ethereum_to_cosmos_ibc_messaging_full_integration_test() { // TODO: tendermint misbehaviour? // ibc_messaging_submit_misbehaviour(&mut chain_a, &mut chain_b).await; } - +/* #[tokio::test] #[ignore] async fn cosmos_to_ethereum_ibc_messaging_full_integration_test() { @@ -409,3 +452,46 @@ async fn cosmos_to_ethereum_ibc_messaging_full_integration_test() { ibc_messaging_submit_misbehaviour(&mut chain_a, &mut chain_b).await; } + */ + +#[tokio::test] +async fn send_tokens() { + let config = toml::from_str::( + &std::fs::read_to_string("../../config/ethereum-local.toml").unwrap(), + ) + .unwrap(); + let mut client = EthereumClient::new(config).await.unwrap(); + let abi = Ics20BankAbi::new( + Address::from_str("0x0486ee42d89d569c4d8143e47a82c4b14545ae43").unwrap(), + client.client(), + ); + let from = Address::from_str("0x73db010c3275eb7a92e5c38770316248f4c644ee").unwrap(); + let to = Address::from_str("0x0486ee42d89d569c4d8143e47a82c4b14545ae43").unwrap(); + + async fn get_balance(abi: &Ics20BankAbi, acc: H160) -> U256 + where + M: Middleware + Debug + Send + Sync, + { + abi.method("balanceOf", (acc, "pica".to_string())) + .unwrap() + .call() + .await + .unwrap() + }; + dbg!(get_balance(&abi, from).await); + dbg!(get_balance(&abi, to).await); + + let tx = abi + .method::<_, ()>("transferFrom", (from, to, "pica".to_string(), U256::from(10000000u32))) + .unwrap() + .send() + .await + .unwrap() + .await + .unwrap() + .unwrap(); + assert_eq!(tx.status, Some(1u32.into())); + + dbg!(get_balance(&abi, from).await); + dbg!(get_balance(&abi, to).await); +} diff --git a/light-clients/icsxx-ethereum/Cargo.toml b/light-clients/icsxx-ethereum/Cargo.toml index ac4fe9324..896de0cd6 100644 --- a/light-clients/icsxx-ethereum/Cargo.toml +++ b/light-clients/icsxx-ethereum/Cargo.toml @@ -29,7 +29,7 @@ serde = { version = "1.0.144", default-features = false, features = ["derive"] } tendermint = { git = "https://github.com/informalsystems/tendermint-rs", rev = "e81f7bf23d63ffbcd242381d1ce5e35da3515ff1", default-features = false } tendermint-proto = { git = "https://github.com/informalsystems/tendermint-rs", rev = "e81f7bf23d63ffbcd242381d1ce5e35da3515ff1", default-features = false } -serde_cbor = "0.11.2" +serde_cbor = { version = "0.11.2", default-features = false } ethers-core = { version = "2.0.10", default-features = false } eth_merkle_tree = { version = "0.1.1", default-features = false } rs_merkle = { version = "1.4.1", default-features = false } @@ -70,4 +70,5 @@ std = [ "sync-committee-primitives/std", "ssz-rs/std", "tendermint/std", + "trie-db/std", ] diff --git a/light-clients/icsxx-ethereum/src/lib.rs b/light-clients/icsxx-ethereum/src/lib.rs index 9757371d3..f932dae40 100644 --- a/light-clients/icsxx-ethereum/src/lib.rs +++ b/light-clients/icsxx-ethereum/src/lib.rs @@ -19,7 +19,6 @@ //! ICS-10: Grandpa IBC light client protocol implementation extern crate alloc; -extern crate core; pub mod client_def; pub mod client_message; diff --git a/light-clients/icsxx-ethereum/src/proof/ethereum_trie.rs b/light-clients/icsxx-ethereum/src/proof/ethereum_trie.rs index 04f6aea35..d34a306f0 100644 --- a/light-clients/icsxx-ethereum/src/proof/ethereum_trie.rs +++ b/light-clients/icsxx-ethereum/src/proof/ethereum_trie.rs @@ -12,289 +12,291 @@ use trie_db::{ CError, NibbleSlice, NodeCodec, TrieHash, TrieLayout, }; -// /// Errors that may occur during proof verification. Most of the errors types simply indicate -// that /// the proof is invalid with respect to the statement being verified, and the exact error -// type can /// be used for debugging. -// #[derive(PartialEq, Eq, Debug)] -// pub enum VerifyError<'a, HO, CE> { -// /// The proof does not contain any value for the given key -// /// the error carries the nibbles left after traversing the trie -// NonExistingValue(NibbleSlice<'a>), -// /// The proof contains a value for the given key -// /// while we were expecting to find a non-existence proof -// ExistingValue(Vec), -// /// The proof indicates that the trie contains a different value. -// /// the error carries the value contained in the trie -// ValueMismatch(Vec), -// /// The proof is missing trie nodes required to verify. -// IncompleteProof, -// /// The node hash computed from the proof is not matching. -// HashMismatch(HO), -// /// One of the proof nodes could not be decoded. -// DecodeError(CE), -// /// Error in converting a plain hash into a HO -// HashDecodeError(&'a [u8]), -// } -// -// #[cfg(feature = "std")] -// impl<'a, HO: std::fmt::Debug, CE: std::error::Error> std::fmt::Display for VerifyError<'a, HO, -// CE> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { -// match self { -// VerifyError::NonExistingValue(key) => { -// write!(f, "Key does not exist in trie: reaming key") -// }, -// VerifyError::ExistingValue(value) => { -// write!(f, "trie contains a value for given key value={:?}", value) -// }, -// VerifyError::ValueMismatch(key) => { -// write!(f, "Expected value was not found in the trie: key={:?}", key) -// }, -// VerifyError::IncompleteProof => write!(f, "Proof is incomplete -- expected more nodes"), -// VerifyError::HashMismatch(hash) => write!(f, "hash mismatch found: hash={:?}", hash), -// VerifyError::DecodeError(err) => write!(f, "Unable to decode proof node: {}", err), -// VerifyError::HashDecodeError(plain_hash) => { -// write!(f, "Unable to decode hash value plain_hash: {:?}", plain_hash) -// }, -// } -// } -// } -// -// #[cfg(feature = "std")] -// impl<'a, HO: std::fmt::Debug, CE: std::error::Error + 'static> std::error::Error -// for VerifyError<'a, HO, CE> -// { -// fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { -// match self { -// VerifyError::DecodeError(err) => Some(err), -// _ => None, -// } -// } -// } -// -// /// Verify a compact proof for key-value pairs in a trie given a root hash. -// pub fn verify_proof<'a, L>( -// root: &::Out, -// proof: &'a [Vec], -// raw_key: &'a [u8], -// expected_value: Option<&[u8]>, -// ) -> Result<(), VerifyError<'a, TrieHash, CError>> -// where -// L: TrieLayout, -// ::Hash: hash_db::Hasher, -// { -// if proof.is_empty() { -// return Err(VerifyError::IncompleteProof) -// } -// let key = NibbleSlice::new(raw_key); -// process_node::(Some(root), &proof[0], key, expected_value, &proof[1..]) -// } -// -// fn process_node<'a, L>( -// expected_node_hash: Option<&::Out>, -// encoded_node: &'a [u8], -// key: NibbleSlice<'a>, -// expected_value: Option<&[u8]>, -// proof: &'a [Vec], -// ) -> Result<(), VerifyError<'a, TrieHash, CError>> -// where -// L: TrieLayout, -// ::Hash: hash_db::Hasher, -// { -// if let Some(value) = expected_value { -// if encoded_node == value { -// return Ok(()) -// } -// } -// if let Some(expected) = expected_node_hash { -// let calculated_node_hash = ::hash(encoded_node); -// if calculated_node_hash != *expected { -// return Err(VerifyError::HashMismatch(calculated_node_hash)) -// } -// } -// let node = ::decode(encoded_node).map_err(VerifyError::DecodeError)?; -// match node { -// Node::Empty => process_empty::(key, expected_value, proof), -// Node::Leaf(nib, data) => process_leaf::(nib, data, key, expected_value, proof), -// Node::Extension(nib, handle) => -// process_extension::(&nib, handle, key, expected_value, proof), -// Node::Branch(children, maybe_data) => -// process_branch::(children, maybe_data, key, expected_value, proof), -// Node::NibbledBranch(nib, children, maybe_data) => -// process_nibbledbranch::(nib, children, maybe_data, key, expected_value, proof), -// } -// } -// -// fn process_empty<'a, L>( -// key: NibbleSlice<'a>, -// expected_value: Option<&[u8]>, -// _: &[Vec], -// ) -> Result<(), VerifyError<'a, TrieHash, CError>> -// where -// L: TrieLayout, -// { -// if expected_value.is_none() { -// Ok(()) -// } else { -// Err(VerifyError::NonExistingValue(key)) -// } -// } -// -// fn process_leaf<'a, L>( -// nib: NibbleSlice, -// data: Value<'a>, -// key: NibbleSlice<'a>, -// expected_value: Option<&[u8]>, -// proof: &'a [Vec], -// ) -> Result<(), VerifyError<'a, TrieHash, CError>> -// where -// L: TrieLayout, -// { -// if key != nib && expected_value.is_none() { -// return Ok(()) -// } else if key != nib { -// return Err(VerifyError::NonExistingValue(key)) -// } -// match_value::(Some(data), key, expected_value, proof) -// } -// fn process_extension<'a, L>( -// nib: &NibbleSlice, -// handle: NodeHandle<'a>, -// mut key: NibbleSlice<'a>, -// expected_value: Option<&[u8]>, -// proof: &'a [Vec], -// ) -> Result<(), VerifyError<'a, TrieHash, CError>> -// where -// L: TrieLayout, -// { -// if !key.starts_with(nib) && expected_value.is_none() { -// return Ok(()) -// } else if !key.starts_with(nib) { -// return Err(VerifyError::NonExistingValue(key)) -// } -// key.advance(nib.len()); -// -// match handle { -// NodeHandle::Inline(encoded_node) => -// process_node::(None, encoded_node, key, expected_value, proof), -// NodeHandle::Hash(plain_hash) => { -// let new_root = decode_hash::(plain_hash) -// .ok_or_else(|| VerifyError::HashDecodeError(plain_hash))?; -// process_node::(Some(&new_root), &proof[0], key, expected_value, &proof[1..]) -// }, -// } -// } -// -// fn process_nibbledbranch<'a, L>( -// nib: NibbleSlice, -// children: [Option>; 16], -// maybe_data: Option>, -// mut key: NibbleSlice<'a>, -// expected_value: Option<&[u8]>, -// proof: &'a [Vec], -// ) -> Result<(), VerifyError<'a, TrieHash, CError>> -// where -// L: TrieLayout, -// { -// if !key.starts_with(&nib) && expected_value.is_none() { -// return Ok(()) -// } else if !key.starts_with(&nib) && expected_value.is_some() { -// return Err(VerifyError::NonExistingValue(key)) -// } -// key.advance(nib.len()); -// -// if key.is_empty() { -// match_value::(maybe_data, key, expected_value, proof) -// } else { -// match_children::(children, key, expected_value, proof) -// } -// } -// -// fn process_branch<'a, L>( -// children: [Option>; 16], -// maybe_data: Option>, -// key: NibbleSlice<'a>, -// expected_value: Option<&[u8]>, -// proof: &'a [Vec], -// ) -> Result<(), VerifyError<'a, TrieHash, CError>> -// where -// L: TrieLayout, -// { -// if key.is_empty() { -// match_value::(maybe_data, key, expected_value, proof) -// } else { -// match_children::(children, key, expected_value, proof) -// } -// } -// fn match_children<'a, L>( -// children: [Option>; 16], -// mut key: NibbleSlice<'a>, -// expected_value: Option<&[u8]>, -// proof: &'a [Vec], -// ) -> Result<(), VerifyError<'a, TrieHash, CError>> -// where -// L: TrieLayout, -// { -// match children.get(key.at(0) as usize) { -// Some(Some(NodeHandle::Hash(hash))) => -// if proof.is_empty() { -// Err(VerifyError::IncompleteProof) -// } else { -// key.advance(1); -// let new_root = decode_hash::(hash) -// .ok_or_else(|| VerifyError::HashDecodeError(hash))?; -// process_node::(Some(&new_root), &proof[0], key, expected_value, &proof[1..]) -// }, -// Some(Some(NodeHandle::Inline(encoded_node))) => { -// key.advance(1); -// process_node::(None, encoded_node, key, expected_value, proof) -// }, -// Some(None) => -// if expected_value.is_none() { -// Ok(()) -// } else { -// Err(VerifyError::NonExistingValue(key)) -// }, -// None => panic!("key index is out of range in children array"), -// } -// } -// -// fn match_value<'a, L>( -// maybe_data: Option>, -// key: NibbleSlice<'a>, -// expected_value: Option<&[u8]>, -// proof: &'a [Vec], -// ) -> Result<(), VerifyError<'a, TrieHash, CError>> -// where -// L: TrieLayout, -// { -// match (maybe_data, proof.first(), expected_value) { -// (None, _, None) => Ok(()), -// (None, _, Some(_)) => Err(VerifyError::NonExistingValue(key)), -// (Some(Value::Inline(inline_data)), _, Some(value)) => -// if inline_data == value { -// Ok(()) -// } else { -// Err(VerifyError::ValueMismatch(inline_data.to_vec())) -// }, -// (Some(Value::Inline(inline_data)), _, None) => -// Err(VerifyError::ExistingValue(inline_data.to_vec())), -// (Some(Value::Node(plain_hash)), Some(next_proof_item), Some(value)) => { -// let value_hash = L::Hash::hash(value); -// let node_hash = decode_hash::(plain_hash) -// .ok_or_else(|| VerifyError::HashDecodeError(plain_hash))?; -// if node_hash != value_hash { -// Err(VerifyError::HashMismatch(node_hash)) -// } else if next_proof_item != value { -// Err(VerifyError::ValueMismatch(next_proof_item.to_vec())) -// } else { -// Ok(()) -// } -// }, -// (Some(Value::Node(_)), None, _) => Err(VerifyError::IncompleteProof), -// (Some(Value::Node(_)), Some(proof_item), None) => -// Err(VerifyError::ExistingValue(proof_item.to_vec())), -// } -// } +/// Errors that may occur during proof verification. Most of the errors types simply indicate +/// that the proof is invalid with respect to the statement being verified, and the exact error +/// type can be used for debugging. +#[derive(PartialEq, Eq, Debug)] +pub enum VerifyError<'a, HO, CE> { + /// The proof does not contain any value for the given key + /// the error carries the nibbles left after traversing the trie + NonExistingValue(NibbleSlice<'a>), + /// The proof contains a value for the given key + /// while we were expecting to find a non-existence proof + ExistingValue(Vec), + /// The proof indicates that the trie contains a different value. + /// the error carries the value contained in the trie + ValueMismatch(Vec), + /// The proof is missing trie nodes required to verify. + IncompleteProof, + /// The node hash computed from the proof is not matching. + HashMismatch(HO), + /// One of the proof nodes could not be decoded. + DecodeError(CE), + /// Error in converting a plain hash into a HO + HashDecodeError(&'a [u8]), +} + +#[cfg(feature = "std")] +impl<'a, HO: std::fmt::Debug, CE: std::error::Error> std::fmt::Display for VerifyError<'a, HO, CE> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { + match self { + VerifyError::NonExistingValue(key) => { + write!(f, "Key does not exist in trie: reaming key") + }, + VerifyError::ExistingValue(value) => { + write!(f, "trie contains a value for given key value={:?}", value) + }, + VerifyError::ValueMismatch(key) => { + write!(f, "Expected value was not found in the trie: key={:?}", key) + }, + VerifyError::IncompleteProof => write!(f, "Proof is incomplete -- expected more nodes"), + VerifyError::HashMismatch(hash) => write!(f, "hash mismatch found: hash={:?}", hash), + VerifyError::DecodeError(err) => write!(f, "Unable to decode proof node: {}", err), + VerifyError::HashDecodeError(plain_hash) => { + write!(f, "Unable to decode hash value plain_hash: {:?}", plain_hash) + }, + } + } +} + +#[cfg(feature = "std")] +impl<'a, HO: std::fmt::Debug, CE: std::error::Error + 'static> std::error::Error + for VerifyError<'a, HO, CE> +{ + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + VerifyError::DecodeError(err) => Some(err), + _ => None, + } + } +} + +/// Verify a compact proof for key-value pairs in a trie given a root hash. +pub fn verify_proof<'a, L>( + root: &::Out, + proof: &'a [Vec], + raw_key: &'a [u8], + expected_value: Option<&[u8]>, +) -> Result<(), VerifyError<'a, TrieHash, CError>> +where + L: TrieLayout, + ::Hash: hash_db::Hasher, +{ + if proof.is_empty() { + return Err(VerifyError::IncompleteProof) + } + let key = NibbleSlice::new(raw_key); + process_node::(Some(root), &proof[0], key, expected_value, &proof[1..]) +} + +fn process_node<'a, L>( + expected_node_hash: Option<&::Out>, + encoded_node: &'a [u8], + key: NibbleSlice<'a>, + expected_value: Option<&[u8]>, + proof: &'a [Vec], +) -> Result<(), VerifyError<'a, TrieHash, CError>> +where + L: TrieLayout, + ::Hash: hash_db::Hasher, +{ + if let Some(value) = expected_value { + if encoded_node == value { + return Ok(()) + } + } + if let Some(expected) = expected_node_hash { + let calculated_node_hash = ::hash(encoded_node); + if calculated_node_hash != *expected { + return Err(VerifyError::HashMismatch(calculated_node_hash)) + } + } + let node = ::decode(encoded_node).map_err(VerifyError::DecodeError)?; + match node { + Node::Empty => process_empty::(key, expected_value, proof), + Node::Leaf(nib, data) => process_leaf::(nib, data, key, expected_value, proof), + Node::Extension(nib, handle) => + process_extension::(&nib, handle, key, expected_value, proof), + Node::Branch(children, maybe_data) => + process_branch::(children, maybe_data, key, expected_value, proof), + Node::NibbledBranch(nib, children, maybe_data) => + process_nibbledbranch::(nib, children, maybe_data, key, expected_value, proof), + } +} + +fn process_empty<'a, L>( + key: NibbleSlice<'a>, + expected_value: Option<&[u8]>, + _: &[Vec], +) -> Result<(), VerifyError<'a, TrieHash, CError>> +where + L: TrieLayout, +{ + if expected_value.is_none() { + Ok(()) + } else { + Err(VerifyError::NonExistingValue(key)) + } +} + +fn process_leaf<'a, L>( + nib: NibbleSlice, + data: Value<'a>, + key: NibbleSlice<'a>, + expected_value: Option<&[u8]>, + proof: &'a [Vec], +) -> Result<(), VerifyError<'a, TrieHash, CError>> +where + L: TrieLayout, +{ + if key != nib && expected_value.is_none() { + return Ok(()) + } else if key != nib { + return Err(VerifyError::NonExistingValue(key)) + } + match_value::(Some(data), key, expected_value, proof) +} + +fn process_extension<'a, L>( + nib: &NibbleSlice, + handle: NodeHandle<'a>, + mut key: NibbleSlice<'a>, + expected_value: Option<&[u8]>, + proof: &'a [Vec], +) -> Result<(), VerifyError<'a, TrieHash, CError>> +where + L: TrieLayout, +{ + if !key.starts_with(nib) && expected_value.is_none() { + return Ok(()) + } else if !key.starts_with(nib) { + return Err(VerifyError::NonExistingValue(key)) + } + key.advance(nib.len()); + + match handle { + NodeHandle::Inline(encoded_node) => + process_node::(None, encoded_node, key, expected_value, proof), + NodeHandle::Hash(plain_hash) => { + let new_root = decode_hash::(plain_hash) + .ok_or_else(|| VerifyError::HashDecodeError(plain_hash))?; + process_node::(Some(&new_root), &proof[0], key, expected_value, &proof[1..]) + }, + } +} + +fn process_nibbledbranch<'a, L>( + nib: NibbleSlice, + children: [Option>; 16], + maybe_data: Option>, + mut key: NibbleSlice<'a>, + expected_value: Option<&[u8]>, + proof: &'a [Vec], +) -> Result<(), VerifyError<'a, TrieHash, CError>> +where + L: TrieLayout, +{ + if !key.starts_with(&nib) && expected_value.is_none() { + return Ok(()) + } else if !key.starts_with(&nib) && expected_value.is_some() { + return Err(VerifyError::NonExistingValue(key)) + } + key.advance(nib.len()); + + if key.is_empty() { + match_value::(maybe_data, key, expected_value, proof) + } else { + match_children::(children, key, expected_value, proof) + } +} + +fn process_branch<'a, L>( + children: [Option>; 16], + maybe_data: Option>, + key: NibbleSlice<'a>, + expected_value: Option<&[u8]>, + proof: &'a [Vec], +) -> Result<(), VerifyError<'a, TrieHash, CError>> +where + L: TrieLayout, +{ + if key.is_empty() { + match_value::(maybe_data, key, expected_value, proof) + } else { + match_children::(children, key, expected_value, proof) + } +} + +fn match_children<'a, L>( + children: [Option>; 16], + mut key: NibbleSlice<'a>, + expected_value: Option<&[u8]>, + proof: &'a [Vec], +) -> Result<(), VerifyError<'a, TrieHash, CError>> +where + L: TrieLayout, +{ + match children.get(key.at(0) as usize) { + Some(Some(NodeHandle::Hash(hash))) => + if proof.is_empty() { + Err(VerifyError::IncompleteProof) + } else { + key.advance(1); + let new_root = decode_hash::(hash) + .ok_or_else(|| VerifyError::HashDecodeError(hash))?; + process_node::(Some(&new_root), &proof[0], key, expected_value, &proof[1..]) + }, + Some(Some(NodeHandle::Inline(encoded_node))) => { + key.advance(1); + process_node::(None, encoded_node, key, expected_value, proof) + }, + Some(None) => + if expected_value.is_none() { + Ok(()) + } else { + Err(VerifyError::NonExistingValue(key)) + }, + None => panic!("key index is out of range in children array"), + } +} + +fn match_value<'a, L>( + maybe_data: Option>, + key: NibbleSlice<'a>, + expected_value: Option<&[u8]>, + proof: &'a [Vec], +) -> Result<(), VerifyError<'a, TrieHash, CError>> +where + L: TrieLayout, +{ + match (maybe_data, proof.first(), expected_value) { + (None, _, None) => Ok(()), + (None, _, Some(_)) => Err(VerifyError::NonExistingValue(key)), + (Some(Value::Inline(inline_data)), _, Some(value)) => + if inline_data == value { + Ok(()) + } else { + Err(VerifyError::ValueMismatch(inline_data.to_vec())) + }, + (Some(Value::Inline(inline_data)), _, None) => + Err(VerifyError::ExistingValue(inline_data.to_vec())), + (Some(Value::Node(plain_hash)), Some(next_proof_item), Some(value)) => { + let value_hash = L::Hash::hash(value); + let node_hash = decode_hash::(plain_hash) + .ok_or_else(|| VerifyError::HashDecodeError(plain_hash))?; + if node_hash != value_hash { + Err(VerifyError::HashMismatch(node_hash)) + } else if next_proof_item != value { + Err(VerifyError::ValueMismatch(next_proof_item.to_vec())) + } else { + Ok(()) + } + }, + (Some(Value::Node(_)), None, _) => Err(VerifyError::IncompleteProof), + (Some(Value::Node(_)), Some(proof_item), None) => + Err(VerifyError::ExistingValue(proof_item.to_vec())), + } +} /// Trie layout for EIP-1186 state proof nodes. #[derive(Default, Clone)] diff --git a/light-clients/icsxx-ethereum/src/proof/node_codec.rs b/light-clients/icsxx-ethereum/src/proof/node_codec.rs index edbd5d2bf..180fb655d 100644 --- a/light-clients/icsxx-ethereum/src/proof/node_codec.rs +++ b/light-clients/icsxx-ethereum/src/proof/node_codec.rs @@ -17,16 +17,19 @@ //! [`NodeCodec`] implementation for [`TrieDb`] use alloc::vec::Vec; -use core::{borrow::Borrow, marker::PhantomData}; +use core::{borrow::Borrow, marker::PhantomData, str::FromStr}; +use ethers_core::{ + abi::Address, + utils::{get_contract_address, keccak256}, +}; use hash_db::Hasher; -use primitive_types::H256; +use primitive_types::{H160, H256}; use rlp::{DecoderError, Prototype, Rlp, RlpStream}; use trie_db::{ node::{NibbleSlicePlan, NodeHandlePlan, NodePlan, Value, ValuePlan}, ChildReference, NodeCodec, }; -/// Concrete implementation of a `NodeCodec` with Rlp encoding, generic over the `Hasher` #[derive(Default, Clone)] pub struct RlpNodeCodec { mark: PhantomData, diff --git a/light-clients/icsxx-ethereum/src/proof/tests.rs b/light-clients/icsxx-ethereum/src/proof/tests.rs index aa85a284f..d03cba6e7 100644 --- a/light-clients/icsxx-ethereum/src/proof/tests.rs +++ b/light-clients/icsxx-ethereum/src/proof/tests.rs @@ -1,9 +1,9 @@ use super::{node_codec::RlpNodeCodec, *}; -use crate::proof::ethereum_trie::{EIP1186Layout, KeccakHasher}; +use crate::proof::ethereum_trie::{verify_proof, EIP1186Layout, KeccakHasher}; use ethers_core::utils::keccak256; use hex_literal::hex; use primitive_types::H256; -use trie_db::{node::Node, proof::verify_proof, NodeCodec}; +use trie_db::{node::Node, NodeCodec}; #[test] fn test_verify_membership() { @@ -15,17 +15,7 @@ fn test_verify_membership() { let key: Vec = keccak256(&hex!("24264ae01b1abbc9a91e18926818ad5cbf39017b")).into(); let root = H256(hex!("7bac2ed96e9c1b0bf578c52fd6e86a2d74c555f8e74d5954aff57939f144299a")); - /* - // pub fn verify_proof<'a, L>( - // root: &::Out, - // proof: &'a [Vec], - // raw_key: &'a [u8], - // expected_value: Option<&[u8]>, - // ) -> Result<(), VerifyError<'a, TrieHash, CError>> - - */ - verify_proof::, I, K, V>(&root, &proof, [&(&key, Some(&proof[2]))]) - .unwrap(); + verify_proof::>(&root, &proof, &key, Some(&proof[2])).unwrap(); } #[test] diff --git a/light-clients/icsxx-ethereum/src/verify.rs b/light-clients/icsxx-ethereum/src/verify.rs index d1cbc4407..4a04a5468 100644 --- a/light-clients/icsxx-ethereum/src/verify.rs +++ b/light-clients/icsxx-ethereum/src/verify.rs @@ -27,24 +27,25 @@ where { use VerifyError::*; - let eth_proof = serde_cbor::from_slice::(proof.as_bytes()).unwrap(); - let key = keccak256(path.into().into_bytes()); - let value_hash = value.map(keccak256).map(|x| x.as_slice()); - let root = H256::from_slice(root.as_bytes()); - let res = verify_proof::>( - &root, - ð_proof.account_proof.into_iter().map(|x| x.to_vec()).collect::>(), - &key, - value_hash, - ); + // let eth_proof = serde_cbor::from_slice::(proof.as_bytes()).unwrap(); + // let key = keccak256(path.into().into_bytes()); + // let value_hash = value.map(keccak256).map(|x| x.as_slice()); + // let root = H256::from_slice(root.as_bytes()); + // let res = verify_proof::>( + // &root, + // ð_proof.account_proof.into_iter().map(|x| x.to_vec()).collect::>(), + // &key, + // value_hash, + // ); - match res { - Ok(_) => Ok(true), - Err(err) => match err { - NonExistingValue(_) | ExistingValue(_) | ValueMismatch(_) | HashMismatch(_) => - Ok(false), - e @ IncompleteProof | e @ DecodeError(_) | e @ HashDecodeError(_) => - return Err(e.into()), - }, - } + // match res { + // Ok(_) => Ok(true), + // Err(err) => match err { + // NonExistingValue(_) | ExistingValue(_) | ValueMismatch(_) | HashMismatch(_) => + // Ok(false), + // e @ IncompleteProof | e @ DecodeError(_) | e @ HashDecodeError(_) => + // return Err(e.into()), + // }, + // } + todo!() } diff --git a/utils/subxt/codegen/src/lib.rs b/utils/subxt/codegen/src/lib.rs index 6fb7ada77..c8a8c4bda 100644 --- a/utils/subxt/codegen/src/lib.rs +++ b/utils/subxt/codegen/src/lib.rs @@ -21,7 +21,7 @@ use jsonrpsee::{ core::{client::ClientT, Error}, rpc_params, }; -use std::{env, fs, path::Path}; +use std::{env, fs, future::Future, path::Path}; use subxt_codegen::{CratePath, DerivesRegistry, TypeSubstitutes}; pub async fn fetch_metadata_ws(url: &str) -> anyhow::Result> { From d1edc1da1338b63630cc9fd8724a1cbb5402c54a Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Fri, 22 Sep 2023 11:16:11 -0300 Subject: [PATCH 37/43] generate ics20-bank ABI --- hyperspace/ethereum/scripts/generate_abi.sh | 1 + .../ethereum/src/abi/ics20-bank-abi.json | 394 ++++++++++++++++++ 2 files changed, 395 insertions(+) create mode 100644 hyperspace/ethereum/src/abi/ics20-bank-abi.json diff --git a/hyperspace/ethereum/scripts/generate_abi.sh b/hyperspace/ethereum/scripts/generate_abi.sh index 2cf365341..7846d8e24 100644 --- a/hyperspace/ethereum/scripts/generate_abi.sh +++ b/hyperspace/ethereum/scripts/generate_abi.sh @@ -15,6 +15,7 @@ forge inspect ../contracts/core/04-channel/IBCChannelHandshake.sol:IBCChannelHan forge inspect ../contracts/core/25-handler/IBCQuerier.sol:IBCQuerier abi > ../../src/abi/ibc-querier-abi.json forge inspect ../contracts/apps/20-transfer/ICS20TransferBank.sol:ICS20TransferBank abi > ../../src/abi/ics20-transfer-bank-abi.json +forge inspect ../contracts/apps/20-transfer/ICS20Bank.sol:ICS20Bank abi > ../../src/abi/ics20-bank-abi.json forge inspect ../contracts/clients/TendermintLightClientSimple.sol:TendermintLightClientSimple abi > ../../src/abi/tendermint-client-abi.json # remove all "."s inside the abi files to make them compatible with the derive macro diff --git a/hyperspace/ethereum/src/abi/ics20-bank-abi.json b/hyperspace/ethereum/src/abi/ics20-bank-abi.json new file mode 100644 index 000000000..571222a2c --- /dev/null +++ b/hyperspace/ethereum/src/abi/ics20-bank-abi.json @@ -0,0 +1,394 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "inputs": [], + "name": "ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "OPERATOR_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "string", + "name": "id", + "type": "string" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "string", + "name": "id", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenContract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "deposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "string", + "name": "id", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "setOperator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "string", + "name": "id", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenContract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] From 6167083b023663bbeb0349566096a841e19b7865 Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Mon, 25 Sep 2023 13:40:42 -0300 Subject: [PATCH 38/43] add a check for empty client state --- hyperspace/cosmos/src/provider.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hyperspace/cosmos/src/provider.rs b/hyperspace/cosmos/src/provider.rs index f0b5eef82..7267a978e 100644 --- a/hyperspace/cosmos/src/provider.rs +++ b/hyperspace/cosmos/src/provider.rs @@ -308,6 +308,9 @@ where Path::ClientState(ClientStatePath(client_id.clone())).to_string().into_bytes(); let (q, proof) = self.query_path(path_bytes.clone(), at, true).await?; let client_state = Any::decode(&*q.value)?; + if client_state.type_url.is_empty() || client_state.value.is_empty() { + return Err(Error::Custom(format!("empty client state for height {at}"))) + } Ok(QueryClientStateResponse { client_state: Some(client_state), proof, From 6a583cebd3cc0d1c42f633953c8705fe0f381c1e Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Mon, 25 Sep 2023 22:36:47 -0300 Subject: [PATCH 39/43] Ethereum membership proofs are working --- Cargo.lock | 235 ++---------------- hyperspace/ethereum/src/client.rs | 24 +- hyperspace/ethereum/src/ibc_provider.rs | 116 ++++----- .../icsxx-ethereum-cw/src/contract.rs | 35 +-- light-clients/icsxx-ethereum/Cargo.toml | 7 +- light-clients/icsxx-ethereum/src/lib.rs | 1 + .../icsxx-ethereum/src/proof/ethereum_trie.rs | 41 ++- .../icsxx-ethereum/src/proof/node_codec.rs | 5 +- .../icsxx-ethereum/src/proof/tests.rs | 6 +- light-clients/icsxx-ethereum/src/utils.rs | 9 + light-clients/icsxx-ethereum/src/verify.rs | 60 ++--- 11 files changed, 205 insertions(+), 334 deletions(-) create mode 100644 light-clients/icsxx-ethereum/src/utils.rs diff --git a/Cargo.lock b/Cargo.lock index 7074b98e2..9cf7f1c13 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1443,21 +1443,6 @@ dependencies = [ "cfg-if 1.0.0", ] -[[package]] -name = "clap" -version = "2.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" -dependencies = [ - "ansi_term", - "atty", - "bitflags 1.3.2", - "strsim 0.8.0", - "textwrap 0.11.0", - "unicode-width", - "vec_map", -] - [[package]] name = "clap" version = "3.2.23" @@ -1470,9 +1455,9 @@ dependencies = [ "clap_lex 0.2.4", "indexmap 1.9.2", "once_cell", - "strsim 0.10.0", + "strsim", "termcolor", - "textwrap 0.16.0", + "textwrap", ] [[package]] @@ -1494,7 +1479,7 @@ dependencies = [ "anstream", "anstyle", "clap_lex 0.5.1", - "strsim 0.10.0", + "strsim", "terminal_size", "unicase", "unicode-width", @@ -1515,7 +1500,7 @@ version = "3.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65" dependencies = [ - "heck 0.4.1", + "heck", "proc-macro-error", "proc-macro2", "quote", @@ -1528,7 +1513,7 @@ version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873" dependencies = [ - "heck 0.4.1", + "heck", "proc-macro2", "quote", "syn 2.0.28", @@ -1665,17 +1650,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" -[[package]] -name = "colored" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2674ec482fbc38012cf31e6c42ba0177b431a0cb6f15fe40efa5aab1bda516f6" -dependencies = [ - "is-terminal", - "lazy_static", - "windows-sys 0.48.0", -] - [[package]] name = "comfy-table" version = "6.1.4" @@ -2145,27 +2119,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "csv" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "626ae34994d3d8d668f4269922248239db4ae42d538b14c398b74a52208e8086" -dependencies = [ - "csv-core", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "csv-core" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" -dependencies = [ - "memchr", -] - [[package]] name = "ct-logs" version = "0.8.0" @@ -2384,7 +2337,7 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim 0.10.0", + "strsim", "syn 1.0.109", ] @@ -2903,7 +2856,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9720bba047d567ffc8a3cba48bf19126600e249ab7f128e9233e6376976a116" dependencies = [ - "heck 0.4.1", + "heck", "proc-macro2", "quote", "syn 1.0.109", @@ -3012,20 +2965,6 @@ dependencies = [ "uuid 0.8.2", ] -[[package]] -name = "eth_merkle_tree" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4e0a617d300b8c5e6bf8d87bacd3e8d0927bbe0c37ad01c6426f37c73a8f86d" -dependencies = [ - "colored", - "csv", - "hex", - "petgraph", - "rust-crypto", - "structopt", -] - [[package]] name = "ethabi" version = "18.0.0" @@ -4094,12 +4033,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "fuchsia-cprng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" - [[package]] name = "funty" version = "2.0.0" @@ -4251,12 +4184,6 @@ dependencies = [ "byteorder", ] -[[package]] -name = "gcc" -version = "0.3.55" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" - [[package]] name = "generic-array" version = "0.12.4" @@ -4646,15 +4573,6 @@ dependencies = [ "http", ] -[[package]] -name = "heck" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] - [[package]] name = "heck" version = "0.4.1" @@ -5229,6 +5147,7 @@ dependencies = [ "parity-scale-codec", "polkadot-core-primitives", "rand 0.8.5", + "reqwest", "serde_json", "sp-core 7.0.0", "sp-finality-grandpa", @@ -5541,8 +5460,7 @@ dependencies = [ "anyhow", "derive_more", "env_logger 0.9.3", - "eth_merkle_tree", - "ethers-core 2.0.10", + "ethabi", "futures", "hash-db 0.16.0", "hash256-std-hasher", @@ -5560,7 +5478,6 @@ dependencies = [ "rlp", "rs_merkle", "serde", - "serde_cbor", "serde_json", "ssz-rs", "sync-committee-primitives", @@ -5568,6 +5485,7 @@ dependencies = [ "sync-committee-verifier", "tendermint", "tendermint-proto", + "tiny-keccak", "tokio", "trie-db 0.28.0", ] @@ -5829,7 +5747,7 @@ dependencies = [ "socket2 0.4.9", "widestring", "winapi", - "winreg", + "winreg 0.10.1", ] [[package]] @@ -5990,7 +5908,7 @@ version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baa6da1e4199c10d7b1d0a6e5e8bd8e55f351163b6f4b3cbb044672a69bd4c1c" dependencies = [ - "heck 0.4.1", + "heck", "proc-macro-crate", "proc-macro2", "quote", @@ -6473,7 +6391,7 @@ version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d527d5827582abd44a6d80c07ff8b50b4ee238a8979e05998474179e79dc400" dependencies = [ - "heck 0.4.1", + "heck", "quote", "syn 1.0.109", ] @@ -8716,7 +8634,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3f8ad728fb08fe212df3c05169e940fbb6d9d16a877ddde14644a983ba2012e" dependencies = [ "bytes", - "heck 0.4.1", + "heck", "itertools", "lazy_static", "log", @@ -8882,29 +8800,6 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" -[[package]] -name = "rand" -version = "0.3.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c" -dependencies = [ - "libc", - "rand 0.4.6", -] - -[[package]] -name = "rand" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" -dependencies = [ - "fuchsia-cprng", - "libc", - "rand_core 0.3.1", - "rdrand", - "winapi", -] - [[package]] name = "rand" version = "0.7.3" @@ -8949,21 +8844,6 @@ dependencies = [ "rand_core 0.6.4", ] -[[package]] -name = "rand_core" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -dependencies = [ - "rand_core 0.4.2", -] - -[[package]] -name = "rand_core" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" - [[package]] name = "rand_core" version = "0.5.1" @@ -9053,15 +8933,6 @@ dependencies = [ "yasna", ] -[[package]] -name = "rdrand" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -dependencies = [ - "rand_core 0.3.1", -] - [[package]] name = "redox_syscall" version = "0.2.16" @@ -9181,9 +9052,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.18" +version = "0.11.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" +checksum = "3e9ad3fe7488d7e34558a2033d45a0c90b72d97b4f80705666fea71472e2e6a1" dependencies = [ "base64 0.21.0", "bytes", @@ -9217,8 +9088,8 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots 0.22.6", - "winreg", + "webpki-roots 0.25.2", + "winreg 0.50.0", ] [[package]] @@ -9523,19 +9394,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "rust-crypto" -version = "0.2.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a" -dependencies = [ - "gcc", - "libc", - "rand 0.3.23", - "rustc-serialize", - "time 0.1.45", -] - [[package]] name = "rustc-demangle" version = "0.1.21" @@ -9554,12 +9412,6 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" -[[package]] -name = "rustc-serialize" -version = "0.3.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" - [[package]] name = "rustc_version" version = "0.4.0" @@ -12174,42 +12026,12 @@ dependencies = [ "precomputed-hash", ] -[[package]] -name = "strsim" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" - [[package]] name = "strsim" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" -[[package]] -name = "structopt" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10" -dependencies = [ - "clap 2.34.0", - "lazy_static", - "structopt-derive", -] - -[[package]] -name = "structopt-derive" -version = "0.4.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" -dependencies = [ - "heck 0.3.3", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "strum" version = "0.24.1" @@ -12234,7 +12056,7 @@ version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" dependencies = [ - "heck 0.4.1", + "heck", "proc-macro2", "quote", "rustversion", @@ -12247,7 +12069,7 @@ version = "0.25.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad8d03b598d3d0fff69bf533ee3ef19b8eeb342729596df84bcc7e1f96ec4059" dependencies = [ - "heck 0.4.1", + "heck", "proc-macro2", "quote", "rustversion", @@ -12396,7 +12218,7 @@ source = "git+https://github.com/paritytech/subxt?rev=2a4da618a033bb82f768e4ef67 dependencies = [ "darling", "frame-metadata", - "heck 0.4.1", + "heck", "hex", "jsonrpsee", "parity-scale-codec", @@ -12802,15 +12624,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] - [[package]] name = "textwrap" version = "0.16.0" @@ -13718,12 +13531,6 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - [[package]] name = "version_check" version = "0.9.4" diff --git a/hyperspace/ethereum/src/client.rs b/hyperspace/ethereum/src/client.rs index 15d26db3b..eeb0ac923 100644 --- a/hyperspace/ethereum/src/client.rs +++ b/hyperspace/ethereum/src/client.rs @@ -1,6 +1,7 @@ use crate::{ config::EthereumClientConfig, contract::UnwrapContractError, + ibc_provider::u256_to_bytes, jwt::{JwtAuth, JwtKey}, utils::{DeployYuiIbc, ProviderImpl}, }; @@ -8,7 +9,7 @@ use anyhow::Error; use async_trait::async_trait; use cast::revm::db; use ethers::{ - abi::{AbiEncode, Address, ParamType, Token}, + abi::{encode, AbiEncode, Address, Bytes, ParamType, Token}, core::k256, prelude::{ coins_bip39::English, signer::SignerMiddlewareError, Authorization, BlockId, BlockNumber, @@ -616,6 +617,27 @@ impl EthereumClient { Ok(receipt) } } + + pub(crate) async fn query_proof_with_value( + &self, + path: &str, + at: Height, + ) -> Result<(Bytes, Vec), ClientError> { + let proof = self + .eth_query_proof(&path, Some(at.revision_height), COMMITMENTS_STORAGE_INDEX) + .await?; + let storage = proof + .storage_proof + .first() + .ok_or(ClientError::Other("storage proof not found".to_string()))?; + let bytes = u256_to_bytes(&storage.value); + + let proof = encode(&[Token::Array( + storage.proof.clone().into_iter().map(|p| Token::Bytes(p.to_vec())).collect(), + )]); + + Ok((proof, bytes)) + } } // #[cfg(any(test, feature = "testing"))] diff --git a/hyperspace/ethereum/src/ibc_provider.rs b/hyperspace/ethereum/src/ibc_provider.rs index 7dd462a15..a757e3bd5 100644 --- a/hyperspace/ethereum/src/ibc_provider.rs +++ b/hyperspace/ethereum/src/ibc_provider.rs @@ -83,6 +83,9 @@ use ibc::{ events::SendPacket, }, ics23_commitment::commitment::CommitmentRoot, + ics24_host::path::{ + ChannelEndsPath, ClientConsensusStatePath, ClientStatePath, ConnectionsPath, + }, }, events::IbcEvent, protobuf::Protobuf, @@ -433,7 +436,6 @@ impl IbcProvider for EthereumClient { let proof_height = Some(at.into()); let mut cs = client_state_from_abi_token::(client_state_token)?; */ - // First, we try to find an `UpdateClient` event at the given height... let mut consensus_state = None; let mut event_filter = self @@ -499,11 +501,24 @@ impl IbcProvider for EthereumClient { // TODO: figure out how to distinguish between the same function calls let proof_height = Some(at.into()); + let proof = self + .query_proof( + at, + vec![ClientConsensusStatePath { + client_id: client_id.clone(), + epoch: consensus_height.revision_number, + height: consensus_height.revision_height, + } + .to_string() + .into_bytes()], + ) + .await?; + return Ok(QueryConsensusStateResponse { consensus_state: Some( consensus_state.expect("should always be initialized").to_any(), ), - proof: vec![0], + proof, proof_height, }) } @@ -564,10 +579,24 @@ impl IbcProvider for EthereumClient { } } + let proof = self + .query_proof( + at, + vec![ClientConsensusStatePath { + client_id: client_id.clone(), + epoch: consensus_height.revision_number, + height: consensus_height.revision_height, + } + .to_string() + .into_bytes()], + ) + .await?; + let proof_height = Some(at.into()); - let any = consensus_state.expect("should always be initialized").to_any(); + let state = consensus_state.expect("should always be initialized"); + let any = state.to_any(); - Ok(QueryConsensusStateResponse { consensus_state: Some(any), proof: vec![0], proof_height }) + Ok(QueryConsensusStateResponse { consensus_state: Some(any), proof, proof_height }) } async fn query_client_state( @@ -733,6 +762,9 @@ impl IbcProvider for EthereumClient { } let proof_height = Some(at.into()); + let proof = self + .query_proof(at, vec![ClientStatePath(client_id.clone()).to_string().into_bytes()]) + .await?; Ok(QueryClientStateResponse { client_state: Some( @@ -741,7 +773,7 @@ impl IbcProvider for EthereumClient { .to_any(), ), proof_height, - proof: vec![0], + proof, }) } @@ -790,7 +822,11 @@ impl IbcProvider for EthereumClient { None }; - Ok(QueryConnectionResponse { connection, proof: vec![0], proof_height: Some(at.into()) }) + let proof = self + .query_proof(at, vec![ConnectionsPath(connection_id.clone()).to_string().into_bytes()]) + .await?; + + Ok(QueryConnectionResponse { connection, proof, proof_height: Some(at.into()) }) } async fn query_channel_end( @@ -819,6 +855,10 @@ impl IbcProvider for EthereumClient { port_id: channel_data.counterparty.port_id, channel_id: channel_data.counterparty.channel_id, }); + let proof = self + .query_proof(at, vec![ChannelEndsPath(port_id, channel_id).to_string().into_bytes()]) + .await?; + Ok(QueryChannelResponse { channel: Some(Channel { state: channel_data.state as _, @@ -827,7 +867,7 @@ impl IbcProvider for EthereumClient { connection_hops: channel_data.connection_hops, version: channel_data.version, }), - proof: vec![0], + proof, proof_height: Some(at.into()), }) } @@ -835,20 +875,7 @@ impl IbcProvider for EthereumClient { async fn query_proof(&self, at: Height, keys: Vec>) -> Result, Self::Error> { assert_eq!(keys.len(), 1); let key = String::from_utf8(keys[0].clone()).unwrap(); - - let proof_result = self - .eth_query_proof(&key, Some(at.revision_height), COMMITMENTS_STORAGE_INDEX) - .await?; - - let bytes = proof_result - .storage_proof - .first() - .map(|p| { - let token = p.proof.clone().into_iter().map(|p| Token::Bytes(p.to_vec())).collect(); - encode(&[token]) - }) - .ok_or_else(|| ClientError::Other("storage proof not found".to_string()))?; - + let (bytes, _) = self.query_proof_with_value(&key, at).await?; Ok(bytes) } @@ -866,20 +893,10 @@ impl IbcProvider for EthereumClient { }) .to_string(); - let proof = self - .eth_query_proof(&path, Some(at.revision_height), COMMITMENTS_STORAGE_INDEX) - .await?; - let storage = proof - .storage_proof - .first() - .ok_or(ClientError::Other("storage proof not found".to_string()))?; - let bytes = u256_to_bytes(&storage.value); - + let (proof, bytes) = self.query_proof_with_value(&path, at).await?; Ok(QueryPacketCommitmentResponse { commitment: bytes, - proof: encode(&[Token::Array( - storage.proof.clone().into_iter().map(|p| Token::Bytes(p.to_vec())).collect(), - )]), + proof, proof_height: Some(at.into()), }) } @@ -899,21 +916,11 @@ impl IbcProvider for EthereumClient { }) .to_string(); - let proof = self - .eth_query_proof(&path, Some(at.revision_height), COMMITMENTS_STORAGE_INDEX) - .await?; - let storage = proof - .storage_proof - .first() - .ok_or(ClientError::Other("storage proof not found".to_string()))?; - - let bytes = u256_to_bytes(&storage.value); + let (proof, bytes) = self.query_proof_with_value(&path, at).await?; Ok(ibc_proto::ibc::core::channel::v1::QueryPacketAcknowledgementResponse { acknowledgement: bytes, - proof: encode(&[Token::Array( - storage.proof.clone().into_iter().map(|p| Token::Bytes(p.to_vec())).collect(), - )]), + proof, proof_height: Some(at.into()), }) } @@ -961,25 +968,12 @@ impl IbcProvider for EthereumClient { }) .to_string(); - let proof = self - .eth_query_proof(&path, Some(at.revision_height), COMMITMENTS_STORAGE_INDEX) - .await?; - let storage = proof - .storage_proof - .first() - .ok_or(ClientError::Other("storage proof not found".to_string()))?; - + let proof = self.query_proof(at, vec![path.into_bytes()]).await?; let received = self .has_packet_receipt(at, port_id.as_str().to_owned(), format!("{channel_id}"), sequence) .await?; - Ok(QueryPacketReceiptResponse { - received, - proof: encode(&[Token::Array( - storage.proof.clone().into_iter().map(|p| Token::Bytes(p.to_vec())).collect(), - )]), - proof_height: Some(at.into()), - }) + Ok(QueryPacketReceiptResponse { received, proof, proof_height: Some(at.into()) }) } async fn latest_height_and_timestamp(&self) -> Result<(Height, Timestamp), Self::Error> { @@ -1781,7 +1775,7 @@ impl IbcProvider for EthereumClient { } } -fn u256_to_bytes(n: &U256) -> Vec { +pub(crate) fn u256_to_bytes(n: &U256) -> Vec { let mut bytes = vec![0u8; 256 / 8]; n.to_big_endian(&mut bytes); bytes diff --git a/light-clients/icsxx-ethereum-cw/src/contract.rs b/light-clients/icsxx-ethereum-cw/src/contract.rs index 6d4db65c0..1ccd02286 100644 --- a/light-clients/icsxx-ethereum-cw/src/contract.rs +++ b/light-clients/icsxx-ethereum-cw/src/contract.rs @@ -47,6 +47,7 @@ use icsxx_ethereum::{ consensus_state::ConsensusState, }; // use light_client_common::{verify_membership, verify_non_membership}; +use icsxx_ethereum::verify::verify_ibc_proof; use std::{collections::BTreeSet, str::FromStr}; use sync_committee_verifier::LightClientState; /* @@ -110,14 +111,18 @@ fn process_message( let consensus_state = ctx .consensus_state(&client_id, msg.height) .map_err(|e| ContractError::Client(e.to_string()))?; - // verify_membership::( - // &msg.prefix, - // &msg.proof, - // &consensus_state.root, - // msg.path, - // msg.value, - // ) - // .map_err(|e| ContractError::Ethereum(e.to_string()))?; + verify_ibc_proof( + &msg.prefix, + &msg.proof, + &consensus_state.root, + msg.path, + Some(&msg.value), + ) + .map_err(|e| { + ctx.log(&format!("VerifyMembership: error = {:?}", e)); + ContractError::Client(e.to_string()) + })?; + Ok(()).map(|_| to_binary(&ContractResult::success())) }, ExecuteMsg::VerifyNonMembership(msg) => { @@ -126,14 +131,12 @@ fn process_message( .consensus_state(&client_id, msg.height) .map_err(|e| ContractError::Client(e.to_string()))?; - // verify_non_membership::( - // &msg.prefix, - // &msg.proof, - // &consensus_state.root, - // msg.path, - // ) - // .map_err(|e| ContractError::Ethereum(e.to_string())) - // .map(|_| to_binary(&ContractResult::success())) + verify_ibc_proof(&msg.prefix, &msg.proof, &consensus_state.root, msg.path, None) + .map_err(|e| { + ctx.log(&format!("VerifyNonMembership: error = {:?}", e)); + ContractError::Client(e.to_string()) + })?; + Ok(()).map(|_| to_binary(&ContractResult::success())) }, ExecuteMsg::VerifyClientMessage(msg) => { diff --git a/light-clients/icsxx-ethereum/Cargo.toml b/light-clients/icsxx-ethereum/Cargo.toml index 896de0cd6..f02157be9 100644 --- a/light-clients/icsxx-ethereum/Cargo.toml +++ b/light-clients/icsxx-ethereum/Cargo.toml @@ -29,16 +29,14 @@ serde = { version = "1.0.144", default-features = false, features = ["derive"] } tendermint = { git = "https://github.com/informalsystems/tendermint-rs", rev = "e81f7bf23d63ffbcd242381d1ce5e35da3515ff1", default-features = false } tendermint-proto = { git = "https://github.com/informalsystems/tendermint-rs", rev = "e81f7bf23d63ffbcd242381d1ce5e35da3515ff1", default-features = false } -serde_cbor = { version = "0.11.2", default-features = false } -ethers-core = { version = "2.0.10", default-features = false } -eth_merkle_tree = { version = "0.1.1", default-features = false } rs_merkle = { version = "1.4.1", default-features = false } -#serde_json = { version = "1.0.105" , default-features = false } hash-db = { version = "0.16.0", default-features = false } trie-db = { version = "0.28.0", default-features = false } rlp = { version = "0.5.2", default-features = false } hex-literal = { version = "0.4.1", default-features = false } hash256-std-hasher = { version = "0.15.2", default-features = false } +ethabi = { version = "18.0.0", default-features = false } +tiny-keccak = { version = "2.0.2", default-features = false, features = ["keccak"] } [dev-dependencies] hex = "0.4.3" @@ -71,4 +69,5 @@ std = [ "ssz-rs/std", "tendermint/std", "trie-db/std", + "rlp/std", ] diff --git a/light-clients/icsxx-ethereum/src/lib.rs b/light-clients/icsxx-ethereum/src/lib.rs index f932dae40..bdbfd9939 100644 --- a/light-clients/icsxx-ethereum/src/lib.rs +++ b/light-clients/icsxx-ethereum/src/lib.rs @@ -27,6 +27,7 @@ pub mod consensus_state; pub mod error; pub mod proof; pub mod proto; +pub mod utils; pub mod verify; // #[cfg(test)] diff --git a/light-clients/icsxx-ethereum/src/proof/ethereum_trie.rs b/light-clients/icsxx-ethereum/src/proof/ethereum_trie.rs index d34a306f0..b2cb52a70 100644 --- a/light-clients/icsxx-ethereum/src/proof/ethereum_trie.rs +++ b/light-clients/icsxx-ethereum/src/proof/ethereum_trie.rs @@ -1,12 +1,15 @@ extern crate alloc; -use crate::proof::node_codec; -use ethers_core::utils::keccak256; +use crate::{proof::node_codec, utils::keccak256}; +use alloc::vec::Vec; +use core::{ + fmt::{Display, Formatter}, + marker::PhantomData, +}; use hash256_std_hasher::Hash256StdHasher; use hash_db::Hasher; /// Taken from https://github.com/paritytech/trie/blob/aa3168d6de01793e71ebd906d3a82ae4b363db59/trie-eip1186/src/eip1186.rs use primitive_types::H256; -use std::marker::PhantomData; use trie_db::{ node::{decode_hash, Node, NodeHandle, Value}, CError, NibbleSlice, NodeCodec, TrieHash, TrieLayout, @@ -15,7 +18,8 @@ use trie_db::{ /// Errors that may occur during proof verification. Most of the errors types simply indicate /// that the proof is invalid with respect to the statement being verified, and the exact error /// type can be used for debugging. -#[derive(PartialEq, Eq, Debug)] +#[derive(PartialEq, Eq)] +#[cfg_attr(feature = "std", derive(Debug))] pub enum VerifyError<'a, HO, CE> { /// The proof does not contain any value for the given key /// the error carries the nibbles left after traversing the trie @@ -36,6 +40,35 @@ pub enum VerifyError<'a, HO, CE> { HashDecodeError(&'a [u8]), } +#[cfg(not(feature = "std"))] +impl Display for VerifyError<'_, HO, CE> { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + match self { + VerifyError::NonExistingValue(_) => { + write!(f, "Key does not exist in trie: reaming key") + }, + VerifyError::ExistingValue(_) => { + write!(f, "trie contains a value for given key") + }, + VerifyError::ValueMismatch(_) => { + write!(f, "Expected value was not found in the trie") + }, + VerifyError::IncompleteProof => { + write!(f, "Proof is incomplete -- expected more nodes") + }, + VerifyError::HashMismatch(_) => { + write!(f, "hash mismatch found") + }, + VerifyError::DecodeError(_) => { + write!(f, "Unable to decode proof node") + }, + VerifyError::HashDecodeError(_) => { + write!(f, "Unable to decode hash value") + }, + } + } +} + #[cfg(feature = "std")] impl<'a, HO: std::fmt::Debug, CE: std::error::Error> std::fmt::Display for VerifyError<'a, HO, CE> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { diff --git a/light-clients/icsxx-ethereum/src/proof/node_codec.rs b/light-clients/icsxx-ethereum/src/proof/node_codec.rs index 180fb655d..1f86f951c 100644 --- a/light-clients/icsxx-ethereum/src/proof/node_codec.rs +++ b/light-clients/icsxx-ethereum/src/proof/node_codec.rs @@ -16,12 +16,9 @@ //! [`NodeCodec`] implementation for [`TrieDb`] +use crate::utils::keccak256; use alloc::vec::Vec; use core::{borrow::Borrow, marker::PhantomData, str::FromStr}; -use ethers_core::{ - abi::Address, - utils::{get_contract_address, keccak256}, -}; use hash_db::Hasher; use primitive_types::{H160, H256}; use rlp::{DecoderError, Prototype, Rlp, RlpStream}; diff --git a/light-clients/icsxx-ethereum/src/proof/tests.rs b/light-clients/icsxx-ethereum/src/proof/tests.rs index d03cba6e7..877dbb354 100644 --- a/light-clients/icsxx-ethereum/src/proof/tests.rs +++ b/light-clients/icsxx-ethereum/src/proof/tests.rs @@ -1,6 +1,8 @@ use super::{node_codec::RlpNodeCodec, *}; -use crate::proof::ethereum_trie::{verify_proof, EIP1186Layout, KeccakHasher}; -use ethers_core::utils::keccak256; +use crate::{ + proof::ethereum_trie::{verify_proof, EIP1186Layout, KeccakHasher}, + utils::keccak256, +}; use hex_literal::hex; use primitive_types::H256; use trie_db::{node::Node, NodeCodec}; diff --git a/light-clients/icsxx-ethereum/src/utils.rs b/light-clients/icsxx-ethereum/src/utils.rs new file mode 100644 index 000000000..d956420a7 --- /dev/null +++ b/light-clients/icsxx-ethereum/src/utils.rs @@ -0,0 +1,9 @@ +use tiny_keccak::Hasher; + +pub fn keccak256>(x: T) -> [u8; 32] { + let mut hasher = tiny_keccak::Keccak::v256(); + hasher.update(x.as_ref()); + let mut output = [0u8; 32]; + hasher.finalize(&mut output); + output +} diff --git a/light-clients/icsxx-ethereum/src/verify.rs b/light-clients/icsxx-ethereum/src/verify.rs index 4a04a5468..5bc69fc7b 100644 --- a/light-clients/icsxx-ethereum/src/verify.rs +++ b/light-clients/icsxx-ethereum/src/verify.rs @@ -1,19 +1,16 @@ use crate::{ + alloc::string::ToString, error::Error, proof::ethereum_trie::{verify_proof, EIP1186Layout, KeccakHasher, VerifyError}, + utils::keccak256, }; -use ethers_core::{ - abi, - types::EIP1186ProofResponse, - utils::{keccak256, rlp}, -}; +use alloc::{boxed::Box, format, vec::Vec}; +use ethabi::{ParamType, Token}; use ibc::core::{ ics23_commitment::commitment::{CommitmentPrefix, CommitmentProofBytes, CommitmentRoot}, - ics24_host::Path, + ics24_host::{identifier::ConnectionId, path::ConnectionsPath, Path}, }; use primitive_types::H256; -use rlp::DecoderError; -use rs_merkle::Hasher; pub fn verify_ibc_proof

( prefix: &CommitmentPrefix, // TODO: use prefix @@ -27,25 +24,32 @@ where { use VerifyError::*; - // let eth_proof = serde_cbor::from_slice::(proof.as_bytes()).unwrap(); - // let key = keccak256(path.into().into_bytes()); - // let value_hash = value.map(keccak256).map(|x| x.as_slice()); - // let root = H256::from_slice(root.as_bytes()); - // let res = verify_proof::>( - // &root, - // ð_proof.account_proof.into_iter().map(|x| x.to_vec()).collect::>(), - // &key, - // value_hash, - // ); + let mut tokens = + ethabi::decode(&[ParamType::Array(Box::new(ParamType::Bytes))], proof.as_bytes()) + .map_err(|e| Error::Custom(format!("failed to decode proof: {:?}", e)))?; + let Token::Array(tokens) = tokens.remove(0) else { + return Err(Error::Custom("invalid proof".to_string())) + }; + let proof = tokens + .into_iter() + .map(|x| x.into_bytes()) + .collect::>>() + .ok_or_else(|| Error::Custom("invalid proof (expected bytes)".to_string()))?; + let key = keccak256(path.into().into_bytes()); + let option = + value + .map(|x| if x.len() <= H256::len_bytes() { x.to_vec() } else { keccak256(x).to_vec() }); + let value_hash = option.as_ref().map(|x| x.as_slice()); + let root = H256::from_slice(root.as_bytes()); + let res = verify_proof::>(&root, &proof, &key, value_hash); - // match res { - // Ok(_) => Ok(true), - // Err(err) => match err { - // NonExistingValue(_) | ExistingValue(_) | ValueMismatch(_) | HashMismatch(_) => - // Ok(false), - // e @ IncompleteProof | e @ DecodeError(_) | e @ HashDecodeError(_) => - // return Err(e.into()), - // }, - // } - todo!() + match res { + Ok(_) => Ok(true), + Err(err) => match err { + NonExistingValue(_) | ExistingValue(_) | ValueMismatch(_) | HashMismatch(_) => + Ok(false), + e @ IncompleteProof | e @ DecodeError(_) | e @ HashDecodeError(_) => + return Err(Error::Custom(format!("{e}"))), + }, + } } From 25fe8f208b26eab6d9c26cddaf6187dcf0180879 Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Tue, 26 Sep 2023 14:30:46 -0300 Subject: [PATCH 40/43] Improve logging and empty log handling --- hyperspace/ethereum/src/client.rs | 4 +--- hyperspace/ethereum/src/ibc_provider.rs | 5 +++++ hyperspace/ethereum/src/utils.rs | 2 ++ hyperspace/testsuite/src/lib.rs | 2 +- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/hyperspace/ethereum/src/client.rs b/hyperspace/ethereum/src/client.rs index eeb0ac923..b3078cbe4 100644 --- a/hyperspace/ethereum/src/client.rs +++ b/hyperspace/ethereum/src/client.rs @@ -661,9 +661,7 @@ impl primitives::TestProvider for EthereumClient { let _ = method.call().await.unwrap_contract_error(); let receipt = method.send().await.unwrap().await.unwrap().unwrap(); assert_eq!(receipt.status, Some(1.into())); - for log in receipt.logs { - log::info!("tx.log.t0 = {}", hex::encode(log.topics[0])); - } + log::info!("Sent transfer. Tx hash: {:?}", receipt.transaction_hash); Ok(()) } diff --git a/hyperspace/ethereum/src/ibc_provider.rs b/hyperspace/ethereum/src/ibc_provider.rs index a757e3bd5..aef06a805 100644 --- a/hyperspace/ethereum/src/ibc_provider.rs +++ b/hyperspace/ethereum/src/ibc_provider.rs @@ -1204,6 +1204,11 @@ impl IbcProvider for EthereumClient { .await .map_err(|err| ClientError::Other(format!("failed to get logs: {}", err)))?; logs.extend(logs2); + + if logs.is_empty() { + return Ok(vec![]) + } + let channel = self.query_channel_end(at, channel_id, port_id).await?; let channel = channel.channel.ok_or(ClientError::Other("channel is none".to_string()))?; diff --git a/hyperspace/ethereum/src/utils.rs b/hyperspace/ethereum/src/utils.rs index 00c8386c5..e75f44454 100644 --- a/hyperspace/ethereum/src/utils.rs +++ b/hyperspace/ethereum/src/utils.rs @@ -799,6 +799,8 @@ where .await .unwrap(); + println!("Deployed Diamond on {:?}", diamond.address()); + // let predefined_layout = serde_json::from_reader::<_, StorageLayout>( // File::open("/Users/vmark/work/centauri-private/hyperspace/ethereum/src/storage_layout/ // ibc_storage.json").unwrap(), ) diff --git a/hyperspace/testsuite/src/lib.rs b/hyperspace/testsuite/src/lib.rs index d4fef001a..c614c1434 100644 --- a/hyperspace/testsuite/src/lib.rs +++ b/hyperspace/testsuite/src/lib.rs @@ -146,7 +146,7 @@ where } /// Attempts to send 20% of funds of chain_a's signer to chain b's signer. -async fn send_transfer( +pub async fn send_transfer( chain_a: &A, chain_b: &B, asset_a: A::AssetId, From 9a21de64b1f78f3fed6b1b54e387c04062f1ec52 Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Wed, 27 Sep 2023 11:27:46 -0300 Subject: [PATCH 41/43] post-merge fixes --- hyperspace/ethereum/src/chain.rs | 39 --------- hyperspace/ethereum/src/ibc_provider.rs | 18 ++-- hyperspace/testsuite/tests/ethereum_cosmos.rs | 83 ------------------- .../icsxx-ethereum-cw/src/contract.rs | 4 +- 4 files changed, 7 insertions(+), 137 deletions(-) diff --git a/hyperspace/ethereum/src/chain.rs b/hyperspace/ethereum/src/chain.rs index 735fbe140..e397af002 100644 --- a/hyperspace/ethereum/src/chain.rs +++ b/hyperspace/ethereum/src/chain.rs @@ -1461,42 +1461,3 @@ impl Chain for EthereumClient { Ok(()) } } - -#[test] -fn fooo() { - let xs = hex::encode(&[ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 3, 208, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 175, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 114, 47, 235, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 126, 17, 214, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 213, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 18, 99, 101, 110, 116, 97, 117, 114, 105, 45, 116, 101, 115, 116, 110, 101, - 116, 45, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ]); - let ys = hex::encode(&[ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 100, 249, 5, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 23, 130, 113, 216, 219, 130, 80, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 118, 127, 0, 9, 235, 180, 151, - 199, 145, 16, 123, 132, 67, 44, 202, 236, 69, 233, 46, 77, 5, 229, 121, 154, 197, 91, 45, - 72, 242, 213, 212, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 32, 96, 47, 163, 90, 207, 211, 119, 144, 13, 127, 227, 69, 151, 48, - 217, 100, 21, 238, 243, 105, 189, 3, 60, 9, 35, 178, 210, 226, 121, 106, 151, 217, - ]); - println!("{xs}\n{ys}"); -} diff --git a/hyperspace/ethereum/src/ibc_provider.rs b/hyperspace/ethereum/src/ibc_provider.rs index 57bc91199..857dd8ebf 100644 --- a/hyperspace/ethereum/src/ibc_provider.rs +++ b/hyperspace/ethereum/src/ibc_provider.rs @@ -24,7 +24,10 @@ use ibc::{ ics23_commitment::commitment::CommitmentPrefix, ics24_host::{ identifier::{ChannelId, ClientId, ConnectionId, PortId}, - path::{AcksPath, CommitmentsPath, ReceiptsPath}, + path::{ + AcksPath, ChannelEndsPath, ClientConsensusStatePath, ClientStatePath, + CommitmentsPath, ConnectionsPath, ReceiptsPath, + }, Path, }, }, @@ -129,7 +132,7 @@ abigen!( "hyperspace/ethereum/src/abi/ics20-transfer-bank-abi.json"; Ics20BankAbi, - "/Users/vmark/work/centauri-private/hyperspace/ethereum/src/abi/ics20-bank-abi.json"; + "hyperspace/ethereum/src/abi/ics20-bank-abi.json"; TendermintClientAbi, "hyperspace/ethereum/src/abi/tendermint-client-abi.json"; @@ -373,17 +376,6 @@ impl IbcProvider for EthereumClient { let height = Height::new(0, log.block_number.unwrap().as_u64()); let topic0 = log.topics[0]; - let recv_packet_stream = ws - .subscribe_logs( - &Filter::new() - .from_block(BlockNumber::Latest) - .address(ibc_handler_address) - .event("RecvPacket((uint64,string,string,string,string,bytes,(uint64,uint64),uint64))"), - ) - .await - .expect("failed to subscribe to RecvPacket event") - .map(decode_client_id_log); - let mut maybe_ibc_event = if topic0 == UpdateClientHeightFilter::signature() { let event = UpdateClientHeightFilter::decode_log(&raw_log).expect("decode event"); let topic1 = H256::from_slice(&encode(&[Token::FixedBytes( diff --git a/hyperspace/testsuite/tests/ethereum_cosmos.rs b/hyperspace/testsuite/tests/ethereum_cosmos.rs index 847321406..ffe44be64 100644 --- a/hyperspace/testsuite/tests/ethereum_cosmos.rs +++ b/hyperspace/testsuite/tests/ethereum_cosmos.rs @@ -248,9 +248,6 @@ async fn setup_clients() -> (AnyChain, AnyChain) { let code_id_str = hex::encode(code_id); config_b.wasm_code_id = Some(code_id_str); - println!("{}", toml::to_string_pretty(&config_a).unwrap()); - println!("\n{}", toml::to_string_pretty(&config_b).unwrap()); - let mut chain_a_wrapped = AnyConfig::Ethereum(config_a).into_client().await.unwrap(); let mut chain_b_wrapped = AnyConfig::Cosmos(config_b).into_client().await.unwrap(); @@ -322,44 +319,6 @@ async fn ethereum_to_cosmos_ibc_messaging_full_integration_test() { ) .await; - // loop { - // let client_a_clone = chain_a.clone(); - // let client_b_clone = chain_b.clone(); - // let handle = tokio::task::spawn(async move { - // hyperspace_core::relay(client_a_clone, client_b_clone, None, None, None) - // .await - // .map_err(|e| { - // log::error!(target: "hyperspace", "Relayer loop failed: {:?}", e); - // e - // }) - // .unwrap() - // }); - // tokio::task::spawn(async move { - // let x = handle - // .map_err(|e| { - // log::error!(target: "hyperspace", "Relayer loop failed: {:?}", e); - // e - // }) - // .await; - // }) - // .await - // .map_err(|e| { - // log::error!(target: "hyperspace", "Relayer loop failed: {:?}", e); - // e - // }) - // .unwrap(); - // - // let balance = chain_a - // .query_ibc_balance(asset_id_a) - // .await - // .expect("Can't query ibc balance") - // .pop() - // .expect("No Ibc balances"); - // let amount = balance.amount.as_u256().as_u128(); - // - // log::info!("my balance = {amount}"); - // } - // // timeouts + connection delay // ibc_messaging_packet_height_timeout_with_connection_delay( // &mut chain_a, @@ -453,45 +412,3 @@ async fn cosmos_to_ethereum_ibc_messaging_full_integration_test() { ibc_messaging_submit_misbehaviour(&mut chain_a, &mut chain_b).await; } */ - -#[tokio::test] -async fn send_tokens() { - let config = toml::from_str::( - &std::fs::read_to_string("../../config/ethereum-local.toml").unwrap(), - ) - .unwrap(); - let mut client = EthereumClient::new(config).await.unwrap(); - let abi = Ics20BankAbi::new( - Address::from_str("0x0486ee42d89d569c4d8143e47a82c4b14545ae43").unwrap(), - client.client(), - ); - let from = Address::from_str("0x73db010c3275eb7a92e5c38770316248f4c644ee").unwrap(); - let to = Address::from_str("0x0486ee42d89d569c4d8143e47a82c4b14545ae43").unwrap(); - - async fn get_balance(abi: &Ics20BankAbi, acc: H160) -> U256 - where - M: Middleware + Debug + Send + Sync, - { - abi.method("balanceOf", (acc, "pica".to_string())) - .unwrap() - .call() - .await - .unwrap() - }; - dbg!(get_balance(&abi, from).await); - dbg!(get_balance(&abi, to).await); - - let tx = abi - .method::<_, ()>("transferFrom", (from, to, "pica".to_string(), U256::from(10000000u32))) - .unwrap() - .send() - .await - .unwrap() - .await - .unwrap() - .unwrap(); - assert_eq!(tx.status, Some(1u32.into())); - - dbg!(get_balance(&abi, from).await); - dbg!(get_balance(&abi, to).await); -} diff --git a/light-clients/icsxx-ethereum-cw/src/contract.rs b/light-clients/icsxx-ethereum-cw/src/contract.rs index 88c4ee5a7..872d4c293 100644 --- a/light-clients/icsxx-ethereum-cw/src/contract.rs +++ b/light-clients/icsxx-ethereum-cw/src/contract.rs @@ -120,7 +120,7 @@ fn process_message( ) .map_err(|e| { ctx.log(&format!("VerifyMembership: error = {:?}", e)); - ContractError::Ethereum(e.to_string()) + ContractError::Client(e.to_string()) })?; Ok(()).map(|_| to_binary(&ContractResult::success())) }, @@ -133,7 +133,7 @@ fn process_message( verify_ibc_proof(&msg.prefix, &msg.proof, &consensus_state.root, msg.path, None) .map_err(|e| { ctx.log(&format!("VerifyNonMembership: error = {:?}", e)); - ContractError::Ethereum(e.to_string()) + ContractError::Client(e.to_string()) })?; Ok(()).map(|_| to_binary(&ContractResult::success())) }, From 7c54cff68dc2e34b54fac14384a8d8e271ba6028 Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Wed, 27 Sep 2023 12:00:10 -0300 Subject: [PATCH 42/43] Update ABI --- .../ethereum/src/abi/ics20-transfer-bank-abi.json | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/hyperspace/ethereum/src/abi/ics20-transfer-bank-abi.json b/hyperspace/ethereum/src/abi/ics20-transfer-bank-abi.json index e9d73c246..abf1b6ae6 100644 --- a/hyperspace/ethereum/src/abi/ics20-transfer-bank-abi.json +++ b/hyperspace/ethereum/src/abi/ics20-transfer-bank-abi.json @@ -15,6 +15,19 @@ "stateMutability": "nonpayable", "type": "constructor" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "sequence", + "type": "uint64" + } + ], + "name": "TransferInitiated", + "type": "event" + }, { "inputs": [ { From b2ca07dc3d2fdf3e498aaa2ebda7d49cd340fcd8 Mon Sep 17 00:00:00 2001 From: Vladislav Markushin Date: Thu, 28 Sep 2023 11:28:45 -0300 Subject: [PATCH 43/43] update ABI, small refactor --- hyperspace/ethereum/scripts/generate_abi.sh | 0 .../ethereum/src/abi/ibc-connection-abi.json | 13 + hyperspace/ethereum/src/abi/ibc-host-abi.json | 44 +-- .../ethereum/src/abi/ibc-packet-abi.json | 341 ++++++++++++++++++ .../src/abi/ics20-transfer-bank-abi.json | 72 ++++ hyperspace/ethereum/src/utils.rs | 48 ++- hyperspace/testsuite/tests/ethereum_cosmos.rs | 14 +- .../icsxx-ethereum/src/client_def.rs | 2 +- 8 files changed, 483 insertions(+), 51 deletions(-) mode change 100644 => 100755 hyperspace/ethereum/scripts/generate_abi.sh diff --git a/hyperspace/ethereum/scripts/generate_abi.sh b/hyperspace/ethereum/scripts/generate_abi.sh old mode 100644 new mode 100755 diff --git a/hyperspace/ethereum/src/abi/ibc-connection-abi.json b/hyperspace/ethereum/src/abi/ibc-connection-abi.json index 70fa13023..1f190b668 100644 --- a/hyperspace/ethereum/src/abi/ibc-connection-abi.json +++ b/hyperspace/ethereum/src/abi/ibc-connection-abi.json @@ -527,5 +527,18 @@ ], "stateMutability": "nonpayable", "type": "function" + }, + { + "inputs": [], + "name": "getCommitmentPrefix", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "pure", + "type": "function" } ] diff --git a/hyperspace/ethereum/src/abi/ibc-host-abi.json b/hyperspace/ethereum/src/abi/ibc-host-abi.json index c0541973d..7b09de627 100644 --- a/hyperspace/ethereum/src/abi/ibc-host-abi.json +++ b/hyperspace/ethereum/src/abi/ibc-host-abi.json @@ -171,12 +171,12 @@ { "components": [ { - "internalType": "enum Channel.State", + "internalType": "enum ChannelState", "name": "state", "type": "uint8" }, { - "internalType": "enum Channel.Order", + "internalType": "enum ChannelOrder", "name": "ordering", "type": "uint8" }, @@ -193,7 +193,7 @@ "type": "string" } ], - "internalType": "struct ChannelCounterparty.Data", + "internalType": "struct ChannelCounterpartyData", "name": "counterparty", "type": "tuple" }, @@ -208,7 +208,7 @@ "type": "string" } ], - "internalType": "struct Channel.Data", + "internalType": "struct ChannelData", "name": "channel", "type": "tuple" }, @@ -318,12 +318,12 @@ "type": "string[]" } ], - "internalType": "struct Version.Data[]", + "internalType": "struct VersionData[]", "name": "versions", "type": "tuple[]" }, { - "internalType": "enum ConnectionEnd.State", + "internalType": "enum ConnectionEndState", "name": "state", "type": "uint8" }, @@ -347,12 +347,12 @@ "type": "bytes" } ], - "internalType": "struct MerklePrefix.Data", + "internalType": "struct MerklePrefixData", "name": "prefix", "type": "tuple" } ], - "internalType": "struct Counterparty.Data", + "internalType": "struct CounterpartyData", "name": "counterparty", "type": "tuple" }, @@ -362,7 +362,7 @@ "type": "uint64" } ], - "internalType": "struct ConnectionEnd.Data", + "internalType": "struct ConnectionEndData", "name": "connection", "type": "tuple" }, @@ -797,7 +797,7 @@ "type": "uint64" } ], - "internalType": "struct Height.Data", + "internalType": "struct HeightData", "name": "timeout_height", "type": "tuple" }, @@ -807,7 +807,7 @@ "type": "uint64" } ], - "internalType": "struct Packet.Data", + "internalType": "struct PacketData", "name": "packet", "type": "tuple" } @@ -852,12 +852,12 @@ { "components": [ { - "internalType": "enum Channel.State", + "internalType": "enum ChannelState", "name": "state", "type": "uint8" }, { - "internalType": "enum Channel.Order", + "internalType": "enum ChannelOrder", "name": "ordering", "type": "uint8" }, @@ -874,7 +874,7 @@ "type": "string" } ], - "internalType": "struct ChannelCounterparty.Data", + "internalType": "struct ChannelCounterpartyData", "name": "counterparty", "type": "tuple" }, @@ -889,7 +889,7 @@ "type": "string" } ], - "internalType": "struct Channel.Data", + "internalType": "struct ChannelData", "name": "channel", "type": "tuple" } @@ -980,12 +980,12 @@ "type": "string[]" } ], - "internalType": "struct Version.Data[]", + "internalType": "struct VersionData[]", "name": "versions", "type": "tuple[]" }, { - "internalType": "enum ConnectionEnd.State", + "internalType": "enum ConnectionEndState", "name": "state", "type": "uint8" }, @@ -1009,12 +1009,12 @@ "type": "bytes" } ], - "internalType": "struct MerklePrefix.Data", + "internalType": "struct MerklePrefixData", "name": "prefix", "type": "tuple" } ], - "internalType": "struct Counterparty.Data", + "internalType": "struct CounterpartyData", "name": "counterparty", "type": "tuple" }, @@ -1024,7 +1024,7 @@ "type": "uint64" } ], - "internalType": "struct ConnectionEnd.Data", + "internalType": "struct ConnectionEndData", "name": "connection", "type": "tuple" } @@ -1242,7 +1242,7 @@ "type": "uint64" } ], - "internalType": "struct Height.Data", + "internalType": "struct HeightData", "name": "timeout_height", "type": "tuple" }, @@ -1252,7 +1252,7 @@ "type": "uint64" } ], - "internalType": "struct Packet.Data", + "internalType": "struct PacketData", "name": "packet", "type": "tuple" } diff --git a/hyperspace/ethereum/src/abi/ibc-packet-abi.json b/hyperspace/ethereum/src/abi/ibc-packet-abi.json index 8eb54db04..ec769b177 100644 --- a/hyperspace/ethereum/src/abi/ibc-packet-abi.json +++ b/hyperspace/ethereum/src/abi/ibc-packet-abi.json @@ -206,6 +206,73 @@ "name": "SendPacket", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "sequence", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "string", + "name": "source_port", + "type": "string" + }, + { + "indexed": true, + "internalType": "string", + "name": "source_channel", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "destination_port", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "destination_channel", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "revision_number", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "revision_height", + "type": "uint64" + } + ], + "indexed": false, + "internalType": "struct HeightData", + "name": "timeout_height", + "type": "tuple" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "timeout_timestamp", + "type": "uint64" + } + ], + "name": "TimeoutOnClosePacket", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -273,6 +340,73 @@ "name": "TimeoutPacket", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "sequence", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "string", + "name": "source_port", + "type": "string" + }, + { + "indexed": true, + "internalType": "string", + "name": "source_channel", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "destination_port", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "destination_channel", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "revision_number", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "revision_height", + "type": "uint64" + } + ], + "indexed": false, + "internalType": "struct HeightData", + "name": "timeout_height", + "type": "tuple" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "timeout_timestamp", + "type": "uint64" + } + ], + "name": "TimeoutPacket", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -564,6 +698,213 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "uint64", + "name": "sequence", + "type": "uint64" + }, + { + "internalType": "string", + "name": "source_port", + "type": "string" + }, + { + "internalType": "string", + "name": "source_channel", + "type": "string" + }, + { + "internalType": "string", + "name": "destination_port", + "type": "string" + }, + { + "internalType": "string", + "name": "destination_channel", + "type": "string" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "revision_number", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "revision_height", + "type": "uint64" + } + ], + "internalType": "struct HeightData", + "name": "timeout_height", + "type": "tuple" + }, + { + "internalType": "uint64", + "name": "timeout_timestamp", + "type": "uint64" + } + ], + "internalType": "struct PacketData", + "name": "packet", + "type": "tuple" + }, + { + "internalType": "bytes", + "name": "proofUnreceived", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "proofClose", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "revision_number", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "revision_height", + "type": "uint64" + } + ], + "internalType": "struct HeightData", + "name": "proofHeight", + "type": "tuple" + }, + { + "internalType": "uint64", + "name": "nextSequenceRecv", + "type": "uint64" + } + ], + "internalType": "struct IBCMsgsMsgTimeoutOnClose", + "name": "msg_", + "type": "tuple" + } + ], + "name": "timeoutOnClose", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "uint64", + "name": "sequence", + "type": "uint64" + }, + { + "internalType": "string", + "name": "source_port", + "type": "string" + }, + { + "internalType": "string", + "name": "source_channel", + "type": "string" + }, + { + "internalType": "string", + "name": "destination_port", + "type": "string" + }, + { + "internalType": "string", + "name": "destination_channel", + "type": "string" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "revision_number", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "revision_height", + "type": "uint64" + } + ], + "internalType": "struct HeightData", + "name": "timeout_height", + "type": "tuple" + }, + { + "internalType": "uint64", + "name": "timeout_timestamp", + "type": "uint64" + } + ], + "internalType": "struct PacketData", + "name": "packet", + "type": "tuple" + }, + { + "internalType": "bytes", + "name": "proof", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "revision_number", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "revision_height", + "type": "uint64" + } + ], + "internalType": "struct HeightData", + "name": "proofHeight", + "type": "tuple" + }, + { + "internalType": "uint64", + "name": "nextSequenceRecv", + "type": "uint64" + } + ], + "internalType": "struct IBCMsgsMsgTimeoutPacket", + "name": "msg_", + "type": "tuple" + } + ], + "name": "timeoutPacket", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { diff --git a/hyperspace/ethereum/src/abi/ics20-transfer-bank-abi.json b/hyperspace/ethereum/src/abi/ics20-transfer-bank-abi.json index abf1b6ae6..a77bed825 100644 --- a/hyperspace/ethereum/src/abi/ics20-transfer-bank-abi.json +++ b/hyperspace/ethereum/src/abi/ics20-transfer-bank-abi.json @@ -402,6 +402,78 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint64", + "name": "sequence", + "type": "uint64" + }, + { + "internalType": "string", + "name": "source_port", + "type": "string" + }, + { + "internalType": "string", + "name": "source_channel", + "type": "string" + }, + { + "internalType": "string", + "name": "destination_port", + "type": "string" + }, + { + "internalType": "string", + "name": "destination_channel", + "type": "string" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "revision_number", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "revision_height", + "type": "uint64" + } + ], + "internalType": "struct HeightData", + "name": "timeout_height", + "type": "tuple" + }, + { + "internalType": "uint64", + "name": "timeout_timestamp", + "type": "uint64" + } + ], + "internalType": "struct PacketData", + "name": "packet", + "type": "tuple" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "onTimeoutPacket", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { diff --git a/hyperspace/ethereum/src/utils.rs b/hyperspace/ethereum/src/utils.rs index e75f44454..b7ed66b40 100644 --- a/hyperspace/ethereum/src/utils.rs +++ b/hyperspace/ethereum/src/utils.rs @@ -17,13 +17,13 @@ use ethers_solc::{ output_selection::OutputSelection, Libraries, Optimizer, OptimizerDetails, Settings, StorageLayout, }, - Artifact, ConfigurableContractArtifact, EvmVersion, Project, ProjectCompileOutput, - ProjectPathsConfig, SolcConfig, + Artifact, ArtifactOutput, ConfigurableContractArtifact, EvmVersion, Project, + ProjectCompileOutput, ProjectPathsConfig, SolcConfig, }; use ibc::core::{ics02_client::client_state::ClientType, ics04_channel::packet::Packet}; use std::{ borrow::Borrow, - collections::HashMap, + collections::{HashMap, HashSet}, fs::File, iter::once, path::{Path, PathBuf}, @@ -702,6 +702,30 @@ where .collect() } +pub fn check_code_size<'a>( + artifacts: impl Iterator, +) { + let ignore_list = ["Verifier"].into_iter().collect::>(); + artifacts + .filter_map(|(name, artifact)| { + Some((name, artifact.bytecode.as_ref()?.object.as_bytes()?.len())) + }) + .filter(|(name, _)| { + let ignored = ignore_list.contains(name.as_str()); + if ignored { + log::warn!("{} size is ignored", name); + } + !ignored + }) + .for_each(|(name, size)| { + let max = 24 * 1024; + if size > max { + panic!("{} size is too big: {}/{}", name, size, max); + } + log::info!("{} size: {}/{}", name, size, max); + }); +} + pub async fn deploy_yui_ibc( project_output: &ProjectCompileOutput, diamond_project_output: &ProjectCompileOutput, @@ -722,22 +746,8 @@ where OwnershipFacet, ]; - project_output.artifacts().for_each(|(name, artifact)| { - let size = artifact.bytecode.as_ref().unwrap().object.as_bytes().unwrap().len(); - let max = 24 * 1024; - if size > max { - panic!("{} size is too big: {}/{}", name, size, max); - } - log::info!("{} size: {}/{}", name, size, max); - }); - diamond_project_output.artifacts().for_each(|(name, artifact)| { - let size = artifact.bytecode.as_ref().unwrap().object.as_bytes().unwrap().len(); - let max = 24 * 1024; - if size > max { - panic!("{} size is too big: {}/{}", name, size, max); - } - log::info!("{} size: {}/{}", name, size, max); - }); + check_code_size(project_output.artifacts()); + check_code_size(diamond_project_output.artifacts()); let acc = client.default_sender().unwrap(); diff --git a/hyperspace/testsuite/tests/ethereum_cosmos.rs b/hyperspace/testsuite/tests/ethereum_cosmos.rs index ffe44be64..052bac56b 100644 --- a/hyperspace/testsuite/tests/ethereum_cosmos.rs +++ b/hyperspace/testsuite/tests/ethereum_cosmos.rs @@ -39,6 +39,10 @@ use hyperspace_ethereum::{ }, utils::{DeployYuiIbc, ProviderImpl}, }; +use hyperspace_ethereum::{ + ibc_provider::{Ics20BankAbi, SendPacketFilter, TransferInitiatedFilter}, + utils::check_code_size, +}; use hyperspace_parachain::{finality_protocol::FinalityProtocol, ParachainClientConfig}; use hyperspace_primitives::{utils::create_clients, CommonClientConfig, IbcProvider}; use hyperspace_testsuite::{ @@ -111,15 +115,7 @@ pub async fn deploy_yui_ibc_and_tendermint_client_fixture() -> DeployYuiIbcTende ) .await; - project_output1.artifacts().for_each(|(name, artifact)| { - if let Some(size) = artifact.bytecode.as_ref().unwrap().object.as_bytes().map(|x| x.len()) { - let max = 24 * 1024; - if size > max { - log::warn!("{} size is too big: {}/{}", name, size, max); - } - log::info!("{} size: {}/{}", name, size, max); - } - }); + check_code_size(project_output1.artifacts()); let upd = project_output1.find_first("DelegateTendermintUpdate").unwrap(); let (abi, bytecode, _) = upd.clone().into_parts(); diff --git a/light-clients/icsxx-ethereum/src/client_def.rs b/light-clients/icsxx-ethereum/src/client_def.rs index 5ba941f59..e5b0508a5 100644 --- a/light-clients/icsxx-ethereum/src/client_def.rs +++ b/light-clients/icsxx-ethereum/src/client_def.rs @@ -145,7 +145,7 @@ where b.execution_payload.block_number as u64, ); let cs = Ctx::AnyConsensusState::wrap(&ConsensusState::new( - b.execution_payload.state_root.clone(), // b.header.state_root? + b.execution_payload.state_root.clone(), b.execution_payload.timestamp, )) .unwrap();