From 021bbeb906d2dc70f2f2e7f38aa8d5fe9e5a7167 Mon Sep 17 00:00:00 2001 From: wenyuanhust Date: Mon, 30 Oct 2023 16:55:11 +0800 Subject: [PATCH] feat: extract axon-tools, add serialization & deserialization --- Cargo.lock | 36 ++++++++++- Cargo.toml | 1 + devtools/axon-tools/Cargo.toml | 85 ++++++++++++++++++++++++ devtools/axon-tools/src/error.rs | 63 ++++++++++++++++++ devtools/axon-tools/src/hash.rs | 22 +++++++ devtools/axon-tools/src/lib.rs | 12 ++++ devtools/axon-tools/src/proof.rs | 108 +++++++++++++++++++++++++++++++ devtools/axon-tools/src/types.rs | 3 + protocol/Cargo.toml | 1 + protocol/src/codec/mod.rs | 60 ++++++++++++++++- protocol/src/types/block.rs | 78 ++++++++++++++++++---- protocol/src/types/primitive.rs | 94 ++++++++++++++++++++++----- 12 files changed, 532 insertions(+), 31 deletions(-) create mode 100644 devtools/axon-tools/Cargo.toml create mode 100644 devtools/axon-tools/src/error.rs create mode 100644 devtools/axon-tools/src/hash.rs create mode 100644 devtools/axon-tools/src/lib.rs create mode 100644 devtools/axon-tools/src/proof.rs create mode 100644 devtools/axon-tools/src/types.rs diff --git a/Cargo.lock b/Cargo.lock index 935ab3e16..7e46262cf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -303,7 +303,7 @@ dependencies = [ "async-trait", "bincode", "bytes", - "cita_trie", + "cita_trie 5.0.0", "ckb-hash", "ckb-jsonrpc-types", "ckb-sdk", @@ -335,6 +335,29 @@ dependencies = [ "zeroize", ] +[[package]] +name = "axon-tools" +version = "0.1.1" +dependencies = [ + "axon-protocol", + "bit-vec", + "blst", + "bytes", + "cita_trie 4.1.0", + "derive_more", + "ethereum", + "ethereum-types 0.14.1", + "faster-hex 0.8.1", + "log", + "overlord", + "rand 0.8.5", + "rlp", + "rlp-derive", + "serde", + "serde_json", + "tiny-keccak", +] + [[package]] name = "axum" version = "0.6.18" @@ -860,6 +883,17 @@ dependencies = [ "zeroize", ] +[[package]] +name = "cita_trie" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8c3d2abadaa28e0d277f9f6d07a2052544f045d929cd4d6f7bcfb43567c9767" +dependencies = [ + "hasher", + "parking_lot 0.12.1", + "rlp", +] + [[package]] name = "cita_trie" version = "5.0.0" diff --git a/Cargo.toml b/Cargo.toml index b4a9b6015..0448e3739 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,6 +42,7 @@ members = [ "core/run", "core/storage", "devtools/abi-generator", + "devtools/axon-tools", "devtools/keypair", "protocol", ] diff --git a/devtools/axon-tools/Cargo.toml b/devtools/axon-tools/Cargo.toml new file mode 100644 index 000000000..01e6d2f54 --- /dev/null +++ b/devtools/axon-tools/Cargo.toml @@ -0,0 +1,85 @@ +[package] +name = "axon-tools" +version = "0.1.1" +edition = "2021" +authors = ["Axon Dev "] +license = "MIT" +include = ["src/*", "README.md", "LICENSE"] +readme = "README.md" +keywords = ["axon", "tool"] +categories = ["cryptography"] +repository = "https://github.com/axonweb3/axon" +description = """ +Some axon related utilities. +""" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[dependencies.bit-vec] +version = "0.6" +default_features = false +optional = true + +[dependencies.blst] +version = "0.3" +optional = true + +[dependencies.bytes] +version = "1.4" +default-features = false +features = ["serde"] + +[dependencies.cita_trie] +version = "4.0" +optional = true + +[dependencies.ethereum-types] +version = "0.14" +default-features = false +features = ["serialize"] + +[dependencies.faster-hex] +version = "0.8" +optional = true + +[dependencies.rlp] +version = "0.5" +default-features = false +optional = true + +[dependencies.rlp-derive] +version = "0.1" +optional = true + +[dependencies.serde] +version = "1.0" +default_features = false +optional = true +features = ["derive"] + +[dependencies.tiny-keccak] +version = "2.0" +optional = true +features = ["keccak"] + +[dev-dependencies] +ethereum = "0.14" +rand = "0.8" + +[dependencies] +derive_more = "0.99" +log = "0.4.19" +overlord = "0.4" +protocol = { path = "../../protocol", features = ["hex-deserialize"], package = "axon-protocol" } +serde_json = "1.0" + +[features] +default = ["proof", "hash"] +proof = ["blst", "bit-vec", "cita_trie", "hash", "impl-rlp"] +hash = ["tiny-keccak"] +hex = ["faster-hex"] +impl-rlp = ["rlp", "rlp-derive", "ethereum-types/rlp"] +impl-serde = ["serde", "ethereum-types/serialize", "hex"] + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "doc_cfg"] diff --git a/devtools/axon-tools/src/error.rs b/devtools/axon-tools/src/error.rs new file mode 100644 index 000000000..91134881c --- /dev/null +++ b/devtools/axon-tools/src/error.rs @@ -0,0 +1,63 @@ +use std::fmt::{self, Display}; + +#[allow(dead_code)] +#[derive(Debug)] +pub enum Error { + InvalidProofBlockHash, + NotEnoughSignatures, + VerifyMptProof, + HexPrefix, + + #[cfg(feature = "hex")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "hex")))] + Hex(faster_hex::Error), + + #[cfg(feature = "proof")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "proof")))] + Bls(blst::BLST_ERROR), + + #[cfg(feature = "proof")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "proof")))] + Trie(cita_trie::TrieError), +} + +#[cfg(feature = "hex")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "hex")))] +impl From for Error { + fn from(value: faster_hex::Error) -> Self { + Self::Hex(value) + } +} + +#[cfg(feature = "proof")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "proof")))] +impl From for Error { + fn from(e: blst::BLST_ERROR) -> Self { + Self::Bls(e) + } +} + +#[cfg(feature = "proof")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "proof")))] +impl From for Error { + fn from(e: cita_trie::TrieError) -> Self { + Self::Trie(e) + } +} + +impl Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Error::InvalidProofBlockHash => write!(f, "Invalid proof block hash"), + Error::NotEnoughSignatures => write!(f, "Not enough signatures"), + Error::VerifyMptProof => write!(f, "Verify mpt proof"), + Error::HexPrefix => write!(f, "Hex prefix"), + #[cfg(feature = "hex")] + Error::Hex(e) => write!(f, "Hex error: {:?}", e), + #[cfg(feature = "proof")] + Error::Bls(e) => write!(f, "Bls error: {:?}", e), + #[cfg(feature = "proof")] + Error::Trie(e) => write!(f, "Trie error: {:?}", e), + } + } +} diff --git a/devtools/axon-tools/src/hash.rs b/devtools/axon-tools/src/hash.rs new file mode 100644 index 000000000..bc051bbe6 --- /dev/null +++ b/devtools/axon-tools/src/hash.rs @@ -0,0 +1,22 @@ +use tiny_keccak::{Hasher, Keccak}; + +#[cfg(feature = "hash")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "hash")))] +pub fn keccak_256(data: &[u8]) -> [u8; 32] { + let mut ret = [0u8; 32]; + let mut hasher = Keccak::v256(); + hasher.update(data); + hasher.finalize(&mut ret); + ret +} + +#[derive(Default)] +pub(crate) struct InnerKeccak; + +impl cita_trie::Hasher for InnerKeccak { + const LENGTH: usize = 32; + + fn digest(&self, data: &[u8]) -> Vec { + keccak_256(data).to_vec() + } +} diff --git a/devtools/axon-tools/src/lib.rs b/devtools/axon-tools/src/lib.rs new file mode 100644 index 000000000..73e69a7b6 --- /dev/null +++ b/devtools/axon-tools/src/lib.rs @@ -0,0 +1,12 @@ +#![cfg_attr(doc_cfg, feature(doc_cfg))] + +extern crate alloc; + +mod error; +mod hash; +mod proof; +pub mod types; + +#[cfg(feature = "proof")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "proof")))] +pub use proof::{verify_proof, verify_trie_proof}; diff --git a/devtools/axon-tools/src/proof.rs b/devtools/axon-tools/src/proof.rs new file mode 100644 index 000000000..fb02221e0 --- /dev/null +++ b/devtools/axon-tools/src/proof.rs @@ -0,0 +1,108 @@ +use alloc::vec::Vec; + +use bit_vec::BitVec; +use blst::min_pk::{AggregatePublicKey, PublicKey, Signature}; +use blst::BLST_ERROR; +use bytes::Bytes; +use ethereum_types::H256; +use rlp::Encodable; + +use crate::{ + error::Error, + hash::{keccak_256, InnerKeccak}, + types::{Block, Proof, Proposal, ValidatorExtend}, +}; +use overlord::types::{Vote, VoteType::Precommit}; + +const DST: &str = "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RONUL"; + +pub fn verify_trie_proof( + root: H256, + key: &[u8], + proof: Vec>, +) -> Result>, Error> { + let value = cita_trie::verify_proof(&root.0, key, proof, InnerKeccak)?; + log::debug!("key: {:?}, value: {:?}", key, value); + Ok(value) +} + +pub fn verify_proof( + block: Block, + previous_state_root: H256, + validator_list: &mut [ValidatorExtend], + proof: Proof, +) -> Result<(), Error> { + let raw_proposal = Proposal { + version: block.header.version, + prev_hash: block.header.prev_hash, + proposer: block.header.proposer, + prev_state_root: previous_state_root, + transactions_root: block.header.transactions_root, + signed_txs_hash: block.header.signed_txs_hash, + timestamp: block.header.timestamp, + number: block.header.number, + gas_limit: block.header.gas_limit, + extra_data: block.header.extra_data, + base_fee_per_gas: block.header.base_fee_per_gas, + proof: block.header.proof, + chain_id: block.header.chain_id, + call_system_script_count: block.header.call_system_script_count, + tx_hashes: block.tx_hashes, + } + .rlp_bytes(); + + if keccak_256(&raw_proposal) != proof.block_hash.0 { + return Err(Error::InvalidProofBlockHash); + } + + let vote = Vote { + height: proof.number, + round: proof.round, + vote_type: Precommit, + block_hash: Bytes::from(proof.block_hash.0.to_vec()), + }; + + let hash_vote = keccak_256(rlp::encode(&vote).as_ref()); + let pks = extract_pks(&proof, validator_list)?; + let pks = pks.iter().collect::>(); + let c_pk = PublicKey::from_aggregate(&AggregatePublicKey::aggregate(&pks, true)?); + let sig = Signature::from_bytes(&proof.signature)?; + let res = sig.verify(true, &hash_vote, DST.as_bytes(), &[], &c_pk, true); + + if res == BLST_ERROR::BLST_SUCCESS { + return Ok(()); + } + + Err(res.into()) +} + +fn extract_pks( + proof: &Proof, + validator_list: &mut [ValidatorExtend], +) -> Result, Error> { + validator_list.sort(); + + let bit_map = BitVec::from_bytes(&proof.bitmap); + let mut pks = Vec::with_capacity(validator_list.len()); + let mut count = 0usize; + + for (v, bit) in validator_list.iter().zip(bit_map.iter()) { + if !bit { + continue; + } + + pks.push(PublicKey::from_bytes(&v.bls_pub_key.as_bytes())?); + count += 1; + } + + log::debug!( + "extract_pks count: {}, validator len: {}", + count, + validator_list.len() + ); + if count * 3 <= validator_list.len() * 2 { + return Err(Error::NotEnoughSignatures); + } + + Ok(pks) +} diff --git a/devtools/axon-tools/src/types.rs b/devtools/axon-tools/src/types.rs new file mode 100644 index 000000000..3d8ff6412 --- /dev/null +++ b/devtools/axon-tools/src/types.rs @@ -0,0 +1,3 @@ +pub use protocol::types::{ + Block, CkbRelatedInfo, Header, Metadata, Proof, Proposal, ValidatorExtend, +}; diff --git a/protocol/Cargo.toml b/protocol/Cargo.toml index db9374b6a..02572074c 100644 --- a/protocol/Cargo.toml +++ b/protocol/Cargo.toml @@ -53,3 +53,4 @@ common-merkle = { path = "../common/merkle" } [features] default = ["hex-serialize"] hex-serialize = [] +hex-deserialize = [] diff --git a/protocol/src/codec/mod.rs b/protocol/src/codec/mod.rs index 19529c157..c21a9e81f 100644 --- a/protocol/src/codec/mod.rs +++ b/protocol/src/codec/mod.rs @@ -8,7 +8,7 @@ pub use transaction::truncate_slice; use ethers_core::utils::parse_checksummed; use rlp::{Decodable, DecoderError, Encodable, Rlp, RlpStream}; -use serde::{Deserialize as _, Deserializer, Serializer}; +use serde::{Deserializer, Serializer}; use crate::types::{Address, Bytes, DBBytes, Hex, Key256Bits, TypesError, H160, U256}; use crate::ProtocolResult; @@ -109,6 +109,64 @@ where } } +use serde::de::Deserialize; + +pub fn from_hex(hex: &str) -> Result, &'static str> { + let mut bytes = Vec::with_capacity((hex.len() + 1) / 2); + + let mut start_i = 0; + if hex.len() % 2 != 0 { + let byte = u8::from_str_radix(&hex[0..1], 16).map_err(|_| "Failed to parse hex string")?; + bytes.push(byte); + start_i = 1; + } + + for i in (start_i..hex.len()).step_by(2) { + let end_i = if i + 2 > hex.len() { i + 1 } else { i + 2 }; + let byte = + u8::from_str_radix(&hex[i..end_i], 16).map_err(|_| "Failed to parse hex string")?; + bytes.push(byte); + } + + Ok(bytes) +} + +pub fn deserialize_hex_u32<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + let s = String::deserialize(deserializer)?; + if s == "0x0" { + return Ok(0); + } + + if s.len() >= 2 && &s[0..2] == "0x" { + let bytes = from_hex(&s[2..]).map_err(serde::de::Error::custom)?; + let val = U256::from_big_endian(&bytes); + Ok(val.low_u32()) + } else { + Err(serde::de::Error::custom("Invalid format")) + } +} + +pub fn deserialize_hex_u64<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + let s = String::deserialize(deserializer)?; + if s == "0x0" { + return Ok(0); + } + + if s.len() >= 2 && &s[0..2] == "0x" { + let bytes = from_hex(&s[2..]).map_err(serde::de::Error::custom)?; + let val = U256::from_big_endian(&bytes); + Ok(val.low_u64()) + } else { + Err(serde::de::Error::custom("Invalid format")) + } +} + pub fn decode_256bits_key(s: &str) -> Result { const LEN: usize = 66; if s.starts_with("0x") || s.starts_with("0X") { diff --git a/protocol/src/types/block.rs b/protocol/src/types/block.rs index b56194fec..8edd2e0ad 100644 --- a/protocol/src/types/block.rs +++ b/protocol/src/types/block.rs @@ -4,12 +4,13 @@ use serde::{Deserialize, Serialize}; #[cfg(feature = "hex-serialize")] use crate::codec::serialize_uint; +#[cfg(feature = "hex-deserialize")] +use crate::codec::{deserialize_hex_u32, deserialize_hex_u64}; use crate::types::{ logs_bloom, Bloom, BloomInput, Bytes, ExecResp, Hash, Hasher, Log, MerkleRoot, Receipt, SignedTransaction, H160, U256, }; use crate::{codec::ProtocolCodec, types::TypesError}; - pub type BlockNumber = u64; pub const MAX_BLOCK_GAS_LIMIT: u64 = 30_000_000; @@ -53,17 +54,33 @@ pub struct Proposal { pub prev_state_root: MerkleRoot, pub transactions_root: MerkleRoot, pub signed_txs_hash: Hash, - #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint"))] + #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint",))] + #[cfg_attr( + feature = "hex-deserialize", + serde(deserialize_with = "deserialize_hex_u64") + )] pub timestamp: u64, - #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint"))] + #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint",))] + #[cfg_attr( + feature = "hex-deserialize", + serde(deserialize_with = "deserialize_hex_u64") + )] pub number: BlockNumber, pub gas_limit: U256, pub extra_data: Vec, pub base_fee_per_gas: U256, pub proof: Proof, - #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint"))] + #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint",))] + #[cfg_attr( + feature = "hex-deserialize", + serde(deserialize_with = "deserialize_hex_u64") + )] pub chain_id: u64, - #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint"))] + #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint",))] + #[cfg_attr( + feature = "hex-deserialize", + serde(deserialize_with = "deserialize_hex_u32") + )] pub call_system_script_count: u32, pub tx_hashes: Vec, } @@ -213,9 +230,17 @@ pub struct Header { pub signed_txs_hash: Hash, pub receipts_root: MerkleRoot, pub log_bloom: Bloom, - #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint"))] + #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint",))] + #[cfg_attr( + feature = "hex-deserialize", + serde(deserialize_with = "deserialize_hex_u64") + )] pub timestamp: u64, - #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint"))] + #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint",))] + #[cfg_attr( + feature = "hex-deserialize", + serde(deserialize_with = "deserialize_hex_u64") + )] pub number: BlockNumber, pub gas_used: U256, pub gas_limit: U256, @@ -225,9 +250,17 @@ pub struct Header { pub extra_data: Vec, pub base_fee_per_gas: U256, pub proof: Proof, - #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint"))] + #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint",))] + #[cfg_attr( + feature = "hex-deserialize", + serde(deserialize_with = "deserialize_hex_u32") + )] pub call_system_script_count: u32, - #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint"))] + #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint",))] + #[cfg_attr( + feature = "hex-deserialize", + serde(deserialize_with = "deserialize_hex_u64") + )] pub chain_id: u64, } @@ -247,7 +280,10 @@ impl Header { pub struct ExtraData { #[cfg_attr( feature = "hex-serialize", - serde(serialize_with = "withpfx_lowercase::serialize") + serde( + serialize_with = "withpfx_lowercase::serialize", + deserialize_with = "withpfx_lowercase::deserialize" + ) )] pub inner: Bytes, } @@ -256,19 +292,33 @@ pub struct ExtraData { RlpEncodable, RlpDecodable, Serialize, Deserialize, Default, Clone, Debug, PartialEq, Eq, )] pub struct Proof { - #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint"))] + #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint",))] + #[cfg_attr( + feature = "hex-deserialize", + serde(deserialize_with = "deserialize_hex_u64") + )] pub number: u64, - #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint"))] + #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint",))] + #[cfg_attr( + feature = "hex-deserialize", + serde(deserialize_with = "deserialize_hex_u64") + )] pub round: u64, pub block_hash: Hash, #[cfg_attr( feature = "hex-serialize", - serde(serialize_with = "withpfx_lowercase::serialize") + serde( + serialize_with = "withpfx_lowercase::serialize", + deserialize_with = "withpfx_lowercase::deserialize" + ) )] pub signature: Bytes, #[cfg_attr( feature = "hex-serialize", - serde(serialize_with = "withpfx_lowercase::serialize") + serde( + serialize_with = "withpfx_lowercase::serialize", + deserialize_with = "withpfx_lowercase::deserialize" + ) )] pub bitmap: Bytes, } diff --git a/protocol/src/types/primitive.rs b/protocol/src/types/primitive.rs index eecf51cb2..7088ad5e2 100644 --- a/protocol/src/types/primitive.rs +++ b/protocol/src/types/primitive.rs @@ -17,6 +17,10 @@ use common_crypto::Secp256k1PublicKey; use common_hasher::keccak256; use crate::codec::{deserialize_address, hex_decode, hex_encode, serialize_uint}; + +#[cfg(feature = "hex-deserialize")] +use crate::codec::{deserialize_hex_u32, deserialize_hex_u64}; + use crate::types::{BlockNumber, Bytes, BytesMut, TypesError}; use crate::{ProtocolError, ProtocolResult}; @@ -275,9 +279,17 @@ impl fmt::Display for Address { RlpEncodable, RlpDecodable, Serialize, Deserialize, Default, Clone, Debug, Copy, PartialEq, Eq, )] pub struct MetadataVersion { - #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint"))] + #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint",))] + #[cfg_attr( + feature = "hex-deserialize", + serde(deserialize_with = "deserialize_hex_u64") + )] pub start: BlockNumber, - #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint"))] + #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint",))] + #[cfg_attr( + feature = "hex-deserialize", + serde(deserialize_with = "deserialize_hex_u64") + )] pub end: BlockNumber, } @@ -296,7 +308,11 @@ impl MetadataVersion { )] pub struct Metadata { pub version: MetadataVersion, - #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint"))] + #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint",))] + #[cfg_attr( + feature = "hex-deserialize", + serde(deserialize_with = "deserialize_hex_u64") + )] pub epoch: u64, pub verifier_list: Vec, #[serde(skip_deserializing)] @@ -378,23 +394,59 @@ impl From for ConsensusConfig { RlpEncodable, RlpDecodable, Serialize, Deserialize, Default, Clone, Debug, PartialEq, Eq, )] pub struct ConsensusConfig { - #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint"))] + #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint",))] + #[cfg_attr( + feature = "hex-deserialize", + serde(deserialize_with = "deserialize_hex_u64") + )] pub gas_limit: u64, - #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint"))] + #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint",))] + #[cfg_attr( + feature = "hex-deserialize", + serde(deserialize_with = "deserialize_hex_u64") + )] pub interval: u64, - #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint"))] + #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint",))] + #[cfg_attr( + feature = "hex-deserialize", + serde(deserialize_with = "deserialize_hex_u64") + )] pub propose_ratio: u64, - #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint"))] + #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint",))] + #[cfg_attr( + feature = "hex-deserialize", + serde(deserialize_with = "deserialize_hex_u64") + )] pub prevote_ratio: u64, - #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint"))] + #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint",))] + #[cfg_attr( + feature = "hex-deserialize", + serde(deserialize_with = "deserialize_hex_u64") + )] pub precommit_ratio: u64, - #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint"))] + #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint",))] + #[cfg_attr( + feature = "hex-deserialize", + serde(deserialize_with = "deserialize_hex_u64") + )] pub brake_ratio: u64, - #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint"))] + #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint",))] + #[cfg_attr( + feature = "hex-deserialize", + serde(deserialize_with = "deserialize_hex_u64") + )] pub tx_num_limit: u64, - #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint"))] + #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint",))] + #[cfg_attr( + feature = "hex-deserialize", + serde(deserialize_with = "deserialize_hex_u64") + )] pub max_tx_size: u64, - #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint"))] + #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint",))] + #[cfg_attr( + feature = "hex-deserialize", + serde(deserialize_with = "deserialize_hex_u64") + )] #[serde(default = "default_max_contract_limit")] pub max_contract_limit: u64, } @@ -431,7 +483,11 @@ impl From for DurationConfig { #[derive(RlpEncodable, RlpDecodable, Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] pub struct ProposeCount { pub address: H160, - #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint"))] + #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint",))] + #[cfg_attr( + feature = "hex-deserialize", + serde(deserialize_with = "deserialize_hex_u64") + )] pub count: u64, } @@ -462,9 +518,17 @@ pub struct ValidatorExtend { pub bls_pub_key: Hex, pub pub_key: Hex, pub address: H160, - #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint"))] + #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint",))] + #[cfg_attr( + feature = "hex-deserialize", + serde(deserialize_with = "deserialize_hex_u32") + )] pub propose_weight: u32, - #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint"))] + #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint",))] + #[cfg_attr( + feature = "hex-deserialize", + serde(deserialize_with = "deserialize_hex_u32") + )] pub vote_weight: u32, }