diff --git a/crates/cnidarium/src/snapshot.rs b/crates/cnidarium/src/snapshot.rs index f4ae267da6..eb3518805a 100644 --- a/crates/cnidarium/src/snapshot.rs +++ b/crates/cnidarium/src/snapshot.rs @@ -82,13 +82,11 @@ impl Snapshot { db: db.clone(), }; - println!("HERE_"); let (substore_value, substore_commitment_proof) = tokio::task::spawn_blocking({ let span = span.clone(); move || span.in_scope(|| substore.get_with_proof(substore_key_bytes)) }) .await??; - println!("HERE2"); proofs.push(substore_commitment_proof); @@ -105,18 +103,15 @@ impl Snapshot { db, }; - println!("HERE3"); let (_, main_commitment_proof) = tokio::task::spawn_blocking({ let span = span.clone(); move || span.in_scope(|| mainstore.get_with_proof(key_to_substore_root.into())) }) .await??; - println!("HERE4"); proofs.push(main_commitment_proof); } - println!("HERE5, substore_value: {:?}", substore_value); Ok(( substore_value, MerkleProof { diff --git a/crates/core/app/tests/common/ibc_tests/relayer.rs b/crates/core/app/tests/common/ibc_tests/relayer.rs index b508fc8f44..5d8fa7ca58 100644 --- a/crates/core/app/tests/common/ibc_tests/relayer.rs +++ b/crates/core/app/tests/common/ibc_tests/relayer.rs @@ -366,7 +366,6 @@ impl MockRelayer { // TODO: copypaste not important to fix rn pub async fn _build_and_send_update_client_b(&mut self) -> Result<()> { - self._sync_chains().await?; tracing::info!( "send update client for chain {} to chain {}", self.chain_a_ibc.chain_id, @@ -465,7 +464,6 @@ impl MockRelayer { // helper function to build UpdateClient to send to chain A pub async fn _build_and_send_update_client_a(&mut self) -> Result<()> { - self._sync_chains().await?; tracing::info!( "send update client for chain {} to chain {}", self.chain_b_ibc.chain_id, @@ -706,10 +704,11 @@ impl MockRelayer { // Make sure chain B has a client state for this height println!("UPDATE1"); self._build_and_send_update_client_b().await?; - self._sync_chains().await?; + // self._sync_chains().await?; // the height chain b's client for chain a should have state for - let chain_b_client_a_target_height = self.chain_a_ibc.get_latest_height().await?; + let chain_b_client_a_target_height = + self.chain_a_ibc.get_latest_height().await?.increment(); let client_state_of_b_on_a_response = self .chain_a_ibc @@ -857,6 +856,9 @@ impl MockRelayer { "proof height: {:?}", connection_of_b_on_a_response.proof_height ); + + // d01e8818de18fb050c7aff28a59d430db07802f91c14c4370cf8be785381d4c7 is trusted (for height 6) + // but the proof comes in for ae0565596d0d8fb9019815400868ecf002b3aa48f4e0134e116f3184cfa49c4a (height 7) println!( "chain b latest height: {:?}", self.chain_b_ibc.get_latest_height().await? @@ -884,7 +886,7 @@ impl MockRelayer { proof_conn_end_on_a, proof_client_state_of_b_on_a, proof_consensus_state_of_b_on_a, - proofs_height_on_a: client_state_of_b_on_a_response + proofs_height_on_a: connection_of_b_on_a_response .proof_height .expect("proof height") .try_into()?, diff --git a/crates/core/app/tests/ibc_handshake.rs b/crates/core/app/tests/ibc_handshake.rs index 0e93d2b540..2e6b036ae5 100644 --- a/crates/core/app/tests/ibc_handshake.rs +++ b/crates/core/app/tests/ibc_handshake.rs @@ -11,7 +11,10 @@ use { ibc_proto::{ google::protobuf::Any, ibc::core::{ - client::v1::{QueryClientStateRequest, QueryConsensusStateRequest}, + client::v1::{ + query_client::QueryClient as IbcClientQueryClient, QueryClientStateRequest, + QueryConsensusStateRequest, + }, connection::v1::QueryConnectionRequest, }, }, @@ -22,7 +25,9 @@ use { connection::ConnectionEnd, }, lightclients::tendermint::{ - client_state::{AllowUpdate, ClientState as TendermintClientState}, + client_state::{ + AllowUpdate, ClientState as TendermintClientState, TENDERMINT_CLIENT_STATE_TYPE_URL, + }, consensus_state::ConsensusState as TendermintConsensusState, TrustThreshold, }, @@ -137,6 +142,7 @@ async fn verify_storage_proof_simple() -> anyhow::Result<()> { let start_time = tendermint::Time::parse_from_rfc3339("2022-02-11T17:30:50.425417198Z")?; + let proxy = penumbra_mock_tendermint_proxy::TestNodeProxy::new::(); let mut node = { let app_state = AppState::Content( genesis::Content::default().with_chain_id(TestNode::<()>::CHAIN_ID.to_string()), @@ -146,6 +152,7 @@ async fn verify_storage_proof_simple() -> anyhow::Result<()> { TestNode::builder() .single_validator() .with_penumbra_auto_app_state(app_state)? + .on_block(proxy.on_block_callback()) .init_chain(consensus) .await .tap_ok(|e| tracing::info!(hash = %e.last_app_hash_hex(), "finished init chain"))? @@ -280,7 +287,6 @@ async fn verify_storage_proof_simple() -> anyhow::Result<()> { let grpc_url = "http://127.0.0.1:8081" // see #4517 .parse::()? .tap(|url| tracing::debug!(%url, "parsed grpc url")); - let proxy = penumbra_mock_tendermint_proxy::TestNodeProxy::new::(); // Spawn the node's RPC server. let _rpc_server = { let make_svc = @@ -305,7 +311,9 @@ async fn verify_storage_proof_simple() -> anyhow::Result<()> { .await .with_context(|| "could not connect to grpc server") .tap_err(|error| tracing::error!(?error, "could not connect to grpc server"))?; - let mut cnidarium_client = CnidariumQueryServiceClient::new(channel); + let mut cnidarium_client = CnidariumQueryServiceClient::new(channel.clone()); + let mut ibc_client_query_client = IbcClientQueryClient::new(channel.clone()); + let mut tendermint_proxy_service_client = TendermintProxyServiceClient::new(channel.clone()); let kvr = cnidarium_client .key_value(tonic::Request::new(KeyValueRequest { key: String::from_utf8(key.clone()).unwrap(), @@ -323,7 +331,74 @@ async fn verify_storage_proof_simple() -> anyhow::Result<()> { // Same for the values. assert_eq!(value, conn); - proof.verify_membership(&proof_specs, root.clone(), merkle_path, value, 0)?; + proof.verify_membership( + &proof_specs, + root.clone(), + merkle_path.clone(), + value.clone(), + 0, + )?; + + // Try fetching the client state via the IBC API + let ibc_client_state_response = ibc_client_query_client + .client_state(QueryClientStateRequest { + client_id: "07-tendermint-0".to_string(), + }) + .await? + .into_inner(); + + let ibc_proof = MerkleProof::decode(ibc_client_state_response.clone().proof.as_slice())?; + let ibc_value = ibc_client_state_response.client_state.unwrap(); + + let cs = ibc_types::lightclients::tendermint::client_state::ClientState::try_from( + ibc_value.clone(), + )?; + println!("client state: {:?}", cs); + // let cs2 = ibc_types::lightclients::tendermint::client_state::ClientState::try_from(Any { + // type_url: TENDERMINT_CLIENT_STATE_TYPE_URL.to_string(), + // value: value.clone().into(), + // })?; + let client_state = ibc_proto::google::protobuf::Any::decode(value.as_ref())?; + let cs2 = ibc_proto::ibc::lightclients::tendermint::v1::ClientState::decode( + &*client_state.value.clone(), + )?; + let cs3 = + ibc_types::lightclients::tendermint::client_state::ClientState::try_from(client_state)?; + println!("client state2: {:?}", cs2); + println!("client state3: {:?}", cs3); + + // let client_state = ibc_proto::google::protobuf::Any::decode(value.as_ref())?; + // let cs1 = ibc_proto::ibc::lightclients::tendermint::v1::ClientState::decode(&*client.value)?; + // let client_state1 = TendermintClientState::try_from(cs1.clone())?; + + assert_eq!(ibc_value.encode_to_vec(), value); + + // We should be able to get the block from the proof_height associated with + // the proof and use the app_hash as the jmt root and succeed in proving: + let proof_block: penumbra_proto::util::tendermint_proxy::v1::GetBlockByHeightResponse = + tendermint_proxy_service_client + .get_block_by_height(GetBlockByHeightRequest { + height: ibc_client_state_response + .proof_height + .unwrap() + .revision_height + .try_into()?, + }) + .await? + .into_inner(); + + let proof_block_root = MerkleRoot { + hash: proof_block.block.unwrap().header.unwrap().app_hash, + }; + ibc_proof + .verify_membership( + &proof_specs, + proof_block_root, + merkle_path, + ibc_value.encode_to_vec(), + 0, + ) + .expect("the ibc proof should validate against the root of the proof_height's block"); Ok(()) .tap(|_| drop(node)) @@ -675,12 +750,12 @@ async fn real_cometbft_tests() -> Result<()> { let mut tendermint_proxy_service_client = TendermintProxyServiceClient::new(channel.clone()); let b = tendermint_proxy_service_client - .get_block_by_height(GetBlockByHeightRequest { height: 1 }) + .get_block_by_height(GetBlockByHeightRequest { height: 333 }) .await? .into_inner(); println!( - "block 1 app_hash: {}, last_block_id: {:?}, height: {} last_commit_hash: {}", + "block 333 app_hash: {}, last_block_id: {:?}, height: {} last_commit_hash: {}", hex::encode(b.clone().block.unwrap().header.unwrap().app_hash), b.clone().block.unwrap().header.unwrap().last_block_id, b.clone().block.unwrap().header.unwrap().height, diff --git a/crates/core/component/ibc/src/component/msg_handler/connection_open_try.rs b/crates/core/component/ibc/src/component/msg_handler/connection_open_try.rs index 1133b8f44a..66fab36ca0 100644 --- a/crates/core/component/ibc/src/component/msg_handler/connection_open_try.rs +++ b/crates/core/component/ibc/src/component/msg_handler/connection_open_try.rs @@ -97,6 +97,11 @@ impl MsgHandler for MsgConnectionOpenTry { let trusted_consensus_state = state .get_verified_consensus_state(&self.proofs_height_on_a, &self.client_id_on_b) .await?; + println!( + "trusted consensus state for height {} -- root: {}", + self.proofs_height_on_a, + hex::encode(trusted_consensus_state.clone().root.hash) + ); // PROOF VERIFICATION // 1. verify that the counterparty chain committed the expected_conn to its state @@ -143,7 +148,7 @@ impl MsgHandler for MsgConnectionOpenTry { ); println!( "trusted_consensus_state.root.hash: {}", - hex::encode(trusted_consensus_state.root.hash.clone()) + hex::encode(trusted_consensus_state.clone().root.hash.clone()) ); // assert_eq!( // hex::encode(trusted_consensus_state.root.hash.clone()), @@ -163,7 +168,7 @@ impl MsgHandler for MsgConnectionOpenTry { self.proofs_height_on_a, &self.counterparty.prefix, &proof_conn_end_on_a, - &trusted_consensus_state.root, + &trusted_consensus_state.root.clone(), &ConnectionPath::new( self.counterparty .connection_id