diff --git a/.solhint.json b/.solhint.json
index 2a4f3ae..8a88fc3 100644
--- a/.solhint.json
+++ b/.solhint.json
@@ -1,7 +1,7 @@
{
"extends": "solhint:recommended",
"rules": {
- "code-complexity": ["error", 8],
+ "code-complexity": ["error", 11],
"compiler-version": ["error", ">=0.8.25"],
"func-name-mixedcase": "off",
"func-visibility": ["error", { "ignoreConstructors": true }],
diff --git a/Cargo.lock b/Cargo.lock
index 7ad2c8d..00b5502 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -5710,6 +5710,7 @@ dependencies = [
"serde",
"serde_cbor",
"serde_json",
+ "serde_with",
"sha2 0.10.8",
"sp1-ics07-tendermint-solidity",
"sp1-ics07-tendermint-update-client",
diff --git a/Cargo.toml b/Cargo.toml
index 66ecef0..725d78d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -66,6 +66,7 @@ async-trait = "0.1.80"
hex = "0.4.3"
prost = { version = "0.12", default-features = false }
futures = "0.3"
+serde_with = { version = "3.9.0", features = ["hex"] }
[patch.crates-io]
sha2-v0-9-8 = { git = "https://github.com/sp1-patches/RustCrypto-hashes", package = "sha2", branch = "patch-v0.9.8" }
diff --git a/README.md b/README.md
index e675bc9..b46fc06 100644
--- a/README.md
+++ b/README.md
@@ -3,14 +3,14 @@
[![Github Actions][gha-badge]][gha]
-[![Foundry][foundry-badge]][foundry]
+[![SP1][sp1-badge]][sp1]
[![License: MIT][license-badge]][license]
[gha]: https://github.com/cosmos/sp1-ics07-tendermint/actions
[gha-badge]: https://github.com/cosmos/sp1-ics07-tendermint/actions/workflows/e2e.yml/badge.svg
-[foundry]: https://getfoundry.sh/
-[foundry-badge]: https://img.shields.io/badge/Built%20with-Foundry-FFDB1C.svg
+[sp1]: https://github.com/succinctlabs/sp1
+[sp1-badge]: https://img.shields.io/badge/Built%20with-SP1-1D4351.svg
[license]: https://opensource.org/licenses/MIT
[license-badge]: https://img.shields.io/badge/License-MIT-blue.svg
@@ -58,6 +58,7 @@ This project contains the following programs
| `membership` | As consensus states are added to the client, they can be used for proof verification by relayers wishing to prove packet flow messages against a particular height on the counterparty. This uses the `verify_membership` and `verify_non_membership` methods on the tendermint client. | ✅ |
| `uc-and-membership` | This is a program that combines `update-client` and `membership` to update the client, and prove membership of packet flow messages against the new consensus state. | ✅ |
| `misbehaviour` | In case, the malicious subset of the validators exceeds the trust level of the client; then the client can be deceived into accepting invalid blocks and the connection is no longer secure. The tendermint client has some mitigations in place to prevent this. | ⏳ |
+| `upgrade-client` | The chain which this light client is tracking can elect to write a special pre-determined key in state to allow the light client to update its client state (e.g. with a new chain ID or revision). | ⏳ |
## Requirements
@@ -65,7 +66,7 @@ This project contains the following programs
- [SP1](https://succinctlabs.github.io/sp1/getting-started/install.html)
- [Foundry](https://book.getfoundry.sh/getting-started/installation)
- [Bun](https://bun.sh/)
-- [Just](https://just.systems/man/en/) (recommended)
+- [Just](https://just.systems/man/en/)
Foundry typically uses git submodules to manage contract dependencies, but this template uses Node.js packages (via Bun) because submodules don't scale. You can install the contracts dependencies by running the following command:
@@ -155,7 +156,8 @@ just test-foundry
There are several end-to-end tests in the `e2e/interchaintestv8` directory. These tests are written in Go and use the [`interchaintest`](https://github.com/strangelove-ventures/interchaintest) library. It spins up a local Ethereum and a Tendermint network and runs the tests found in [`e2e/interchaintestv8/sp1_ics07_test.go`](e2e/interchaintestv8/sp1_ics07_test.go). Some of the tests use the prover network to generate the proofs, so you need to provide your SP1 network private key to `.env` for these tests to pass.
-> If you are running on a mac with an M chip, you will need to do the following:
+> [!NOTE]
+> If you are running on a Mac with an M chip, you will need to do the following:
> - Set up Rosetta
> - Enable Rosetta for Docker (in Docker Desktop: Settings -> General -> enable "Use Rosetta for x86_64/amd64 emulation on Apple Silicon")
> - Pull the foundry image with the following command:
diff --git a/bun.lockb b/bun.lockb
index 560c37f..72bc1d7 100755
Binary files a/bun.lockb and b/bun.lockb differ
diff --git a/contracts/abi/SP1ICS07Tendermint.json b/contracts/abi/SP1ICS07Tendermint.json
index 6faa133..22bf14e 100644
--- a/contracts/abi/SP1ICS07Tendermint.json
+++ b/contracts/abi/SP1ICS07Tendermint.json
@@ -48,14 +48,66 @@
],
"stateMutability": "view"
},
+ {
+ "type": "function",
+ "name": "MEMBERSHIP_PROGRAM_VKEY",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "UPDATE_CLIENT_AND_MEMBERSHIP_PROGRAM_VKEY",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "UPDATE_CLIENT_PROGRAM_VKEY",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "VERIFIER",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "contract ISP1Verifier"
+ }
+ ],
+ "stateMutability": "view"
+ },
{
"type": "function",
"name": "abiPublicTypes",
"inputs": [
{
- "name": "output",
+ "name": "o1",
"type": "tuple",
- "internalType": "struct MembershipProgram.MembershipOutput",
+ "internalType": "struct IMembershipMsgs.MembershipOutput",
"components": [
{
"name": "commitmentRoot",
@@ -65,12 +117,12 @@
{
"name": "kvPairs",
"type": "tuple[]",
- "internalType": "struct MembershipProgram.KVPair[]",
+ "internalType": "struct IMembershipMsgs.KVPair[]",
"components": [
{
- "name": "key",
- "type": "string",
- "internalType": "string"
+ "name": "path",
+ "type": "bytes",
+ "internalType": "bytes"
},
{
"name": "value",
@@ -82,19 +134,19 @@
]
},
{
- "name": "output2",
+ "name": "o2",
"type": "tuple",
- "internalType": "struct UpdateClientAndMembershipProgram.UcAndMembershipOutput",
+ "internalType": "struct IUpdateClientAndMembershipMsgs.UcAndMembershipOutput",
"components": [
{
"name": "updateClientOutput",
"type": "tuple",
- "internalType": "struct UpdateClientProgram.UpdateClientOutput",
+ "internalType": "struct IUpdateClientMsgs.UpdateClientOutput",
"components": [
{
"name": "trustedConsensusState",
"type": "tuple",
- "internalType": "struct ICS07Tendermint.ConsensusState",
+ "internalType": "struct IICS07TendermintMsgs.ConsensusState",
"components": [
{
"name": "timestamp",
@@ -116,7 +168,7 @@
{
"name": "newConsensusState",
"type": "tuple",
- "internalType": "struct ICS07Tendermint.ConsensusState",
+ "internalType": "struct IICS07TendermintMsgs.ConsensusState",
"components": [
{
"name": "timestamp",
@@ -138,7 +190,7 @@
{
"name": "env",
"type": "tuple",
- "internalType": "struct UpdateClientProgram.Env",
+ "internalType": "struct IUpdateClientMsgs.Env",
"components": [
{
"name": "chainId",
@@ -148,7 +200,7 @@
{
"name": "trustThreshold",
"type": "tuple",
- "internalType": "struct ICS07Tendermint.TrustThreshold",
+ "internalType": "struct IICS07TendermintMsgs.TrustThreshold",
"components": [
{
"name": "numerator",
@@ -177,7 +229,7 @@
{
"name": "trustedHeight",
"type": "tuple",
- "internalType": "struct ICS07Tendermint.Height",
+ "internalType": "struct IICS02ClientMsgs.Height",
"components": [
{
"name": "revisionNumber",
@@ -194,7 +246,7 @@
{
"name": "newHeight",
"type": "tuple",
- "internalType": "struct ICS07Tendermint.Height",
+ "internalType": "struct IICS02ClientMsgs.Height",
"components": [
{
"name": "revisionNumber",
@@ -213,12 +265,12 @@
{
"name": "kvPairs",
"type": "tuple[]",
- "internalType": "struct MembershipProgram.KVPair[]",
+ "internalType": "struct IMembershipMsgs.KVPair[]",
"components": [
{
- "name": "key",
- "type": "string",
- "internalType": "string"
+ "name": "path",
+ "type": "bytes",
+ "internalType": "bytes"
},
{
"name": "value",
@@ -228,43 +280,136 @@
]
}
]
- }
- ],
- "outputs": [],
- "stateMutability": "pure"
- },
- {
- "type": "function",
- "name": "batchVerifyMembership",
- "inputs": [
- {
- "name": "proof",
- "type": "bytes",
- "internalType": "bytes"
},
{
- "name": "publicValues",
- "type": "bytes",
- "internalType": "bytes"
+ "name": "o3",
+ "type": "tuple",
+ "internalType": "struct IUpdateClientMsgs.MsgUpdateClient",
+ "components": [
+ {
+ "name": "sp1Proof",
+ "type": "tuple",
+ "internalType": "struct ISP1Msgs.SP1Proof",
+ "components": [
+ {
+ "name": "vKey",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ },
+ {
+ "name": "publicValues",
+ "type": "bytes",
+ "internalType": "bytes"
+ },
+ {
+ "name": "proof",
+ "type": "bytes",
+ "internalType": "bytes"
+ }
+ ]
+ }
+ ]
},
{
- "name": "proofHeight",
- "type": "uint32",
- "internalType": "uint32"
+ "name": "o4",
+ "type": "tuple",
+ "internalType": "struct IMembershipMsgs.MembershipProof",
+ "components": [
+ {
+ "name": "proofType",
+ "type": "uint8",
+ "internalType": "enum IMembershipMsgs.MembershipProofType"
+ },
+ {
+ "name": "proof",
+ "type": "bytes",
+ "internalType": "bytes"
+ }
+ ]
},
{
- "name": "trustedConsensusStateBz",
- "type": "bytes",
- "internalType": "bytes"
+ "name": "o5",
+ "type": "tuple",
+ "internalType": "struct IMembershipMsgs.SP1MembershipProof",
+ "components": [
+ {
+ "name": "sp1Proof",
+ "type": "tuple",
+ "internalType": "struct ISP1Msgs.SP1Proof",
+ "components": [
+ {
+ "name": "vKey",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ },
+ {
+ "name": "publicValues",
+ "type": "bytes",
+ "internalType": "bytes"
+ },
+ {
+ "name": "proof",
+ "type": "bytes",
+ "internalType": "bytes"
+ }
+ ]
+ },
+ {
+ "name": "trustedConsensusState",
+ "type": "tuple",
+ "internalType": "struct IICS07TendermintMsgs.ConsensusState",
+ "components": [
+ {
+ "name": "timestamp",
+ "type": "uint64",
+ "internalType": "uint64"
+ },
+ {
+ "name": "root",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ },
+ {
+ "name": "nextValidatorsHash",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ }
+ ]
+ }
+ ]
},
{
- "name": "kvPairHashes",
- "type": "bytes32[]",
- "internalType": "bytes32[]"
+ "name": "o6",
+ "type": "tuple",
+ "internalType": "struct IMembershipMsgs.SP1MembershipAndUpdateClientProof",
+ "components": [
+ {
+ "name": "sp1Proof",
+ "type": "tuple",
+ "internalType": "struct ISP1Msgs.SP1Proof",
+ "components": [
+ {
+ "name": "vKey",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ },
+ {
+ "name": "publicValues",
+ "type": "bytes",
+ "internalType": "bytes"
+ },
+ {
+ "name": "proof",
+ "type": "bytes",
+ "internalType": "bytes"
+ }
+ ]
+ }
+ ]
}
],
"outputs": [],
- "stateMutability": "view"
+ "stateMutability": "pure"
},
{
"type": "function",
@@ -274,7 +419,7 @@
{
"name": "",
"type": "tuple",
- "internalType": "struct ICS07Tendermint.ClientState",
+ "internalType": "struct IICS07TendermintMsgs.ClientState",
"components": [
{
"name": "chainId",
@@ -284,7 +429,7 @@
{
"name": "trustLevel",
"type": "tuple",
- "internalType": "struct ICS07Tendermint.TrustThreshold",
+ "internalType": "struct IICS07TendermintMsgs.TrustThreshold",
"components": [
{
"name": "numerator",
@@ -301,7 +446,7 @@
{
"name": "latestHeight",
"type": "tuple",
- "internalType": "struct ICS07Tendermint.Height",
+ "internalType": "struct IICS02ClientMsgs.Height",
"components": [
{
"name": "revisionNumber",
@@ -356,83 +501,291 @@
},
{
"type": "function",
- "name": "getVerifierInfo",
- "inputs": [],
+ "name": "membership",
+ "inputs": [
+ {
+ "name": "msgMembership",
+ "type": "tuple",
+ "internalType": "struct ILightClientMsgs.MsgMembership",
+ "components": [
+ {
+ "name": "proof",
+ "type": "bytes",
+ "internalType": "bytes"
+ },
+ {
+ "name": "proofHeight",
+ "type": "tuple",
+ "internalType": "struct IICS02ClientMsgs.Height",
+ "components": [
+ {
+ "name": "revisionNumber",
+ "type": "uint32",
+ "internalType": "uint32"
+ },
+ {
+ "name": "revisionHeight",
+ "type": "uint32",
+ "internalType": "uint32"
+ }
+ ]
+ },
+ {
+ "name": "path",
+ "type": "bytes",
+ "internalType": "bytes"
+ },
+ {
+ "name": "value",
+ "type": "bytes",
+ "internalType": "bytes"
+ }
+ ]
+ }
+ ],
+ "outputs": [
+ {
+ "name": "timestamp",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "updateClient",
+ "inputs": [
+ {
+ "name": "updateMsg",
+ "type": "bytes",
+ "internalType": "bytes"
+ }
+ ],
"outputs": [
{
"name": "",
- "type": "address",
- "internalType": "address"
+ "type": "uint8",
+ "internalType": "enum ILightClientMsgs.UpdateResult"
+ }
+ ],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "error",
+ "name": "CannotHandleMisbehavior",
+ "inputs": []
+ },
+ {
+ "type": "error",
+ "name": "ChainIdMismatch",
+ "inputs": [
+ {
+ "name": "expected",
+ "type": "string",
+ "internalType": "string"
},
{
- "name": "",
+ "name": "actual",
+ "type": "string",
+ "internalType": "string"
+ }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "ConsensusStateHashMismatch",
+ "inputs": [
+ {
+ "name": "expected",
"type": "bytes32",
"internalType": "bytes32"
},
{
- "name": "",
+ "name": "actual",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "ConsensusStateNotFound",
+ "inputs": []
+ },
+ {
+ "type": "error",
+ "name": "ConsensusStateRootMismatch",
+ "inputs": [
+ {
+ "name": "expected",
"type": "bytes32",
"internalType": "bytes32"
},
{
- "name": "",
+ "name": "actual",
"type": "bytes32",
"internalType": "bytes32"
}
- ],
- "stateMutability": "view"
+ ]
},
{
- "type": "function",
- "name": "updateClient",
+ "type": "error",
+ "name": "FrozenClientState",
+ "inputs": []
+ },
+ {
+ "type": "error",
+ "name": "LengthIsOutOfRange",
"inputs": [
{
- "name": "proof",
- "type": "bytes",
- "internalType": "bytes"
+ "name": "length",
+ "type": "uint256",
+ "internalType": "uint256"
},
{
- "name": "publicValues",
- "type": "bytes",
- "internalType": "bytes"
+ "name": "min",
+ "type": "uint256",
+ "internalType": "uint256"
+ },
+ {
+ "name": "max",
+ "type": "uint256",
+ "internalType": "uint256"
}
- ],
- "outputs": [
+ ]
+ },
+ {
+ "type": "error",
+ "name": "MembershipProofKeyNotFound",
+ "inputs": [
{
- "name": "",
- "type": "uint8",
- "internalType": "enum UpdateClientProgram.UpdateResult"
+ "name": "path",
+ "type": "bytes",
+ "internalType": "bytes"
}
- ],
- "stateMutability": "nonpayable"
+ ]
},
{
- "type": "function",
- "name": "updateClientAndBatchVerifyMembership",
+ "type": "error",
+ "name": "MembershipProofValueMismatch",
"inputs": [
{
- "name": "proof",
+ "name": "expected",
"type": "bytes",
"internalType": "bytes"
},
{
- "name": "publicValues",
+ "name": "actual",
"type": "bytes",
"internalType": "bytes"
+ }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "ProofIsInTheFuture",
+ "inputs": [
+ {
+ "name": "now",
+ "type": "uint256",
+ "internalType": "uint256"
},
{
- "name": "kvPairHashes",
- "type": "bytes32[]",
- "internalType": "bytes32[]"
+ "name": "proofTimestamp",
+ "type": "uint256",
+ "internalType": "uint256"
}
- ],
- "outputs": [
+ ]
+ },
+ {
+ "type": "error",
+ "name": "ProofIsTooOld",
+ "inputs": [
{
- "name": "",
- "type": "uint8",
- "internalType": "enum UpdateClientProgram.UpdateResult"
+ "name": "now",
+ "type": "uint256",
+ "internalType": "uint256"
+ },
+ {
+ "name": "proofTimestamp",
+ "type": "uint256",
+ "internalType": "uint256"
}
- ],
- "stateMutability": "nonpayable"
+ ]
+ },
+ {
+ "type": "error",
+ "name": "TrustThresholdMismatch",
+ "inputs": [
+ {
+ "name": "expectedNumerator",
+ "type": "uint256",
+ "internalType": "uint256"
+ },
+ {
+ "name": "expectedDenominator",
+ "type": "uint256",
+ "internalType": "uint256"
+ },
+ {
+ "name": "actualNumerator",
+ "type": "uint256",
+ "internalType": "uint256"
+ },
+ {
+ "name": "actualDenominator",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "TrustingPeriodMismatch",
+ "inputs": [
+ {
+ "name": "expected",
+ "type": "uint256",
+ "internalType": "uint256"
+ },
+ {
+ "name": "actual",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "TrustingPeriodTooLong",
+ "inputs": [
+ {
+ "name": "trustingPeriod",
+ "type": "uint256",
+ "internalType": "uint256"
+ },
+ {
+ "name": "unbondingPeriod",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "VerificationKeyMismatch",
+ "inputs": [
+ {
+ "name": "expected",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ },
+ {
+ "name": "actual",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ }
+ ]
}
]
diff --git a/contracts/fixtures/memberships_fixture.json b/contracts/fixtures/memberships_fixture.json
index 6a541a8..4016216 100644
--- a/contracts/fixtures/memberships_fixture.json
+++ b/contracts/fixtures/memberships_fixture.json
@@ -1,12 +1,9 @@
{
- "proofHeight": 2330000,
"trustedClientState": "000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000238d90000000000000000000000000000000000000000000000000000000000012750000000000000000000000000000000000000000000000000000000000001baf80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000076d6f6368612d3400000000000000000000000000000000000000000000000000",
"trustedConsensusState": "0000000000000000000000000000000000000000000000000000000066a03c102bab132312afa95add5dec8f90e2fdc48085e7494ca6d39ee9431ff434e22775e0373a8b805881ecdbb47fce30b66956aa13e9a573107ba9ac495b9cef3365d3",
- "commitmentRoot": "2bab132312afa95add5dec8f90e2fdc48085e7494ca6d39ee9431ff434e22775",
- "updateClientVkey": "0x00b8a6a2873e2eb2b0456023e69672caf877239e7c1f1b77cb84e7eb748af3eb",
- "membershipVkey": "0x005dee562962534ba45f120968c2e0eaa59ace5404e49252264f9f3699edad82",
- "ucAndMembershipVkey": "0x00dc223d082fda575a3950f0cf145ac567f7e479a44513e79a76f5f5529233a0",
- "publicValues": "0x00000000000000000000000000000000000000000000000000000000000000202bab132312afa95add5dec8f90e2fdc48085e7494ca6d39ee9431ff434e2277500000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000023636c69656e74732f30372d74656e6465726d696e742d302f636c69656e745374617465000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b70a2b2f6962632e6c69676874636c69656e74732e74656e6465726d696e742e76312e436c69656e7453746174651287010a1174686574612d746573746e65742d3030311204080110031a040880840722040880c60a2a02082832003a0510b7e3c60842190a090801180120012a0100120c0a02000110211804200c300142190a090801180120012a0100120c0a02000110201801200130014a07757067726164654a107570677261646564494243537461746550015801000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000025636c69656e74732f30372d74656e6465726d696e742d3030312f636c69656e7453746174650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "proof": "0xfedc1fcc2f7106806a2388f5fad021402976c5eaa2d33cacf0c01464140e1fbab0cdb5c212a6301c2afea26ffe31aecdd06a6a73692c4b5fe89b41c03882658d66f8fdce022040e51c6b1dcbfc6ab33ad21fdb5bbe9eace383578d5208d25555fffffb7727f20a4d7a38c1408de8cd2b96af70b1c3cc1ea1a25d20c510f1735b09b5a34b16c4f390ef1d31c31645d81f29f70752457c5cf572c897c21bb2f19434c0a00629da202ce9cf3e1dca24ff59899b80ccc55cdbe30c3fd67f8ed6cdd7529e5624211fe33f4c27a76e02f8cf4c04eac4097fd85e6c0f55ac61a96c77df982f738003500e106ad7e9008ef56c97e825fc99de6916df0f8baf1583dd8e77558438e321ce184b2123847adf6ce4f5b3570182bda369b7c29549b75adf09d0d8e2d486021d02f7c42733a3edb25aabc0bf237518da54548922f3dffc7a1ba9f9d8cce82c4b8e1913f97dc55fbad60d7330476fcf3542c328b25ac29c9156d2701a45b4296e7a70480ca56b320eecf3b3ec55f5033bea418753c479dce2fb60bd7ae4fb19466da70b7990c4a9c830bec94fc846e266128353a29c249f793ad108433704103a3391f038004ad80f2d4c6b0af9027778cf82260bfd7ad16ccfb33cb6165a0b4ed97b31a1d50f648c8c3931aa280204ee2bdc5db1cbca11b0fa8d5659e3442ddddf649b8ad9f27a0281e37a80d680eb253a7f03335aebe42117aea1aab8ce0dd7615312f4314de60b011c494ec4fa1c170322cac312ab98694c23317f6ccc26aace6ffc5327875ae4e9c566e6a00a98d81b0139f890400f8de89ee5f0ca030b1c0ac225569668a86f153af7b119b2b9fd9ed0a41dd83eb13d48b37eaa33361f3cc82b47e4502b79a2aa20b8f29c50c6fce5949e7d160b90a5c6af70bc85af1947df96d71ab3a1aeeca5e872d3b9228a4dd0019eaa4ce532db0ebf2025385f166c3e299968d5cfc258951ffb520e36b4f64eeecfda875f34af258b014ada4c17338aea3c87d89aa712620aead4d4bb78038b9d7a693bc9d5480e7633c9053c2a572bfc3892e30c2ef3f6aa2ac4542b517d4be9c176655c9962824ab445b73d046df05b70a07f7f35e57bbb40eac40a345cf41fd369643382dbf31efc250e432be1fe67399db3efe3326c8c7efe07528a6bebee99d2f92992e6416613f1c8ae1f19cc6d872571c585c7ae95d3117e2e5b9c8c2fbf5fa722a8c900e9e7e47460",
- "kvPairs": "00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000023636c69656e74732f30372d74656e6465726d696e742d302f636c69656e745374617465000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b70a2b2f6962632e6c69676874636c69656e74732e74656e6465726d696e742e76312e436c69656e7453746174651287010a1174686574612d746573746e65742d3030311204080110031a040880840722040880c60a2a02082832003a0510b7e3c60842190a090801180120012a0100120c0a02000110211804200c300142190a090801180120012a0100120c0a02000110201801200130014a07757067726164654a107570677261646564494243537461746550015801000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000025636c69656e74732f30372d74656e6465726d696e742d3030312f636c69656e7453746174650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
-}
\ No newline at end of file
+ "updateClientVkey": "0x00d8ae8feed5fd1f82dbf7862b219cd74c516e5d09ee5ec9024b439e95f5a3e2",
+ "membershipVkey": "0x001ae64fb3c0ac2e5a62e4941b26edf05798f0dc3417ae105e4bd1c443de6188",
+ "ucAndMembershipVkey": "0x008ddefe335385fdfe8e6eefcebe2f9519cb27e95afd392537657bb4525883f9",
+ "proofHeight": "00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000238d90",
+ "membershipProof": "00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000007c0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000066a03c102bab132312afa95add5dec8f90e2fdc48085e7494ca6d39ee9431ff434e22775e0373a8b805881ecdbb47fce30b66956aa13e9a573107ba9ac495b9cef3365d3001ae64fb3c0ac2e5a62e4941b26edf05798f0dc3417ae105e4bd1c443de618800000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000202bab132312afa95add5dec8f90e2fdc48085e7494ca6d39ee9431ff434e2277500000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000023636c69656e74732f30372d74656e6465726d696e742d302f636c69656e745374617465000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b70a2b2f6962632e6c69676874636c69656e74732e74656e6465726d696e742e76312e436c69656e7453746174651287010a1174686574612d746573746e65742d3030311204080110031a040880840722040880c60a2a02082832003a0510b7e3c60842190a090801180120012a0100120c0a02000110211804200c300142190a090801180120012a0100120c0a02000110201801200130014a07757067726164654a107570677261646564494243537461746550015801000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000025636c69656e74732f30372d74656e6465726d696e742d3030312f636c69656e74537461746500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000364fedc1fcc07811b854cbebd70a778c6cb49649c3272a078f8f232a29b0470d134d28d670a0abdf1051fbebab954294ee6844dce87e2ca2f22da6e1c4dfd3003f99d843dce1d007ef3e06b43faf857392ee147d57ac29d7a3ea1f8c808becd6bf29e1e69ad1252c82e35bbc3d0e27b1054140a7acdfd5a8767d04e3c6861f34d284304f1980286ce6d2ce4a1845d528e04f096beb4f063665c13bfb5470adc74b2ac346bf31012ef4a3ac183786449b39dc4fae7f7120da7078a100a88eb2c9bf37d6791b21d4a8ca48f4e793863d3b8d3a011683d4cb2dec6febe645139627e4aa32426640dbb2cb851d7da339bbb1bcb0dd0252aaa2c4da8441a283c48b0e7b2e60914a0142a43fcf9ed3408c49540039a0cf50d18d9543029654eb454516873cfb143fa14769b4cc3c6369e561b50c20fdb9f1870aa1f3b15dd0d8e794044bbcfc6a5f50d0533e61f243bcc7b492de91b219cc233f67754b434250516c8390d95e686670391e491acddcc4e611b11ec6b32b8ef8d3efb7f6ee983f8a0ef150e06ac3e1b1350bbcc6f8d3e3b2b83e572fc839449268c54b9523b0b7b7880185206a4ab7806b4e3c795fc00d42b62d73d244c294dc557d1cc54a113c93ac6888133c41411302b2ec6c6dff6a09217d2c5644542d76272e2f942f428b8ec6561e8ae66ed9402af4197a5b794da79e8d6236457d63bf99245f55b885154d4caf4739714b3e12c2f484039ca1af1ba45452512486ae82758c6280cda54510cc8dc327ba8fcbe043caba365df3bf67292fa481c3edb5d686a6af55f610570156ebeb663bd7c420f17104104a8d19898a10152b09391be54d2e3bbfe376fbe889529deee25b7a22fff51d27d0b6dcffad97cb6eb3ff50949b7f61797d3550097db4bc8097a8a8a095267777cd10c708963a3f7ac8f7ba960ae1ba3d6913843e189d9adeba36db1234e5b331d47228818a6ed07086a3a624a1110aaa3c400ec0806030cb14b495921701ed981bab9a6ca62fa45747b8910e13dbd083da9e5540e9d0bb39b21b9121fa8d061ce81d874e7707977878183ac482b4476f7382fa373df22a67556e7bb264090d48814f7fb8480df0a68074aca027d340bc2c852f393cc13ed67a9e9a521ab429a8d1f60e84815d69fa57fd6f490e4b6fd87b149057bc82e119a5ba13b2ce0ff8a5c227464b239351be3626cded845f46d6c78c80d7cbf90376c2a485400000000000000000000000000000000000000000000000000000000"
+}
diff --git a/contracts/fixtures/mock_memberships_fixture.json b/contracts/fixtures/mock_memberships_fixture.json
deleted file mode 100644
index e842ba4..000000000
--- a/contracts/fixtures/mock_memberships_fixture.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "proofHeight": 2230264,
- "trustedClientState": "0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000002207f800000000000000000000000000000000000000000000000000000000001baf8000000000000000000000000000000000000000000000000000000000001baf80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000076d6f6368612d3400000000000000000000000000000000000000000000000000",
- "trustedConsensusState": "00000000000000000000000000000000000000000000000000000000668df173c7656d84561185b88f82507efaa6d578b46ebe5010c0d37de05109254d2f9ff1b655d16f9452ed96e4d7cf8143e927a1e0d9ff1e1d315f134f2ad6b798b35ce0",
- "commitmentRoot": "c7656d84561185b88f82507efaa6d578b46ebe5010c0d37de05109254d2f9ff1",
- "updateClientVkey": "0x00dccbd5282da6b04c730721f21b40fee41302d148eb16d1aede6632224a1874",
- "membershipVkey": "0x0083f60b9a6e2c5eecbeec4d63514073ea981defcaa39e4a06339152067fa699",
- "ucAndMembershipVkey": "0x0071a54676e22f1e088807fe801e79f2d419a1f48242e764b244a1683bf6a02a",
- "publicValues": "0x0000000000000000000000000000000000000000000000000000000000000020c7656d84561185b88f82507efaa6d578b46ebe5010c0d37de05109254d2f9ff100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000023636c69656e74732f30372d74656e6465726d696e742d302f636c69656e745374617465000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b70a2b2f6962632e6c69676874636c69656e74732e74656e6465726d696e742e76312e436c69656e7453746174651287010a1174686574612d746573746e65742d3030311204080110031a040880840722040880c60a2a02082832003a0510b7e3c60842190a090801180120012a0100120c0a02000110211804200c300142190a090801180120012a0100120c0a02000110201801200130014a07757067726164654a107570677261646564494243537461746550015801000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000025636c69656e74732f30372d74656e6465726d696e742d3030312f636c69656e7453746174650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "proof": "0x00000000",
- "kvPairs": "00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000023636c69656e74732f30372d74656e6465726d696e742d302f636c69656e745374617465000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b70a2b2f6962632e6c69676874636c69656e74732e74656e6465726d696e742e76312e436c69656e7453746174651287010a1174686574612d746573746e65742d3030311204080110031a040880840722040880c60a2a02082832003a0510b7e3c60842190a090801180120012a0100120c0a02000110211804200c300142190a090801180120012a0100120c0a02000110201801200130014a07757067726164654a107570677261646564494243537461746550015801000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000025636c69656e74732f30372d74656e6465726d696e742d3030312f636c69656e7453746174650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
-}
\ No newline at end of file
diff --git a/contracts/fixtures/mock_uc_and_memberships_fixture.json b/contracts/fixtures/mock_uc_and_memberships_fixture.json
deleted file mode 100644
index eccb772..000000000
--- a/contracts/fixtures/mock_uc_and_memberships_fixture.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "trustedClientState": "000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000238d90000000000000000000000000000000000000000000000000000000000012750000000000000000000000000000000000000000000000000000000000001baf80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000076d6f6368612d3400000000000000000000000000000000000000000000000000",
- "trustedConsensusState": "0000000000000000000000000000000000000000000000000000000066a03c102bab132312afa95add5dec8f90e2fdc48085e7494ca6d39ee9431ff434e22775e0373a8b805881ecdbb47fce30b66956aa13e9a573107ba9ac495b9cef3365d3",
- "targetConsensusState": "0000000000000000000000000000000000000000000000000000000066a03c8ace271cd333ff2f0cd166fe30bcd67431aca0d94c5c8ed0079a30761311bbd3a2e0373a8b805881ecdbb47fce30b66956aa13e9a573107ba9ac495b9cef3365d3",
- "targetHeight": 2330010,
- "updateClientVkey": "0x00b063f9e7801cf716517d15f440ca4ed60ec44ee399f7581720abba843470e6",
- "membershipVkey": "0x00cbb765f4e3196e7322a30d7963d330e3fe67eb1904b977e0cb92bb11c31e9e",
- "ucAndMembershipVkey": "0x001fd7cbd018123bee2ec2dcfa2f12355138ff29bb9b68840a25026a94c46c4f",
- "publicValues": "0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000066a03c102bab132312afa95add5dec8f90e2fdc48085e7494ca6d39ee9431ff434e22775e0373a8b805881ecdbb47fce30b66956aa13e9a573107ba9ac495b9cef3365d30000000000000000000000000000000000000000000000000000000066a03c8ace271cd333ff2f0cd166fe30bcd67431aca0d94c5c8ed0079a30761311bbd3a2e0373a8b805881ecdbb47fce30b66956aa13e9a573107ba9ac495b9cef3365d3000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000238d9000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000238d9a00000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000001275000000000000000000000000000000000000000000000000000000000066a0c8a000000000000000000000000000000000000000000000000000000000000000076d6f6368612d34000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000023636c69656e74732f30372d74656e6465726d696e742d302f636c69656e745374617465000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b70a2b2f6962632e6c69676874636c69656e74732e74656e6465726d696e742e76312e436c69656e7453746174651287010a1174686574612d746573746e65742d3030311204080110031a040880840722040880c60a2a02082832003a0510b7e3c60842190a090801180120012a0100120c0a02000110211804200c300142190a090801180120012a0100120c0a02000110201801200130014a07757067726164654a107570677261646564494243537461746550015801000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000025636c69656e74732f30372d74656e6465726d696e742d3030312f636c69656e7453746174650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "proof": "0x00000000",
- "kvPairs": "00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000023636c69656e74732f30372d74656e6465726d696e742d302f636c69656e745374617465000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b70a2b2f6962632e6c69676874636c69656e74732e74656e6465726d696e742e76312e436c69656e7453746174651287010a1174686574612d746573746e65742d3030311204080110031a040880840722040880c60a2a02082832003a0510b7e3c60842190a090801180120012a0100120c0a02000110211804200c300142190a090801180120012a0100120c0a02000110201801200130014a07757067726164654a107570677261646564494243537461746550015801000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000025636c69656e74732f30372d74656e6465726d696e742d3030312f636c69656e7453746174650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
-}
\ No newline at end of file
diff --git a/contracts/fixtures/mock_update_client_fixture.json b/contracts/fixtures/mock_update_client_fixture.json
deleted file mode 100644
index 328bbe4..000000000
--- a/contracts/fixtures/mock_update_client_fixture.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "trustedClientState": "000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000238d90000000000000000000000000000000000000000000000000000000000012750000000000000000000000000000000000000000000000000000000000001baf80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000076d6f6368612d3400000000000000000000000000000000000000000000000000",
- "trustedConsensusState": "0000000000000000000000000000000000000000000000000000000066a03c102bab132312afa95add5dec8f90e2fdc48085e7494ca6d39ee9431ff434e22775e0373a8b805881ecdbb47fce30b66956aa13e9a573107ba9ac495b9cef3365d3",
- "targetConsensusState": "0000000000000000000000000000000000000000000000000000000066a03c8ace271cd333ff2f0cd166fe30bcd67431aca0d94c5c8ed0079a30761311bbd3a2e0373a8b805881ecdbb47fce30b66956aa13e9a573107ba9ac495b9cef3365d3",
- "targetHeight": 2330010,
- "updateClientVkey": "0x00b063f9e7801cf716517d15f440ca4ed60ec44ee399f7581720abba843470e6",
- "membershipVkey": "0x00cbb765f4e3196e7322a30d7963d330e3fe67eb1904b977e0cb92bb11c31e9e",
- "ucAndMembershipVkey": "0x001fd7cbd018123bee2ec2dcfa2f12355138ff29bb9b68840a25026a94c46c4f",
- "publicValues": "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000066a03c102bab132312afa95add5dec8f90e2fdc48085e7494ca6d39ee9431ff434e22775e0373a8b805881ecdbb47fce30b66956aa13e9a573107ba9ac495b9cef3365d30000000000000000000000000000000000000000000000000000000066a03c8ace271cd333ff2f0cd166fe30bcd67431aca0d94c5c8ed0079a30761311bbd3a2e0373a8b805881ecdbb47fce30b66956aa13e9a573107ba9ac495b9cef3365d3000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000238d9000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000238d9a00000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000001275000000000000000000000000000000000000000000000000000000000066a0c89100000000000000000000000000000000000000000000000000000000000000076d6f6368612d3400000000000000000000000000000000000000000000000000",
- "proof": "0x00000000"
-}
\ No newline at end of file
diff --git a/contracts/fixtures/mock_verify_membership_fixture.json b/contracts/fixtures/mock_verify_membership_fixture.json
deleted file mode 100644
index 1a310fb..000000000
--- a/contracts/fixtures/mock_verify_membership_fixture.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "proofHeight": 2230264,
- "trustedClientState": "0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000002207f800000000000000000000000000000000000000000000000000000000001baf8000000000000000000000000000000000000000000000000000000000001baf80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000076d6f6368612d3400000000000000000000000000000000000000000000000000",
- "trustedConsensusState": "00000000000000000000000000000000000000000000000000000000668df173c7656d84561185b88f82507efaa6d578b46ebe5010c0d37de05109254d2f9ff1b655d16f9452ed96e4d7cf8143e927a1e0d9ff1e1d315f134f2ad6b798b35ce0",
- "commitmentRoot": "c7656d84561185b88f82507efaa6d578b46ebe5010c0d37de05109254d2f9ff1",
- "updateClientVkey": "0x00dccbd5282da6b04c730721f21b40fee41302d148eb16d1aede6632224a1874",
- "membershipVkey": "0x0083f60b9a6e2c5eecbeec4d63514073ea981defcaa39e4a06339152067fa699",
- "ucAndMembershipVkey": "0x0071a54676e22f1e088807fe801e79f2d419a1f48242e764b244a1683bf6a02a",
- "publicValues": "0x0000000000000000000000000000000000000000000000000000000000000020c7656d84561185b88f82507efaa6d578b46ebe5010c0d37de05109254d2f9ff1000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000023636c69656e74732f30372d74656e6465726d696e742d302f636c69656e745374617465000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b70a2b2f6962632e6c69676874636c69656e74732e74656e6465726d696e742e76312e436c69656e7453746174651287010a1174686574612d746573746e65742d3030311204080110031a040880840722040880c60a2a02082832003a0510b7e3c60842190a090801180120012a0100120c0a02000110211804200c300142190a090801180120012a0100120c0a02000110201801200130014a07757067726164654a107570677261646564494243537461746550015801000000000000000000",
- "proof": "0x00000000",
- "kvPairs": "000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000023636c69656e74732f30372d74656e6465726d696e742d302f636c69656e745374617465000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b70a2b2f6962632e6c69676874636c69656e74732e74656e6465726d696e742e76312e436c69656e7453746174651287010a1174686574612d746573746e65742d3030311204080110031a040880840722040880c60a2a02082832003a0510b7e3c60842190a090801180120012a0100120c0a02000110211804200c300142190a090801180120012a0100120c0a02000110201801200130014a07757067726164654a107570677261646564494243537461746550015801000000000000000000"
-}
\ No newline at end of file
diff --git a/contracts/fixtures/uc_and_memberships_fixture.json b/contracts/fixtures/uc_and_memberships_fixture.json
index 3649327..2c445cf 100644
--- a/contracts/fixtures/uc_and_memberships_fixture.json
+++ b/contracts/fixtures/uc_and_memberships_fixture.json
@@ -1,12 +1,9 @@
{
"trustedClientState": "000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000238d90000000000000000000000000000000000000000000000000000000000012750000000000000000000000000000000000000000000000000000000000001baf80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000076d6f6368612d3400000000000000000000000000000000000000000000000000",
"trustedConsensusState": "0000000000000000000000000000000000000000000000000000000066a03c102bab132312afa95add5dec8f90e2fdc48085e7494ca6d39ee9431ff434e22775e0373a8b805881ecdbb47fce30b66956aa13e9a573107ba9ac495b9cef3365d3",
- "targetConsensusState": "0000000000000000000000000000000000000000000000000000000066a03c8ace271cd333ff2f0cd166fe30bcd67431aca0d94c5c8ed0079a30761311bbd3a2e0373a8b805881ecdbb47fce30b66956aa13e9a573107ba9ac495b9cef3365d3",
- "targetHeight": 2330010,
- "updateClientVkey": "0x00b8a6a2873e2eb2b0456023e69672caf877239e7c1f1b77cb84e7eb748af3eb",
- "membershipVkey": "0x005dee562962534ba45f120968c2e0eaa59ace5404e49252264f9f3699edad82",
- "ucAndMembershipVkey": "0x00dc223d082fda575a3950f0cf145ac567f7e479a44513e79a76f5f5529233a0",
- "publicValues": "0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000066a03c102bab132312afa95add5dec8f90e2fdc48085e7494ca6d39ee9431ff434e22775e0373a8b805881ecdbb47fce30b66956aa13e9a573107ba9ac495b9cef3365d30000000000000000000000000000000000000000000000000000000066a03c8ace271cd333ff2f0cd166fe30bcd67431aca0d94c5c8ed0079a30761311bbd3a2e0373a8b805881ecdbb47fce30b66956aa13e9a573107ba9ac495b9cef3365d3000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000238d9000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000238d9a00000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000001275000000000000000000000000000000000000000000000000000000000066a23fa200000000000000000000000000000000000000000000000000000000000000076d6f6368612d34000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000023636c69656e74732f30372d74656e6465726d696e742d302f636c69656e745374617465000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b70a2b2f6962632e6c69676874636c69656e74732e74656e6465726d696e742e76312e436c69656e7453746174651287010a1174686574612d746573746e65742d3030311204080110031a040880840722040880c60a2a02082832003a0510b7e3c60842190a090801180120012a0100120c0a02000110211804200c300142190a090801180120012a0100120c0a02000110201801200130014a07757067726164654a107570677261646564494243537461746550015801000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000025636c69656e74732f30372d74656e6465726d696e742d3030312f636c69656e7453746174650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "proof": "0xfedc1fcc0decf5c6ef20d1568f9f087047c4f426f95bbad2080fb86074fea6ab104c102a00b5203a430029799b0be9f6e5c29982b67e6e54d9e8da8aa7956d75b9cea90d0b62bec78d7fe5882af92d40c34b74eb066a02aa7aaaaae12d02dc5caa70bf480d713d5abbd7b7a499102cc8c260c4a2c8c16b90d08ddeacbbe755b91981a8f92962fa72484b245aa87f6be63e3be69f48615650fec4ba06c451f524f58a1e82168dcdeafde2997c7e7443d286082ba80368dedc8c54fe4b94a20cad10631f7a21385fce909b0927c36902932dd06f6efb0da383aadd5826e56009642463543f085d407c66c194e74bea82b4f46a4752c0a817148b730207d94980d2b55b8c0d0ca860acfd628375205a26c9a115ee11dd628cc6074ba0cd2bd613b24377f5e40f906a969862b6881fcc116bda60939d7f2f22a6fe14af14063f21a88eebf0ae1843dfce39a618366e1551e1f846f9b7e843f31ccddfdb83aaf3efd63a8543b72ab094908724bf3b46d47432e005d2b338f50aa7418e82a04b106f91338deba82a1dfab0875ed411d484c4f68df2fa5df69b9fbfbe417781a93a3aadc5db50472bba0eea4fc33a2fed9049f003fd36c49b48b31e00628e30796d771ef35bd5d5095a417034c2bec400d2aa808680513bb3fb2ca7fce197dd3e1e2d749e48687e106b7e37be6b496b8c1203b4c53ef5b80053261a0d901bf46e88e1ec27635e1f2407204d341baaa875736a576f4082ee731f541ffef4cd8909a7a0da6f4fe37e0fa511a9ce5475a3284a484265d851a8fb763ee366f0bd6237a423f3aa602c5d0070e4ec36c8839d978aef1710c0f43b155638a7988382be1ba59bf307ba256d10309fcbc955a9b3b786ac12a8d62764c527dd9ad4fe203d1897b0b85d2d002821b6235d0d1add158052a8ff38735be4727f445bea6d93a522e9e53d894b375b24c0e466dfd3d9acc2ac2bc02a7029ef674d404f10e007a703c2570acdd2a0f72b29a3496110f9cebd389421d9b369499e0b80fcadc08058ab54969440bfc1e4249be8ab9294fa69de9b850cf309d6d42274614436c1714901f21aa24ad428c403c6646a7403ec2a594877c178ecf6e9d99287797ad44e252028ad89d8cae012166393f7a88d51fbc8a42843ff66d1c941a68b7110da2f31db4a86ddf7e91fe426d3d5c4d7d54fc88006313ec5235f94d4d1d31f11d7329a1e007a92f6636dcf",
- "kvPairs": "00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000023636c69656e74732f30372d74656e6465726d696e742d302f636c69656e745374617465000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b70a2b2f6962632e6c69676874636c69656e74732e74656e6465726d696e742e76312e436c69656e7453746174651287010a1174686574612d746573746e65742d3030311204080110031a040880840722040880c60a2a02082832003a0510b7e3c60842190a090801180120012a0100120c0a02000110211804200c300142190a090801180120012a0100120c0a02000110201801200130014a07757067726164654a107570677261646564494243537461746550015801000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000025636c69656e74732f30372d74656e6465726d696e742d3030312f636c69656e7453746174650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
+ "updateClientVkey": "0x00d8ae8feed5fd1f82dbf7862b219cd74c516e5d09ee5ec9024b439e95f5a3e2",
+ "membershipVkey": "0x001ae64fb3c0ac2e5a62e4941b26edf05798f0dc3417ae105e4bd1c443de6188",
+ "ucAndMembershipVkey": "0x008ddefe335385fdfe8e6eefcebe2f9519cb27e95afd392537657bb4525883f9",
+ "proofHeight": "00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000238d9a",
+ "membershipProof": "00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000009a000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020008ddefe335385fdfe8e6eefcebe2f9519cb27e95afd392537657bb4525883f9000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000005c000000000000000000000000000000000000000000000000000000000000005400000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000066a03c102bab132312afa95add5dec8f90e2fdc48085e7494ca6d39ee9431ff434e22775e0373a8b805881ecdbb47fce30b66956aa13e9a573107ba9ac495b9cef3365d30000000000000000000000000000000000000000000000000000000066a03c8ace271cd333ff2f0cd166fe30bcd67431aca0d94c5c8ed0079a30761311bbd3a2e0373a8b805881ecdbb47fce30b66956aa13e9a573107ba9ac495b9cef3365d3000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000238d9000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000238d9a00000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000001275000000000000000000000000000000000000000000000000000000000066a78ab500000000000000000000000000000000000000000000000000000000000000076d6f6368612d34000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000023636c69656e74732f30372d74656e6465726d696e742d302f636c69656e745374617465000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b70a2b2f6962632e6c69676874636c69656e74732e74656e6465726d696e742e76312e436c69656e7453746174651287010a1174686574612d746573746e65742d3030311204080110031a040880840722040880c60a2a02082832003a0510b7e3c60842190a090801180120012a0100120c0a02000110211804200c300142190a090801180120012a0100120c0a02000110201801200130014a07757067726164654a107570677261646564494243537461746550015801000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000025636c69656e74732f30372d74656e6465726d696e742d3030312f636c69656e74537461746500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000364fedc1fcc1a4b3d8e0dbccc49b477072c7c8158316eec15529b381baf333c53e5708df89e003118c1c0ebae3bdb4947749018628f6a3388bfbb2cad59c85b4fca020e264617abb3cff089ad1f0b5e881f7c6ff19672022bbcac1de7c7a784fdde3d5f759327abb7e89154625253e5b308d2addfb2abb95cb243dec4780abba2dbcac07e7a2f682f08bd5ee3cfcf7ca249f7f748fbd6e31e31163e1b44145a8b7f887ce5cb110f09c6e8dd82e6c28eda8c64afd08ac944a9fd30e27b2127cd3f0e3995bce43010c09319ae02deaa82ed45fb6bbbd03b382a73bafecd436113890c8c2268420d15e1c05b3ee05be5d24fb891bf9129f49177c5a38eacfa9c3770fd3035d8d510592dea5229c68510ac0ef595f9c24eac274671732c490a87a05b3a28fccc6322954f3a48d7ebf11a859d2d8e67a6f5f66e4c5e19e903170299adffa820d5e222e035f2f7273355bc341ab14d3c63f310b70cba5030e098cd494117072c93bc08ee53615704fd42c025cb3a34ca545a577b2679387e54066d5f1ffba41d576c223baac0f4f43a0d8cf45af70a30b50ede8f951ac662077ff73936d940d1ad50232b5b2de6f7523aad2203e9eedc5c0cf207c74481fda2ebd7c2e1c3eabef36f1bd12598235ace606b15da53f94c24c40b51baaf3767b7dbe8e7fb583e4e33da1543c8185ebdc566229eb8d30f403c47ce81e98ee7e4ab2b7964cfb6a60d4d4d1cce047ca11c49e5b8cb40577a14d91c7fe838bd35a2e8fa6f8cd84020e5037d123afd9557937529665cf75c47b3f7d56f9227df29be8f332ed1c37ef387a72b22c6df0b6f827f3783d9b5e541858db82150910c8a690146c320234bebc304f9020bef12fc2e4c2b06f6a21965e2fb50aef3794e6e4c6b298e195d71f7c2498914de80e87d7f411987011cc07f00061d9b40f82878506705506c7968f00efe811e7b16a1a34cdae472c9d84665f4b57bb025d848eebdd1aec859f86fa70a12c116807e938312c91f93456783b45b282b6a7f7b00cd1b78561dd8fbd9fd25a8981e750869e6731010ac042b925258d00899648795241e6831a1d01a3dde70a97d03e3052d67e437c1e3ad2fbbc8b3b040a9ae25a6ecacaccde41ea29bf3da1d2c2c4382aaff91ea37e2b9138833cd1c23a5790581079295c3636706dc4614c19e1b26ca404e9dfca7cd48ddd8026f66eae7429846a8209cea42bfea7ce0a1375000000000000000000000000000000000000000000000000000000000"
}
\ No newline at end of file
diff --git a/contracts/fixtures/update_client_fixture.json b/contracts/fixtures/update_client_fixture.json
index defce54..1a9e034 100644
--- a/contracts/fixtures/update_client_fixture.json
+++ b/contracts/fixtures/update_client_fixture.json
@@ -1,11 +1,10 @@
{
"trustedClientState": "000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000238d90000000000000000000000000000000000000000000000000000000000012750000000000000000000000000000000000000000000000000000000000001baf80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000076d6f6368612d3400000000000000000000000000000000000000000000000000",
"trustedConsensusState": "0000000000000000000000000000000000000000000000000000000066a03c102bab132312afa95add5dec8f90e2fdc48085e7494ca6d39ee9431ff434e22775e0373a8b805881ecdbb47fce30b66956aa13e9a573107ba9ac495b9cef3365d3",
+ "updateClientVkey": "0x00d8ae8feed5fd1f82dbf7862b219cd74c516e5d09ee5ec9024b439e95f5a3e2",
+ "membershipVkey": "0x001ae64fb3c0ac2e5a62e4941b26edf05798f0dc3417ae105e4bd1c443de6188",
+ "ucAndMembershipVkey": "0x008ddefe335385fdfe8e6eefcebe2f9519cb27e95afd392537657bb4525883f9",
"targetConsensusState": "0000000000000000000000000000000000000000000000000000000066a03c8ace271cd333ff2f0cd166fe30bcd67431aca0d94c5c8ed0079a30761311bbd3a2e0373a8b805881ecdbb47fce30b66956aa13e9a573107ba9ac495b9cef3365d3",
"targetHeight": 2330010,
- "updateClientVkey": "0x00b8a6a2873e2eb2b0456023e69672caf877239e7c1f1b77cb84e7eb748af3eb",
- "membershipVkey": "0x005dee562962534ba45f120968c2e0eaa59ace5404e49252264f9f3699edad82",
- "ucAndMembershipVkey": "0x00dc223d082fda575a3950f0cf145ac567f7e479a44513e79a76f5f5529233a0",
- "publicValues": "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000066a03c102bab132312afa95add5dec8f90e2fdc48085e7494ca6d39ee9431ff434e22775e0373a8b805881ecdbb47fce30b66956aa13e9a573107ba9ac495b9cef3365d30000000000000000000000000000000000000000000000000000000066a03c8ace271cd333ff2f0cd166fe30bcd67431aca0d94c5c8ed0079a30761311bbd3a2e0373a8b805881ecdbb47fce30b66956aa13e9a573107ba9ac495b9cef3365d3000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000238d9000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000238d9a00000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000001275000000000000000000000000000000000000000000000000000000000066a365de00000000000000000000000000000000000000000000000000000000000000076d6f6368612d3400000000000000000000000000000000000000000000000000",
- "proof": "0xfedc1fcc24c655481805f42c8b8f22e968ab2f97506f902740ecdb6b94edd518477991481158eb6fbd85f8b7c6b56795e0a4e82de6f1afa30f7d720f688abf7feba9d4ed0b708984613e55e9e7a3b93d79c3267e556e924d585eb7e503b25878afd7a3b426cb1ce0ee343d3c2d2f9e58182dc12d19677a37fbb19a2533e846527d4296c52c4bf6de2a6812bef3aaae1471cf1ba8a24da64d7b173838180924698d0519a52389408e9c71b92a8aa97e3440504793e3ea4f454049b1878b0191797261d8ff2f13aa0a89d2f1499bb2504c6f225d4ebe5f90125cd0ad0b06b1396b3a8582f6045011cc5d4aa1e746a5bd69b7ebe6cf7fb45fbf0b1b9fcd91730b7d1dba8dd7035b0a45ab05acbda57fe2e8fc4f7521464fe7081e80106e1871ce2bbd11c1c30897c18f49794335ab980dc688f98f7fd132bc62c0a09eeadaea0fbd52e5b4dd2debed1d7ba5ac4e39c3b0b588451a981f69ea77172e35497cd6ead2935475191e97daa7fbb8f14d97b3262621425b0f792fa5cc9bc27bc73308439963d1ae8c11f4ff5cc261bb2d7a42101004b6792987270652c55a4a808202953574ad131a1740a2bd915159e02edf0f9bc69b270b83fde1f6cd91507bcf81cfae7496d584046bd2d3557d6559c9512eb894c85d72d6251e862fef2897780dd2330cc14e3a281316a23d96b8d5dc7360271868504ef45d0d5171e27531ba6cec82a46c3c8704c299e72a89baf38a24b2bbb53a120c76386d560ea960253259fa9e24921b64148f529dcece953bab1bd45459709bce3a0d80e1d62f21a44a7da62d7150f14319d00074d76e3754dfd6047e87fdafbc7f2e59e30c626ffb93273999f949edad140e009464288501752f5a6a9298e4ba61ff1a1bf305eaf20e6808ec6edefcfa22b7ab84a986a44481c958d4a231037c3c28fd5f28b51af87a5b4f2e936364eb06ba23424ecc3cd4028e87a023e43ca1b31ca648b26125f2ec3d9089ed75863a1631c3500e39d96cb98ed80b8a6bb72a626c08f3e2843d7ad71d6495319b265623d3914fbefa0b8e0fc8c7f42310bea3636f7db8f21e7499da6f8afcda56c59f2d6c99298ba4ed8ecbc42b737006101fb793b2c78843cd4cb5e18a4978f7a78703e83f371230c8c030acf0a81e31e60b61789e4c93287e406a0c8888649b45f72efe2781ab733d7dbd19ba80b2c29fb12503899f348a54e64823fee0d8ef934f"
+ "updateMsg": "0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000d8ae8feed5fd1f82dbf7862b219cd74c516e5d09ee5ec9024b439e95f5a3e2000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000066a03c102bab132312afa95add5dec8f90e2fdc48085e7494ca6d39ee9431ff434e22775e0373a8b805881ecdbb47fce30b66956aa13e9a573107ba9ac495b9cef3365d30000000000000000000000000000000000000000000000000000000066a03c8ace271cd333ff2f0cd166fe30bcd67431aca0d94c5c8ed0079a30761311bbd3a2e0373a8b805881ecdbb47fce30b66956aa13e9a573107ba9ac495b9cef3365d3000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000238d9000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000238d9a00000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000001275000000000000000000000000000000000000000000000000000000000066a7791a00000000000000000000000000000000000000000000000000000000000000076d6f6368612d34000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000364fedc1fcc21d4cb89fedbd13cf9acd5731f20c369f38718bdf8b94180c1adabe6378dfc7a27e2e9173d73b69982cf970f53b7b62f79ed4803dbb0a5f6869f266b327771ea1040398aba67924a2d59d9815032337af9fa1dc5f61005711c47981d474e9a57222f80f1c524aec826bd7bf6cb9a497ac72b24b05d788d61b0ed60903431bc011df07d8bbfb5d7265a421b32ac8955b37f1b311634898275b1ac0a19157b38cf0790e285feb4b1dc6aedd83e91a1210b52cb807b250730af2e077e84fa8a520924ae52b1b63b9527ea839fb62064243efc3969ba5910aa55aeae4c20b68fc68b00d2bcb435d7b86eab0ff604bbab690e60e73242ae3ee469db8cecbcb2133b5f22fc1e3b9b750cf0f7ed71d320f77d88b40d614bedc80a1ae14798061fa46b9f02f8bb9f87d69ac6ff1eba0a2ca8e759db8933abeba5859e820a4181e6e4f31a1492f750537950ed0c0c74649f1f4f868ab12e27d599f61bfbff79e713f6eae6286199280e99b98cfdbc05405d604edd916594ed8cdd4caf21fe69d209be1b260a6a346d505db38ea6e5d8bc4e70eb67e1858a3b3d5253b1b6ca12fa740540ca0f75667111ce6f736e1439ecb8e87a7c6112f83a5a99db68a29b67a2a09c463729099c79ca85d0f4c9fdfc8c5140d3f4efe9c4e3dc4a3defca6d7d39ec0074a42a04aaf4901cdc995c61fae737faabd9a9f85beb7144af46a212bd2949fe9b8d1669dda969058aa06b06784ac20da6ae828dfa6eaa62ed82b9216afb3f116a9f289a8d1a6eee991d612278fe280867669552a6c8c1263b08d137ed704df2e6b221180dd18758f8afe62aa7e4c363f6e8437095b71e0f7e0912f29b842979a54e19b3139696a8325418d27b0ed48b0a6022e5cfaec4d9a115477fa2f883de9d120514b8b22a1d60bb46ba8ca82743da563ada8f86358dbf325771f4540d4c2bab2b3072a1eedeba01be74e9133bc5ad64d473c1b241a4deba79f08e1a85f804db08130bcc930e0908ed1405aefaf41d8cc43d57a0d5a98b91003e8af394f51e2803f5ca2b2f7966907d710fa27f22d3ded83b7fa707267c5519e8a60b4ff8db5e20206ffc5e270b4e9f7a52d034fe632455426c48570e2a8bbf31fe897edb99d723e2368051b80b32829be5582e3346b8258779b66152e5a33ff73fda80108c0300f971037c828d59736b2b3372a9d9d1479896eb349c532499f8bc60d1100d2000000000000000000000000000000000000000000000000000000000"
}
\ No newline at end of file
diff --git a/contracts/fixtures/verify_membership_fixture.json b/contracts/fixtures/verify_membership_fixture.json
deleted file mode 100644
index be87188..000000000
--- a/contracts/fixtures/verify_membership_fixture.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "proofHeight": 2330000,
- "trustedClientState": "000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000238d90000000000000000000000000000000000000000000000000000000000012750000000000000000000000000000000000000000000000000000000000001baf80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000076d6f6368612d3400000000000000000000000000000000000000000000000000",
- "trustedConsensusState": "0000000000000000000000000000000000000000000000000000000066a03c102bab132312afa95add5dec8f90e2fdc48085e7494ca6d39ee9431ff434e22775e0373a8b805881ecdbb47fce30b66956aa13e9a573107ba9ac495b9cef3365d3",
- "commitmentRoot": "2bab132312afa95add5dec8f90e2fdc48085e7494ca6d39ee9431ff434e22775",
- "updateClientVkey": "0x00b8a6a2873e2eb2b0456023e69672caf877239e7c1f1b77cb84e7eb748af3eb",
- "membershipVkey": "0x005dee562962534ba45f120968c2e0eaa59ace5404e49252264f9f3699edad82",
- "ucAndMembershipVkey": "0x00dc223d082fda575a3950f0cf145ac567f7e479a44513e79a76f5f5529233a0",
- "publicValues": "0x00000000000000000000000000000000000000000000000000000000000000202bab132312afa95add5dec8f90e2fdc48085e7494ca6d39ee9431ff434e22775000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000023636c69656e74732f30372d74656e6465726d696e742d302f636c69656e745374617465000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b70a2b2f6962632e6c69676874636c69656e74732e74656e6465726d696e742e76312e436c69656e7453746174651287010a1174686574612d746573746e65742d3030311204080110031a040880840722040880c60a2a02082832003a0510b7e3c60842190a090801180120012a0100120c0a02000110211804200c300142190a090801180120012a0100120c0a02000110201801200130014a07757067726164654a107570677261646564494243537461746550015801000000000000000000",
- "proof": "0xfedc1fcc0d5eac3bed8054390094c280873f26ed15f519f2741e53f0967fdaee3ca5d7710d0878ff85b76b5f52d9e0e650d7f7224c0c6bdf859c2c57e7efcf855ab1c68e0c5a170b6ef5914f3d0869a2a742ec4e25e0de8150bd6e205a11d61290301efd2e37cf3f2bcf75bad5b830e03b7f8541007300988c8c7ab808f45e436c52dbf42e38891db719b52da0b27d0735df1671a0f0d0b03fe704bae09d92788a71047d24482ddbda544746d8bf67dab9f84420b9b59e1d7c03f3843e8dbc93c866fffd22d31fa59f17df872516fb246c2d6b4158dd6d8dd74b878090197cafc5f4d69d0b8524299c1d65354c59cdde6482a0d77b29cdc69bbe380ea5d827bd2c7383160a69db35e40496836c8c2a1bcbf925c6f2f529188f6b4e006fad7bc2b6dd6b252276b08d16f1c07fd6496709524ddee7fcd0dca51930793d12ab18c72e6223eb02a59af09a9362384daf3d2a75195ad903825cc06dee4002f4ef25cfa7f8e0922cc107349ed93cfbc62d59200366c5fb41021e03abad61e0b0beac1158504fd21e4aad7c16ce4bdcdbe8bd5d83c7f1c649a3698f8fe7e888cfddd2f15d11e6d92560996e096b17928f538f1c05d6fe2e2cea202da00972beecd42d8b2b3eb8ae0b446031d9cf859f2b699240977ef2c5694ee886d121f9dfbec2077f73497253206d9044a4a777562d3eea57175db35dea5b2d9dcf8c2f6a37fc1574b2c7538e2b8a477167f7e915c8a15cc533cfc6110d2400462284ba91f2ac9e4dab98e8fe086251d29e83db3da03452fdbd761f5d9e5a1949c1c128c3658cacfd5dbac4362cc7f5e45888110b39527bcecaad245e157040a708e97e0dcccb2cf62154671010a3750b68e87b0ba8c3de48ceddd20c1ddde6e0c57d17b3fa0fcd787ed6dc3929ed1df4c9d3ebcde87e5cedc2cd04c45c8744f01d744f901ebaf914b54252c40f86a3a3cde08f34abdd787ac1d27e6613f8f89d6102a6860b2fa169cbaf87912fd191ef11c72ac816d52e251d82bd8ff60daf255a51163b1e203e437b43957a258ffe4e9225a2316d85dfff963ccccb647a58f425416d11aeeee7e07f1fb3270476023abeeb8edbf2ca60155d3e92dcefa157549f2d3f05823419296893add2230268c8d16df6a9461f75c77b355cfa0311e7d5b984529adfbf905f5fac51d004703be4554e96dd36105575af610312f5a2e021c8df26fcf94c27911a978851",
- "kvPairs": "000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000023636c69656e74732f30372d74656e6465726d696e742d302f636c69656e745374617465000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b70a2b2f6962632e6c69676874636c69656e74732e74656e6465726d696e742e76312e436c69656e7453746174651287010a1174686574612d746573746e65742d3030311204080110031a040880840722040880c60a2a02082832003a0510b7e3c60842190a090801180120012a0100120c0a02000110211804200c300142190a090801180120012a0100120c0a02000110201801200130014a07757067726164654a107570677261646564494243537461746550015801000000000000000000"
-}
\ No newline at end of file
diff --git a/contracts/script/SP1ICS07Tendermint.s.sol b/contracts/script/SP1ICS07Tendermint.s.sol
index 65340da..449891d 100644
--- a/contracts/script/SP1ICS07Tendermint.s.sol
+++ b/contracts/script/SP1ICS07Tendermint.s.sol
@@ -5,7 +5,7 @@ import { Script } from "forge-std/Script.sol";
import { stdJson } from "forge-std/StdJson.sol";
import { SP1ICS07Tendermint } from "../src/SP1ICS07Tendermint.sol";
import { SP1Verifier } from "@sp1-contracts/v1.0.1/SP1Verifier.sol";
-import { ICS07Tendermint } from "../src/ics07-tendermint/ICS07Tendermint.sol";
+import { IICS07TendermintMsgs } from "../src/msgs/IICS07TendermintMsgs.sol";
struct SP1ICS07TendermintGenesisJson {
bytes trustedClientState;
@@ -15,7 +15,7 @@ struct SP1ICS07TendermintGenesisJson {
bytes32 ucAndMembershipVkey;
}
-contract SP1TendermintScript is Script {
+contract SP1TendermintScript is Script, IICS07TendermintMsgs {
using stdJson for string;
SP1ICS07Tendermint public ics07Tendermint;
@@ -25,8 +25,7 @@ contract SP1TendermintScript is Script {
// Read the initialization parameters for the SP1 Tendermint contract.
SP1ICS07TendermintGenesisJson memory genesis = loadGenesis("genesis.json");
- ICS07Tendermint.ConsensusState memory trustedConsensusState =
- abi.decode(genesis.trustedConsensusState, (ICS07Tendermint.ConsensusState));
+ ConsensusState memory trustedConsensusState = abi.decode(genesis.trustedConsensusState, (ConsensusState));
bytes32 trustedConsensusHash = keccak256(abi.encode(trustedConsensusState));
@@ -44,7 +43,7 @@ contract SP1TendermintScript is Script {
vm.stopBroadcast();
- ICS07Tendermint.ClientState memory clientState = ics07Tendermint.getClientState();
+ ClientState memory clientState = ics07Tendermint.getClientState();
assert(keccak256(abi.encode(clientState)) == keccak256(genesis.trustedClientState));
bytes32 consensusHash = ics07Tendermint.getConsensusStateHash(clientState.latestHeight.revisionHeight);
diff --git a/contracts/script/genesis.json b/contracts/script/genesis.json
index bab5152..082cdb4 100644
--- a/contracts/script/genesis.json
+++ b/contracts/script/genesis.json
@@ -1,7 +1,7 @@
{
- "trustedClientState": "00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000012754500000000000000000000000000000000000000000000000000000000001baf800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000673696d642d310000000000000000000000000000000000000000000000000000",
- "trustedConsensusState": "0000000000000000000000000000000000000000000000000000000066a36d61154d94d8b1a960773c26199c0b1982cf3496a025e602bf2ef7e307d1e6c0fb8227aef26dd65a2fa3db2c2c9cd895141599627abdf089fcff81d827329809c076",
- "updateClientVkey": "0x00b8a6a2873e2eb2b0456023e69672caf877239e7c1f1b77cb84e7eb748af3eb",
- "membershipVkey": "0x005dee562962534ba45f120968c2e0eaa59ace5404e49252264f9f3699edad82",
- "ucAndMembershipVkey": "0x00dc223d082fda575a3950f0cf145ac567f7e479a44513e79a76f5f5529233a0"
+ "trustedClientState": "0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000008b2c60000000000000000000000000000000000000000000000000000000000012750000000000000000000000000000000000000000000000000000000000001baf80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000076e6f626c652d3100000000000000000000000000000000000000000000000000",
+ "trustedConsensusState": "0000000000000000000000000000000000000000000000000000000066a5e5bf9a6a1996e105a21fa1ad7b90dffc6189b2762185644f7cdda4850e94bd7e9e5fb694f433191c7b4644b4285bf994f580aa12b59229008d2b26e958f09b181535",
+ "updateClientVkey": "0x00e101bccf2e9fa8dcdecd9f0467d00cfbbdae486b189a6d0e1b500ad7c7641a",
+ "membershipVkey": "0x001ae64fb3c0ac2e5a62e4941b26edf05798f0dc3417ae105e4bd1c443de6188",
+ "ucAndMembershipVkey": "0x008e7ae959dba05a6c3167c1bbe7a9e9427d083370907c08cbcb4ba8315c6087"
}
\ No newline at end of file
diff --git a/contracts/src/ISP1ICS07Tendermint.sol b/contracts/src/ISP1ICS07Tendermint.sol
deleted file mode 100644
index 45c8a23..000000000
--- a/contracts/src/ISP1ICS07Tendermint.sol
+++ /dev/null
@@ -1,68 +0,0 @@
-// SPDX-License-Identifier: MIT
-pragma solidity >=0.8.25;
-
-import { ICS07Tendermint } from "./ics07-tendermint/ICS07Tendermint.sol";
-import { UpdateClientProgram } from "./ics07-tendermint/UpdateClientProgram.sol";
-
-/// @title SP1 ICS07 Tendermint Light Client Interface
-/// @author srdtrk
-/// @notice This interface is used to interact with the SP1 ICS07 Tendermint Light Client
-interface ISP1ICS07Tendermint {
- /// @notice The allowed clock drift between the prover and the verifier in seconds.
- function ALLOWED_SP1_CLOCK_DRIFT() external view returns (uint16);
-
- /// @notice Get the client state
- function getClientState() external view returns (ICS07Tendermint.ClientState memory);
-
- /// @notice Get the consensus state keccak256 hash at the given height
- function getConsensusStateHash(uint32) external view returns (bytes32);
-
- /// @notice Returns the verifier information.
- /// @return Returns the verifier contract address and the program verification keys.
- function getVerifierInfo() external view returns (address, bytes32, bytes32, bytes32);
-
- /// @notice The entrypoint for updating the client.
- /// @dev This function verifies the public values and forwards the proof to the SP1 verifier.
- /// @param proof The encoded proof.
- /// @param publicValues The encoded public values.
- /// @return The result of the update.
- function updateClient(
- bytes calldata proof,
- bytes calldata publicValues
- )
- external
- returns (UpdateClientProgram.UpdateResult);
-
- /// @notice The entrypoint for batch verifying (non)membership proof.
- /// @dev This function verifies the public values and forwards the proof to the SP1 verifier.
- /// @dev It can validate a subset of the key-value pairs by providing their hashes.
- /// @dev This is useful for batch verification. Zero hashes are skipped.
- /// @param proof The encoded proof.
- /// @param publicValues The encoded public values.
- /// @param proofHeight The height of the proof.
- /// @param trustedConsensusStateBz The encoded trusted consensus state.
- /// @param kvPairHashes The hashes of the key-value pairs.
- function batchVerifyMembership(
- bytes calldata proof,
- bytes calldata publicValues,
- uint32 proofHeight,
- bytes calldata trustedConsensusStateBz,
- bytes32[] calldata kvPairHashes
- )
- external
- view;
-
- /// @notice The entrypoint for updating the client and membership proof.
- /// @dev This function verifies the public values and forwards the proof to the SP1 verifier.
- /// @param proof The encoded proof.
- /// @param publicValues The encoded public values.
- /// @param kvPairHashes The hashes of the key-value pairs.
- /// @return The result of the update.
- function updateClientAndBatchVerifyMembership(
- bytes calldata proof,
- bytes calldata publicValues,
- bytes32[] calldata kvPairHashes
- )
- external
- returns (UpdateClientProgram.UpdateResult);
-}
diff --git a/contracts/src/SP1ICS07Tendermint.sol b/contracts/src/SP1ICS07Tendermint.sol
index 071b186..c1ec1fc 100644
--- a/contracts/src/SP1ICS07Tendermint.sol
+++ b/contracts/src/SP1ICS07Tendermint.sol
@@ -1,29 +1,39 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.25;
-import { ICS07Tendermint } from "./ics07-tendermint/ICS07Tendermint.sol";
-import { UpdateClientProgram } from "./ics07-tendermint/UpdateClientProgram.sol";
-import { MembershipProgram } from "./ics07-tendermint/MembershipProgram.sol";
-import { UpdateClientAndMembershipProgram } from "./ics07-tendermint/UcAndMembershipProgram.sol";
+import { IICS07TendermintMsgs } from "./msgs/IICS07TendermintMsgs.sol";
+import { IUpdateClientMsgs } from "./msgs/IUpdateClientMsgs.sol";
+import { IMembershipMsgs } from "./msgs/IMembershipMsgs.sol";
+import { IUpdateClientAndMembershipMsgs } from "./msgs/IUcAndMembershipMsgs.sol";
import { ISP1Verifier } from "@sp1-contracts/ISP1Verifier.sol";
-import { ISP1ICS07Tendermint } from "./ISP1ICS07Tendermint.sol";
+import { ISP1ICS07TendermintErrors } from "./errors/ISP1ICS07TendermintErrors.sol";
+import { ILightClientMsgs } from "solidity-ibc/msgs/ILightClientMsgs.sol";
+import { ILightClient } from "solidity-ibc/interfaces/ILightClient.sol";
/// @title SP1 ICS07 Tendermint Light Client
/// @author srdtrk
/// @notice This contract implements an ICS07 IBC tendermint light client using SP1.
/// @custom:poc This is a proof of concept implementation.
-contract SP1ICS07Tendermint is ISP1ICS07Tendermint {
+contract SP1ICS07Tendermint is
+ IICS07TendermintMsgs,
+ IUpdateClientMsgs,
+ IMembershipMsgs,
+ IUpdateClientAndMembershipMsgs,
+ ISP1ICS07TendermintErrors,
+ ILightClientMsgs,
+ ILightClient
+{
/// @notice The verification key for the update client program.
- bytes32 private immutable UPDATE_CLIENT_PROGRAM_VKEY;
+ bytes32 public immutable UPDATE_CLIENT_PROGRAM_VKEY;
/// @notice The verification key for the verify (non)membership program.
- bytes32 private immutable MEMBERSHIP_PROGRAM_VKEY;
+ bytes32 public immutable MEMBERSHIP_PROGRAM_VKEY;
/// @notice The verification key for the update client and membership program.
- bytes32 private immutable UPDATE_CLIENT_AND_MEMBERSHIP_PROGRAM_VKEY;
+ bytes32 public immutable UPDATE_CLIENT_AND_MEMBERSHIP_PROGRAM_VKEY;
/// @notice The SP1 verifier contract.
- ISP1Verifier private immutable VERIFIER;
+ ISP1Verifier public immutable VERIFIER;
/// @notice The ICS07Tendermint client state
- ICS07Tendermint.ClientState private clientState;
+ ClientState private clientState;
/// @notice The mapping from height to consensus state keccak256 hashes.
mapping(uint32 height => bytes32 hash) private consensusStateHashes;
@@ -50,13 +60,13 @@ contract SP1ICS07Tendermint is ISP1ICS07Tendermint {
UPDATE_CLIENT_AND_MEMBERSHIP_PROGRAM_VKEY = updateClientAndMembershipProgramVkey;
VERIFIER = ISP1Verifier(verifier);
- clientState = abi.decode(_clientState, (ICS07Tendermint.ClientState));
+ clientState = abi.decode(_clientState, (ClientState));
consensusStateHashes[clientState.latestHeight.revisionHeight] = _consensusState;
}
/// @notice Returns the client state.
/// @return The client state.
- function getClientState() public view returns (ICS07Tendermint.ClientState memory) {
+ function getClientState() public view returns (ClientState memory) {
return clientState;
}
@@ -64,231 +74,310 @@ contract SP1ICS07Tendermint is ISP1ICS07Tendermint {
/// @param revisionHeight The revision height.
/// @return The consensus state at the given revision height.
function getConsensusStateHash(uint32 revisionHeight) public view returns (bytes32) {
- return consensusStateHashes[revisionHeight];
- }
-
- /// @notice Returns the verifier information.
- /// @return Returns the verifier contract address and the program verification keys.
- function getVerifierInfo() public view returns (address, bytes32, bytes32, bytes32) {
- return (
- address(VERIFIER),
- UPDATE_CLIENT_PROGRAM_VKEY,
- MEMBERSHIP_PROGRAM_VKEY,
- UPDATE_CLIENT_AND_MEMBERSHIP_PROGRAM_VKEY
- );
+ bytes32 hash = consensusStateHashes[revisionHeight];
+ if (hash == 0) {
+ revert ConsensusStateNotFound();
+ }
+ return hash;
}
/// @notice The entrypoint for updating the client.
/// @dev This function verifies the public values and forwards the proof to the SP1 verifier.
- /// @param proof The encoded proof.
- /// @param publicValues The encoded public values.
+ /// @param updateMsg The encoded update message.
/// @return The result of the update.
- function updateClient(
- bytes calldata proof,
- bytes calldata publicValues
- )
- public
- returns (UpdateClientProgram.UpdateResult)
- {
- UpdateClientProgram.UpdateClientOutput memory output =
- abi.decode(publicValues, (UpdateClientProgram.UpdateClientOutput));
+ function updateClient(bytes calldata updateMsg) public returns (UpdateResult) {
+ MsgUpdateClient memory msgUpdateClient = abi.decode(updateMsg, (MsgUpdateClient));
+ if (msgUpdateClient.sp1Proof.vKey != UPDATE_CLIENT_PROGRAM_VKEY) {
+ revert VerificationKeyMismatch(UPDATE_CLIENT_PROGRAM_VKEY, msgUpdateClient.sp1Proof.vKey);
+ }
- validateUpdateClientPublicValues(output);
+ UpdateClientOutput memory output = abi.decode(msgUpdateClient.sp1Proof.publicValues, (UpdateClientOutput));
- // TODO: Make sure that other checks have been made in the proof verification
- VERIFIER.verifyProof(UPDATE_CLIENT_PROGRAM_VKEY, publicValues, proof);
+ validateUpdateClientPublicValues(output);
- UpdateClientProgram.UpdateResult updateResult = checkUpdateResult(output);
- if (updateResult == UpdateClientProgram.UpdateResult.Update) {
+ UpdateResult updateResult = checkUpdateResult(output);
+ if (updateResult == UpdateResult.Update) {
// adding the new consensus state to the mapping
if (output.newHeight.revisionHeight > clientState.latestHeight.revisionHeight) {
clientState.latestHeight = output.newHeight;
}
consensusStateHashes[output.newHeight.revisionHeight] = keccak256(abi.encode(output.newConsensusState));
- } else if (updateResult == UpdateClientProgram.UpdateResult.Misbehaviour) {
+ } else if (updateResult == UpdateResult.Misbehaviour) {
clientState.isFrozen = true;
- } // else: NoOp
+ } else if (updateResult == UpdateResult.NoOp) {
+ return UpdateResult.NoOp;
+ }
+
+ verifySP1Proof(msgUpdateClient.sp1Proof);
return updateResult;
}
- /// @notice The entrypoint for batch verifying (non)membership proof.
- /// @dev This function verifies the public values and forwards the proof to the SP1 verifier.
- /// @dev It can validate a subset of the key-value pairs by providing their hashes.
- /// @dev This is useful for batch verification. Zero hashes are skipped.
- /// @param proof The encoded proof.
- /// @param publicValues The encoded public values.
- /// @param proofHeight The height of the proof.
- /// @param trustedConsensusStateBz The encoded trusted consensus state.
- /// @param kvPairHashes The hashes of the key-value pairs.
- function batchVerifyMembership(
- bytes calldata proof,
- bytes calldata publicValues,
- uint32 proofHeight,
- bytes calldata trustedConsensusStateBz,
- bytes32[] calldata kvPairHashes
+ /// @notice The entrypoint for verifying (non)membership proof.
+ /// @param msgMembership The membership message.
+ /// @return timestamp The timestamp of the trusted consensus state.
+ function membership(MsgMembership calldata msgMembership) public returns (uint256 timestamp) {
+ MembershipProof memory membershipProof = abi.decode(msgMembership.proof, (MembershipProof));
+ if (membershipProof.proofType == MembershipProofType.SP1MembershipProof) {
+ return handleSP1MembershipProof(
+ msgMembership.proofHeight, membershipProof.proof, msgMembership.path, msgMembership.value
+ );
+ } else if (membershipProof.proofType == MembershipProofType.SP1MembershipAndUpdateClientProof) {
+ return handleSP1UpdateClientAndMembership(
+ msgMembership.proofHeight, membershipProof.proof, msgMembership.path, msgMembership.value
+ );
+ } else {
+ revert UnknownMembershipProofType(uint8(membershipProof.proofType));
+ }
+ }
+
+ /// @notice The entrypoint for misbehaviour.
+ /// TODO: Not yet implemented. (#56)
+ function misbehaviour(bytes calldata) public pure {
+ revert FeatureNotSupported();
+ }
+
+ /// @notice The entrypoint for upgrading the client.
+ /// TODO: Not yet implemented. (#78)
+ function upgradeClient(bytes calldata) public pure {
+ revert FeatureNotSupported();
+ }
+
+ function handleSP1MembershipProof(
+ Height memory proofHeight,
+ bytes memory proofBytes,
+ bytes memory kvPath,
+ bytes memory kvValue
)
- public
+ private
view
+ returns (uint256)
{
- MembershipProgram.MembershipOutput memory output =
- abi.decode(publicValues, (MembershipProgram.MembershipOutput));
+ if (proofHeight.revisionNumber != clientState.latestHeight.revisionNumber) {
+ revert ProofHeightMismatch(
+ proofHeight.revisionNumber,
+ proofHeight.revisionHeight,
+ clientState.latestHeight.revisionNumber,
+ clientState.latestHeight.revisionHeight
+ );
+ }
- require(kvPairHashes.length != 0, "SP1ICS07Tendermint: kvPairs length is zero");
+ SP1MembershipProof memory proof = abi.decode(proofBytes, (SP1MembershipProof));
+ if (proof.sp1Proof.vKey != MEMBERSHIP_PROGRAM_VKEY) {
+ revert VerificationKeyMismatch(MEMBERSHIP_PROGRAM_VKEY, proof.sp1Proof.vKey);
+ }
- require(kvPairHashes.length <= output.kvPairs.length, "SP1ICS07Tendermint: kvPairs length mismatch");
+ MembershipOutput memory output = abi.decode(proof.sp1Proof.publicValues, (MembershipOutput));
+ if (output.kvPairs.length == 0 || output.kvPairs.length > 256) {
+ revert LengthIsOutOfRange(output.kvPairs.length, 1, 256);
+ }
// loop through the key-value pairs and validate them
- for (uint8 i = 0; i < kvPairHashes.length; i++) {
- bytes32 kvPairHash = kvPairHashes[i];
- if (kvPairHash == 0) {
- // skip the empty hash
+ bool found = false;
+ for (uint8 i = 0; i < output.kvPairs.length; i++) {
+ bytes memory path = output.kvPairs[i].path;
+ if (keccak256(path) != keccak256(kvPath)) {
continue;
}
- require(kvPairHash == keccak256(abi.encode(output.kvPairs[i])), "SP1ICS07Tendermint: kvPair hash mismatch");
+ bytes memory value = output.kvPairs[i].value;
+ if (keccak256(value) != keccak256(kvValue)) {
+ revert MembershipProofValueMismatch(kvValue, value);
+ }
+
+ found = true;
+ break;
}
+ if (!found) {
+ revert MembershipProofKeyNotFound(kvPath);
+ }
+
+ validateMembershipOutput(output.commitmentRoot, proofHeight.revisionHeight, proof.trustedConsensusState);
- validateMembershipOutput(output.commitmentRoot, proofHeight, trustedConsensusStateBz);
+ verifySP1Proof(proof.sp1Proof);
- VERIFIER.verifyProof(MEMBERSHIP_PROGRAM_VKEY, publicValues, proof);
+ return proof.trustedConsensusState.timestamp;
}
/// @notice The entrypoint for updating the client and membership proof.
/// @dev This function verifies the public values and forwards the proof to the SP1 verifier.
- /// @param proof The encoded proof.
- /// @param publicValues The encoded public values.
- /// @param kvPairHashes The hashes of the key-value pairs.
- /// @return The result of the update.
- function updateClientAndBatchVerifyMembership(
- bytes calldata proof,
- bytes calldata publicValues,
- bytes32[] calldata kvPairHashes
+ /// @param proofHeight The height of the proof.
+ /// @param proofBytes The encoded proof.
+ /// @param kvPath The path of the key-value pair.
+ /// @param kvValue The value of the key-value pair.
+ /// @return The timestamp of the new consensus state.
+ function handleSP1UpdateClientAndMembership(
+ Height memory proofHeight,
+ bytes memory proofBytes,
+ bytes memory kvPath,
+ bytes memory kvValue
)
- public
- returns (UpdateClientProgram.UpdateResult)
+ private
+ returns (uint256)
{
- UpdateClientAndMembershipProgram.UcAndMembershipOutput memory output =
- abi.decode(publicValues, (UpdateClientAndMembershipProgram.UcAndMembershipOutput));
+ SP1MembershipAndUpdateClientProof memory proof = abi.decode(proofBytes, (SP1MembershipAndUpdateClientProof));
+ if (proof.sp1Proof.vKey != UPDATE_CLIENT_AND_MEMBERSHIP_PROGRAM_VKEY) {
+ revert VerificationKeyMismatch(UPDATE_CLIENT_AND_MEMBERSHIP_PROGRAM_VKEY, proof.sp1Proof.vKey);
+ }
+
+ UcAndMembershipOutput memory output = abi.decode(proof.sp1Proof.publicValues, (UcAndMembershipOutput));
+ if (output.kvPairs.length == 0 || output.kvPairs.length > 256) {
+ revert LengthIsOutOfRange(output.kvPairs.length, 1, 256);
+ }
+
+ if (
+ proofHeight.revisionHeight != output.updateClientOutput.newHeight.revisionHeight
+ || proofHeight.revisionNumber != output.updateClientOutput.newHeight.revisionNumber
+ ) {
+ revert ProofHeightMismatch(
+ proofHeight.revisionNumber,
+ proofHeight.revisionHeight,
+ output.updateClientOutput.newHeight.revisionNumber,
+ output.updateClientOutput.newHeight.revisionHeight
+ );
+ }
validateUpdateClientPublicValues(output.updateClientOutput);
- VERIFIER.verifyProof(UPDATE_CLIENT_AND_MEMBERSHIP_PROGRAM_VKEY, publicValues, proof);
+ verifySP1Proof(proof.sp1Proof);
- UpdateClientProgram.UpdateResult updateResult = checkUpdateResult(output.updateClientOutput);
- if (updateResult == UpdateClientProgram.UpdateResult.Update) {
+ UpdateResult updateResult = checkUpdateResult(output.updateClientOutput);
+ if (updateResult == UpdateResult.Update) {
// adding the new consensus state to the mapping
- clientState.latestHeight = output.updateClientOutput.newHeight;
- consensusStateHashes[output.updateClientOutput.newHeight.revisionHeight] =
+ if (proofHeight.revisionHeight > clientState.latestHeight.revisionHeight) {
+ clientState.latestHeight = output.updateClientOutput.newHeight;
+ }
+ consensusStateHashes[proofHeight.revisionHeight] =
keccak256(abi.encode(output.updateClientOutput.newConsensusState));
- } else if (updateResult == UpdateClientProgram.UpdateResult.Misbehaviour) {
+ } else if (updateResult == UpdateResult.Misbehaviour) {
clientState.isFrozen = true;
- return UpdateClientProgram.UpdateResult.Misbehaviour;
+ revert CannotHandleMisbehavior();
} // else: NoOp
- require(kvPairHashes.length != 0, "SP1ICS07Tendermint: kvPairs length is zero");
-
- require(kvPairHashes.length <= output.kvPairs.length, "SP1ICS07Tendermint: kvPairs length mismatch");
-
// loop through the key-value pairs and validate them
- for (uint8 i = 0; i < kvPairHashes.length; i++) {
- bytes32 kvPairHash = kvPairHashes[i];
- if (kvPairHash == 0) {
- // skip the empty hash
+ bool found = false;
+ for (uint8 i = 0; i < output.kvPairs.length; i++) {
+ bytes memory path = output.kvPairs[i].path;
+ if (keccak256(path) != keccak256(kvPath)) {
continue;
}
- require(kvPairHash == keccak256(abi.encode(output.kvPairs[i])), "SP1ICS07Tendermint: kvPair hash mismatch");
+ bytes memory value = output.kvPairs[i].value;
+ if (keccak256(value) != keccak256(kvValue)) {
+ revert MembershipProofValueMismatch(kvValue, value);
+ }
+
+ found = true;
+ break;
+ }
+ if (!found) {
+ revert MembershipProofKeyNotFound(kvPath);
}
validateMembershipOutput(
output.updateClientOutput.newConsensusState.root,
output.updateClientOutput.newHeight.revisionHeight,
- abi.encode(output.updateClientOutput.newConsensusState)
+ output.updateClientOutput.newConsensusState
);
- return updateResult;
+ return output.updateClientOutput.newConsensusState.timestamp;
}
/// @notice Validates the MembershipOutput public values.
/// @param outputCommitmentRoot The commitment root of the output.
/// @param proofHeight The height of the proof.
- /// @param trustedConsensusStateBz The encoded trusted consensus state.
+ /// @param trustedConsensusState The trusted consensus state.
function validateMembershipOutput(
bytes32 outputCommitmentRoot,
uint32 proofHeight,
- bytes memory trustedConsensusStateBz
+ ConsensusState memory trustedConsensusState
)
private
view
{
- require(clientState.isFrozen == false, "SP1ICS07Tendermint: client is frozen");
- require(
- consensusStateHashes[proofHeight] == keccak256(trustedConsensusStateBz),
- "SP1ICS07Tendermint: trusted consensus state mismatch"
- );
-
- ICS07Tendermint.ConsensusState memory trustedConsensusState =
- abi.decode(trustedConsensusStateBz, (ICS07Tendermint.ConsensusState));
-
- require(outputCommitmentRoot == trustedConsensusState.root, "SP1ICS07Tendermint: invalid commitment root");
+ if (clientState.isFrozen) {
+ revert FrozenClientState();
+ }
+ if (outputCommitmentRoot != trustedConsensusState.root) {
+ revert ConsensusStateRootMismatch(trustedConsensusState.root, outputCommitmentRoot);
+ }
+ bytes32 trustedConsensusStateHash = keccak256(abi.encode(trustedConsensusState));
+ if (consensusStateHashes[proofHeight] != trustedConsensusStateHash) {
+ revert ConsensusStateHashMismatch(trustedConsensusStateHash, consensusStateHashes[proofHeight]);
+ }
}
/// @notice Validates the SP1ICS07UpdateClientOutput public values.
/// @param output The public values.
- function validateUpdateClientPublicValues(UpdateClientProgram.UpdateClientOutput memory output) private view {
- require(clientState.isFrozen == false, "SP1ICS07Tendermint: client is frozen");
- require(block.timestamp >= output.env.now, "SP1ICS07Tendermint: proof is in the future");
- require(block.timestamp - output.env.now <= ALLOWED_SP1_CLOCK_DRIFT, "SP1ICS07Tendermint: proof is too old");
- require(
- keccak256(bytes(output.env.chainId)) == keccak256(bytes(clientState.chainId)),
- "SP1ICS07Tendermint: chain ID mismatch"
- );
- require(
- output.env.trustThreshold.numerator == clientState.trustLevel.numerator
- && output.env.trustThreshold.denominator == clientState.trustLevel.denominator,
- "SP1ICS07Tendermint: trust threshold mismatch"
- );
- require(output.env.trustingPeriod == clientState.trustingPeriod, "SP1ICS07Tendermint: trusting period mismatch");
- require(
- output.env.trustingPeriod <= clientState.unbondingPeriod,
- "SP1ICS07Tendermint: trusting period longer than unbonding period"
- );
- require(
- consensusStateHashes[output.trustedHeight.revisionHeight]
- == keccak256(abi.encode(output.trustedConsensusState)),
- "SP1ICS07Tendermint: trusted consensus state mismatch"
- );
- // TODO: Make sure that we don't need more checks.
+ function validateUpdateClientPublicValues(UpdateClientOutput memory output) private view {
+ if (clientState.isFrozen) {
+ revert FrozenClientState();
+ }
+ if (output.env.now > block.timestamp) {
+ revert ProofIsInTheFuture(block.timestamp, output.env.now);
+ }
+ if (block.timestamp - output.env.now > ALLOWED_SP1_CLOCK_DRIFT) {
+ revert ProofIsTooOld(block.timestamp, output.env.now);
+ }
+ if (keccak256(bytes(output.env.chainId)) != keccak256(bytes(clientState.chainId))) {
+ revert ChainIdMismatch(clientState.chainId, output.env.chainId);
+ }
+ if (
+ output.env.trustThreshold.numerator != clientState.trustLevel.numerator
+ || output.env.trustThreshold.denominator != clientState.trustLevel.denominator
+ ) {
+ revert TrustThresholdMismatch(
+ clientState.trustLevel.numerator,
+ clientState.trustLevel.denominator,
+ output.env.trustThreshold.numerator,
+ output.env.trustThreshold.denominator
+ );
+ }
+ if (output.env.trustingPeriod != clientState.trustingPeriod) {
+ revert TrustingPeriodMismatch(clientState.trustingPeriod, output.env.trustingPeriod);
+ }
+ if (output.env.trustingPeriod > clientState.unbondingPeriod) {
+ revert TrustingPeriodTooLong(output.env.trustingPeriod, clientState.unbondingPeriod);
+ }
+
+ bytes32 outputConsensusStateHash = keccak256(abi.encode(output.trustedConsensusState));
+ bytes32 trustedConsensusStateHash = getConsensusStateHash(output.trustedHeight.revisionHeight);
+ if (outputConsensusStateHash != trustedConsensusStateHash) {
+ revert ConsensusStateHashMismatch(trustedConsensusStateHash, outputConsensusStateHash);
+ }
}
/// @notice Checks for basic misbehaviour.
/// @dev This function checks if the consensus state at the new height is different than the one in the mapping.
/// @dev This function does not check timestamp misbehaviour (a niche case).
/// @param output The public values of the update client program.
- function checkUpdateResult(UpdateClientProgram.UpdateClientOutput memory output)
- private
- view
- returns (UpdateClientProgram.UpdateResult)
- {
+ function checkUpdateResult(UpdateClientOutput memory output) private view returns (UpdateResult) {
bytes32 consensusStateHash = consensusStateHashes[output.newHeight.revisionHeight];
if (consensusStateHash == bytes32(0)) {
// No consensus state at the new height, so no misbehaviour
- return UpdateClientProgram.UpdateResult.Update;
+ return UpdateResult.Update;
}
if (consensusStateHash != keccak256(abi.encode(output.newConsensusState))) {
// The consensus state at the new height is different than the one in the mapping
- return UpdateClientProgram.UpdateResult.Misbehaviour;
+ return UpdateResult.Misbehaviour;
} else {
// The consensus state at the new height is the same as the one in the mapping
- return UpdateClientProgram.UpdateResult.NoOp;
+ return UpdateResult.NoOp;
}
}
+ function verifySP1Proof(SP1Proof memory proof) private view {
+ VERIFIER.verifyProof(proof.vKey, proof.publicValues, proof.proof);
+ }
+
/// @notice A dummy function to generate the ABI for the parameters.
function abiPublicTypes(
- MembershipProgram.MembershipOutput memory output,
- UpdateClientAndMembershipProgram.UcAndMembershipOutput memory output2
+ MembershipOutput memory o1,
+ UcAndMembershipOutput memory o2,
+ MsgUpdateClient memory o3,
+ MembershipProof memory o4,
+ SP1MembershipProof memory o5,
+ SP1MembershipAndUpdateClientProof memory o6
)
public
pure
diff --git a/contracts/src/errors/ISP1ICS07TendermintErrors.sol b/contracts/src/errors/ISP1ICS07TendermintErrors.sol
new file mode 100644
index 000000000..71ea755
--- /dev/null
+++ b/contracts/src/errors/ISP1ICS07TendermintErrors.sol
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.8.25;
+
+interface ISP1ICS07TendermintErrors {
+ /// @notice The error that is returned when the verification key does not match the expected value.
+ /// @param expected The expected verification key.
+ /// @param actual The actual verification key.
+ error VerificationKeyMismatch(bytes32 expected, bytes32 actual);
+
+ /// @notice The error that is returned when the client state is frozen.
+ error FrozenClientState();
+
+ /// @notice The error that is returned when a proof is in the future.
+ /// @param now The current timestamp in seconds.
+ /// @param proofTimestamp The timestamp in the proof in seconds.
+ error ProofIsInTheFuture(uint256 now, uint256 proofTimestamp);
+
+ /// @notice The error that is returned when a proof is too old.
+ /// @param now The current timestamp in seconds.
+ /// @param proofTimestamp The timestamp in the proof in seconds.
+ error ProofIsTooOld(uint256 now, uint256 proofTimestamp);
+
+ /// @notice The error that is returned when the chain ID does not match the expected value.
+ /// @param expected The expected chain ID.
+ /// @param actual The actual chain ID.
+ error ChainIdMismatch(string expected, string actual);
+
+ /// @notice The error that is returned when the trust threshold does not match the expected value.
+ /// @param expectedNumerator The expected numerator of the trust threshold.
+ /// @param expectedDenominator The expected denominator of the trust threshold.
+ /// @param actualNumerator The actual numerator of the trust threshold.
+ /// @param actualDenominator The actual denominator of the trust threshold.
+ error TrustThresholdMismatch(
+ uint256 expectedNumerator, uint256 expectedDenominator, uint256 actualNumerator, uint256 actualDenominator
+ );
+
+ /// @notice The error that is returned when the trusting period does not match the expected value.
+ /// @param expected The expected trusting period in seconds.
+ /// @param actual The actual trusting period in seconds.
+ error TrustingPeriodMismatch(uint256 expected, uint256 actual);
+
+ /// @notice The error that is returned when the trusting period is longer than the unbonding period.
+ /// @param trustingPeriod The trusting period in seconds.
+ /// @param unbondingPeriod The unbonding period in seconds.
+ error TrustingPeriodTooLong(uint256 trustingPeriod, uint256 unbondingPeriod);
+
+ /// @notice The error that is returned when the consensus state hash does not match the expected value.
+ /// @param expected The expected consensus state hash.
+ /// @param actual The actual consensus state hash.
+ error ConsensusStateHashMismatch(bytes32 expected, bytes32 actual);
+
+ /// @notice The error that is returned when the consensus state is not found.
+ error ConsensusStateNotFound();
+
+ /// @notice The error that is returned when the length of a value is out of range.
+ /// @param length The length of the value.
+ /// @param min The minimum length of the value.
+ /// @param max The maximum length of the value.
+ error LengthIsOutOfRange(uint256 length, uint256 min, uint256 max);
+
+ /// @notice The error that is returned when the key-value pair's value does not match the expected value.
+ /// @param expected The expected value.
+ /// @param actual The actual value.
+ error MembershipProofValueMismatch(bytes expected, bytes actual);
+
+ /// @notice The error that is returned when the key-value pair's path is not contained in the proof.
+ /// @param path The path of the key-value pair.
+ error MembershipProofKeyNotFound(bytes path);
+
+ /// @notice The error that is returned when the consensus state root does not match the expected value.
+ /// @param expected The expected consensus state root.
+ /// @param actual The actual consensus state root.
+ error ConsensusStateRootMismatch(bytes32 expected, bytes32 actual);
+
+ /// @notice The error that is returned when the update client and membership program contains misbehavior.
+ /// @dev Misbehavior cannot be handled in membership handler, so it is returned as an error.
+ error CannotHandleMisbehavior();
+
+ /// @notice The error that is returned when the proof height does not match the expected value.
+ /// @param expectedRevisionNumber The expected revision number.
+ /// @param expectedRevisionHeight The expected revision height.
+ /// @param actualRevisionNumber The actual revision number.
+ /// @param actualRevisionHeight The actual revision height.
+ error ProofHeightMismatch(
+ uint64 expectedRevisionNumber,
+ uint64 expectedRevisionHeight,
+ uint64 actualRevisionNumber,
+ uint64 actualRevisionHeight
+ );
+
+ /// @notice The error that is returned when the membership proof type is unknown.
+ /// @param proofType The unknown membership proof type.
+ error UnknownMembershipProofType(uint8 proofType);
+
+ /// @notice Returned when the feature is not supported.
+ error FeatureNotSupported();
+}
diff --git a/contracts/src/ics07-tendermint/MembershipProgram.sol b/contracts/src/ics07-tendermint/MembershipProgram.sol
deleted file mode 100644
index 3e6dddb..000000000
--- a/contracts/src/ics07-tendermint/MembershipProgram.sol
+++ /dev/null
@@ -1,19 +0,0 @@
-// SPDX-License-Identifier: UNLICENSED
-pragma solidity >=0.8.25;
-
-/// @title MembershipProgram
-/// @author srdtrk
-/// @notice Defines shared types for the verify (non)membership program.
-contract MembershipProgram {
- /// @notice The public value output for the sp1 verify (non)membership program.
- struct MembershipOutput {
- bytes32 commitmentRoot;
- KVPair[] kvPairs;
- }
-
- /// @notice The key-value pair.
- struct KVPair {
- string key;
- bytes value;
- }
-}
diff --git a/contracts/src/ics07-tendermint/ICS07Tendermint.sol b/contracts/src/msgs/IICS07TendermintMsgs.sol
similarity index 84%
rename from contracts/src/ics07-tendermint/ICS07Tendermint.sol
rename to contracts/src/msgs/IICS07TendermintMsgs.sol
index 4644bc0..c4767ea 100644
--- a/contracts/src/ics07-tendermint/ICS07Tendermint.sol
+++ b/contracts/src/msgs/IICS07TendermintMsgs.sol
@@ -1,18 +1,12 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.25;
-/// @title ICS07Tendermint
+import { IICS02ClientMsgs } from "solidity-ibc/msgs/IICS02ClientMsgs.sol";
+
+/// @title ICS07 Tendermint Messages
/// @author srdtrk
/// @notice Defines shared types for ICS07Tendermint implementations.
-contract ICS07Tendermint {
- /// @notice Height of the counterparty chain
- struct Height {
- /// Previously known as "epoch"
- uint32 revisionNumber;
- /// The height of a block
- uint32 revisionHeight;
- }
-
+interface IICS07TendermintMsgs is IICS02ClientMsgs {
/// Fraction of validator overlap needed to update header
struct TrustThreshold {
/// Numerator of the fraction
diff --git a/contracts/src/msgs/IMembershipMsgs.sol b/contracts/src/msgs/IMembershipMsgs.sol
new file mode 100644
index 000000000..5f20cb0
--- /dev/null
+++ b/contracts/src/msgs/IMembershipMsgs.sol
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: UNLICENSED
+pragma solidity >=0.8.25;
+
+import { ISP1Msgs } from "./ISP1Msgs.sol";
+import { IICS07TendermintMsgs } from "./IICS07TendermintMsgs.sol";
+
+/// @title Membership Program Messages
+/// @author srdtrk
+/// @notice Defines shared types for the verify (non)membership program.
+interface IMembershipMsgs is ISP1Msgs {
+ /// @notice The key-value pair used in the verify (non)membership program.
+ struct KVPair {
+ /// The path of the value in the key-value store.
+ bytes path;
+ /// The value of the key-value pair.
+ bytes value;
+ }
+
+ /// @notice The public value output for the sp1 verify (non)membership program.
+ struct MembershipOutput {
+ /// The app hash of the header.
+ bytes32 commitmentRoot;
+ /// The key-value pairs verified by the program.
+ KVPair[] kvPairs;
+ }
+
+ /// @notice The membership proof for the sp1 verify (non)membership program.
+ struct SP1MembershipProof {
+ /// The sp1 proof for the membership program.
+ SP1Proof sp1Proof;
+ /// The trusted consensus state that the proof is based on.
+ IICS07TendermintMsgs.ConsensusState trustedConsensusState;
+ }
+
+ /// @notice The membership proof for the sp1 verify (non)membership and update client program.
+ struct SP1MembershipAndUpdateClientProof {
+ /// The sp1 proof for the membership and update client program.
+ SP1Proof sp1Proof;
+ }
+
+ /// @notice The type of the membership proof.
+ enum MembershipProofType {
+ /// The proof is for the verify membership program.
+ SP1MembershipProof,
+ /// The proof is for the verify membership and update client program.
+ SP1MembershipAndUpdateClientProof
+ }
+
+ /// @notice The membership proof that can be submitted to the SP1Verifier contract.
+ struct MembershipProof {
+ /// The type of the membership proof.
+ MembershipProofType proofType;
+ /// The membership proof.
+ bytes proof;
+ }
+}
diff --git a/contracts/src/msgs/ISP1Msgs.sol b/contracts/src/msgs/ISP1Msgs.sol
new file mode 100644
index 000000000..11730b3
--- /dev/null
+++ b/contracts/src/msgs/ISP1Msgs.sol
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.8.25;
+
+/// @title SP1 Messages
+interface ISP1Msgs {
+ /// @notice The SP1 proof that can be submitted to the SP1Verifier contract.
+ struct SP1Proof {
+ /// The verification key for the program.
+ bytes32 vKey;
+ /// The public values for the program.
+ bytes publicValues;
+ /// The proof for the program.
+ bytes proof;
+ }
+}
diff --git a/contracts/src/ics07-tendermint/UcAndMembershipProgram.sol b/contracts/src/msgs/IUcAndMembershipMsgs.sol
similarity index 56%
rename from contracts/src/ics07-tendermint/UcAndMembershipProgram.sol
rename to contracts/src/msgs/IUcAndMembershipMsgs.sol
index 8b73432..30a85fd 100644
--- a/contracts/src/ics07-tendermint/UcAndMembershipProgram.sol
+++ b/contracts/src/msgs/IUcAndMembershipMsgs.sol
@@ -1,18 +1,18 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.25;
-import { MembershipProgram } from "./MembershipProgram.sol";
-import { UpdateClientProgram } from "./UpdateClientProgram.sol";
+import { IUpdateClientMsgs } from "./IUpdateClientMsgs.sol";
+import { IMembershipMsgs } from "./IMembershipMsgs.sol";
-/// @title UpdateClientAndMembershipProgram
+/// @title Update Client and Membership Program Messages
/// @author srdtrk
/// @notice Defines shared types for the update client and membership program.
-contract UpdateClientAndMembershipProgram {
+interface IUpdateClientAndMembershipMsgs is IUpdateClientMsgs {
/// @notice The public value output for the sp1 update client and membership program.
struct UcAndMembershipOutput {
/// Update client program output.
- UpdateClientProgram.UpdateClientOutput updateClientOutput;
+ UpdateClientOutput updateClientOutput;
/// The key-value pairs verified by the membership program in the proposed header.
- MembershipProgram.KVPair[] kvPairs;
+ IMembershipMsgs.KVPair[] kvPairs;
}
}
diff --git a/contracts/src/ics07-tendermint/UpdateClientProgram.sol b/contracts/src/msgs/IUpdateClientMsgs.sol
similarity index 60%
rename from contracts/src/ics07-tendermint/UpdateClientProgram.sol
rename to contracts/src/msgs/IUpdateClientMsgs.sol
index f586cf0..e448a20 100644
--- a/contracts/src/ics07-tendermint/UpdateClientProgram.sol
+++ b/contracts/src/msgs/IUpdateClientMsgs.sol
@@ -1,24 +1,31 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.25;
-import { ICS07Tendermint } from "./ICS07Tendermint.sol";
+import { IICS07TendermintMsgs } from "./IICS07TendermintMsgs.sol";
+import { ISP1Msgs } from "./ISP1Msgs.sol";
-/// @title UpdateClientProgram
+/// @title Update Client Program Messages
/// @author srdtrk
/// @notice Defines shared types for the update client program.
-contract UpdateClientProgram {
+interface IUpdateClientMsgs is IICS07TendermintMsgs, ISP1Msgs {
+ /// @notice The message that is submitted to the updateClient function.
+ struct MsgUpdateClient {
+ /// SP1 proof for updating the client.
+ SP1Proof sp1Proof;
+ }
+
/// @notice The public value output for the sp1 update client program.
struct UpdateClientOutput {
/// The trusted consensus state.
- ICS07Tendermint.ConsensusState trustedConsensusState;
+ ConsensusState trustedConsensusState;
/// The new consensus state with the verified header.
- ICS07Tendermint.ConsensusState newConsensusState;
+ ConsensusState newConsensusState;
/// The validation environment.
Env env;
/// trusted height
- ICS07Tendermint.Height trustedHeight;
+ Height trustedHeight;
/// new height
- ICS07Tendermint.Height newHeight;
+ Height newHeight;
}
/// @notice The environment output for the sp1 program.
@@ -26,21 +33,11 @@ contract UpdateClientProgram {
/// The chain ID of the chain that the client is tracking.
string chainId;
/// Fraction of validator overlap needed to update header
- ICS07Tendermint.TrustThreshold trustThreshold;
+ TrustThreshold trustThreshold;
/// Duration of the period since the `LatestTimestamp` during which the
/// submitted headers are valid for upgrade in seconds.
uint32 trustingPeriod;
/// Timestamp in seconds
uint64 now;
}
-
- /// The result of an update operation
- enum UpdateResult {
- /// The update was successful
- Update,
- /// A misbehaviour was detected
- Misbehaviour,
- /// Client is already up to date
- NoOp
- }
}
diff --git a/contracts/test/Membership.t.sol b/contracts/test/Membership.t.sol
new file mode 100644
index 000000000..fcddad8
--- /dev/null
+++ b/contracts/test/Membership.t.sol
@@ -0,0 +1,187 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.8.25;
+
+// solhint-disable-next-line no-global-import
+import "forge-std/console.sol";
+import { stdJson } from "forge-std/StdJson.sol";
+import { MembershipTest } from "./MembershipTest.sol";
+
+contract SP1ICS07MembershipTest is MembershipTest {
+ using stdJson for string;
+
+ SP1MembershipProof public proof;
+
+ function setUp() public {
+ setUpTestWithFixtures("memberships_fixture.json");
+
+ proof = abi.decode(fixture.membershipProof.proof, (SP1MembershipProof));
+ }
+
+ function test_ValidateFixtures() public view {
+ MembershipOutput memory output = abi.decode(proof.sp1Proof.publicValues, (MembershipOutput));
+
+ assertEq(output.kvPairs.length, 2);
+ assertEq(string(output.kvPairs[0].path), VERIFY_MEMBERSHIP_PATH);
+ assert(output.kvPairs[0].value.length != 0);
+ assertEq(string(output.kvPairs[1].path), VERIFY_NON_MEMBERSHIP_PATH);
+ assertEq(output.kvPairs[1].value.length, 0);
+ }
+
+ function verifyMembershipValue() public view returns (bytes memory) {
+ MembershipOutput memory output = abi.decode(proof.sp1Proof.publicValues, (MembershipOutput));
+
+ return output.kvPairs[0].value;
+ }
+
+ // Confirm that submitting a real proof passes the verifier.
+ function test_ValidVerifyMembership() public {
+ MsgMembership memory membershipMsg = MsgMembership({
+ proof: abi.encode(fixture.membershipProof),
+ proofHeight: fixture.proofHeight,
+ path: bytes(VERIFY_MEMBERSHIP_PATH),
+ value: verifyMembershipValue()
+ });
+
+ ics07Tendermint.membership(membershipMsg);
+
+ // to console
+ console.log("VerifyMultiMembership gas used: ", vm.lastCallGas().gasTotalUsed);
+ }
+
+ // Modify the proof to make it a non-membership proof.
+ function test_ValidVerifyNonMembership() public {
+ MsgMembership memory membershipMsg = MsgMembership({
+ proof: abi.encode(fixture.membershipProof),
+ proofHeight: fixture.proofHeight,
+ path: bytes(VERIFY_NON_MEMBERSHIP_PATH),
+ value: bytes("")
+ });
+
+ ics07Tendermint.membership(membershipMsg);
+ // to console
+ console.log("VerifyNonMembership gas used: ", vm.lastCallGas().gasTotalUsed);
+ }
+
+ // Confirm that submitting an invalid proof with the real verifier fails.
+ function test_Invalid_VerifyMembership() public {
+ SP1MembershipProof memory proofMsg = proof;
+ proofMsg.sp1Proof.proof = bytes("invalid");
+
+ MembershipProof memory membershipProof =
+ MembershipProof({ proofType: MembershipProofType.SP1MembershipProof, proof: abi.encode(proofMsg) });
+
+ MsgMembership memory membershipMsg = MsgMembership({
+ proof: abi.encode(membershipProof),
+ proofHeight: fixture.proofHeight,
+ path: bytes(VERIFY_NON_MEMBERSHIP_PATH),
+ value: bytes("")
+ });
+
+ vm.expectRevert();
+ ics07Tendermint.membership(membershipMsg);
+ }
+
+ function test_Invalid_MockMembership() public {
+ MockInvalidMembershipTestCase[] memory testCases = new MockInvalidMembershipTestCase[](7);
+ testCases[0] = MockInvalidMembershipTestCase({
+ name: "success: valid mock",
+ sp1Proof: SP1Proof({ proof: bytes(""), publicValues: proof.sp1Proof.publicValues, vKey: proof.sp1Proof.vKey }),
+ proofHeight: fixture.proofHeight.revisionHeight,
+ path: bytes(VERIFY_NON_MEMBERSHIP_PATH),
+ value: bytes(""),
+ expPass: true
+ });
+ testCases[1] = MockInvalidMembershipTestCase({
+ name: "Invalid proof",
+ sp1Proof: SP1Proof({
+ proof: bytes("invalid"),
+ publicValues: proof.sp1Proof.publicValues,
+ vKey: proof.sp1Proof.vKey
+ }),
+ proofHeight: fixture.proofHeight.revisionHeight,
+ path: bytes(VERIFY_NON_MEMBERSHIP_PATH),
+ value: bytes(""),
+ expPass: false
+ });
+ testCases[2] = MockInvalidMembershipTestCase({
+ name: "Invalid proof height",
+ sp1Proof: SP1Proof({ proof: bytes(""), publicValues: proof.sp1Proof.publicValues, vKey: proof.sp1Proof.vKey }),
+ proofHeight: fixture.proofHeight.revisionHeight + 1,
+ path: bytes(VERIFY_NON_MEMBERSHIP_PATH),
+ value: bytes(""),
+ expPass: false
+ });
+ testCases[3] = MockInvalidMembershipTestCase({
+ name: "Invalid path",
+ sp1Proof: SP1Proof({ proof: bytes(""), publicValues: proof.sp1Proof.publicValues, vKey: proof.sp1Proof.vKey }),
+ proofHeight: fixture.proofHeight.revisionHeight,
+ path: bytes("invalid"),
+ value: bytes(""),
+ expPass: false
+ });
+ testCases[4] = MockInvalidMembershipTestCase({
+ name: "Invalid value",
+ sp1Proof: SP1Proof({ proof: bytes(""), publicValues: proof.sp1Proof.publicValues, vKey: proof.sp1Proof.vKey }),
+ proofHeight: fixture.proofHeight.revisionHeight,
+ path: bytes(VERIFY_NON_MEMBERSHIP_PATH),
+ value: bytes("invalid"),
+ expPass: false
+ });
+ testCases[5] = MockInvalidMembershipTestCase({
+ name: "Invalid vKey",
+ sp1Proof: SP1Proof({
+ proof: bytes(""),
+ publicValues: proof.sp1Proof.publicValues,
+ vKey: genesisFixture.ucAndMembershipVkey
+ }),
+ proofHeight: fixture.proofHeight.revisionHeight,
+ path: bytes(VERIFY_NON_MEMBERSHIP_PATH),
+ value: bytes(""),
+ expPass: false
+ });
+ testCases[6] = MockInvalidMembershipTestCase({
+ name: "Invalid public values",
+ sp1Proof: SP1Proof({ proof: bytes(""), publicValues: bytes("invalid"), vKey: proof.sp1Proof.vKey }),
+ proofHeight: fixture.proofHeight.revisionHeight,
+ path: bytes(VERIFY_NON_MEMBERSHIP_PATH),
+ value: bytes(""),
+ expPass: false
+ });
+
+ for (uint256 i = 0; i < testCases.length; i++) {
+ MockInvalidMembershipTestCase memory tc = testCases[i];
+
+ SP1MembershipProof memory proofMsg = proof;
+ proofMsg.sp1Proof = tc.sp1Proof;
+
+ MembershipProof memory membershipProof =
+ MembershipProof({ proofType: MembershipProofType.SP1MembershipProof, proof: abi.encode(proofMsg) });
+
+ Height memory proofHeight = fixture.proofHeight;
+ proofHeight.revisionHeight = tc.proofHeight;
+
+ MsgMembership memory membershipMsg = MsgMembership({
+ proof: abi.encode(membershipProof),
+ proofHeight: proofHeight,
+ path: tc.path,
+ value: tc.value
+ });
+
+ if (tc.expPass) {
+ mockIcs07Tendermint.membership(membershipMsg);
+ } else {
+ vm.expectRevert();
+ mockIcs07Tendermint.membership(membershipMsg);
+ }
+ }
+ }
+
+ struct MockInvalidMembershipTestCase {
+ string name;
+ SP1Proof sp1Proof;
+ uint32 proofHeight;
+ bytes path;
+ bytes value;
+ bool expPass;
+ }
+}
diff --git a/contracts/test/MembershipTest.sol b/contracts/test/MembershipTest.sol
index 11376a8..c8e9cda 100644
--- a/contracts/test/MembershipTest.sol
+++ b/contracts/test/MembershipTest.sol
@@ -5,59 +5,37 @@ pragma solidity >=0.8.25;
import "forge-std/console.sol";
import { stdJson } from "forge-std/StdJson.sol";
import { SP1ICS07TendermintTest } from "./SP1ICS07TendermintTest.sol";
-import { MembershipProgram } from "../src/ics07-tendermint/MembershipProgram.sol";
-
-struct SP1ICS07MembershipFixtureJson {
- uint32 proofHeight;
- bytes trustedClientState;
- bytes trustedConsensusState;
- bytes32 commitmentRoot;
- bytes publicValues;
- bytes proof;
- bytes kvPairsBz;
-}
abstract contract MembershipTest is SP1ICS07TendermintTest {
+ // set constant string
+ string public constant VERIFY_MEMBERSHIP_PATH = "clients/07-tendermint-0/clientState";
+ string public constant VERIFY_NON_MEMBERSHIP_PATH = "clients/07-tendermint-001/clientState";
+
+ struct SP1ICS07MembershipFixtureJson {
+ Height proofHeight;
+ MembershipProof membershipProof;
+ }
+
using stdJson for string;
SP1ICS07MembershipFixtureJson public fixture;
- SP1ICS07MembershipFixtureJson public mockFixture;
- function setUpTestWithFixtures(string memory fileName, string memory mockFileName) public {
+ function setUpTestWithFixtures(string memory fileName) public {
fixture = loadFixture(fileName);
- mockFixture = loadFixture(mockFileName);
-
- setUpTest(fileName, mockFileName);
- }
-
- function kvPairs() public view returns (MembershipProgram.KVPair[] memory) {
- return abi.decode(fixture.kvPairsBz, (MembershipProgram.KVPair[]));
- }
- function mockKvPairs() public view returns (MembershipProgram.KVPair[] memory) {
- return abi.decode(mockFixture.kvPairsBz, (MembershipProgram.KVPair[]));
+ setUpTest(fileName);
}
function loadFixture(string memory fileName) public view returns (SP1ICS07MembershipFixtureJson memory) {
string memory root = vm.projectRoot();
string memory path = string.concat(root, "/contracts/fixtures/", fileName);
string memory json = vm.readFile(path);
- bytes memory trustedClientState = json.readBytes(".trustedClientState");
- bytes memory trustedConsensusState = json.readBytes(".trustedConsensusState");
- uint32 proofHeight = uint32(json.readUint(".proofHeight"));
- bytes32 commitmentRoot = json.readBytes32(".commitmentRoot");
- bytes memory publicValues = json.readBytes(".publicValues");
- bytes memory proof = json.readBytes(".proof");
- bytes memory kvPairsBz = json.readBytes(".kvPairs");
+ bytes memory proofHeightBz = json.readBytes(".proofHeight");
+ bytes memory membershipProofBz = json.readBytes(".membershipProof");
SP1ICS07MembershipFixtureJson memory fix = SP1ICS07MembershipFixtureJson({
- commitmentRoot: commitmentRoot,
- trustedClientState: trustedClientState,
- trustedConsensusState: trustedConsensusState,
- proofHeight: proofHeight,
- publicValues: publicValues,
- proof: proof,
- kvPairsBz: kvPairsBz
+ proofHeight: abi.decode(proofHeightBz, (Height)),
+ membershipProof: abi.decode(membershipProofBz, (MembershipProof))
});
return fix;
diff --git a/contracts/test/MultiMembership.t.sol b/contracts/test/MultiMembership.t.sol
deleted file mode 100644
index 587f01b..000000000
--- a/contracts/test/MultiMembership.t.sol
+++ /dev/null
@@ -1,124 +0,0 @@
-// SPDX-License-Identifier: UNLICENSED
-pragma solidity >=0.8.25;
-
-// solhint-disable-next-line no-global-import
-import "forge-std/console.sol";
-import { stdJson } from "forge-std/StdJson.sol";
-import { MembershipTest } from "./MembershipTest.sol";
-
-// set constant string
-string constant verifyMembershipPath = "clients/07-tendermint-0/clientState";
-string constant verifyNonMembershipPath = "clients/07-tendermint-001/clientState";
-
-contract SP1ICS07MultiMembershipTest is MembershipTest {
- using stdJson for string;
-
- function setUp() public {
- setUpTestWithFixtures("memberships_fixture.json", "mock_memberships_fixture.json");
- }
-
- function test_ValidateFixtures() public view {
- assertEq(kvPairs().length, 2);
- assertEq(kvPairs()[0].key, verifyMembershipPath);
- assert(kvPairs()[0].value.length != 0);
- assertEq(kvPairs()[1].key, verifyNonMembershipPath);
- assertEq(kvPairs()[1].value.length, 0);
-
- assertEq(mockKvPairs().length, 2);
- assertEq(mockKvPairs()[0].key, verifyMembershipPath);
- assert(mockKvPairs()[0].value.length != 0);
- assertEq(mockKvPairs()[1].key, verifyNonMembershipPath);
- assertEq(mockKvPairs()[1].value.length, 0);
- }
-
- function test_ValidVerifyNonMembership() public view {
- bytes32[] memory kvPairHashes = new bytes32[](2);
- kvPairHashes[0] = bytes32(0); // skip validation of the first kvPair
- kvPairHashes[1] = keccak256(abi.encode(kvPairs()[1]));
-
- ics07Tendermint.batchVerifyMembership(
- fixture.proof, fixture.publicValues, fixture.proofHeight, fixture.trustedConsensusState, kvPairHashes
- );
-
- // to console
- console.log("VerifyNonMembership gas used: ", vm.lastCallGas().gasTotalUsed);
- }
-
- // Confirm that submitting a real proof passes the verifier.
- function test_ValidMultiMembership() public view {
- bytes32[] memory kvPairHashes = new bytes32[](2);
- kvPairHashes[0] = keccak256(abi.encode(kvPairs()[0]));
- kvPairHashes[1] = keccak256(abi.encode(kvPairs()[1]));
-
- ics07Tendermint.batchVerifyMembership(
- fixture.proof, fixture.publicValues, fixture.proofHeight, fixture.trustedConsensusState, kvPairHashes
- );
-
- // to console
- console.log("VerifyMultiMembership gas used: ", vm.lastCallGas().gasTotalUsed);
- }
-
- // Confirm that submitting an empty proof passes the mock verifier.
- function test_ValidMockMultiMembership() public view {
- bytes32[] memory kvPairHashes = new bytes32[](2);
- kvPairHashes[0] = keccak256(abi.encode(mockKvPairs()[0]));
- kvPairHashes[1] = keccak256(abi.encode(mockKvPairs()[1]));
-
- mockIcs07Tendermint.batchVerifyMembership(
- bytes(""),
- mockFixture.publicValues,
- mockFixture.proofHeight,
- mockFixture.trustedConsensusState,
- kvPairHashes
- );
- }
-
- function test_Invalid_MockMultiMembership() public {
- bytes32[] memory kvPairHashes = new bytes32[](2);
- kvPairHashes[0] = keccak256(abi.encode(mockKvPairs()[0]));
- kvPairHashes[1] = keccak256(abi.encode(mockKvPairs()[1]));
- // Invalid proof
- vm.expectRevert();
- mockIcs07Tendermint.batchVerifyMembership(
- bytes("invalid"),
- mockFixture.publicValues,
- mockFixture.proofHeight,
- mockFixture.trustedConsensusState,
- kvPairHashes
- );
-
- // Invalid proof height
- vm.expectRevert();
- mockIcs07Tendermint.batchVerifyMembership(
- bytes(""), mockFixture.publicValues, 1, mockFixture.trustedConsensusState, kvPairHashes
- );
-
- // Invalid trusted consensus state
- vm.expectRevert();
- mockIcs07Tendermint.batchVerifyMembership(
- bytes(""), mockFixture.publicValues, mockFixture.proofHeight, bytes("invalid"), kvPairHashes
- );
-
- // Empty kvPairHashes length
- vm.expectRevert();
- mockIcs07Tendermint.batchVerifyMembership(
- bytes(""),
- mockFixture.publicValues,
- mockFixture.proofHeight,
- mockFixture.trustedConsensusState,
- new bytes32[](0)
- );
- }
-
- // Confirm that submitting a random proof with the real verifier fails.
- function test_Invalid_MultiMembership() public {
- bytes32[] memory kvPairHashes = new bytes32[](2);
- kvPairHashes[0] = keccak256(abi.encode(mockKvPairs()[0]));
- kvPairHashes[1] = keccak256(abi.encode(mockKvPairs()[1]));
-
- vm.expectRevert();
- ics07Tendermint.batchVerifyMembership(
- bytes("invalid"), fixture.publicValues, fixture.proofHeight, fixture.trustedConsensusState, kvPairHashes
- );
- }
-}
diff --git a/contracts/test/SP1ICS07TendermintTest.sol b/contracts/test/SP1ICS07TendermintTest.sol
index e0ed057..b0708d9 100644
--- a/contracts/test/SP1ICS07TendermintTest.sol
+++ b/contracts/test/SP1ICS07TendermintTest.sol
@@ -5,10 +5,14 @@ pragma solidity >=0.8.25;
import "forge-std/console.sol";
import { Test } from "forge-std/Test.sol";
import { stdJson } from "forge-std/StdJson.sol";
-import { ICS07Tendermint } from "../src/ics07-tendermint/ICS07Tendermint.sol";
+import { IICS07TendermintMsgs } from "../src/msgs/IICS07TendermintMsgs.sol";
+import { IUpdateClientMsgs } from "../src/msgs/IUpdateClientMsgs.sol";
+import { IMembershipMsgs } from "../src/msgs/IMembershipMsgs.sol";
+import { IUpdateClientAndMembershipMsgs } from "../src/msgs/IUcAndMembershipMsgs.sol";
import { SP1ICS07Tendermint } from "../src/SP1ICS07Tendermint.sol";
import { SP1Verifier } from "@sp1-contracts/v1.0.1/SP1Verifier.sol";
import { SP1MockVerifier } from "@sp1-contracts/SP1MockVerifier.sol";
+import { ILightClientMsgs } from "solidity-ibc/msgs/ILightClientMsgs.sol";
struct SP1ICS07GenesisFixtureJson {
bytes trustedClientState;
@@ -18,7 +22,14 @@ struct SP1ICS07GenesisFixtureJson {
bytes32 ucAndMembershipVkey;
}
-abstract contract SP1ICS07TendermintTest is Test {
+abstract contract SP1ICS07TendermintTest is
+ Test,
+ IICS07TendermintMsgs,
+ IUpdateClientMsgs,
+ IMembershipMsgs,
+ IUpdateClientAndMembershipMsgs,
+ ILightClientMsgs
+{
using stdJson for string;
SP1Verifier public verifier;
@@ -27,13 +38,11 @@ abstract contract SP1ICS07TendermintTest is Test {
SP1ICS07Tendermint public mockIcs07Tendermint;
SP1ICS07GenesisFixtureJson internal genesisFixture;
- SP1ICS07GenesisFixtureJson internal mockGenesisFixture;
- function setUpTest(string memory fileName, string memory mockFileName) public {
+ function setUpTest(string memory fileName) public {
genesisFixture = loadGenesisFixture(fileName);
- ICS07Tendermint.ConsensusState memory trustedConsensusState =
- abi.decode(genesisFixture.trustedConsensusState, (ICS07Tendermint.ConsensusState));
+ ConsensusState memory trustedConsensusState = abi.decode(genesisFixture.trustedConsensusState, (ConsensusState));
bytes32 trustedConsensusHash = keccak256(abi.encode(trustedConsensusState));
@@ -47,28 +56,21 @@ abstract contract SP1ICS07TendermintTest is Test {
trustedConsensusHash
);
- mockGenesisFixture = loadGenesisFixture(mockFileName);
-
- ICS07Tendermint.ConsensusState memory mockTrustedConsensusState =
- abi.decode(mockGenesisFixture.trustedConsensusState, (ICS07Tendermint.ConsensusState));
-
- bytes32 mockTrustedConsensusHash = keccak256(abi.encode(mockTrustedConsensusState));
-
SP1MockVerifier mockVerifier = new SP1MockVerifier();
mockIcs07Tendermint = new SP1ICS07Tendermint(
- mockGenesisFixture.updateClientVkey,
- mockGenesisFixture.membershipVkey,
- mockGenesisFixture.ucAndMembershipVkey,
+ genesisFixture.updateClientVkey,
+ genesisFixture.membershipVkey,
+ genesisFixture.ucAndMembershipVkey,
address(mockVerifier),
- mockGenesisFixture.trustedClientState,
- mockTrustedConsensusHash
+ genesisFixture.trustedClientState,
+ trustedConsensusHash
);
- ICS07Tendermint.ClientState memory clientState = mockIcs07Tendermint.getClientState();
- assert(keccak256(abi.encode(clientState)) == keccak256(mockGenesisFixture.trustedClientState));
+ ClientState memory clientState = mockIcs07Tendermint.getClientState();
+ assert(keccak256(abi.encode(clientState)) == keccak256(genesisFixture.trustedClientState));
bytes32 consensusHash = mockIcs07Tendermint.getConsensusStateHash(clientState.latestHeight.revisionHeight);
- assert(consensusHash == mockTrustedConsensusHash);
+ assert(consensusHash == trustedConsensusHash);
}
function loadGenesisFixture(string memory fileName) public view returns (SP1ICS07GenesisFixtureJson memory) {
diff --git a/contracts/test/UcAndMembership.t.sol b/contracts/test/UcAndMembership.t.sol
index 43ff4e3..d09c0ae 100644
--- a/contracts/test/UcAndMembership.t.sol
+++ b/contracts/test/UcAndMembership.t.sol
@@ -1,176 +1,111 @@
-// SPDX-License-Identifier: UNLICENSED
+// SPDX-License-Identifier: MIT
pragma solidity >=0.8.25;
// solhint-disable-next-line no-global-import
import "forge-std/console.sol";
import { stdJson } from "forge-std/StdJson.sol";
-import { ICS07Tendermint } from "../src/ics07-tendermint/ICS07Tendermint.sol";
-import { UpdateClientAndMembershipProgram } from "../src/ics07-tendermint/UcAndMembershipProgram.sol";
-import { MembershipProgram } from "../src/ics07-tendermint/MembershipProgram.sol";
-import { SP1ICS07TendermintTest } from "./SP1ICS07TendermintTest.sol";
-
-struct SP1ICS07UcAndMemberhsipFixtureJson {
- bytes trustedClientState;
- bytes trustedConsensusState;
- bytes targetConsensusState;
- uint32 targetHeight;
- bytes publicValues;
- bytes proof;
- bytes kvPairsBz;
-}
-
-string constant verifyMembershipPath = "clients/07-tendermint-0/clientState";
-string constant verifyNonMembershipPath = "clients/07-tendermint-001/clientState";
+import { MembershipTest } from "./MembershipTest.sol";
-contract SP1ICS07UpdateClientAndMembershipTest is SP1ICS07TendermintTest {
+contract SP1ICS07UpdateClientAndMembershipTest is MembershipTest {
using stdJson for string;
- SP1ICS07UcAndMemberhsipFixtureJson public fixture;
- SP1ICS07UcAndMemberhsipFixtureJson public mockFixture;
+ SP1MembershipAndUpdateClientProof public proof;
function setUp() public {
- fixture = loadFixture("uc_and_memberships_fixture.json");
- mockFixture = loadFixture("mock_uc_and_memberships_fixture.json");
+ setUpTestWithFixtures("uc_and_memberships_fixture.json");
- setUpTest("uc_and_memberships_fixture.json", "mock_uc_and_memberships_fixture.json");
+ proof = abi.decode(fixture.membershipProof.proof, (SP1MembershipAndUpdateClientProof));
- ICS07Tendermint.ClientState memory clientState = mockIcs07Tendermint.getClientState();
- assert(clientState.latestHeight.revisionHeight < mockFixture.targetHeight);
+ UcAndMembershipOutput memory output = abi.decode(proof.sp1Proof.publicValues, (UcAndMembershipOutput));
+
+ ClientState memory clientState = mockIcs07Tendermint.getClientState();
+ assert(clientState.latestHeight.revisionHeight < output.updateClientOutput.newHeight.revisionHeight);
}
- function loadFixture(string memory fileName) public view returns (SP1ICS07UcAndMemberhsipFixtureJson memory) {
- string memory root = vm.projectRoot();
- string memory path = string.concat(root, "/contracts/fixtures/", fileName);
- string memory json = vm.readFile(path);
- bytes memory trustedClientState = json.readBytes(".trustedClientState");
- bytes memory trustedConsensusState = json.readBytes(".trustedConsensusState");
- bytes memory targetConsensusStateHash = json.readBytes(".targetConsensusState");
- uint32 targetHeight = uint32(json.readUint(".targetHeight"));
- bytes memory publicValues = json.readBytes(".publicValues");
- bytes memory proof = json.readBytes(".proof");
- bytes memory kvPairsBz = json.readBytes(".kvPairs");
-
- SP1ICS07UcAndMemberhsipFixtureJson memory fix = SP1ICS07UcAndMemberhsipFixtureJson({
- trustedClientState: trustedClientState,
- trustedConsensusState: trustedConsensusState,
- targetConsensusState: targetConsensusStateHash,
- targetHeight: targetHeight,
- publicValues: publicValues,
- proof: proof,
- kvPairsBz: kvPairsBz
- });
+ function verifyMembershipValue() public view returns (bytes memory) {
+ UcAndMembershipOutput memory output = abi.decode(proof.sp1Proof.publicValues, (UcAndMembershipOutput));
- return fix;
+ return output.kvPairs[0].value;
}
// Confirm that submitting a real proof passes the verifier.
- function test_ValidUpdateClientAndMultiMembership() public {
- UpdateClientAndMembershipProgram.UcAndMembershipOutput memory output =
- abi.decode(fixture.publicValues, (UpdateClientAndMembershipProgram.UcAndMembershipOutput));
+ function test_Valid_UpdateClientAndVerifyMembership() public {
+ UcAndMembershipOutput memory output = abi.decode(proof.sp1Proof.publicValues, (UcAndMembershipOutput));
// set a correct timestamp
vm.warp(output.updateClientOutput.env.now + 300);
- bytes32[] memory kvPairHashes = new bytes32[](2);
- kvPairHashes[0] = keccak256(abi.encode(kvPairs()[0]));
- kvPairHashes[1] = keccak256(abi.encode(kvPairs()[1]));
+ MsgMembership memory membershipMsg = MsgMembership({
+ proof: abi.encode(fixture.membershipProof),
+ proofHeight: fixture.proofHeight,
+ path: bytes(VERIFY_MEMBERSHIP_PATH),
+ value: verifyMembershipValue()
+ });
// run verify
- ics07Tendermint.updateClientAndBatchVerifyMembership(fixture.proof, fixture.publicValues, kvPairHashes);
+ ics07Tendermint.membership(membershipMsg);
// to console
- console.log("UpdateClientAndMultiMembership gas used: ", vm.lastCallGas().gasTotalUsed);
-
- ICS07Tendermint.ClientState memory clientState = ics07Tendermint.getClientState();
- assert(clientState.latestHeight.revisionHeight == fixture.targetHeight);
- assert(clientState.isFrozen == false);
-
- bytes32 consensusHash = ics07Tendermint.getConsensusStateHash(fixture.targetHeight);
- ICS07Tendermint.ConsensusState memory expConsensusState =
- abi.decode(fixture.targetConsensusState, (ICS07Tendermint.ConsensusState));
- assert(consensusHash == keccak256(abi.encode(expConsensusState)));
- }
-
- function test_ValidMockUpdateClientAndMultiMembership() public {
- UpdateClientAndMembershipProgram.UcAndMembershipOutput memory output =
- abi.decode(mockFixture.publicValues, (UpdateClientAndMembershipProgram.UcAndMembershipOutput));
- vm.warp(output.updateClientOutput.env.now + 300);
-
- bytes32[] memory kvPairHashes = new bytes32[](2);
- kvPairHashes[0] = keccak256(abi.encode(mockKvPairs()[0]));
- kvPairHashes[1] = keccak256(abi.encode(mockKvPairs()[1]));
-
- mockIcs07Tendermint.updateClientAndBatchVerifyMembership(bytes(""), mockFixture.publicValues, kvPairHashes);
+ console.log("UpdateClientAndVerifyMembership gas used: ", vm.lastCallGas().gasTotalUsed);
- ICS07Tendermint.ClientState memory clientState = mockIcs07Tendermint.getClientState();
- assert(keccak256(bytes(clientState.chainId)) == keccak256(bytes("mocha-4")));
- assert(clientState.latestHeight.revisionHeight == fixture.targetHeight);
+ ClientState memory clientState = ics07Tendermint.getClientState();
+ assert(clientState.latestHeight.revisionHeight == output.updateClientOutput.newHeight.revisionHeight);
assert(clientState.isFrozen == false);
- bytes32 consensusHash = mockIcs07Tendermint.getConsensusStateHash(mockFixture.targetHeight);
- ICS07Tendermint.ConsensusState memory expConsensusState =
- abi.decode(mockFixture.targetConsensusState, (ICS07Tendermint.ConsensusState));
- assert(consensusHash == keccak256(abi.encode(expConsensusState)));
+ bytes32 consensusHash =
+ ics07Tendermint.getConsensusStateHash(output.updateClientOutput.newHeight.revisionHeight);
+ assert(consensusHash == keccak256(abi.encode(output.updateClientOutput.newConsensusState)));
}
- function test_ValidUpdateClientAndVerifyMembership() public {
- UpdateClientAndMembershipProgram.UcAndMembershipOutput memory output =
- abi.decode(fixture.publicValues, (UpdateClientAndMembershipProgram.UcAndMembershipOutput));
+ // Confirm that submitting a real proof passes the verifier.
+ function test_Valid_UpdateClientAndVerifyNonMembership() public {
+ UcAndMembershipOutput memory output = abi.decode(proof.sp1Proof.publicValues, (UcAndMembershipOutput));
// set a correct timestamp
vm.warp(output.updateClientOutput.env.now + 300);
- bytes32[] memory kvPairHashes = new bytes32[](2);
- kvPairHashes[0] = keccak256(abi.encode(kvPairs()[0]));
- kvPairHashes[1] = bytes32(0);
+ MsgMembership memory membershipMsg = MsgMembership({
+ proof: abi.encode(fixture.membershipProof),
+ proofHeight: fixture.proofHeight,
+ path: bytes(VERIFY_NON_MEMBERSHIP_PATH),
+ value: bytes("")
+ });
// run verify
- ics07Tendermint.updateClientAndBatchVerifyMembership(fixture.proof, fixture.publicValues, kvPairHashes);
+ ics07Tendermint.membership(membershipMsg);
// to console
- console.log("UpdateClientAndVerifyMembership gas used: ", vm.lastCallGas().gasTotalUsed);
+ console.log("UpdateClientAndVerifyNonMembership gas used: ", vm.lastCallGas().gasTotalUsed);
- ICS07Tendermint.ClientState memory clientState = ics07Tendermint.getClientState();
- assert(keccak256(bytes(clientState.chainId)) == keccak256(bytes("mocha-4")));
- assert(clientState.latestHeight.revisionHeight == fixture.targetHeight);
+ ClientState memory clientState = ics07Tendermint.getClientState();
+ assert(clientState.latestHeight.revisionHeight == output.updateClientOutput.newHeight.revisionHeight);
assert(clientState.isFrozen == false);
- bytes32 consensusHash = ics07Tendermint.getConsensusStateHash(fixture.targetHeight);
- ICS07Tendermint.ConsensusState memory expConsensusState =
- abi.decode(fixture.targetConsensusState, (ICS07Tendermint.ConsensusState));
- assert(consensusHash == keccak256(abi.encode(expConsensusState)));
+ bytes32 consensusHash =
+ ics07Tendermint.getConsensusStateHash(output.updateClientOutput.newHeight.revisionHeight);
+ assert(consensusHash == keccak256(abi.encode(output.updateClientOutput.newConsensusState)));
}
- // Confirm that submitting a non-empty proof with the mock verifier fails.
- function test_Invalid_MockUpdateClient() public {
- bytes32[] memory kvPairHashes = new bytes32[](2);
- kvPairHashes[0] = keccak256(abi.encode(mockKvPairs()[0]));
- kvPairHashes[1] = keccak256(abi.encode(mockKvPairs()[1]));
+ // Confirm that submitting a real proof passes the verifier.
+ function test_Invalid_UpdateClientAndMembership() public {
+ UcAndMembershipOutput memory output = abi.decode(proof.sp1Proof.publicValues, (UcAndMembershipOutput));
+ // set a correct timestamp
+ vm.warp(output.updateClientOutput.env.now + 300);
- vm.expectRevert();
- mockIcs07Tendermint.updateClientAndBatchVerifyMembership(
- bytes("invalid"), mockFixture.publicValues, kvPairHashes
- );
+ SP1MembershipAndUpdateClientProof memory ucAndMemProof = proof;
+ ucAndMemProof.sp1Proof.proof = bytes("invalid");
- // wrong hash
- kvPairHashes[0] = keccak256("random");
- vm.expectRevert();
- mockIcs07Tendermint.updateClientAndBatchVerifyMembership(bytes(""), mockFixture.publicValues, kvPairHashes);
- }
+ MembershipProof memory membershipProof = MembershipProof({
+ proofType: MembershipProofType.SP1MembershipAndUpdateClientProof,
+ proof: abi.encode(ucAndMemProof)
+ });
- // Confirm that submitting a random proof with the real verifier fails.
- function test_Invalid_UpdateClient() public {
- bytes32[] memory kvPairHashes = new bytes32[](2);
- kvPairHashes[0] = keccak256(abi.encode(kvPairs()[0]));
- kvPairHashes[1] = keccak256(abi.encode(kvPairs()[1]));
+ MsgMembership memory membershipMsg = MsgMembership({
+ proof: abi.encode(membershipProof),
+ proofHeight: fixture.proofHeight,
+ path: bytes(VERIFY_NON_MEMBERSHIP_PATH),
+ value: bytes("")
+ });
vm.expectRevert();
- ics07Tendermint.updateClientAndBatchVerifyMembership(bytes("invalid"), fixture.publicValues, kvPairHashes);
- }
-
- function kvPairs() public view returns (MembershipProgram.KVPair[] memory) {
- return abi.decode(fixture.kvPairsBz, (MembershipProgram.KVPair[]));
- }
-
- function mockKvPairs() public view returns (MembershipProgram.KVPair[] memory) {
- return abi.decode(mockFixture.kvPairsBz, (MembershipProgram.KVPair[]));
+ ics07Tendermint.membership(membershipMsg);
}
}
diff --git a/contracts/test/UpdateClient.t.sol b/contracts/test/UpdateClient.t.sol
index 83513e7..88b1360 100644
--- a/contracts/test/UpdateClient.t.sol
+++ b/contracts/test/UpdateClient.t.sol
@@ -4,35 +4,39 @@ pragma solidity >=0.8.25;
// solhint-disable-next-line no-global-import
import "forge-std/console.sol";
import { stdJson } from "forge-std/StdJson.sol";
-import { ICS07Tendermint } from "../src/ics07-tendermint/ICS07Tendermint.sol";
-import { UpdateClientProgram } from "../src/ics07-tendermint/UpdateClientProgram.sol";
import { SP1ICS07TendermintTest } from "./SP1ICS07TendermintTest.sol";
struct SP1ICS07UpdateClientFixtureJson {
bytes trustedClientState;
bytes trustedConsensusState;
- bytes targetConsensusState;
- uint32 targetHeight;
- bytes publicValues;
- bytes proof;
+ bytes updateMsg;
}
contract SP1ICS07UpdateClientTest is SP1ICS07TendermintTest {
using stdJson for string;
SP1ICS07UpdateClientFixtureJson public fixture;
- SP1ICS07UpdateClientFixtureJson public mockFixture;
+
+ uint32 public targetHeight;
+ ConsensusState public targetConsensusState;
+ Env public env;
function setUp() public {
fixture = loadFixture("update_client_fixture.json");
- mockFixture = loadFixture("mock_update_client_fixture.json");
- setUpTest("update_client_fixture.json", "mock_update_client_fixture.json");
+ setUpTest("update_client_fixture.json");
+
+ MsgUpdateClient memory updateMsg = abi.decode(fixture.updateMsg, (MsgUpdateClient));
+ UpdateClientOutput memory output = abi.decode(updateMsg.sp1Proof.publicValues, (UpdateClientOutput));
+ targetHeight = output.newHeight.revisionHeight;
+ targetConsensusState = output.newConsensusState;
+ env = output.env;
- ICS07Tendermint.ClientState memory clientState = mockIcs07Tendermint.getClientState();
- assert(clientState.latestHeight.revisionHeight < mockFixture.targetHeight);
+ ClientState memory clientState = mockIcs07Tendermint.getClientState();
+ assert(clientState.latestHeight.revisionHeight < targetHeight);
- assert(mockIcs07Tendermint.getConsensusStateHash(mockFixture.targetHeight) == bytes32(0));
+ vm.expectRevert();
+ mockIcs07Tendermint.getConsensusStateHash(targetHeight);
}
function loadFixture(string memory fileName) public view returns (SP1ICS07UpdateClientFixtureJson memory) {
@@ -41,18 +45,12 @@ contract SP1ICS07UpdateClientTest is SP1ICS07TendermintTest {
string memory json = vm.readFile(path);
bytes memory trustedClientState = json.readBytes(".trustedClientState");
bytes memory trustedConsensusState = json.readBytes(".trustedConsensusState");
- bytes memory targetConsensusState = json.readBytes(".targetConsensusState");
- uint32 targetHeight = uint32(json.readUint(".targetHeight"));
- bytes memory publicValues = json.readBytes(".publicValues");
- bytes memory proof = json.readBytes(".proof");
+ bytes memory updateMsg = json.readBytes(".updateMsg");
SP1ICS07UpdateClientFixtureJson memory fix = SP1ICS07UpdateClientFixtureJson({
trustedClientState: trustedClientState,
trustedConsensusState: trustedConsensusState,
- targetConsensusState: targetConsensusState,
- targetHeight: targetHeight,
- publicValues: publicValues,
- proof: proof
+ updateMsg: updateMsg
});
return fix;
@@ -61,77 +59,44 @@ contract SP1ICS07UpdateClientTest is SP1ICS07TendermintTest {
// Confirm that submitting a real proof passes the verifier.
function test_ValidUpdateClient() public {
// set a correct timestamp
- UpdateClientProgram.UpdateClientOutput memory output =
- abi.decode(fixture.publicValues, (UpdateClientProgram.UpdateClientOutput));
- vm.warp(output.env.now + 300);
+ vm.warp(env.now + 300);
// run verify
- UpdateClientProgram.UpdateResult res = ics07Tendermint.updateClient(fixture.proof, fixture.publicValues);
+ UpdateResult res = ics07Tendermint.updateClient(fixture.updateMsg);
// to console
console.log("UpdateClient gas used: ", vm.lastCallGas().gasTotalUsed);
- assert(res == UpdateClientProgram.UpdateResult.Update);
+ assert(res == UpdateResult.Update);
- ICS07Tendermint.ClientState memory clientState = ics07Tendermint.getClientState();
+ ClientState memory clientState = ics07Tendermint.getClientState();
assert(keccak256(bytes(clientState.chainId)) == keccak256(bytes("mocha-4")));
- assert(clientState.latestHeight.revisionHeight == fixture.targetHeight);
+ assert(clientState.latestHeight.revisionHeight == targetHeight);
assert(clientState.isFrozen == false);
- bytes32 consensusHash = ics07Tendermint.getConsensusStateHash(fixture.targetHeight);
- ICS07Tendermint.ConsensusState memory expConsensusState =
- abi.decode(fixture.targetConsensusState, (ICS07Tendermint.ConsensusState));
- assert(consensusHash == keccak256(abi.encode(expConsensusState)));
+ bytes32 consensusHash = ics07Tendermint.getConsensusStateHash(targetHeight);
+ assert(consensusHash == keccak256(abi.encode(targetConsensusState)));
}
// Confirm that submitting a real proof passes the verifier.
function test_ValidNoOpUpdateClient() public {
// set a correct timestamp
- UpdateClientProgram.UpdateClientOutput memory output =
- abi.decode(fixture.publicValues, (UpdateClientProgram.UpdateClientOutput));
- vm.warp(output.env.now + 300);
+ vm.warp(env.now + 300);
// run verify
- UpdateClientProgram.UpdateResult res = ics07Tendermint.updateClient(fixture.proof, fixture.publicValues);
- assert(res == UpdateClientProgram.UpdateResult.Update);
+ UpdateResult res = ics07Tendermint.updateClient(fixture.updateMsg);
+ assert(res == UpdateResult.Update);
// run verify again
- res = ics07Tendermint.updateClient(fixture.proof, fixture.publicValues);
+ res = ics07Tendermint.updateClient(fixture.updateMsg);
// to console
console.log("UpdateClient_NoOp gas used: ", vm.lastCallGas().gasTotalUsed);
- assert(res == UpdateClientProgram.UpdateResult.NoOp);
- }
-
- // Confirm that submitting an empty proof passes the mock verifier.
- function test_ValidMockUpdateClient() public {
- // set a correct timestamp
- UpdateClientProgram.UpdateClientOutput memory output =
- abi.decode(mockFixture.publicValues, (UpdateClientProgram.UpdateClientOutput));
- vm.warp(output.env.now + 300);
-
- // run verify
- UpdateClientProgram.UpdateResult res = mockIcs07Tendermint.updateClient(bytes(""), mockFixture.publicValues);
-
- assert(res == UpdateClientProgram.UpdateResult.Update);
- ICS07Tendermint.ClientState memory clientState = mockIcs07Tendermint.getClientState();
- assert(clientState.latestHeight.revisionHeight == mockFixture.targetHeight);
- assert(clientState.isFrozen == false);
-
- bytes32 consensusHash = mockIcs07Tendermint.getConsensusStateHash(mockFixture.targetHeight);
- ICS07Tendermint.ConsensusState memory expConsensusState =
- abi.decode(fixture.targetConsensusState, (ICS07Tendermint.ConsensusState));
- assert(consensusHash == keccak256(abi.encode(expConsensusState)));
- }
-
- // Confirm that submitting a non-empty proof with the mock verifier fails.
- function test_Invalid_MockUpdateClient() public {
- vm.expectRevert();
- mockIcs07Tendermint.updateClient(bytes("invalid"), mockFixture.publicValues);
+ assert(res == UpdateResult.NoOp);
}
// Confirm that submitting a random proof with the real verifier fails.
function test_Invalid_UpdateClient() public {
vm.expectRevert();
- ics07Tendermint.updateClient(bytes("invalid"), fixture.publicValues);
+ ics07Tendermint.updateClient(bytes("invalid"));
}
}
diff --git a/contracts/test/VerifyMembership.t.sol b/contracts/test/VerifyMembership.t.sol
deleted file mode 100644
index 8462efb..000000000
--- a/contracts/test/VerifyMembership.t.sol
+++ /dev/null
@@ -1,117 +0,0 @@
-// SPDX-License-Identifier: UNLICENSED
-pragma solidity >=0.8.25;
-
-// solhint-disable-next-line no-global-import
-import "forge-std/console.sol";
-import { MembershipTest } from "./MembershipTest.sol";
-
-// set constant string
-string constant verifyMembershipPath = "clients/07-tendermint-0/clientState";
-
-contract SP1ICS07VerifyMembershipTest is MembershipTest {
- function setUp() public {
- setUpTestWithFixtures("verify_membership_fixture.json", "mock_verify_membership_fixture.json");
- }
-
- function test_ValidateFixtures() public view {
- assertEq(kvPairs().length, 1);
- assertEq(kvPairs()[0].key, verifyMembershipPath);
- assert(kvPairs()[0].value.length != 0);
-
- assertEq(mockKvPairs().length, 1);
- assertEq(mockKvPairs()[0].key, verifyMembershipPath);
- assert(mockKvPairs()[0].value.length != 0);
- }
-
- // Confirm that submitting a real proof passes the verifier.
- function test_ValidVerifyMembership() public view {
- bytes32[] memory kvPairHashes = new bytes32[](1);
- bytes32 kvPairHash = keccak256(abi.encode(kvPairs()[0]));
- kvPairHashes[0] = kvPairHash;
-
- ics07Tendermint.batchVerifyMembership(
- fixture.proof, fixture.publicValues, fixture.proofHeight, fixture.trustedConsensusState, kvPairHashes
- );
-
- // to console
- console.log("VerifyMembership gas used: ", vm.lastCallGas().gasTotalUsed);
- }
-
- // Confirm that submitting an empty proof passes the mock verifier.
- function test_ValidMockVerifyMembership() public view {
- bytes32[] memory kvPairHashes = new bytes32[](1);
- bytes32 kvPairHash = keccak256(abi.encode(mockKvPairs()[0]));
- kvPairHashes[0] = kvPairHash;
-
- mockIcs07Tendermint.batchVerifyMembership(
- bytes(""),
- mockFixture.publicValues,
- mockFixture.proofHeight,
- mockFixture.trustedConsensusState,
- kvPairHashes
- );
- }
-
- // Confirm that submitting a non-empty proof with the mock verifier fails.
- function test_Invalid_MockVerifyMembership() public {
- bytes32[] memory kvPairHashes = new bytes32[](1);
- bytes32 kvPairHash = keccak256(abi.encode(mockKvPairs()[0]));
- kvPairHashes[0] = kvPairHash;
-
- // Invalid proof
- vm.expectRevert();
- mockIcs07Tendermint.batchVerifyMembership(
- bytes("invalid"),
- mockFixture.publicValues,
- mockFixture.proofHeight,
- mockFixture.trustedConsensusState,
- kvPairHashes
- );
-
- // Invalid proof height
- vm.expectRevert();
- mockIcs07Tendermint.batchVerifyMembership(
- bytes(""), mockFixture.publicValues, 1, mockFixture.trustedConsensusState, kvPairHashes
- );
-
- // Invalid trusted consensus state
- vm.expectRevert();
- mockIcs07Tendermint.batchVerifyMembership(
- bytes(""), mockFixture.publicValues, mockFixture.proofHeight, bytes("invalid"), kvPairHashes
- );
-
- // empty kvPairHashes
- vm.expectRevert();
- mockIcs07Tendermint.batchVerifyMembership(
- bytes(""),
- mockFixture.publicValues,
- mockFixture.proofHeight,
- mockFixture.trustedConsensusState,
- new bytes32[](0)
- );
-
- // Invalid kvPairHashes
- bytes32[] memory invalidHashes = new bytes32[](1);
- invalidHashes[0] = keccak256("invalid");
- vm.expectRevert();
- mockIcs07Tendermint.batchVerifyMembership(
- bytes(""),
- mockFixture.publicValues,
- mockFixture.proofHeight,
- mockFixture.trustedConsensusState,
- invalidHashes
- );
- }
-
- // Confirm that submitting a random proof with the real verifier fails.
- function test_Invalid_VerifyMembership() public {
- bytes32[] memory kvPairHashes = new bytes32[](1);
- bytes32 kvPairHash = keccak256(abi.encode(mockKvPairs()[0]));
- kvPairHashes[0] = kvPairHash;
-
- vm.expectRevert();
- ics07Tendermint.batchVerifyMembership(
- bytes("invalid"), fixture.publicValues, fixture.proofHeight, fixture.trustedConsensusState, kvPairHashes
- );
- }
-}
diff --git a/e2e/interchaintestv8/chainconfig/chain_config.go b/e2e/interchaintestv8/chainconfig/chain_config.go
index f0b1f12..6fd0b19 100644
--- a/e2e/interchaintestv8/chainconfig/chain_config.go
+++ b/e2e/interchaintestv8/chainconfig/chain_config.go
@@ -18,7 +18,7 @@ var DefaultChainSpecs = []*interchaintest.ChainSpec{
Images: []ibc.DockerImage{
{
Repository: "ghcr.io/cosmos/ibc-go-simd", // FOR LOCAL IMAGE USE: Docker Image Name
- Version: "v8.3.0", // FOR LOCAL IMAGE USE: Docker Image Tag
+ Version: "v8.4.0", // FOR LOCAL IMAGE USE: Docker Image Tag
UidGid: "1025:1025",
},
},
diff --git a/e2e/interchaintestv8/go.mod b/e2e/interchaintestv8/go.mod
index e72ea40..48416a2 100644
--- a/e2e/interchaintestv8/go.mod
+++ b/e2e/interchaintestv8/go.mod
@@ -10,9 +10,9 @@ require (
cosmossdk.io/x/tx v0.13.3
cosmossdk.io/x/upgrade v0.1.2
github.com/CosmWasm/wasmd v0.50.0
- github.com/cosmos/cosmos-sdk v0.50.6
+ github.com/cosmos/cosmos-sdk v0.50.7
github.com/cosmos/gogoproto v1.4.12
- github.com/cosmos/ibc-go/v8 v8.3.0
+ github.com/cosmos/ibc-go/v8 v8.4.0
github.com/docker/docker v24.0.9+incompatible
github.com/ethereum/go-ethereum v1.14.6
github.com/strangelove-ventures/interchaintest/v8 v8.3.0
diff --git a/e2e/interchaintestv8/go.sum b/e2e/interchaintestv8/go.sum
index c70b8a6..7874d6c 100644
--- a/e2e/interchaintestv8/go.sum
+++ b/e2e/interchaintestv8/go.sum
@@ -385,8 +385,8 @@ github.com/cosmos/cosmos-db v1.0.2 h1:hwMjozuY1OlJs/uh6vddqnk9j7VamLv+0DBlbEXbAK
github.com/cosmos/cosmos-db v1.0.2/go.mod h1:Z8IXcFJ9PqKK6BIsVOB3QXtkKoqUOp1vRvPT39kOXEA=
github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA=
github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec=
-github.com/cosmos/cosmos-sdk v0.50.6 h1:efR3MsvMHX5sxS3be+hOobGk87IzlZbSpsI2x/Vw3hk=
-github.com/cosmos/cosmos-sdk v0.50.6/go.mod h1:lVkRY6cdMJ0fG3gp8y4hFrsKZqF4z7y0M2UXFb9Yt40=
+github.com/cosmos/cosmos-sdk v0.50.7 h1:LsBGKxifENR/DN4E1RZaitsyL93HU44x0p8EnMHp4V4=
+github.com/cosmos/cosmos-sdk v0.50.7/go.mod h1:84xDDJEHttRT7NDGwBaUOLVOMN0JNE9x7NbsYIxXs1s=
github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y=
github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY=
github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw=
@@ -399,8 +399,8 @@ github.com/cosmos/iavl v1.1.2 h1:zL9FK7C4L/P4IF1Dm5fIwz0WXCnn7Bp1M2FxH0ayM7Y=
github.com/cosmos/iavl v1.1.2/go.mod h1:jLeUvm6bGT1YutCaL2fIar/8vGUE8cPZvh/gXEWDaDM=
github.com/cosmos/ibc-go/modules/capability v1.0.0 h1:r/l++byFtn7jHYa09zlAdSeevo8ci1mVZNO9+V0xsLE=
github.com/cosmos/ibc-go/modules/capability v1.0.0/go.mod h1:D81ZxzjZAe0ZO5ambnvn1qedsFQ8lOwtqicG6liLBco=
-github.com/cosmos/ibc-go/v8 v8.3.0 h1:fdW2S7NjZYFhSwmCaFjjyDv80kI1ePOJDQmco4qrnD0=
-github.com/cosmos/ibc-go/v8 v8.3.0/go.mod h1:izwHZvn9lKrBn8xWj0aXWut6HKcwHMPD3uyuvOJoPSA=
+github.com/cosmos/ibc-go/v8 v8.4.0 h1:K2PfX0AZ+1XKZytHGEMuSjQXG/MZshPb83RSTQt2+cE=
+github.com/cosmos/ibc-go/v8 v8.4.0/go.mod h1:zh6x1osR0hNvEcFrC/lhGD08sMfQmr9wHVvZ/mRWMCs=
github.com/cosmos/ics23/go v0.10.0 h1:iXqLLgp2Lp+EdpIuwXTYIQU+AiHj9mOC2X9ab++bZDM=
github.com/cosmos/ics23/go v0.10.0/go.mod h1:ZfJSmng/TBNTBkFemHHHj5YY7VAU/MBU980F4VU1NG0=
github.com/cosmos/interchain-security/v5 v5.0.0-alpha1.0.20240424193412-7cd900ad2a74 h1:6atU/xizTL10q6EprP7oRuvfgUP2F6puvutnVoE+FRc=
diff --git a/e2e/interchaintestv8/types/sp1ics07tendermint/contract.go b/e2e/interchaintestv8/types/sp1ics07tendermint/contract.go
index 99e571d..f89839d 100644
--- a/e2e/interchaintestv8/types/sp1ics07tendermint/contract.go
+++ b/e2e/interchaintestv8/types/sp1ics07tendermint/contract.go
@@ -29,73 +29,110 @@ var (
_ = abi.ConvertType
)
-// ICS07TendermintClientState is an auto generated low-level Go binding around an user-defined struct.
-type ICS07TendermintClientState struct {
+// IICS02ClientMsgsHeight is an auto generated low-level Go binding around an user-defined struct.
+type IICS02ClientMsgsHeight struct {
+ RevisionNumber uint32
+ RevisionHeight uint32
+}
+
+// IICS07TendermintMsgsClientState is an auto generated low-level Go binding around an user-defined struct.
+type IICS07TendermintMsgsClientState struct {
ChainId string
- TrustLevel ICS07TendermintTrustThreshold
- LatestHeight ICS07TendermintHeight
+ TrustLevel IICS07TendermintMsgsTrustThreshold
+ LatestHeight IICS02ClientMsgsHeight
TrustingPeriod uint32
UnbondingPeriod uint32
IsFrozen bool
}
-// ICS07TendermintConsensusState is an auto generated low-level Go binding around an user-defined struct.
-type ICS07TendermintConsensusState struct {
+// IICS07TendermintMsgsConsensusState is an auto generated low-level Go binding around an user-defined struct.
+type IICS07TendermintMsgsConsensusState struct {
Timestamp uint64
Root [32]byte
NextValidatorsHash [32]byte
}
-// ICS07TendermintHeight is an auto generated low-level Go binding around an user-defined struct.
-type ICS07TendermintHeight struct {
- RevisionNumber uint32
- RevisionHeight uint32
-}
-
-// ICS07TendermintTrustThreshold is an auto generated low-level Go binding around an user-defined struct.
-type ICS07TendermintTrustThreshold struct {
+// IICS07TendermintMsgsTrustThreshold is an auto generated low-level Go binding around an user-defined struct.
+type IICS07TendermintMsgsTrustThreshold struct {
Numerator uint8
Denominator uint8
}
-// MembershipProgramKVPair is an auto generated low-level Go binding around an user-defined struct.
-type MembershipProgramKVPair struct {
- Key string
+// ILightClientMsgsMsgMembership is an auto generated low-level Go binding around an user-defined struct.
+type ILightClientMsgsMsgMembership struct {
+ Proof []byte
+ ProofHeight IICS02ClientMsgsHeight
+ Path []byte
+ Value []byte
+}
+
+// IMembershipMsgsKVPair is an auto generated low-level Go binding around an user-defined struct.
+type IMembershipMsgsKVPair struct {
+ Path []byte
Value []byte
}
-// MembershipProgramMembershipOutput is an auto generated low-level Go binding around an user-defined struct.
-type MembershipProgramMembershipOutput struct {
+// IMembershipMsgsMembershipOutput is an auto generated low-level Go binding around an user-defined struct.
+type IMembershipMsgsMembershipOutput struct {
CommitmentRoot [32]byte
- KvPairs []MembershipProgramKVPair
+ KvPairs []IMembershipMsgsKVPair
}
-// UpdateClientAndMembershipProgramUcAndMembershipOutput is an auto generated low-level Go binding around an user-defined struct.
-type UpdateClientAndMembershipProgramUcAndMembershipOutput struct {
- UpdateClientOutput UpdateClientProgramUpdateClientOutput
- KvPairs []MembershipProgramKVPair
+// IMembershipMsgsMembershipProof is an auto generated low-level Go binding around an user-defined struct.
+type IMembershipMsgsMembershipProof struct {
+ ProofType uint8
+ Proof []byte
}
-// UpdateClientProgramEnv is an auto generated low-level Go binding around an user-defined struct.
-type UpdateClientProgramEnv struct {
+// IMembershipMsgsSP1MembershipAndUpdateClientProof is an auto generated low-level Go binding around an user-defined struct.
+type IMembershipMsgsSP1MembershipAndUpdateClientProof struct {
+ Sp1Proof ISP1MsgsSP1Proof
+}
+
+// IMembershipMsgsSP1MembershipProof is an auto generated low-level Go binding around an user-defined struct.
+type IMembershipMsgsSP1MembershipProof struct {
+ Sp1Proof ISP1MsgsSP1Proof
+ TrustedConsensusState IICS07TendermintMsgsConsensusState
+}
+
+// ISP1MsgsSP1Proof is an auto generated low-level Go binding around an user-defined struct.
+type ISP1MsgsSP1Proof struct {
+ VKey [32]byte
+ PublicValues []byte
+ Proof []byte
+}
+
+// IUpdateClientAndMembershipMsgsUcAndMembershipOutput is an auto generated low-level Go binding around an user-defined struct.
+type IUpdateClientAndMembershipMsgsUcAndMembershipOutput struct {
+ UpdateClientOutput IUpdateClientMsgsUpdateClientOutput
+ KvPairs []IMembershipMsgsKVPair
+}
+
+// IUpdateClientMsgsEnv is an auto generated low-level Go binding around an user-defined struct.
+type IUpdateClientMsgsEnv struct {
ChainId string
- TrustThreshold ICS07TendermintTrustThreshold
+ TrustThreshold IICS07TendermintMsgsTrustThreshold
TrustingPeriod uint32
Now uint64
}
-// UpdateClientProgramUpdateClientOutput is an auto generated low-level Go binding around an user-defined struct.
-type UpdateClientProgramUpdateClientOutput struct {
- TrustedConsensusState ICS07TendermintConsensusState
- NewConsensusState ICS07TendermintConsensusState
- Env UpdateClientProgramEnv
- TrustedHeight ICS07TendermintHeight
- NewHeight ICS07TendermintHeight
+// IUpdateClientMsgsMsgUpdateClient is an auto generated low-level Go binding around an user-defined struct.
+type IUpdateClientMsgsMsgUpdateClient struct {
+ Sp1Proof ISP1MsgsSP1Proof
+}
+
+// IUpdateClientMsgsUpdateClientOutput is an auto generated low-level Go binding around an user-defined struct.
+type IUpdateClientMsgsUpdateClientOutput struct {
+ TrustedConsensusState IICS07TendermintMsgsConsensusState
+ NewConsensusState IICS07TendermintMsgsConsensusState
+ Env IUpdateClientMsgsEnv
+ TrustedHeight IICS02ClientMsgsHeight
+ NewHeight IICS02ClientMsgsHeight
}
// ContractMetaData contains all meta data concerning the Contract contract.
var ContractMetaData = &bind.MetaData{
- ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"updateClientProgramVkey\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"membershipProgramVkey\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"updateClientAndMembershipProgramVkey\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"verifier\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_clientState\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"_consensusState\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"ALLOWED_SP1_CLOCK_DRIFT\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint16\",\"internalType\":\"uint16\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"abiPublicTypes\",\"inputs\":[{\"name\":\"output\",\"type\":\"tuple\",\"internalType\":\"structMembershipProgram.MembershipOutput\",\"components\":[{\"name\":\"commitmentRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"kvPairs\",\"type\":\"tuple[]\",\"internalType\":\"structMembershipProgram.KVPair[]\",\"components\":[{\"name\":\"key\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"output2\",\"type\":\"tuple\",\"internalType\":\"structUpdateClientAndMembershipProgram.UcAndMembershipOutput\",\"components\":[{\"name\":\"updateClientOutput\",\"type\":\"tuple\",\"internalType\":\"structUpdateClientProgram.UpdateClientOutput\",\"components\":[{\"name\":\"trustedConsensusState\",\"type\":\"tuple\",\"internalType\":\"structICS07Tendermint.ConsensusState\",\"components\":[{\"name\":\"timestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"root\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"nextValidatorsHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"newConsensusState\",\"type\":\"tuple\",\"internalType\":\"structICS07Tendermint.ConsensusState\",\"components\":[{\"name\":\"timestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"root\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"nextValidatorsHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"env\",\"type\":\"tuple\",\"internalType\":\"structUpdateClientProgram.Env\",\"components\":[{\"name\":\"chainId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"trustThreshold\",\"type\":\"tuple\",\"internalType\":\"structICS07Tendermint.TrustThreshold\",\"components\":[{\"name\":\"numerator\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"denominator\",\"type\":\"uint8\",\"internalType\":\"uint8\"}]},{\"name\":\"trustingPeriod\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"now\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"trustedHeight\",\"type\":\"tuple\",\"internalType\":\"structICS07Tendermint.Height\",\"components\":[{\"name\":\"revisionNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"revisionHeight\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]},{\"name\":\"newHeight\",\"type\":\"tuple\",\"internalType\":\"structICS07Tendermint.Height\",\"components\":[{\"name\":\"revisionNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"revisionHeight\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]}]},{\"name\":\"kvPairs\",\"type\":\"tuple[]\",\"internalType\":\"structMembershipProgram.KVPair[]\",\"components\":[{\"name\":\"key\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]}],\"outputs\":[],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"batchVerifyMembership\",\"inputs\":[{\"name\":\"proof\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"publicValues\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"proofHeight\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"trustedConsensusStateBz\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"kvPairHashes\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}],\"outputs\":[],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getClientState\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structICS07Tendermint.ClientState\",\"components\":[{\"name\":\"chainId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"trustLevel\",\"type\":\"tuple\",\"internalType\":\"structICS07Tendermint.TrustThreshold\",\"components\":[{\"name\":\"numerator\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"denominator\",\"type\":\"uint8\",\"internalType\":\"uint8\"}]},{\"name\":\"latestHeight\",\"type\":\"tuple\",\"internalType\":\"structICS07Tendermint.Height\",\"components\":[{\"name\":\"revisionNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"revisionHeight\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]},{\"name\":\"trustingPeriod\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"unbondingPeriod\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"isFrozen\",\"type\":\"bool\",\"internalType\":\"bool\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getConsensusStateHash\",\"inputs\":[{\"name\":\"revisionHeight\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getVerifierInfo\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"updateClient\",\"inputs\":[{\"name\":\"proof\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"publicValues\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"enumUpdateClientProgram.UpdateResult\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"updateClientAndBatchVerifyMembership\",\"inputs\":[{\"name\":\"proof\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"publicValues\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"kvPairHashes\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"enumUpdateClientProgram.UpdateResult\"}],\"stateMutability\":\"nonpayable\"}]",
+ ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"updateClientProgramVkey\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"membershipProgramVkey\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"updateClientAndMembershipProgramVkey\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"verifier\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_clientState\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"_consensusState\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"ALLOWED_SP1_CLOCK_DRIFT\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint16\",\"internalType\":\"uint16\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"MEMBERSHIP_PROGRAM_VKEY\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"UPDATE_CLIENT_AND_MEMBERSHIP_PROGRAM_VKEY\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"UPDATE_CLIENT_PROGRAM_VKEY\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"VERIFIER\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractISP1Verifier\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"abiPublicTypes\",\"inputs\":[{\"name\":\"o1\",\"type\":\"tuple\",\"internalType\":\"structIMembershipMsgs.MembershipOutput\",\"components\":[{\"name\":\"commitmentRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"kvPairs\",\"type\":\"tuple[]\",\"internalType\":\"structIMembershipMsgs.KVPair[]\",\"components\":[{\"name\":\"path\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"o2\",\"type\":\"tuple\",\"internalType\":\"structIUpdateClientAndMembershipMsgs.UcAndMembershipOutput\",\"components\":[{\"name\":\"updateClientOutput\",\"type\":\"tuple\",\"internalType\":\"structIUpdateClientMsgs.UpdateClientOutput\",\"components\":[{\"name\":\"trustedConsensusState\",\"type\":\"tuple\",\"internalType\":\"structIICS07TendermintMsgs.ConsensusState\",\"components\":[{\"name\":\"timestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"root\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"nextValidatorsHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"newConsensusState\",\"type\":\"tuple\",\"internalType\":\"structIICS07TendermintMsgs.ConsensusState\",\"components\":[{\"name\":\"timestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"root\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"nextValidatorsHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"env\",\"type\":\"tuple\",\"internalType\":\"structIUpdateClientMsgs.Env\",\"components\":[{\"name\":\"chainId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"trustThreshold\",\"type\":\"tuple\",\"internalType\":\"structIICS07TendermintMsgs.TrustThreshold\",\"components\":[{\"name\":\"numerator\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"denominator\",\"type\":\"uint8\",\"internalType\":\"uint8\"}]},{\"name\":\"trustingPeriod\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"now\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"trustedHeight\",\"type\":\"tuple\",\"internalType\":\"structIICS02ClientMsgs.Height\",\"components\":[{\"name\":\"revisionNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"revisionHeight\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]},{\"name\":\"newHeight\",\"type\":\"tuple\",\"internalType\":\"structIICS02ClientMsgs.Height\",\"components\":[{\"name\":\"revisionNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"revisionHeight\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]}]},{\"name\":\"kvPairs\",\"type\":\"tuple[]\",\"internalType\":\"structIMembershipMsgs.KVPair[]\",\"components\":[{\"name\":\"path\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"o3\",\"type\":\"tuple\",\"internalType\":\"structIUpdateClientMsgs.MsgUpdateClient\",\"components\":[{\"name\":\"sp1Proof\",\"type\":\"tuple\",\"internalType\":\"structISP1Msgs.SP1Proof\",\"components\":[{\"name\":\"vKey\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"publicValues\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"proof\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"o4\",\"type\":\"tuple\",\"internalType\":\"structIMembershipMsgs.MembershipProof\",\"components\":[{\"name\":\"proofType\",\"type\":\"uint8\",\"internalType\":\"enumIMembershipMsgs.MembershipProofType\"},{\"name\":\"proof\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"o5\",\"type\":\"tuple\",\"internalType\":\"structIMembershipMsgs.SP1MembershipProof\",\"components\":[{\"name\":\"sp1Proof\",\"type\":\"tuple\",\"internalType\":\"structISP1Msgs.SP1Proof\",\"components\":[{\"name\":\"vKey\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"publicValues\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"proof\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"trustedConsensusState\",\"type\":\"tuple\",\"internalType\":\"structIICS07TendermintMsgs.ConsensusState\",\"components\":[{\"name\":\"timestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"root\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"nextValidatorsHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]}]},{\"name\":\"o6\",\"type\":\"tuple\",\"internalType\":\"structIMembershipMsgs.SP1MembershipAndUpdateClientProof\",\"components\":[{\"name\":\"sp1Proof\",\"type\":\"tuple\",\"internalType\":\"structISP1Msgs.SP1Proof\",\"components\":[{\"name\":\"vKey\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"publicValues\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"proof\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]}],\"outputs\":[],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"getClientState\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structIICS07TendermintMsgs.ClientState\",\"components\":[{\"name\":\"chainId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"trustLevel\",\"type\":\"tuple\",\"internalType\":\"structIICS07TendermintMsgs.TrustThreshold\",\"components\":[{\"name\":\"numerator\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"denominator\",\"type\":\"uint8\",\"internalType\":\"uint8\"}]},{\"name\":\"latestHeight\",\"type\":\"tuple\",\"internalType\":\"structIICS02ClientMsgs.Height\",\"components\":[{\"name\":\"revisionNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"revisionHeight\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]},{\"name\":\"trustingPeriod\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"unbondingPeriod\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"isFrozen\",\"type\":\"bool\",\"internalType\":\"bool\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getConsensusStateHash\",\"inputs\":[{\"name\":\"revisionHeight\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"membership\",\"inputs\":[{\"name\":\"msgMembership\",\"type\":\"tuple\",\"internalType\":\"structILightClientMsgs.MsgMembership\",\"components\":[{\"name\":\"proof\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"proofHeight\",\"type\":\"tuple\",\"internalType\":\"structIICS02ClientMsgs.Height\",\"components\":[{\"name\":\"revisionNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"revisionHeight\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]},{\"name\":\"path\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"outputs\":[{\"name\":\"timestamp\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"updateClient\",\"inputs\":[{\"name\":\"updateMsg\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"enumILightClientMsgs.UpdateResult\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"error\",\"name\":\"CannotHandleMisbehavior\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ChainIdMismatch\",\"inputs\":[{\"name\":\"expected\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"actual\",\"type\":\"string\",\"internalType\":\"string\"}]},{\"type\":\"error\",\"name\":\"ConsensusStateHashMismatch\",\"inputs\":[{\"name\":\"expected\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"actual\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"ConsensusStateNotFound\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ConsensusStateRootMismatch\",\"inputs\":[{\"name\":\"expected\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"actual\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"FrozenClientState\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"LengthIsOutOfRange\",\"inputs\":[{\"name\":\"length\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"min\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"max\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"MembershipProofKeyNotFound\",\"inputs\":[{\"name\":\"path\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"MembershipProofValueMismatch\",\"inputs\":[{\"name\":\"expected\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"actual\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"ProofIsInTheFuture\",\"inputs\":[{\"name\":\"now\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"proofTimestamp\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"ProofIsTooOld\",\"inputs\":[{\"name\":\"now\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"proofTimestamp\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"TrustThresholdMismatch\",\"inputs\":[{\"name\":\"expectedNumerator\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"expectedDenominator\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"actualNumerator\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"actualDenominator\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"TrustingPeriodMismatch\",\"inputs\":[{\"name\":\"expected\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"actual\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"TrustingPeriodTooLong\",\"inputs\":[{\"name\":\"trustingPeriod\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"unbondingPeriod\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"VerificationKeyMismatch\",\"inputs\":[{\"name\":\"expected\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"actual\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]}]",
}
// ContractABI is the input ABI used to generate the binding from.
@@ -275,41 +312,136 @@ func (_Contract *ContractCallerSession) ALLOWEDSP1CLOCKDRIFT() (uint16, error) {
return _Contract.Contract.ALLOWEDSP1CLOCKDRIFT(&_Contract.CallOpts)
}
-// AbiPublicTypes is a free data retrieval call binding the contract method 0x31debad4.
+// MEMBERSHIPPROGRAMVKEY is a free data retrieval call binding the contract method 0xe45a6d0d.
//
-// Solidity: function abiPublicTypes((bytes32,(string,bytes)[]) output, (((uint64,bytes32,bytes32),(uint64,bytes32,bytes32),(string,(uint8,uint8),uint32,uint64),(uint32,uint32),(uint32,uint32)),(string,bytes)[]) output2) pure returns()
-func (_Contract *ContractCaller) AbiPublicTypes(opts *bind.CallOpts, output MembershipProgramMembershipOutput, output2 UpdateClientAndMembershipProgramUcAndMembershipOutput) error {
+// Solidity: function MEMBERSHIP_PROGRAM_VKEY() view returns(bytes32)
+func (_Contract *ContractCaller) MEMBERSHIPPROGRAMVKEY(opts *bind.CallOpts) ([32]byte, error) {
var out []interface{}
- err := _Contract.contract.Call(opts, &out, "abiPublicTypes", output, output2)
+ err := _Contract.contract.Call(opts, &out, "MEMBERSHIP_PROGRAM_VKEY")
if err != nil {
- return err
+ return *new([32]byte), err
}
- return err
+ out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte)
+
+ return out0, err
}
-// AbiPublicTypes is a free data retrieval call binding the contract method 0x31debad4.
+// MEMBERSHIPPROGRAMVKEY is a free data retrieval call binding the contract method 0xe45a6d0d.
//
-// Solidity: function abiPublicTypes((bytes32,(string,bytes)[]) output, (((uint64,bytes32,bytes32),(uint64,bytes32,bytes32),(string,(uint8,uint8),uint32,uint64),(uint32,uint32),(uint32,uint32)),(string,bytes)[]) output2) pure returns()
-func (_Contract *ContractSession) AbiPublicTypes(output MembershipProgramMembershipOutput, output2 UpdateClientAndMembershipProgramUcAndMembershipOutput) error {
- return _Contract.Contract.AbiPublicTypes(&_Contract.CallOpts, output, output2)
+// Solidity: function MEMBERSHIP_PROGRAM_VKEY() view returns(bytes32)
+func (_Contract *ContractSession) MEMBERSHIPPROGRAMVKEY() ([32]byte, error) {
+ return _Contract.Contract.MEMBERSHIPPROGRAMVKEY(&_Contract.CallOpts)
}
-// AbiPublicTypes is a free data retrieval call binding the contract method 0x31debad4.
+// MEMBERSHIPPROGRAMVKEY is a free data retrieval call binding the contract method 0xe45a6d0d.
//
-// Solidity: function abiPublicTypes((bytes32,(string,bytes)[]) output, (((uint64,bytes32,bytes32),(uint64,bytes32,bytes32),(string,(uint8,uint8),uint32,uint64),(uint32,uint32),(uint32,uint32)),(string,bytes)[]) output2) pure returns()
-func (_Contract *ContractCallerSession) AbiPublicTypes(output MembershipProgramMembershipOutput, output2 UpdateClientAndMembershipProgramUcAndMembershipOutput) error {
- return _Contract.Contract.AbiPublicTypes(&_Contract.CallOpts, output, output2)
+// Solidity: function MEMBERSHIP_PROGRAM_VKEY() view returns(bytes32)
+func (_Contract *ContractCallerSession) MEMBERSHIPPROGRAMVKEY() ([32]byte, error) {
+ return _Contract.Contract.MEMBERSHIPPROGRAMVKEY(&_Contract.CallOpts)
}
-// BatchVerifyMembership is a free data retrieval call binding the contract method 0xa3b16959.
+// UPDATECLIENTANDMEMBERSHIPPROGRAMVKEY is a free data retrieval call binding the contract method 0x0225293e.
//
-// Solidity: function batchVerifyMembership(bytes proof, bytes publicValues, uint32 proofHeight, bytes trustedConsensusStateBz, bytes32[] kvPairHashes) view returns()
-func (_Contract *ContractCaller) BatchVerifyMembership(opts *bind.CallOpts, proof []byte, publicValues []byte, proofHeight uint32, trustedConsensusStateBz []byte, kvPairHashes [][32]byte) error {
+// Solidity: function UPDATE_CLIENT_AND_MEMBERSHIP_PROGRAM_VKEY() view returns(bytes32)
+func (_Contract *ContractCaller) UPDATECLIENTANDMEMBERSHIPPROGRAMVKEY(opts *bind.CallOpts) ([32]byte, error) {
var out []interface{}
- err := _Contract.contract.Call(opts, &out, "batchVerifyMembership", proof, publicValues, proofHeight, trustedConsensusStateBz, kvPairHashes)
+ err := _Contract.contract.Call(opts, &out, "UPDATE_CLIENT_AND_MEMBERSHIP_PROGRAM_VKEY")
+
+ if err != nil {
+ return *new([32]byte), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte)
+
+ return out0, err
+
+}
+
+// UPDATECLIENTANDMEMBERSHIPPROGRAMVKEY is a free data retrieval call binding the contract method 0x0225293e.
+//
+// Solidity: function UPDATE_CLIENT_AND_MEMBERSHIP_PROGRAM_VKEY() view returns(bytes32)
+func (_Contract *ContractSession) UPDATECLIENTANDMEMBERSHIPPROGRAMVKEY() ([32]byte, error) {
+ return _Contract.Contract.UPDATECLIENTANDMEMBERSHIPPROGRAMVKEY(&_Contract.CallOpts)
+}
+
+// UPDATECLIENTANDMEMBERSHIPPROGRAMVKEY is a free data retrieval call binding the contract method 0x0225293e.
+//
+// Solidity: function UPDATE_CLIENT_AND_MEMBERSHIP_PROGRAM_VKEY() view returns(bytes32)
+func (_Contract *ContractCallerSession) UPDATECLIENTANDMEMBERSHIPPROGRAMVKEY() ([32]byte, error) {
+ return _Contract.Contract.UPDATECLIENTANDMEMBERSHIPPROGRAMVKEY(&_Contract.CallOpts)
+}
+
+// UPDATECLIENTPROGRAMVKEY is a free data retrieval call binding the contract method 0xca7242f9.
+//
+// Solidity: function UPDATE_CLIENT_PROGRAM_VKEY() view returns(bytes32)
+func (_Contract *ContractCaller) UPDATECLIENTPROGRAMVKEY(opts *bind.CallOpts) ([32]byte, error) {
+ var out []interface{}
+ err := _Contract.contract.Call(opts, &out, "UPDATE_CLIENT_PROGRAM_VKEY")
+
+ if err != nil {
+ return *new([32]byte), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte)
+
+ return out0, err
+
+}
+
+// UPDATECLIENTPROGRAMVKEY is a free data retrieval call binding the contract method 0xca7242f9.
+//
+// Solidity: function UPDATE_CLIENT_PROGRAM_VKEY() view returns(bytes32)
+func (_Contract *ContractSession) UPDATECLIENTPROGRAMVKEY() ([32]byte, error) {
+ return _Contract.Contract.UPDATECLIENTPROGRAMVKEY(&_Contract.CallOpts)
+}
+
+// UPDATECLIENTPROGRAMVKEY is a free data retrieval call binding the contract method 0xca7242f9.
+//
+// Solidity: function UPDATE_CLIENT_PROGRAM_VKEY() view returns(bytes32)
+func (_Contract *ContractCallerSession) UPDATECLIENTPROGRAMVKEY() ([32]byte, error) {
+ return _Contract.Contract.UPDATECLIENTPROGRAMVKEY(&_Contract.CallOpts)
+}
+
+// VERIFIER is a free data retrieval call binding the contract method 0x08c84e70.
+//
+// Solidity: function VERIFIER() view returns(address)
+func (_Contract *ContractCaller) VERIFIER(opts *bind.CallOpts) (common.Address, error) {
+ var out []interface{}
+ err := _Contract.contract.Call(opts, &out, "VERIFIER")
+
+ if err != nil {
+ return *new(common.Address), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address)
+
+ return out0, err
+
+}
+
+// VERIFIER is a free data retrieval call binding the contract method 0x08c84e70.
+//
+// Solidity: function VERIFIER() view returns(address)
+func (_Contract *ContractSession) VERIFIER() (common.Address, error) {
+ return _Contract.Contract.VERIFIER(&_Contract.CallOpts)
+}
+
+// VERIFIER is a free data retrieval call binding the contract method 0x08c84e70.
+//
+// Solidity: function VERIFIER() view returns(address)
+func (_Contract *ContractCallerSession) VERIFIER() (common.Address, error) {
+ return _Contract.Contract.VERIFIER(&_Contract.CallOpts)
+}
+
+// AbiPublicTypes is a free data retrieval call binding the contract method 0xc914d959.
+//
+// Solidity: function abiPublicTypes((bytes32,(bytes,bytes)[]) o1, (((uint64,bytes32,bytes32),(uint64,bytes32,bytes32),(string,(uint8,uint8),uint32,uint64),(uint32,uint32),(uint32,uint32)),(bytes,bytes)[]) o2, ((bytes32,bytes,bytes)) o3, (uint8,bytes) o4, ((bytes32,bytes,bytes),(uint64,bytes32,bytes32)) o5, ((bytes32,bytes,bytes)) o6) pure returns()
+func (_Contract *ContractCaller) AbiPublicTypes(opts *bind.CallOpts, o1 IMembershipMsgsMembershipOutput, o2 IUpdateClientAndMembershipMsgsUcAndMembershipOutput, o3 IUpdateClientMsgsMsgUpdateClient, o4 IMembershipMsgsMembershipProof, o5 IMembershipMsgsSP1MembershipProof, o6 IMembershipMsgsSP1MembershipAndUpdateClientProof) error {
+ var out []interface{}
+ err := _Contract.contract.Call(opts, &out, "abiPublicTypes", o1, o2, o3, o4, o5, o6)
if err != nil {
return err
@@ -319,32 +451,32 @@ func (_Contract *ContractCaller) BatchVerifyMembership(opts *bind.CallOpts, proo
}
-// BatchVerifyMembership is a free data retrieval call binding the contract method 0xa3b16959.
+// AbiPublicTypes is a free data retrieval call binding the contract method 0xc914d959.
//
-// Solidity: function batchVerifyMembership(bytes proof, bytes publicValues, uint32 proofHeight, bytes trustedConsensusStateBz, bytes32[] kvPairHashes) view returns()
-func (_Contract *ContractSession) BatchVerifyMembership(proof []byte, publicValues []byte, proofHeight uint32, trustedConsensusStateBz []byte, kvPairHashes [][32]byte) error {
- return _Contract.Contract.BatchVerifyMembership(&_Contract.CallOpts, proof, publicValues, proofHeight, trustedConsensusStateBz, kvPairHashes)
+// Solidity: function abiPublicTypes((bytes32,(bytes,bytes)[]) o1, (((uint64,bytes32,bytes32),(uint64,bytes32,bytes32),(string,(uint8,uint8),uint32,uint64),(uint32,uint32),(uint32,uint32)),(bytes,bytes)[]) o2, ((bytes32,bytes,bytes)) o3, (uint8,bytes) o4, ((bytes32,bytes,bytes),(uint64,bytes32,bytes32)) o5, ((bytes32,bytes,bytes)) o6) pure returns()
+func (_Contract *ContractSession) AbiPublicTypes(o1 IMembershipMsgsMembershipOutput, o2 IUpdateClientAndMembershipMsgsUcAndMembershipOutput, o3 IUpdateClientMsgsMsgUpdateClient, o4 IMembershipMsgsMembershipProof, o5 IMembershipMsgsSP1MembershipProof, o6 IMembershipMsgsSP1MembershipAndUpdateClientProof) error {
+ return _Contract.Contract.AbiPublicTypes(&_Contract.CallOpts, o1, o2, o3, o4, o5, o6)
}
-// BatchVerifyMembership is a free data retrieval call binding the contract method 0xa3b16959.
+// AbiPublicTypes is a free data retrieval call binding the contract method 0xc914d959.
//
-// Solidity: function batchVerifyMembership(bytes proof, bytes publicValues, uint32 proofHeight, bytes trustedConsensusStateBz, bytes32[] kvPairHashes) view returns()
-func (_Contract *ContractCallerSession) BatchVerifyMembership(proof []byte, publicValues []byte, proofHeight uint32, trustedConsensusStateBz []byte, kvPairHashes [][32]byte) error {
- return _Contract.Contract.BatchVerifyMembership(&_Contract.CallOpts, proof, publicValues, proofHeight, trustedConsensusStateBz, kvPairHashes)
+// Solidity: function abiPublicTypes((bytes32,(bytes,bytes)[]) o1, (((uint64,bytes32,bytes32),(uint64,bytes32,bytes32),(string,(uint8,uint8),uint32,uint64),(uint32,uint32),(uint32,uint32)),(bytes,bytes)[]) o2, ((bytes32,bytes,bytes)) o3, (uint8,bytes) o4, ((bytes32,bytes,bytes),(uint64,bytes32,bytes32)) o5, ((bytes32,bytes,bytes)) o6) pure returns()
+func (_Contract *ContractCallerSession) AbiPublicTypes(o1 IMembershipMsgsMembershipOutput, o2 IUpdateClientAndMembershipMsgsUcAndMembershipOutput, o3 IUpdateClientMsgsMsgUpdateClient, o4 IMembershipMsgsMembershipProof, o5 IMembershipMsgsSP1MembershipProof, o6 IMembershipMsgsSP1MembershipAndUpdateClientProof) error {
+ return _Contract.Contract.AbiPublicTypes(&_Contract.CallOpts, o1, o2, o3, o4, o5, o6)
}
// GetClientState is a free data retrieval call binding the contract method 0xef913a4b.
//
// Solidity: function getClientState() view returns((string,(uint8,uint8),(uint32,uint32),uint32,uint32,bool))
-func (_Contract *ContractCaller) GetClientState(opts *bind.CallOpts) (ICS07TendermintClientState, error) {
+func (_Contract *ContractCaller) GetClientState(opts *bind.CallOpts) (IICS07TendermintMsgsClientState, error) {
var out []interface{}
err := _Contract.contract.Call(opts, &out, "getClientState")
if err != nil {
- return *new(ICS07TendermintClientState), err
+ return *new(IICS07TendermintMsgsClientState), err
}
- out0 := *abi.ConvertType(out[0], new(ICS07TendermintClientState)).(*ICS07TendermintClientState)
+ out0 := *abi.ConvertType(out[0], new(IICS07TendermintMsgsClientState)).(*IICS07TendermintMsgsClientState)
return out0, err
@@ -353,14 +485,14 @@ func (_Contract *ContractCaller) GetClientState(opts *bind.CallOpts) (ICS07Tende
// GetClientState is a free data retrieval call binding the contract method 0xef913a4b.
//
// Solidity: function getClientState() view returns((string,(uint8,uint8),(uint32,uint32),uint32,uint32,bool))
-func (_Contract *ContractSession) GetClientState() (ICS07TendermintClientState, error) {
+func (_Contract *ContractSession) GetClientState() (IICS07TendermintMsgsClientState, error) {
return _Contract.Contract.GetClientState(&_Contract.CallOpts)
}
// GetClientState is a free data retrieval call binding the contract method 0xef913a4b.
//
// Solidity: function getClientState() view returns((string,(uint8,uint8),(uint32,uint32),uint32,uint32,bool))
-func (_Contract *ContractCallerSession) GetClientState() (ICS07TendermintClientState, error) {
+func (_Contract *ContractCallerSession) GetClientState() (IICS07TendermintMsgsClientState, error) {
return _Contract.Contract.GetClientState(&_Contract.CallOpts)
}
@@ -395,78 +527,44 @@ func (_Contract *ContractCallerSession) GetConsensusStateHash(revisionHeight uin
return _Contract.Contract.GetConsensusStateHash(&_Contract.CallOpts, revisionHeight)
}
-// GetVerifierInfo is a free data retrieval call binding the contract method 0xe215abff.
-//
-// Solidity: function getVerifierInfo() view returns(address, bytes32, bytes32, bytes32)
-func (_Contract *ContractCaller) GetVerifierInfo(opts *bind.CallOpts) (common.Address, [32]byte, [32]byte, [32]byte, error) {
- var out []interface{}
- err := _Contract.contract.Call(opts, &out, "getVerifierInfo")
-
- if err != nil {
- return *new(common.Address), *new([32]byte), *new([32]byte), *new([32]byte), err
- }
-
- out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address)
- out1 := *abi.ConvertType(out[1], new([32]byte)).(*[32]byte)
- out2 := *abi.ConvertType(out[2], new([32]byte)).(*[32]byte)
- out3 := *abi.ConvertType(out[3], new([32]byte)).(*[32]byte)
-
- return out0, out1, out2, out3, err
-
-}
-
-// GetVerifierInfo is a free data retrieval call binding the contract method 0xe215abff.
-//
-// Solidity: function getVerifierInfo() view returns(address, bytes32, bytes32, bytes32)
-func (_Contract *ContractSession) GetVerifierInfo() (common.Address, [32]byte, [32]byte, [32]byte, error) {
- return _Contract.Contract.GetVerifierInfo(&_Contract.CallOpts)
-}
-
-// GetVerifierInfo is a free data retrieval call binding the contract method 0xe215abff.
-//
-// Solidity: function getVerifierInfo() view returns(address, bytes32, bytes32, bytes32)
-func (_Contract *ContractCallerSession) GetVerifierInfo() (common.Address, [32]byte, [32]byte, [32]byte, error) {
- return _Contract.Contract.GetVerifierInfo(&_Contract.CallOpts)
-}
-
-// UpdateClient is a paid mutator transaction binding the contract method 0x195c0d3b.
+// Membership is a paid mutator transaction binding the contract method 0xea9179f5.
//
-// Solidity: function updateClient(bytes proof, bytes publicValues) returns(uint8)
-func (_Contract *ContractTransactor) UpdateClient(opts *bind.TransactOpts, proof []byte, publicValues []byte) (*types.Transaction, error) {
- return _Contract.contract.Transact(opts, "updateClient", proof, publicValues)
+// Solidity: function membership((bytes,(uint32,uint32),bytes,bytes) msgMembership) returns(uint256 timestamp)
+func (_Contract *ContractTransactor) Membership(opts *bind.TransactOpts, msgMembership ILightClientMsgsMsgMembership) (*types.Transaction, error) {
+ return _Contract.contract.Transact(opts, "membership", msgMembership)
}
-// UpdateClient is a paid mutator transaction binding the contract method 0x195c0d3b.
+// Membership is a paid mutator transaction binding the contract method 0xea9179f5.
//
-// Solidity: function updateClient(bytes proof, bytes publicValues) returns(uint8)
-func (_Contract *ContractSession) UpdateClient(proof []byte, publicValues []byte) (*types.Transaction, error) {
- return _Contract.Contract.UpdateClient(&_Contract.TransactOpts, proof, publicValues)
+// Solidity: function membership((bytes,(uint32,uint32),bytes,bytes) msgMembership) returns(uint256 timestamp)
+func (_Contract *ContractSession) Membership(msgMembership ILightClientMsgsMsgMembership) (*types.Transaction, error) {
+ return _Contract.Contract.Membership(&_Contract.TransactOpts, msgMembership)
}
-// UpdateClient is a paid mutator transaction binding the contract method 0x195c0d3b.
+// Membership is a paid mutator transaction binding the contract method 0xea9179f5.
//
-// Solidity: function updateClient(bytes proof, bytes publicValues) returns(uint8)
-func (_Contract *ContractTransactorSession) UpdateClient(proof []byte, publicValues []byte) (*types.Transaction, error) {
- return _Contract.Contract.UpdateClient(&_Contract.TransactOpts, proof, publicValues)
+// Solidity: function membership((bytes,(uint32,uint32),bytes,bytes) msgMembership) returns(uint256 timestamp)
+func (_Contract *ContractTransactorSession) Membership(msgMembership ILightClientMsgsMsgMembership) (*types.Transaction, error) {
+ return _Contract.Contract.Membership(&_Contract.TransactOpts, msgMembership)
}
-// UpdateClientAndBatchVerifyMembership is a paid mutator transaction binding the contract method 0xa51c335e.
+// UpdateClient is a paid mutator transaction binding the contract method 0x0bece356.
//
-// Solidity: function updateClientAndBatchVerifyMembership(bytes proof, bytes publicValues, bytes32[] kvPairHashes) returns(uint8)
-func (_Contract *ContractTransactor) UpdateClientAndBatchVerifyMembership(opts *bind.TransactOpts, proof []byte, publicValues []byte, kvPairHashes [][32]byte) (*types.Transaction, error) {
- return _Contract.contract.Transact(opts, "updateClientAndBatchVerifyMembership", proof, publicValues, kvPairHashes)
+// Solidity: function updateClient(bytes updateMsg) returns(uint8)
+func (_Contract *ContractTransactor) UpdateClient(opts *bind.TransactOpts, updateMsg []byte) (*types.Transaction, error) {
+ return _Contract.contract.Transact(opts, "updateClient", updateMsg)
}
-// UpdateClientAndBatchVerifyMembership is a paid mutator transaction binding the contract method 0xa51c335e.
+// UpdateClient is a paid mutator transaction binding the contract method 0x0bece356.
//
-// Solidity: function updateClientAndBatchVerifyMembership(bytes proof, bytes publicValues, bytes32[] kvPairHashes) returns(uint8)
-func (_Contract *ContractSession) UpdateClientAndBatchVerifyMembership(proof []byte, publicValues []byte, kvPairHashes [][32]byte) (*types.Transaction, error) {
- return _Contract.Contract.UpdateClientAndBatchVerifyMembership(&_Contract.TransactOpts, proof, publicValues, kvPairHashes)
+// Solidity: function updateClient(bytes updateMsg) returns(uint8)
+func (_Contract *ContractSession) UpdateClient(updateMsg []byte) (*types.Transaction, error) {
+ return _Contract.Contract.UpdateClient(&_Contract.TransactOpts, updateMsg)
}
-// UpdateClientAndBatchVerifyMembership is a paid mutator transaction binding the contract method 0xa51c335e.
+// UpdateClient is a paid mutator transaction binding the contract method 0x0bece356.
//
-// Solidity: function updateClientAndBatchVerifyMembership(bytes proof, bytes publicValues, bytes32[] kvPairHashes) returns(uint8)
-func (_Contract *ContractTransactorSession) UpdateClientAndBatchVerifyMembership(proof []byte, publicValues []byte, kvPairHashes [][32]byte) (*types.Transaction, error) {
- return _Contract.Contract.UpdateClientAndBatchVerifyMembership(&_Contract.TransactOpts, proof, publicValues, kvPairHashes)
+// Solidity: function updateClient(bytes updateMsg) returns(uint8)
+func (_Contract *ContractTransactorSession) UpdateClient(updateMsg []byte) (*types.Transaction, error) {
+ return _Contract.Contract.UpdateClient(&_Contract.TransactOpts, updateMsg)
}
diff --git a/elf/membership-riscv32im-succinct-zkvm-elf b/elf/membership-riscv32im-succinct-zkvm-elf
index 8ce9c6a..1b5e8df 100755
Binary files a/elf/membership-riscv32im-succinct-zkvm-elf and b/elf/membership-riscv32im-succinct-zkvm-elf differ
diff --git a/elf/uc-and-membership-riscv32im-succinct-zkvm-elf b/elf/uc-and-membership-riscv32im-succinct-zkvm-elf
index dfb3ec8..c2831b7 100755
Binary files a/elf/uc-and-membership-riscv32im-succinct-zkvm-elf and b/elf/uc-and-membership-riscv32im-succinct-zkvm-elf differ
diff --git a/elf/update-client-riscv32im-succinct-zkvm-elf b/elf/update-client-riscv32im-succinct-zkvm-elf
index 8fe358c..c43169a 100755
Binary files a/elf/update-client-riscv32im-succinct-zkvm-elf and b/elf/update-client-riscv32im-succinct-zkvm-elf differ
diff --git a/justfile b/justfile
index e6564c5..1c67c25 100644
--- a/justfile
+++ b/justfile
@@ -17,9 +17,16 @@ build-operator:
cargo build --bin operator --locked --release
@echo "Built the operator executable"
+# Build the contracts using `forge build` command after cleaning up the cache and output directories
+build-contracts:
+ @echo "Cleaning up the contracts cache and output directories..."
+ -rm -r contracts/cache contracts/out # `-` is used to ignore the error if the directories do not exist
+ @echo "Building the contracts..."
+ forge build
+
# Run the Solidity tests using `forge test` command
test-foundry:
- cd contracts && forge test -vvv
+ forge test -vvv
# Run the Rust tests using `cargo test` command (excluding the sp1-ics07-tendermint-update-client crate)
test-cargo:
@@ -33,7 +40,7 @@ genesis:
@echo "Generating the genesis file..."
RUST_LOG=info cargo run --bin operator --release -- genesis
-# Generate the `fixture.json` file for the Celestia Mocha testnet using the prover parameter.
+# Generate the fixture files for the Celestia Mocha testnet using the prover parameter.
# The prover parameter should be one of: ["mock", "network", "local"]
# This generates the fixtures for all programs in parallel using GNU parallel.
# If prover is set to network, this command requires the `SP1_PRIVATE_KEY` environment variable to be set.
@@ -45,10 +52,9 @@ fixtures prover:
just build-operator
@echo "Generating fixtures... This may take a while (up to 20 minutes)"
parallel --progress --shebang --ungroup -j 4 ::: \
- "RUST_LOG=info SP1_PROVER={{prover}} TENDERMINT_RPC_URL='https://rpc.celestia-mocha.com/' ./target/release/operator fixtures update-client --trusted-block 2330000 --target-block 2330010 -o 'contracts/fixtures/{{ if prover == "mock" { "mock_" } else { "" } }}update_client_fixture.json'" \
- "{{ if prover == "network" { "sleep 15 &&" } else { "" } }} RUST_LOG=info SP1_PROVER={{prover}} TENDERMINT_RPC_URL='https://rpc.celestia-mocha.com/' ./target/release/operator fixtures update-client-and-membership --key-paths clients/07-tendermint-0/clientState,clients/07-tendermint-001/clientState --trusted-block 2330000 --target-block 2330010 -o 'contracts/fixtures/{{ if prover == "mock" { "mock_" } else { "" } }}uc_and_memberships_fixture.json'" \
- "{{ if prover == "network" { "sleep 30 &&" } else { "" } }} RUST_LOG=info SP1_PROVER={{prover}} TENDERMINT_RPC_URL='https://rpc.celestia-mocha.com/' ./target/release/operator fixtures membership --key-paths 'clients/07-tendermint-0/clientState' --trusted-block 2330000 -o 'contracts/fixtures/{{ if prover == "mock" { "mock_" } else { "" } }}verify_membership_fixture.json'" \
- "{{ if prover == "network" { "sleep 45 &&" } else { "" } }} RUST_LOG=info SP1_PROVER={{prover}} TENDERMINT_RPC_URL='https://rpc.celestia-mocha.com/' ./target/release/operator fixtures membership --key-paths clients/07-tendermint-0/clientState,clients/07-tendermint-001/clientState --trusted-block 2330000 -o 'contracts/fixtures/{{ if prover == "mock" { "mock_" } else { "" } }}memberships_fixture.json'"
+ "RUST_LOG=info SP1_PROVER={{prover}} TENDERMINT_RPC_URL='https://rpc.celestia-mocha.com/' ./target/release/operator fixtures update-client --trusted-block 2330000 --target-block 2330010 -o 'contracts/fixtures/update_client_fixture.json'" \
+ "sleep 15 && RUST_LOG=info SP1_PROVER={{prover}} TENDERMINT_RPC_URL='https://rpc.celestia-mocha.com/' ./target/release/operator fixtures update-client-and-membership --key-paths clients/07-tendermint-0/clientState,clients/07-tendermint-001/clientState --trusted-block 2330000 --target-block 2330010 -o 'contracts/fixtures/uc_and_memberships_fixture.json'" \
+ "sleep 30 && RUST_LOG=info SP1_PROVER={{prover}} TENDERMINT_RPC_URL='https://rpc.celestia-mocha.com/' ./target/release/operator fixtures membership --key-paths clients/07-tendermint-0/clientState,clients/07-tendermint-001/clientState --trusted-block 2330000 -o 'contracts/fixtures/memberships_fixture.json'"
@echo "Fixtures generated at 'contracts/fixtures'"
# Generate the `SP1ICS07Tendermint.json` file containing the ABI of the SP1ICS07Tendermint contract
@@ -77,7 +83,9 @@ operator:
# Run the e2e tests
test-e2e testname:
- echo "Running {{testname}} test..."
+ @echo "Cleaning up the contracts cache and output directories..."
+ -rm -r contracts/cache contracts/out # `-` is used to ignore the error if the directories do not exist
+ @echo "Running {{testname}} test..."
cd e2e/interchaintestv8 && go test -v -run=TestWithSP1ICS07TendermintTestSuite/{{testname}} -timeout 40m
# Lint the Rust, Solidity, and Go code using `cargo fmt`, `forge fmt`, and `golanci-lint` commands
diff --git a/operator/Cargo.toml b/operator/Cargo.toml
index c289078..79516d0 100644
--- a/operator/Cargo.toml
+++ b/operator/Cargo.toml
@@ -32,6 +32,7 @@ tokio = { workspace = true }
futures = { workspace = true }
serde_json = { workspace = true }
serde = { workspace = true }
+serde_with = { workspace = true }
bincode = { workspace = true }
serde_cbor = { workspace = true }
sha2 = { workspace = true }
diff --git a/operator/src/runners/fixtures/membership.rs b/operator/src/runners/fixtures/membership.rs
index e664f9e..dc9c811 100644
--- a/operator/src/runners/fixtures/membership.rs
+++ b/operator/src/runners/fixtures/membership.rs
@@ -1,49 +1,38 @@
//! Runner for generating `membership` fixtures
use crate::{
- cli::command::fixtures::MembershipCmd,
- helpers::light_block::LightBlockExt,
- programs::{
- MembershipProgram, SP1Program, UpdateClientAndMembershipProgram, UpdateClientProgram,
- },
- prover::SP1ICS07TendermintProver,
- rpc::TendermintRpcExt,
+ cli::command::fixtures::MembershipCmd, programs::MembershipProgram,
+ prover::SP1ICS07TendermintProver, rpc::TendermintRpcExt,
+ runners::genesis::SP1ICS07TendermintGenesis,
};
use alloy_sol_types::SolValue;
+use ibc_client_tendermint::types::ConsensusState;
use ibc_core_commitment_types::merkle::MerkleProof;
use serde::{Deserialize, Serialize};
+use serde_with::serde_as;
use sp1_ics07_tendermint_solidity::sp1_ics07_tendermint::{
- ConsensusState as SolConsensusState, MembershipOutput,
+ ClientState, ConsensusState as SolConsensusState, MembershipOutput, MembershipProof,
+ SP1MembershipProof, SP1Proof,
};
use sp1_ics07_tendermint_utils::convert_tm_to_ics_merkle_proof;
use sp1_sdk::HashableKey;
use std::path::PathBuf;
use tendermint_rpc::{Client, HttpClient};
-/// The fixture data to be used in [`UpdateClientProgram`] tests.
+/// The fixture data to be used in [`MembershipProgram`] tests.
+#[serde_as]
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
-struct SP1ICS07MembershipFixture {
- /// The proof height.
- proof_height: u32,
- /// The encoded trusted client state.
- trusted_client_state: String,
- /// The encoded trusted consensus state.
- trusted_consensus_state: String,
- /// The encoded commitment root.
- commitment_root: String,
- /// The encoded key for the [`UpdateClientProgram`].
- update_client_vkey: String,
- /// The encoded key for the [`MembershipProgram`].
- membership_vkey: String,
- /// The encoded key for the [`UpdateClientAndMembershipProgram`].
- uc_and_membership_vkey: String,
+pub struct SP1ICS07MembershipFixture {
+ /// The genesis data.
+ #[serde(flatten)]
+ pub genesis: SP1ICS07TendermintGenesis,
+ /// The height of the proof.
+ #[serde_as(as = "serde_with::hex::Hex")]
+ pub proof_height: Vec,
/// The encoded public values.
- public_values: String,
- /// The encoded proof.
- proof: String,
- /// Hex-encoded `KVPair` value.
- kv_pairs: String,
+ #[serde_as(as = "serde_with::hex::Hex")]
+ pub membership_proof: Vec,
}
/// Writes the proof data for the given trusted and target blocks to the given fixture path.
@@ -58,27 +47,20 @@ pub async fn run(args: MembershipCmd) -> anyhow::Result<()> {
.get_light_block(Some(args.trusted_block))
.await?;
- let unbonding_period = tm_rpc_client
- .sdk_staking_params()
- .await?
- .unbonding_time
- .ok_or_else(|| anyhow::anyhow!("No unbonding time found"))?
- .seconds
- .try_into()?;
-
- // Defaults to the recommended TrustingPeriod: 2/3 of the UnbondingPeriod
- let trusting_period = args
- .trust_options
- .trusting_period
- .unwrap_or(2 * (unbonding_period / 3));
+ let genesis = SP1ICS07TendermintGenesis::from_env(
+ &trusted_light_block,
+ args.trust_options.trusting_period,
+ args.trust_options.trust_level,
+ )
+ .await?;
- let trusted_client_state = trusted_light_block.to_sol_client_state(
- args.trust_options.trust_level.try_into()?,
- unbonding_period,
- trusting_period,
- )?;
- let trusted_consensus_state = trusted_light_block.to_consensus_state();
- let commitment_root_bytes = trusted_consensus_state.root.as_bytes().to_vec();
+ let trusted_client_state = ClientState::abi_decode(&genesis.trusted_client_state, false)?;
+ let trusted_consensus_state =
+ SolConsensusState::abi_decode(&genesis.trusted_consensus_state, false)?;
+ let commitment_root_bytes = ConsensusState::from(trusted_consensus_state.clone())
+ .root
+ .as_bytes()
+ .to_vec();
let kv_proofs: Vec<(String, MerkleProof, Vec)> =
futures::future::try_join_all(args.key_paths.into_iter().map(|key_path| async {
@@ -112,19 +94,19 @@ pub async fn run(args: MembershipCmd) -> anyhow::Result<()> {
let output = MembershipOutput::abi_decode(bytes, true).unwrap();
assert_eq!(output.commitmentRoot.as_slice(), &commitment_root_bytes);
- let fixture = SP1ICS07MembershipFixture {
- trusted_client_state: hex::encode(trusted_client_state.abi_encode()),
- proof_height: args.trusted_block,
- trusted_consensus_state: hex::encode(
- SolConsensusState::from(trusted_consensus_state).abi_encode(),
+ let sp1_membership_proof = SP1MembershipProof {
+ sp1Proof: SP1Proof::new(
+ &verify_mem_prover.vkey.bytes32(),
+ proof_data.bytes(),
+ proof_data.public_values.to_vec(),
),
- commitment_root: hex::encode(&commitment_root_bytes),
- update_client_vkey: UpdateClientProgram::get_vkey().bytes32(),
- membership_vkey: verify_mem_prover.vkey.bytes32(),
- uc_and_membership_vkey: UpdateClientAndMembershipProgram::get_vkey().bytes32(),
- public_values: proof_data.public_values.raw(),
- proof: format!("0x{}", hex::encode(proof_data.bytes())),
- kv_pairs: hex::encode(output.kvPairs.abi_encode()),
+ trustedConsensusState: trusted_consensus_state,
+ };
+
+ let fixture = SP1ICS07MembershipFixture {
+ genesis,
+ proof_height: trusted_client_state.latestHeight.abi_encode(),
+ membership_proof: MembershipProof::from(sp1_membership_proof).abi_encode(),
};
// Save the proof data to the file path.
diff --git a/operator/src/runners/fixtures/uc_and_mem.rs b/operator/src/runners/fixtures/uc_and_mem.rs
index a67626b..48d6680 100644
--- a/operator/src/runners/fixtures/uc_and_mem.rs
+++ b/operator/src/runners/fixtures/uc_and_mem.rs
@@ -3,47 +3,25 @@
use crate::{
cli::command::fixtures::UpdateClientAndMembershipCmd,
helpers::light_block::LightBlockExt,
- programs::{
- MembershipProgram, SP1Program, UpdateClientAndMembershipProgram, UpdateClientProgram,
- },
+ programs::UpdateClientAndMembershipProgram,
prover::SP1ICS07TendermintProver,
rpc::TendermintRpcExt,
+ runners::{
+ fixtures::membership::SP1ICS07MembershipFixture, genesis::SP1ICS07TendermintGenesis,
+ },
};
use alloy_sol_types::SolValue;
+use ibc_client_tendermint::types::ConsensusState;
use ibc_core_commitment_types::merkle::MerkleProof;
-use serde::{Deserialize, Serialize};
-use sp1_ics07_tendermint_solidity::sp1_ics07_tendermint::{Env, UcAndMembershipOutput};
+use sp1_ics07_tendermint_solidity::sp1_ics07_tendermint::{
+ ClientState, ConsensusState as SolConsensusState, Env, MembershipProof,
+ SP1MembershipAndUpdateClientProof, SP1Proof, UcAndMembershipOutput,
+};
use sp1_ics07_tendermint_utils::convert_tm_to_ics_merkle_proof;
use sp1_sdk::HashableKey;
use std::path::PathBuf;
use tendermint_rpc::{Client, HttpClient};
-/// The fixture data to be used in [`UpdateClientProgram`] tests.
-#[derive(Debug, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-struct SP1ICS07UpdateClientAndMembershipFixture {
- /// The encoded trusted client state.
- trusted_client_state: String,
- /// The encoded trusted consensus state.
- trusted_consensus_state: String,
- /// The encoded target consensus state.
- target_consensus_state: String,
- /// Target height.
- target_height: u32,
- /// The encoded key for the [`UpdateClientProgram`].
- update_client_vkey: String,
- /// The encoded key for the [`MembershipProgram`].
- membership_vkey: String,
- /// The encoded key for the [`UpdateClientAndMembershipProgram`].
- uc_and_membership_vkey: String,
- /// The encoded public values.
- public_values: String,
- /// The encoded proof.
- proof: String,
- /// Hex-encoded `KVPair` value.
- kv_pairs: String,
-}
-
/// Writes the proof data for the given trusted and target blocks to the given fixture path.
#[allow(clippy::missing_errors_doc, clippy::missing_panics_doc)]
pub async fn run(args: UpdateClientAndMembershipCmd) -> anyhow::Result<()> {
@@ -62,26 +40,16 @@ pub async fn run(args: UpdateClientAndMembershipCmd) -> anyhow::Result<()> {
.get_light_block(Some(args.target_block))
.await?;
- let unbonding_period = tm_rpc_client
- .sdk_staking_params()
- .await?
- .unbonding_time
- .ok_or_else(|| anyhow::anyhow!("No unbonding time found"))?
- .seconds
- .try_into()?;
-
- // Defaults to the recommended TrustingPeriod: 2/3 of the UnbondingPeriod
- let trusting_period = args
- .trust_options
- .trusting_period
- .unwrap_or(2 * (unbonding_period / 3));
+ let genesis = SP1ICS07TendermintGenesis::from_env(
+ &trusted_light_block,
+ args.trust_options.trusting_period,
+ args.trust_options.trust_level,
+ )
+ .await?;
+ let trusted_client_state = ClientState::abi_decode(&genesis.trusted_client_state, false)?;
+ let trusted_consensus_state: ConsensusState =
+ SolConsensusState::abi_decode(&genesis.trusted_consensus_state, false)?.into();
- let trusted_client_state = trusted_light_block.to_sol_client_state(
- args.trust_options.trust_level.try_into()?,
- unbonding_period,
- trusting_period,
- )?;
- let trusted_consensus_state = trusted_light_block.to_consensus_state().into();
let proposed_header = target_light_block.into_header(&trusted_light_block);
let contract_env = Env {
chainId: trusted_light_block.chain_id()?.to_string(),
@@ -117,9 +85,10 @@ pub async fn run(args: UpdateClientAndMembershipCmd) -> anyhow::Result<()> {
}))
.await?;
+ let kv_len = kv_proofs.len();
// Generate a header update proof for the specified blocks.
let proof_data = uc_mem_prover.generate_proof(
- &trusted_consensus_state,
+ &trusted_consensus_state.into(),
&proposed_header,
&contract_env,
kv_proofs,
@@ -127,20 +96,20 @@ pub async fn run(args: UpdateClientAndMembershipCmd) -> anyhow::Result<()> {
let bytes = proof_data.public_values.as_slice();
let output = UcAndMembershipOutput::abi_decode(bytes, false)?;
+ assert_eq!(output.kvPairs.len(), kv_len);
- let fixture = SP1ICS07UpdateClientAndMembershipFixture {
- trusted_consensus_state: hex::encode(trusted_consensus_state.abi_encode()),
- trusted_client_state: hex::encode(trusted_client_state.abi_encode()),
- target_consensus_state: hex::encode(
- output.updateClientOutput.newConsensusState.abi_encode(),
+ let sp1_membership_proof = SP1MembershipAndUpdateClientProof {
+ sp1Proof: SP1Proof::new(
+ &uc_mem_prover.vkey.bytes32(),
+ proof_data.bytes(),
+ proof_data.public_values.to_vec(),
),
- target_height: args.target_block,
- update_client_vkey: UpdateClientProgram::get_vkey().bytes32(),
- membership_vkey: MembershipProgram::get_vkey().bytes32(),
- uc_and_membership_vkey: uc_mem_prover.vkey.bytes32(),
- public_values: proof_data.public_values.raw(),
- proof: format!("0x{}", hex::encode(proof_data.bytes())),
- kv_pairs: hex::encode(output.kvPairs.abi_encode()),
+ };
+
+ let fixture = SP1ICS07MembershipFixture {
+ genesis,
+ proof_height: output.updateClientOutput.newHeight.abi_encode(),
+ membership_proof: MembershipProof::from(sp1_membership_proof).abi_encode(),
};
// Save the proof data to the file path.
diff --git a/operator/src/runners/fixtures/update_client.rs b/operator/src/runners/fixtures/update_client.rs
index e7fe9db..94036a7 100644
--- a/operator/src/runners/fixtures/update_client.rs
+++ b/operator/src/runners/fixtures/update_client.rs
@@ -1,43 +1,36 @@
//! Runner for generating `update_client` fixtures
use crate::{
- cli::command::fixtures::UpdateClientCmd,
- helpers::light_block::LightBlockExt,
- programs::{
- MembershipProgram, SP1Program, UpdateClientAndMembershipProgram, UpdateClientProgram,
- },
- prover::SP1ICS07TendermintProver,
- rpc::TendermintRpcExt,
+ cli::command::fixtures::UpdateClientCmd, helpers::light_block::LightBlockExt,
+ programs::UpdateClientProgram, prover::SP1ICS07TendermintProver, rpc::TendermintRpcExt,
+ runners::genesis::SP1ICS07TendermintGenesis,
};
use alloy_sol_types::SolValue;
use serde::{Deserialize, Serialize};
-use sp1_ics07_tendermint_solidity::sp1_ics07_tendermint::{Env, UpdateClientOutput};
+use serde_with::serde_as;
+use sp1_ics07_tendermint_solidity::sp1_ics07_tendermint::{
+ ClientState, ConsensusState, Env, MsgUpdateClient, SP1Proof, UpdateClientOutput,
+};
use sp1_sdk::HashableKey;
use std::path::PathBuf;
use tendermint_rpc::HttpClient;
/// The fixture data to be used in [`UpdateClientProgram`] tests.
+#[serde_as]
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
struct SP1ICS07UpdateClientFixture {
- /// The encoded trusted client state.
- trusted_client_state: String,
- /// The encoded trusted consensus state.
- trusted_consensus_state: String,
+ /// The genesis data.
+ #[serde(flatten)]
+ genesis: SP1ICS07TendermintGenesis,
/// The encoded target consensus state.
- target_consensus_state: String,
+ #[serde_as(as = "serde_with::hex::Hex")]
+ target_consensus_state: Vec,
/// Target height.
target_height: u32,
- /// The encoded key for the [`UpdateClientProgram`].
- update_client_vkey: String,
- /// The encoded key for the [`MembershipProgram`].
- membership_vkey: String,
- /// The encoded key for the [`UpdateClientAndMembershipProgram`].
- uc_and_membership_vkey: String,
- /// The encoded public values.
- public_values: String,
- /// The encoded proof.
- proof: String,
+ /// The encoded update client message.
+ #[serde_as(as = "serde_with::hex::Hex")]
+ update_msg: Vec,
}
/// Writes the proof data for the given trusted and target blocks to the given fixture path.
@@ -58,26 +51,17 @@ pub async fn run(args: UpdateClientCmd) -> anyhow::Result<()> {
.get_light_block(Some(args.target_block))
.await?;
- let unbonding_period = tm_rpc_client
- .sdk_staking_params()
- .await?
- .unbonding_time
- .ok_or_else(|| anyhow::anyhow!("No unbonding time found"))?
- .seconds
- .try_into()?;
+ let genesis = SP1ICS07TendermintGenesis::from_env(
+ &trusted_light_block,
+ args.trust_options.trusting_period,
+ args.trust_options.trust_level,
+ )
+ .await?;
- // Defaults to the recommended TrustingPeriod: 2/3 of the UnbondingPeriod
- let trusting_period = args
- .trust_options
- .trusting_period
- .unwrap_or(2 * (unbonding_period / 3));
+ let trusted_consensus_state =
+ ConsensusState::abi_decode(&genesis.trusted_consensus_state, false)?;
+ let trusted_client_state = ClientState::abi_decode(&genesis.trusted_client_state, false)?;
- let trusted_client_state = trusted_light_block.to_sol_client_state(
- args.trust_options.trust_level.try_into()?,
- unbonding_period,
- trusting_period,
- )?;
- let trusted_consensus_state = trusted_light_block.to_consensus_state().into();
let proposed_header = target_light_block.into_header(&trusted_light_block);
let contract_env = Env {
chainId: trusted_light_block.chain_id()?.to_string(),
@@ -92,19 +76,22 @@ pub async fn run(args: UpdateClientCmd) -> anyhow::Result<()> {
let proof_data =
uc_prover.generate_proof(&trusted_consensus_state, &proposed_header, &contract_env);
- let bytes = proof_data.public_values.as_slice();
- let output = UpdateClientOutput::abi_decode(bytes, false).unwrap();
+ let output =
+ UpdateClientOutput::abi_decode(proof_data.public_values.as_slice(), false).unwrap();
+
+ let update_msg = MsgUpdateClient {
+ sp1Proof: SP1Proof::new(
+ &uc_prover.vkey.bytes32(),
+ proof_data.bytes(),
+ proof_data.public_values.to_vec(),
+ ),
+ };
let fixture = SP1ICS07UpdateClientFixture {
- trusted_consensus_state: hex::encode(trusted_consensus_state.abi_encode()),
- trusted_client_state: hex::encode(trusted_client_state.abi_encode()),
- target_consensus_state: hex::encode(output.newConsensusState.abi_encode()),
+ genesis,
+ target_consensus_state: output.newConsensusState.abi_encode(),
target_height: args.target_block,
- update_client_vkey: uc_prover.vkey.bytes32(),
- membership_vkey: MembershipProgram::get_vkey().bytes32(),
- uc_and_membership_vkey: UpdateClientAndMembershipProgram::get_vkey().bytes32(),
- public_values: proof_data.public_values.raw(),
- proof: format!("0x{}", hex::encode(proof_data.bytes())),
+ update_msg: update_msg.abi_encode(),
};
// Save the proof data to the file path.
diff --git a/operator/src/runners/genesis.rs b/operator/src/runners/genesis.rs
index b104b3e..b8ada6c 100644
--- a/operator/src/runners/genesis.rs
+++ b/operator/src/runners/genesis.rs
@@ -9,19 +9,25 @@ use crate::{
rpc::TendermintRpcExt,
};
use alloy_sol_types::SolValue;
+use serde_with::serde_as;
use sp1_ics07_tendermint_solidity::sp1_ics07_tendermint::ConsensusState as SolConsensusState;
use sp1_sdk::{utils::setup_logger, HashableKey};
use std::{env, path::PathBuf};
+use tendermint_light_client_verifier::types::{LightBlock, TrustThreshold};
use tendermint_rpc::HttpClient;
/// The genesis data for the SP1 ICS07 Tendermint contract.
+#[serde_as]
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
-struct SP1ICS07TendermintGenesis {
+#[allow(clippy::module_name_repetitions)]
+pub struct SP1ICS07TendermintGenesis {
/// The encoded trusted client state.
- trusted_client_state: String,
+ #[serde_as(as = "serde_with::hex::Hex")]
+ pub trusted_client_state: Vec,
/// The encoded trusted consensus state.
- trusted_consensus_state: String,
+ #[serde_as(as = "serde_with::hex::Hex")]
+ pub trusted_consensus_state: Vec,
/// The encoded key for [`UpdateClientProgram`].
update_client_vkey: String,
/// The encoded key for [`MembershipProgram`].
@@ -30,14 +36,58 @@ struct SP1ICS07TendermintGenesis {
uc_and_membership_vkey: String,
}
+impl SP1ICS07TendermintGenesis {
+ /// Creates a new genesis instance by reading the environment variables
+ /// and making the necessary RPC calls.
+ #[allow(clippy::missing_errors_doc)]
+ pub async fn from_env(
+ trusted_light_block: &LightBlock,
+ trusting_period: Option,
+ trust_level: TrustThreshold,
+ ) -> anyhow::Result {
+ setup_logger();
+ if dotenv::dotenv().is_err() {
+ log::warn!("No .env file found");
+ }
+
+ let tm_rpc_client = HttpClient::from_env();
+
+ let unbonding_period = tm_rpc_client
+ .sdk_staking_params()
+ .await?
+ .unbonding_time
+ .ok_or_else(|| anyhow::anyhow!("No unbonding time found"))?
+ .seconds
+ .try_into()?;
+
+ // Defaults to the recommended TrustingPeriod: 2/3 of the UnbondingPeriod
+ let trusting_period = trusting_period.unwrap_or(2 * (unbonding_period / 3));
+ if trusting_period > unbonding_period {
+ return Err(anyhow::anyhow!(
+ "Trusting period cannot be greater than unbonding period"
+ ));
+ }
+
+ let trusted_client_state = trusted_light_block.to_sol_client_state(
+ trust_level.try_into()?,
+ unbonding_period,
+ trusting_period,
+ )?;
+ let trusted_consensus_state = trusted_light_block.to_consensus_state();
+
+ Ok(Self {
+ trusted_consensus_state: SolConsensusState::from(trusted_consensus_state).abi_encode(),
+ trusted_client_state: trusted_client_state.abi_encode(),
+ update_client_vkey: UpdateClientProgram::get_vkey().bytes32(),
+ membership_vkey: MembershipProgram::get_vkey().bytes32(),
+ uc_and_membership_vkey: UpdateClientAndMembershipProgram::get_vkey().bytes32(),
+ })
+ }
+}
+
/// Creates the `genesis.json` file for the `SP1ICS07Tendermint` contract.
#[allow(clippy::missing_errors_doc, clippy::missing_panics_doc)]
pub async fn run(args: Args) -> anyhow::Result<()> {
- setup_logger();
- if dotenv::dotenv().is_err() {
- log::warn!("No .env file found");
- }
-
let tm_rpc_client = HttpClient::from_env();
let trusted_light_block = tm_rpc_client.get_light_block(args.trusted_block).await?;
@@ -48,35 +98,12 @@ pub async fn run(args: Args) -> anyhow::Result<()> {
);
}
- let unbonding_period = tm_rpc_client
- .sdk_staking_params()
- .await?
- .unbonding_time
- .ok_or_else(|| anyhow::anyhow!("No unbonding time found"))?
- .seconds
- .try_into()?;
-
- // Defaults to the recommended TrustingPeriod: 2/3 of the UnbondingPeriod
- let trusting_period = args
- .trust_options
- .trusting_period
- .unwrap_or(2 * (unbonding_period / 3));
-
- let trusted_client_state = trusted_light_block.to_sol_client_state(
- args.trust_options.trust_level.try_into()?,
- unbonding_period,
- trusting_period,
- )?;
- let trusted_consensus_state = trusted_light_block.to_consensus_state();
- let genesis = SP1ICS07TendermintGenesis {
- trusted_consensus_state: hex::encode(
- SolConsensusState::from(trusted_consensus_state).abi_encode(),
- ),
- trusted_client_state: hex::encode(trusted_client_state.abi_encode()),
- update_client_vkey: UpdateClientProgram::get_vkey().bytes32(),
- membership_vkey: MembershipProgram::get_vkey().bytes32(),
- uc_and_membership_vkey: UpdateClientAndMembershipProgram::get_vkey().bytes32(),
- };
+ let genesis = SP1ICS07TendermintGenesis::from_env(
+ &trusted_light_block,
+ args.trust_options.trusting_period,
+ args.trust_options.trust_level,
+ )
+ .await?;
let fixture_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join(args.genesis_path);
std::fs::write(
diff --git a/operator/src/runners/operator.rs b/operator/src/runners/operator.rs
index 1f90d65..a6da569 100644
--- a/operator/src/runners/operator.rs
+++ b/operator/src/runners/operator.rs
@@ -10,10 +10,11 @@ use crate::{
rpc::TendermintRpcExt,
};
use alloy::providers::ProviderBuilder;
+use alloy_sol_types::SolValue;
use log::{debug, info};
use reqwest::Url;
-use sp1_ics07_tendermint_solidity::sp1_ics07_tendermint::{self, Env};
-use sp1_sdk::utils::setup_logger;
+use sp1_ics07_tendermint_solidity::sp1_ics07_tendermint::{self, Env, MsgUpdateClient, SP1Proof};
+use sp1_sdk::{utils::setup_logger, HashableKey};
use tendermint_rpc::HttpClient;
/// An implementation of a Tendermint Light Client operator that will poll an onchain Tendermint
@@ -77,11 +78,16 @@ pub async fn run(args: Args) -> anyhow::Result<()> {
let proof_data =
prover.generate_proof(&trusted_consensus_state, &proposed_header, &contract_env);
+ let update_msg = MsgUpdateClient {
+ sp1Proof: SP1Proof::new(
+ &prover.vkey.bytes32(),
+ proof_data.bytes(),
+ proof_data.public_values.to_vec(),
+ ),
+ };
+
contract
- .updateClient(
- proof_data.bytes().into(),
- proof_data.public_values.to_vec().into(),
- )
+ .updateClient(update_msg.abi_encode().into())
.send()
.await?
.watch()
diff --git a/package.json b/package.json
index 0a75848..fa42a63 100644
--- a/package.json
+++ b/package.json
@@ -9,7 +9,8 @@
"dependencies": {
"@openzeppelin/contracts": "^5.0.1",
"forge-std": "github:foundry-rs/forge-std#v1.9.1",
- "sp1-contracts": "github:succinctlabs/sp1-contracts#v1.0.1"
+ "sp1-contracts": "github:succinctlabs/sp1-contracts#v1.0.1",
+ "solidity-ibc": "github.com:srdtrk/solidity-ibc-eureka#afdaf02d5af2799b61da7524b7abe53581aab1c9"
},
"devDependencies": {
"solhint": "^5.0.1"
@@ -29,7 +30,7 @@
],
"private": true,
"scripts": {
- "clean": "rm -rf contract/cache contract/out",
+ "clean": "rm -rf contracts/cache contracts/out",
"build": "forge build",
"lint": "bun run lint:sol",
"lint:sol": "forge fmt --check && bun solhint -c .solhint.json 'contracts/**/*.sol'",
diff --git a/packages/solidity/Cargo.toml b/packages/solidity/Cargo.toml
index a5ae5da..2a5ecb3 100644
--- a/packages/solidity/Cargo.toml
+++ b/packages/solidity/Cargo.toml
@@ -7,7 +7,7 @@ repository = { workspace = true }
license = { workspace = true }
[features]
-rpc = ["dep:alloy-contract"]
+rpc = ["dep:alloy-contract", "dep:hex"]
[dependencies]
alloy-sol-types = { workspace = true, features = ["json"] }
@@ -18,6 +18,4 @@ ibc-client-tendermint-types = { workspace = true }
tendermint = { workspace = true }
ibc-core-commitment-types = { workspace = true }
time = { workspace = true }
-
-[dev-dependencies]
-hex = { workspace = true }
+hex = { workspace = true, optional = true }
diff --git a/packages/solidity/src/lib.rs b/packages/solidity/src/lib.rs
index b2fa6ad..accf8f2 100644
--- a/packages/solidity/src/lib.rs
+++ b/packages/solidity/src/lib.rs
@@ -2,6 +2,7 @@
#![deny(missing_docs)]
#![deny(clippy::nursery, clippy::pedantic, warnings)]
+use alloy_sol_types::SolValue;
use ibc_client_tendermint_types::ConsensusState as ICS07TendermintConsensusState;
use ibc_core_commitment_types::commitment::CommitmentRoot;
use tendermint::{hash::Algorithm, Time};
@@ -18,9 +19,6 @@ alloy_sol_types::sol!(
);
// NOTE: The riscv program won't compile with the `rpc` features.
-// NOTE: Using the entire `SP1ICS07Tendermint.json` file for the `sol!` macro increases
-// the riscv program size significantly, so we can consider using the `sol!` macro with
-// manually defined structs for the required types when `rpc` feature is disabled.
#[cfg(not(feature = "rpc"))]
alloy_sol_types::sol!(
#[derive(serde::Deserialize, serde::Serialize)]
@@ -29,6 +27,27 @@ alloy_sol_types::sol!(
"../../contracts/abi/SP1ICS07Tendermint.json"
);
+#[cfg(feature = "rpc")]
+impl sp1_ics07_tendermint::SP1Proof {
+ /// Create a new [`sp1_ics07_tendermint::SP1Proof`] instance.
+ ///
+ /// # Panics
+ /// Panics if the vkey is not a valid hex string, or if the bytes cannot be decoded.
+ #[must_use]
+ pub fn new(vkey: &str, proof: Vec, public_values: Vec) -> Self {
+ let stripped = vkey.strip_prefix("0x").expect("failed to strip prefix");
+ let vkey_bytes: [u8; 32] = hex::decode(stripped)
+ .expect("failed to decode vkey")
+ .try_into()
+ .expect("invalid vkey length");
+ Self {
+ vKey: vkey_bytes.into(),
+ proof: proof.into(),
+ publicValues: public_values.into(),
+ }
+ }
+}
+
#[allow(clippy::fallible_impl_from)]
impl From for TendermintTrustThreshold {
fn from(trust_threshold: sp1_ics07_tendermint::TrustThreshold) -> Self {
@@ -92,3 +111,23 @@ impl From for ICS07TendermintConsensusStat
}
}
}
+
+impl From for sp1_ics07_tendermint::MembershipProof {
+ fn from(proof: sp1_ics07_tendermint::SP1MembershipProof) -> Self {
+ Self {
+ proofType: 0,
+ proof: proof.abi_encode().into(),
+ }
+ }
+}
+
+impl From
+ for sp1_ics07_tendermint::MembershipProof
+{
+ fn from(proof: sp1_ics07_tendermint::SP1MembershipAndUpdateClientProof) -> Self {
+ Self {
+ proofType: 1,
+ proof: proof.abi_encode().into(),
+ }
+ }
+}
diff --git a/programs/membership/src/lib.rs b/programs/membership/src/lib.rs
index 21521ac..17eb047 100644
--- a/programs/membership/src/lib.rs
+++ b/programs/membership/src/lib.rs
@@ -46,7 +46,7 @@ pub fn membership(
}
KVPair {
- key: path_str,
+ path: path_str.into(),
value: value.into(),
}
})
diff --git a/remappings.txt b/remappings.txt
index cd0e571..cacb829 100644
--- a/remappings.txt
+++ b/remappings.txt
@@ -1,3 +1,4 @@
@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/
forge-std/=node_modules/forge-std/src/
@sp1-contracts/=node_modules/sp1-contracts/contracts/src/
+solidity-ibc/=node_modules/solidity-ibc/src/