Write serialized proof to file
This commit is contained in:
parent
57d71ed391
commit
2d6ef2ee7f
6 changed files with 166 additions and 49 deletions
|
@ -9,6 +9,8 @@ cosmrs = { version = "0.15.0", default-features = false }
|
||||||
displaydoc = { version = "0.2.4", default-features = false }
|
displaydoc = { version = "0.2.4", default-features = false }
|
||||||
ics23 = { version = "0.11.0", default-features = false, features = ["host-functions"] }
|
ics23 = { version = "0.11.0", default-features = false, features = ["host-functions"] }
|
||||||
prost = { version = "0.12.3", default-features = false }
|
prost = { version = "0.12.3", default-features = false }
|
||||||
|
serde = { version = "1.0.189", features = ["derive"] }
|
||||||
|
serde_with = { version = "3.4.0", default-features = false, features = ["hex", "macros"] }
|
||||||
tendermint = { version = "0.34.0", default-features = false }
|
tendermint = { version = "0.34.0", default-features = false }
|
||||||
tendermint-rpc = { version = "0.34.0", default-features = false, features = ["http-client"] }
|
tendermint-rpc = { version = "0.34.0", default-features = false, features = ["http-client"] }
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,8 @@ use alloc::{boxed::Box, vec::Vec};
|
||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
|
|
||||||
use displaydoc::Display;
|
use displaydoc::Display;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use serde_with::{hex::Hex, serde_as};
|
||||||
use tendermint::merkle::proof::ProofOps;
|
use tendermint::merkle::proof::ProofOps;
|
||||||
use tendermint_rpc::endpoint::abci_query::AbciQuery;
|
use tendermint_rpc::endpoint::abci_query::AbciQuery;
|
||||||
|
|
||||||
|
@ -16,11 +18,10 @@ use crate::{
|
||||||
verifier::cw::CwVerifier,
|
verifier::cw::CwVerifier,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub type RawCwProof = CwProof<Vec<u8>, Vec<u8>>;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct CwProof<K, V> {
|
pub struct CwProof<K = Vec<u8>, V = Vec<u8>> {
|
||||||
proof: ProofOps,
|
proof: ProofOps,
|
||||||
|
// TODO(hu55a1n1): replace `K` with `CwAbciKey`
|
||||||
key: PrefixedKey<PrefixWasm, K>,
|
key: PrefixedKey<PrefixWasm, K>,
|
||||||
value: V,
|
value: V,
|
||||||
}
|
}
|
||||||
|
@ -29,6 +30,75 @@ pub struct CwProof<K, V> {
|
||||||
#[derive(Clone, Debug, Display)]
|
#[derive(Clone, Debug, Display)]
|
||||||
pub struct ErrorWithoutProof;
|
pub struct ErrorWithoutProof;
|
||||||
|
|
||||||
|
impl TryFrom<AbciQuery> for CwProof {
|
||||||
|
type Error = ErrorWithoutProof;
|
||||||
|
|
||||||
|
fn try_from(query: AbciQuery) -> Result<Self, Self::Error> {
|
||||||
|
RawCwProof::try_from(query).map(Into::into)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<K, V> Proof for CwProof<K, V>
|
||||||
|
where
|
||||||
|
K: Clone + Into<Vec<u8>>,
|
||||||
|
V: AsRef<[u8]>,
|
||||||
|
{
|
||||||
|
type Key = K;
|
||||||
|
type Value = V;
|
||||||
|
type ProofOps = ProofOps;
|
||||||
|
|
||||||
|
fn verify(&self, root: Vec<u8>) -> Result<(), ProofError> {
|
||||||
|
fn into_array_of_size_2<T: Debug>(v: Vec<T>) -> Result<[T; 2], ProofError> {
|
||||||
|
let boxed_slice = v.into_boxed_slice();
|
||||||
|
let boxed_array: Box<[T; 2]> = boxed_slice.try_into().expect("todo");
|
||||||
|
Ok(*boxed_array)
|
||||||
|
}
|
||||||
|
|
||||||
|
let Self { proof, key, value } = self;
|
||||||
|
let proofs = convert_tm_to_ics_merkle_proof(proof)?;
|
||||||
|
|
||||||
|
let cw_verifier = CwVerifier::default();
|
||||||
|
cw_verifier.verify(
|
||||||
|
&into_array_of_size_2(proofs)?,
|
||||||
|
&root,
|
||||||
|
&into_array_of_size_2(key.clone().into_keys())?,
|
||||||
|
value.as_ref(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[serde_as]
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
pub struct RawCwProof {
|
||||||
|
#[serde_as(as = "Hex")]
|
||||||
|
key: Vec<u8>,
|
||||||
|
#[serde_as(as = "Hex")]
|
||||||
|
value: Vec<u8>,
|
||||||
|
proof: ProofOps,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<RawCwProof> for CwProof {
|
||||||
|
fn from(RawCwProof { key, value, proof }: RawCwProof) -> Self {
|
||||||
|
Self {
|
||||||
|
proof,
|
||||||
|
key: PrefixedKey::new(key),
|
||||||
|
value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CwProof> for RawCwProof {
|
||||||
|
fn from(CwProof { proof, key, value }: CwProof) -> Self {
|
||||||
|
Self {
|
||||||
|
key: key.into_keys().pop().expect("empty key"),
|
||||||
|
value,
|
||||||
|
proof,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl TryFrom<AbciQuery> for RawCwProof {
|
impl TryFrom<AbciQuery> for RawCwProof {
|
||||||
type Error = ErrorWithoutProof;
|
type Error = ErrorWithoutProof;
|
||||||
|
|
||||||
|
@ -40,41 +110,6 @@ impl TryFrom<AbciQuery> for RawCwProof {
|
||||||
return Err(ErrorWithoutProof);
|
return Err(ErrorWithoutProof);
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self { proof, key, value })
|
||||||
proof,
|
|
||||||
key: PrefixedKey::new(key),
|
|
||||||
value,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<K, V> Proof for CwProof<K, V>
|
|
||||||
where
|
|
||||||
K: Into<Vec<u8>>,
|
|
||||||
V: Into<Vec<u8>>,
|
|
||||||
{
|
|
||||||
type Key = K;
|
|
||||||
type Value = V;
|
|
||||||
type ProofOps = ProofOps;
|
|
||||||
|
|
||||||
fn verify(self, root: Vec<u8>) -> Result<(), ProofError> {
|
|
||||||
fn into_array_of_size_2<T: Debug>(v: Vec<T>) -> Result<[T; 2], ProofError> {
|
|
||||||
let boxed_slice = v.into_boxed_slice();
|
|
||||||
let boxed_array: Box<[T; 2]> = boxed_slice.try_into().expect("todo");
|
|
||||||
Ok(*boxed_array)
|
|
||||||
}
|
|
||||||
|
|
||||||
let Self { proof, key, value } = self;
|
|
||||||
let proofs = convert_tm_to_ics_merkle_proof(&proof)?;
|
|
||||||
|
|
||||||
let cw_verifier = CwVerifier::default();
|
|
||||||
cw_verifier.verify(
|
|
||||||
&into_array_of_size_2(proofs)?,
|
|
||||||
&root,
|
|
||||||
&into_array_of_size_2(key.into_keys())?,
|
|
||||||
&value.into(),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,5 +32,5 @@ pub trait Proof {
|
||||||
type Value;
|
type Value;
|
||||||
type ProofOps;
|
type ProofOps;
|
||||||
|
|
||||||
fn verify(self, root: Vec<u8>) -> Result<(), ProofError>;
|
fn verify(&self, root: Vec<u8>) -> Result<(), ProofError>;
|
||||||
}
|
}
|
||||||
|
|
80
utils/cw-prover/Cargo.lock
generated
80
utils/cw-prover/Cargo.lock
generated
|
@ -206,6 +206,16 @@ version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "chrono"
|
||||||
|
version = "0.4.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "4.4.11"
|
version = "4.4.11"
|
||||||
|
@ -358,6 +368,8 @@ dependencies = [
|
||||||
"displaydoc",
|
"displaydoc",
|
||||||
"ics23",
|
"ics23",
|
||||||
"prost",
|
"prost",
|
||||||
|
"serde",
|
||||||
|
"serde_with",
|
||||||
"tendermint",
|
"tendermint",
|
||||||
"tendermint-rpc",
|
"tendermint-rpc",
|
||||||
]
|
]
|
||||||
|
@ -376,6 +388,41 @@ dependencies = [
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "darling"
|
||||||
|
version = "0.20.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e"
|
||||||
|
dependencies = [
|
||||||
|
"darling_core",
|
||||||
|
"darling_macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "darling_core"
|
||||||
|
version = "0.20.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621"
|
||||||
|
dependencies = [
|
||||||
|
"fnv",
|
||||||
|
"ident_case",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"strsim",
|
||||||
|
"syn 2.0.41",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "darling_macro"
|
||||||
|
version = "0.20.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5"
|
||||||
|
dependencies = [
|
||||||
|
"darling_core",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.41",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "der"
|
name = "der"
|
||||||
version = "0.7.8"
|
version = "0.7.8"
|
||||||
|
@ -790,6 +837,12 @@ dependencies = [
|
||||||
"sha3",
|
"sha3",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ident_case"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "idna"
|
name = "idna"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
|
@ -1424,6 +1477,33 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_with"
|
||||||
|
version = "3.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "64cd236ccc1b7a29e7e2739f27c0b2dd199804abc4290e32f59f3b68d6405c23"
|
||||||
|
dependencies = [
|
||||||
|
"base64",
|
||||||
|
"chrono",
|
||||||
|
"hex",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"serde_with_macros",
|
||||||
|
"time",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_with_macros"
|
||||||
|
version = "3.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "93634eb5f75a2323b16de4748022ac4297f9e76b6dced2be287a099f41b5e788"
|
||||||
|
dependencies = [
|
||||||
|
"darling",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.41",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha2"
|
name = "sha2"
|
||||||
version = "0.9.9"
|
version = "0.9.9"
|
||||||
|
|
1
utils/cw-prover/query.proof
Normal file
1
utils/cw-prover/query.proof
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{"key":"03ade4a5f5803a439835c636395a8d648dee57b2fc90d98dc17fa887159b69638b7367787374617465","value":"7b22636f6d707574655f6d72656e636c617665223a2264633433663863343264386535663532633862626436386634323632343231353366306265313036333066663863636132353531323961336361303364323733222c226b65795f6d616e616765725f6d72656e636c617665223a2231636632653532393131343130666266336631393930353661393864353837393561353539613265383030393333663766636431336430343834363232373163222c227463625f696e666f223a2233313233383736227d","proof":{"ops":[{"field_type":"ics23:iavl","key":"A63kpfWAOkOYNcY2OVqNZI3uV7L8kNmNwX+ohxWbaWOLc2d4c3RhdGU=","data":"CrgDCikDreSl9YA6Q5g1xjY5Wo1kje5XsvyQ2Y3Bf6iHFZtpY4tzZ3hzdGF0ZRLIAXsiY29tcHV0ZV9tcmVuY2xhdmUiOiJkYzQzZjhjNDJkOGU1ZjUyYzhiYmQ2OGY0MjYyNDIxNTNmMGJlMTA2MzBmZjhjY2EyNTUxMjlhM2NhMDNkMjczIiwia2V5X21hbmFnZXJfbXJlbmNsYXZlIjoiMWNmMmU1MjkxMTQxMGZiZjNmMTk5MDU2YTk4ZDU4Nzk1YTU1OWEyZTgwMDkzM2Y3ZmNkMTNkMDQ4NDYyMjcxYyIsInRjYl9pbmZvIjoiMzEyMzg3NiJ9GgwIARgBIAEqBAACmAEiKggBEiYCBJgBIFclzyzP2y2LTcBhP0IxBhvnlMJiEFCsDEMUQ9dM5dvYICIsCAESBQQGmAEgGiEgfUSWe0VMFTsxkzDuMQNE05aSzdRTTvkWzZXkfplWUbEiKggBEiYGDJBnIEkK+nmGmXpOfREXvfonLrK4mEZx1XF4DgJp86QIVF1EICIsCAESBQgakGcgGiEgBl/NSR16eG1vDenJA6GEEJ9xcQv9Bwxv8wyhAL5JLwE="},{"field_type":"ics23:simple","key":"d2FzbQ==","data":"CqgBCgR3YXNtEiDYWxn2B9M/eGP18Gwl3zgWZkT7Yn/iFlcS0THfmfcfDBoJCAEYASABKgEAIiUIARIhAWLU8PgnJ/EMp4BYvtTN9MX/rS70dNQ3ZAzrJLssrLjRIiUIARIhAeZ4u8MKaaJoanRG1ZtncskBGpLgN5tPEXihifKcMflrIiUIARIhASJkYRU83gOvlkSLVW5EV87q/xnJXY2+Iipku/9Sjq/x"}]}}
|
|
@ -26,12 +26,11 @@ use clap::{Parser, Subcommand};
|
||||||
use cosmrs::AccountId;
|
use cosmrs::AccountId;
|
||||||
use tendermint::{block::Height, AppHash};
|
use tendermint::{block::Height, AppHash};
|
||||||
use tendermint_rpc::{
|
use tendermint_rpc::{
|
||||||
client::HttpClient as TmRpcClient,
|
client::HttpClient as TmRpcClient, endpoint::status::Response, Client, HttpClientUrl,
|
||||||
endpoint::{abci_query::AbciQuery, status::Response},
|
|
||||||
Client, HttpClientUrl,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use cw_proof::proof::{cw::RawCwProof, key::CwAbciKey, Proof};
|
use cw_proof::proof::cw::RawCwProof;
|
||||||
|
use cw_proof::proof::{cw::CwProof, key::CwAbciKey, Proof};
|
||||||
|
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
#[command(author, version, about, long_about = None)]
|
#[command(author, version, about, long_about = None)]
|
||||||
|
@ -91,7 +90,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
.abci_query(Some(path), data, Some(proof_height), true)
|
.abci_query(Some(path), data, Some(proof_height), true)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let proof: RawCwProof = result.clone().try_into().map_err(into_string)?;
|
let proof: CwProof = result.clone().try_into().map_err(into_string)?;
|
||||||
proof
|
proof
|
||||||
.verify(latest_app_hash.clone().into())
|
.verify(latest_app_hash.clone().into())
|
||||||
.map_err(into_string)?;
|
.map_err(into_string)?;
|
||||||
|
@ -99,7 +98,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
println!("{}", String::from_utf8(result.value.clone())?);
|
println!("{}", String::from_utf8(result.value.clone())?);
|
||||||
|
|
||||||
if let Some(proof_file) = proof_file {
|
if let Some(proof_file) = proof_file {
|
||||||
write_proof_to_file(proof_file, result)?;
|
write_proof_to_file(proof_file, proof.into())?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -123,18 +122,18 @@ fn latest_proof_height_hash(status: Response) -> (Height, AppHash) {
|
||||||
(proof_height, latest_app_hash)
|
(proof_height, latest_app_hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_proof_to_file(proof_file: PathBuf, output: AbciQuery) -> Result<(), Box<dyn Error>> {
|
fn write_proof_to_file(proof_file: PathBuf, proof: RawCwProof) -> Result<(), Box<dyn Error>> {
|
||||||
let file = File::create(proof_file)?;
|
let file = File::create(proof_file)?;
|
||||||
let mut writer = BufWriter::new(file);
|
let mut writer = BufWriter::new(file);
|
||||||
serde_json::to_writer(&mut writer, &output)?;
|
serde_json::to_writer(&mut writer, &proof)?;
|
||||||
writer.flush()?;
|
writer.flush()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use tendermint_rpc::endpoint::abci_query::AbciQuery;
|
|
||||||
use cw_proof::{proof::cw::RawCwProof, proof::Proof};
|
use cw_proof::{proof::cw::RawCwProof, proof::Proof};
|
||||||
|
use tendermint_rpc::endpoint::abci_query::AbciQuery;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_query_item() {
|
fn test_query_item() {
|
||||||
|
|
Loading…
Reference in a new issue