From d3559c412f496f5ceec19105cd130662f0c4d0a9 Mon Sep 17 00:00:00 2001 From: huwenchao Date: Thu, 20 Aug 2020 00:01:59 +0800 Subject: [PATCH 01/45] feat(MintXT): finish verify data --- .../src/switch/deposit_request/mod.rs | 12 +++++++++--- .../toCKB-typescript/src/switch/mint_xt/mod.rs | 16 +++++++++++++++- .../toCKB-typescript/src/utils/types/error.rs | 2 ++ .../src/utils/types/schemas/toCKB_cell_data.mol | 5 +++++ .../src/utils/types/toCKB_cell.rs | 3 ++- 5 files changed, 33 insertions(+), 5 deletions(-) diff --git a/contracts/toCKB-typescript/src/switch/deposit_request/mod.rs b/contracts/toCKB-typescript/src/switch/deposit_request/mod.rs index 44dcc94..bb5ae82 100644 --- a/contracts/toCKB-typescript/src/switch/deposit_request/mod.rs +++ b/contracts/toCKB-typescript/src/switch/deposit_request/mod.rs @@ -1,7 +1,7 @@ use crate::switch::ToCKBCellDataTuple; use crate::utils::{ config::PLEDGE, - types::{Error, ToCKBCellDataView}, + types::{Error, ToCKBCellDataView, XChainKind}, }; use ckb_std::{ckb_constants::Source, high_level::load_cell_capacity}; use core::result::Result; @@ -24,8 +24,14 @@ fn verify_capacity() -> Result<(), Error> { } fn verify_lot_size(toCKB_data: &ToCKBCellDataView) -> Result<(), Error> { - if toCKB_data.get_btc_lot_size().is_err() && toCKB_data.get_eth_lot_size().is_err() { - return Err(Error::LotSizeInvalid); + if let XChainKind::Btc = toCKB_data.kind { + if toCKB_data.get_btc_lot_size().is_err() { + return Err(Error::LotSizeInvalid); + } + } else { + if toCKB_data.get_eth_lot_size().is_err() { + return Err(Error::LotSizeInvalid); + } } Ok(()) } diff --git a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs index 464e014..13da758 100644 --- a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs +++ b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs @@ -2,6 +2,20 @@ use crate::switch::ToCKBCellDataTuple; use crate::utils::types::Error; use core::result::Result; -pub fn verify(_toCKB_data_tuple: &ToCKBCellDataTuple) -> Result<(), Error> { +fn verify_data(toCKB_data_tuple: &ToCKBCellDataTuple) -> Result<(), Error> { + let input_data = toCKB_data_tuple.0.as_ref().expect("should not happen"); + let output_data = toCKB_data_tuple.1.as_ref().expect("should not happen"); + if input_data.kind != output_data.kind + || input_data.signer_lockscript_hash.as_ref() != output_data.signer_lockscript_hash.as_ref() + || input_data.user_lockscript_hash.as_ref() != output_data.user_lockscript_hash.as_ref() + || input_data.x_lock_address.as_ref() != output_data.x_lock_address.as_ref() + { + return Err(Error::InvalidDataChange); + } + Ok(()) +} + +pub fn verify(toCKB_data_tuple: &ToCKBCellDataTuple) -> Result<(), Error> { + verify_data(toCKB_data_tuple)?; Ok(()) } diff --git a/contracts/toCKB-typescript/src/utils/types/error.rs b/contracts/toCKB-typescript/src/utils/types/error.rs index 433ab7c..8308dc1 100644 --- a/contracts/toCKB-typescript/src/utils/types/error.rs +++ b/contracts/toCKB-typescript/src/utils/types/error.rs @@ -11,6 +11,8 @@ pub enum Error { TxInvalid, LotSizeInvalid, PledgeInvalid, + // MintXT Error + InvalidDataChange, } impl From for Error { diff --git a/contracts/toCKB-typescript/src/utils/types/schemas/toCKB_cell_data.mol b/contracts/toCKB-typescript/src/utils/types/schemas/toCKB_cell_data.mol index a479480..b52e9f9 100644 --- a/contracts/toCKB-typescript/src/utils/types/schemas/toCKB_cell_data.mol +++ b/contracts/toCKB-typescript/src/utils/types/schemas/toCKB_cell_data.mol @@ -12,3 +12,8 @@ table ToCKBCellData { redeemer_lockscript_hash: Byte32, liquidation_trigger_lockscript_hash: Byte32, } + +table MintXTWitness { + spv_proof: Bytes, + cell_dep_index_list: Bytes, +} diff --git a/contracts/toCKB-typescript/src/utils/types/toCKB_cell.rs b/contracts/toCKB-typescript/src/utils/types/toCKB_cell.rs index 310e7e3..5a24310 100644 --- a/contracts/toCKB-typescript/src/utils/types/toCKB_cell.rs +++ b/contracts/toCKB-typescript/src/utils/types/toCKB_cell.rs @@ -7,7 +7,7 @@ use molecule::prelude::*; pub struct ToCKBCellDataView { pub status: ToCKBStatus, pub kind: XChainKind, - lot_size: u8, + pub lot_size: u8, pub user_lockscript_hash: Bytes, pub x_lock_address: Bytes, pub signer_lockscript_hash: Bytes, @@ -109,6 +109,7 @@ impl ToCKBStatus { } #[repr(u8)] +#[derive(PartialEq)] pub enum XChainKind { Btc = 1, Eth, From b528e6ed9a6e24fc0837c0d88105f10257364a2f Mon Sep 17 00:00:00 2001 From: huwenchao Date: Thu, 20 Aug 2020 00:06:20 +0800 Subject: [PATCH 02/45] feat(MintXT): add makefile to generate types --- Makefile | 8 + .../utils/types/generated/toCKB_cell_data.rs | 330 +++++++++++++++--- 2 files changed, 284 insertions(+), 54 deletions(-) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..77d397d --- /dev/null +++ b/Makefile @@ -0,0 +1,8 @@ +watch: + watchexec -w contracts/toCKB-typescript/src -- 'make fmt && capsule build' + +schema: + moleculec --language rust --schema-file contracts/toCKB-typescript/src/utils/types/schemas/toCKB_cell_data.mol > contracts/toCKB-typescript/src/utils/types/generated/toCKB_cell_data.rs + +fmt: + cd contracts/toCKB-typescript && cargo fmt \ No newline at end of file diff --git a/contracts/toCKB-typescript/src/utils/types/generated/toCKB_cell_data.rs b/contracts/toCKB-typescript/src/utils/types/generated/toCKB_cell_data.rs index 354c370..5ee6d4a 100644 --- a/contracts/toCKB-typescript/src/utils/types/generated/toCKB_cell_data.rs +++ b/contracts/toCKB-typescript/src/utils/types/generated/toCKB_cell_data.rs @@ -1,10 +1,8 @@ // Generated by Molecule 0.6.0 use molecule::prelude::*; - #[derive(Clone)] pub struct Byte32(molecule::bytes::Bytes); - impl ::core::fmt::LowerHex for Byte32 { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; @@ -14,13 +12,11 @@ impl ::core::fmt::LowerHex for Byte32 { write!(f, "{}", hex_string(self.as_slice())) } } - impl ::core::fmt::Debug for Byte32 { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:#x})", Self::NAME, self) } } - impl ::core::fmt::Display for Byte32 { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; @@ -28,7 +24,6 @@ impl ::core::fmt::Display for Byte32 { write!(f, "{}(0x{})", Self::NAME, raw_data) } } - impl ::core::default::Default for Byte32 { fn default() -> Self { let v: Vec = vec![ @@ -38,7 +33,6 @@ impl ::core::default::Default for Byte32 { Byte32::new_unchecked(v.into()) } } - impl Byte32 { pub const TOTAL_SIZE: usize = 32; pub const ITEM_SIZE: usize = 1; @@ -146,7 +140,6 @@ impl Byte32 { Byte32Reader::new_unchecked(self.as_slice()) } } - impl molecule::prelude::Entity for Byte32 { type Builder = Byte32Builder; const NAME: &'static str = "Byte32"; @@ -205,10 +198,8 @@ impl molecule::prelude::Entity for Byte32 { ]) } } - #[derive(Clone, Copy)] pub struct Byte32Reader<'r>(&'r [u8]); - impl<'r> ::core::fmt::LowerHex for Byte32Reader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; @@ -218,13 +209,11 @@ impl<'r> ::core::fmt::LowerHex for Byte32Reader<'r> { write!(f, "{}", hex_string(self.as_slice())) } } - impl<'r> ::core::fmt::Debug for Byte32Reader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:#x})", Self::NAME, self) } } - impl<'r> ::core::fmt::Display for Byte32Reader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; @@ -232,7 +221,6 @@ impl<'r> ::core::fmt::Display for Byte32Reader<'r> { write!(f, "{}(0x{})", Self::NAME, raw_data) } } - impl<'r> Byte32Reader<'r> { pub const TOTAL_SIZE: usize = 32; pub const ITEM_SIZE: usize = 1; @@ -337,7 +325,6 @@ impl<'r> Byte32Reader<'r> { self.as_slice() } } - impl<'r> molecule::prelude::Reader<'r> for Byte32Reader<'r> { type Entity = Byte32; const NAME: &'static str = "Byte32Reader"; @@ -359,15 +346,12 @@ impl<'r> molecule::prelude::Reader<'r> for Byte32Reader<'r> { Ok(()) } } - pub struct Byte32Builder(pub(crate) [Byte; 32]); - impl ::core::fmt::Debug for Byte32Builder { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:?})", Self::NAME, &self.0[..]) } } - impl ::core::default::Default for Byte32Builder { fn default() -> Self { Byte32Builder([ @@ -406,7 +390,6 @@ impl ::core::default::Default for Byte32Builder { ]) } } - impl Byte32Builder { pub const TOTAL_SIZE: usize = 32; pub const ITEM_SIZE: usize = 1; @@ -544,7 +527,6 @@ impl Byte32Builder { self } } - impl molecule::prelude::Builder for Byte32Builder { type Entity = Byte32; const NAME: &'static str = "Byte32Builder"; @@ -593,10 +575,8 @@ impl molecule::prelude::Builder for Byte32Builder { Byte32::new_unchecked(inner.into()) } } - #[derive(Clone)] pub struct Bytes(molecule::bytes::Bytes); - impl ::core::fmt::LowerHex for Bytes { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; @@ -606,13 +586,11 @@ impl ::core::fmt::LowerHex for Bytes { write!(f, "{}", hex_string(self.as_slice())) } } - impl ::core::fmt::Debug for Bytes { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:#x})", Self::NAME, self) } } - impl ::core::fmt::Display for Bytes { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; @@ -620,14 +598,12 @@ impl ::core::fmt::Display for Bytes { write!(f, "{}(0x{})", Self::NAME, raw_data) } } - impl ::core::default::Default for Bytes { fn default() -> Self { let v: Vec = vec![0, 0, 0, 0]; Bytes::new_unchecked(v.into()) } } - impl Bytes { pub const ITEM_SIZE: usize = 1; pub fn total_size(&self) -> usize { @@ -661,7 +637,6 @@ impl Bytes { BytesReader::new_unchecked(self.as_slice()) } } - impl molecule::prelude::Entity for Bytes { type Builder = BytesBuilder; const NAME: &'static str = "Bytes"; @@ -687,10 +662,8 @@ impl molecule::prelude::Entity for Bytes { Self::new_builder().extend(self.into_iter()) } } - #[derive(Clone, Copy)] pub struct BytesReader<'r>(&'r [u8]); - impl<'r> ::core::fmt::LowerHex for BytesReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; @@ -700,13 +673,11 @@ impl<'r> ::core::fmt::LowerHex for BytesReader<'r> { write!(f, "{}", hex_string(self.as_slice())) } } - impl<'r> ::core::fmt::Debug for BytesReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:#x})", Self::NAME, self) } } - impl<'r> ::core::fmt::Display for BytesReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; @@ -714,7 +685,6 @@ impl<'r> ::core::fmt::Display for BytesReader<'r> { write!(f, "{}(0x{})", Self::NAME, raw_data) } } - impl<'r> BytesReader<'r> { pub const ITEM_SIZE: usize = 1; pub fn total_size(&self) -> usize { @@ -745,7 +715,6 @@ impl<'r> BytesReader<'r> { &self.as_slice()[molecule::NUMBER_SIZE..] } } - impl<'r> molecule::prelude::Reader<'r> for BytesReader<'r> { type Entity = Bytes; const NAME: &'static str = "BytesReader"; @@ -778,10 +747,8 @@ impl<'r> molecule::prelude::Reader<'r> for BytesReader<'r> { Ok(()) } } - #[derive(Debug, Default)] pub struct BytesBuilder(pub(crate) Vec); - impl BytesBuilder { pub const ITEM_SIZE: usize = 1; pub fn set(mut self, v: Vec) -> Self { @@ -799,7 +766,6 @@ impl BytesBuilder { self } } - impl molecule::prelude::Builder for BytesBuilder { type Entity = Bytes; const NAME: &'static str = "BytesBuilder"; @@ -820,9 +786,7 @@ impl molecule::prelude::Builder for BytesBuilder { Bytes::new_unchecked(inner.into()) } } - pub struct BytesIterator(Bytes, usize, usize); - impl ::core::iter::Iterator for BytesIterator { type Item = Byte; fn next(&mut self) -> Option { @@ -835,13 +799,11 @@ impl ::core::iter::Iterator for BytesIterator { } } } - impl ::core::iter::ExactSizeIterator for BytesIterator { fn len(&self) -> usize { self.2 - self.1 } } - impl ::core::iter::IntoIterator for Bytes { type Item = Byte; type IntoIter = BytesIterator; @@ -850,10 +812,8 @@ impl ::core::iter::IntoIterator for Bytes { BytesIterator(self, 0, len) } } - #[derive(Clone)] pub struct ToCKBCellData(molecule::bytes::Bytes); - impl ::core::fmt::LowerHex for ToCKBCellData { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; @@ -863,13 +823,11 @@ impl ::core::fmt::LowerHex for ToCKBCellData { write!(f, "{}", hex_string(self.as_slice())) } } - impl ::core::fmt::Debug for ToCKBCellData { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:#x})", Self::NAME, self) } } - impl ::core::fmt::Display for ToCKBCellData { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{} {{ ", Self::NAME)?; @@ -909,7 +867,6 @@ impl ::core::fmt::Display for ToCKBCellData { write!(f, " }}") } } - impl ::core::default::Default for ToCKBCellData { fn default() -> Self { let v: Vec = vec![ @@ -924,7 +881,6 @@ impl ::core::default::Default for ToCKBCellData { ToCKBCellData::new_unchecked(v.into()) } } - impl ToCKBCellData { pub const FIELD_COUNT: usize = 9; pub fn total_size(&self) -> usize { @@ -1005,7 +961,6 @@ impl ToCKBCellData { ToCKBCellDataReader::new_unchecked(self.as_slice()) } } - impl molecule::prelude::Entity for ToCKBCellData { type Builder = ToCKBCellDataBuilder; const NAME: &'static str = "ToCKBCellData"; @@ -1040,10 +995,8 @@ impl molecule::prelude::Entity for ToCKBCellData { .liquidation_trigger_lockscript_hash(self.liquidation_trigger_lockscript_hash()) } } - #[derive(Clone, Copy)] pub struct ToCKBCellDataReader<'r>(&'r [u8]); - impl<'r> ::core::fmt::LowerHex for ToCKBCellDataReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; @@ -1053,13 +1006,11 @@ impl<'r> ::core::fmt::LowerHex for ToCKBCellDataReader<'r> { write!(f, "{}", hex_string(self.as_slice())) } } - impl<'r> ::core::fmt::Debug for ToCKBCellDataReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:#x})", Self::NAME, self) } } - impl<'r> ::core::fmt::Display for ToCKBCellDataReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{} {{ ", Self::NAME)?; @@ -1099,7 +1050,6 @@ impl<'r> ::core::fmt::Display for ToCKBCellDataReader<'r> { write!(f, " }}") } } - impl<'r> ToCKBCellDataReader<'r> { pub const FIELD_COUNT: usize = 9; pub fn total_size(&self) -> usize { @@ -1177,7 +1127,6 @@ impl<'r> ToCKBCellDataReader<'r> { } } } - impl<'r> molecule::prelude::Reader<'r> for ToCKBCellDataReader<'r> { type Entity = ToCKBCellData; const NAME: &'static str = "ToCKBCellDataReader"; @@ -1241,7 +1190,6 @@ impl<'r> molecule::prelude::Reader<'r> for ToCKBCellDataReader<'r> { Ok(()) } } - #[derive(Debug, Default)] pub struct ToCKBCellDataBuilder { pub(crate) status: Byte, @@ -1254,7 +1202,6 @@ pub struct ToCKBCellDataBuilder { pub(crate) redeemer_lockscript_hash: Byte32, pub(crate) liquidation_trigger_lockscript_hash: Byte32, } - impl ToCKBCellDataBuilder { pub const FIELD_COUNT: usize = 9; pub fn status(mut self, v: Byte) -> Self { @@ -1294,7 +1241,6 @@ impl ToCKBCellDataBuilder { self } } - impl molecule::prelude::Builder for ToCKBCellDataBuilder { type Entity = ToCKBCellData; const NAME: &'static str = "ToCKBCellDataBuilder"; @@ -1353,3 +1299,279 @@ impl molecule::prelude::Builder for ToCKBCellDataBuilder { ToCKBCellData::new_unchecked(inner.into()) } } +#[derive(Clone)] +pub struct MintXTWitness(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for MintXTWitness { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for MintXTWitness { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for MintXTWitness { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "spv_proof", self.spv_proof())?; + write!( + f, + ", {}: {}", + "cell_dep_index_list", + self.cell_dep_index_list() + )?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl ::core::default::Default for MintXTWitness { + fn default() -> Self { + let v: Vec = vec![ + 20, 0, 0, 0, 12, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ]; + MintXTWitness::new_unchecked(v.into()) + } +} +impl MintXTWitness { + pub const FIELD_COUNT: usize = 2; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn spv_proof(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } + pub fn cell_dep_index_list(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[12..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } else { + Bytes::new_unchecked(self.0.slice(start..)) + } + } + pub fn as_reader<'r>(&'r self) -> MintXTWitnessReader<'r> { + MintXTWitnessReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for MintXTWitness { + type Builder = MintXTWitnessBuilder; + const NAME: &'static str = "MintXTWitness"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + MintXTWitness(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + MintXTWitnessReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + MintXTWitnessReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder() + .spv_proof(self.spv_proof()) + .cell_dep_index_list(self.cell_dep_index_list()) + } +} +#[derive(Clone, Copy)] +pub struct MintXTWitnessReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for MintXTWitnessReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for MintXTWitnessReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for MintXTWitnessReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "spv_proof", self.spv_proof())?; + write!( + f, + ", {}: {}", + "cell_dep_index_list", + self.cell_dep_index_list() + )?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl<'r> MintXTWitnessReader<'r> { + pub const FIELD_COUNT: usize = 2; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn spv_proof(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn cell_dep_index_list(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[12..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } else { + BytesReader::new_unchecked(&self.as_slice()[start..]) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for MintXTWitnessReader<'r> { + type Entity = MintXTWitness; + const NAME: &'static str = "MintXTWitnessReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + MintXTWitnessReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let total_size = molecule::unpack_number(slice) as usize; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + if slice_len == molecule::NUMBER_SIZE && Self::FIELD_COUNT == 0 { + return Ok(()); + } + if slice_len < molecule::NUMBER_SIZE * 2 { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); + } + let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; + if offset_first % 4 != 0 || offset_first < molecule::NUMBER_SIZE * 2 { + return ve!(Self, OffsetsNotMatch); + } + let field_count = offset_first / 4 - 1; + if field_count < Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + } else if !compatible && field_count > Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + }; + let header_size = molecule::NUMBER_SIZE * (field_count + 1); + if slice_len < header_size { + return ve!(Self, HeaderIsBroken, header_size, slice_len); + } + let mut offsets: Vec = slice[molecule::NUMBER_SIZE..] + .chunks(molecule::NUMBER_SIZE) + .take(field_count) + .map(|x| molecule::unpack_number(x) as usize) + .collect(); + offsets.push(total_size); + if offsets.windows(2).any(|i| i[0] > i[1]) { + return ve!(Self, OffsetsNotMatch); + } + BytesReader::verify(&slice[offsets[0]..offsets[1]], compatible)?; + BytesReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct MintXTWitnessBuilder { + pub(crate) spv_proof: Bytes, + pub(crate) cell_dep_index_list: Bytes, +} +impl MintXTWitnessBuilder { + pub const FIELD_COUNT: usize = 2; + pub fn spv_proof(mut self, v: Bytes) -> Self { + self.spv_proof = v; + self + } + pub fn cell_dep_index_list(mut self, v: Bytes) -> Self { + self.cell_dep_index_list = v; + self + } +} +impl molecule::prelude::Builder for MintXTWitnessBuilder { + type Entity = MintXTWitness; + const NAME: &'static str = "MintXTWitnessBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) + + self.spv_proof.as_slice().len() + + self.cell_dep_index_list.as_slice().len() + } + fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { + let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); + let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); + offsets.push(total_size); + total_size += self.spv_proof.as_slice().len(); + offsets.push(total_size); + total_size += self.cell_dep_index_list.as_slice().len(); + writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; + for offset in offsets.into_iter() { + writer.write_all(&molecule::pack_number(offset as molecule::Number))?; + } + writer.write_all(self.spv_proof.as_slice())?; + writer.write_all(self.cell_dep_index_list.as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + MintXTWitness::new_unchecked(inner.into()) + } +} From 3857bd3c87abf18ab775a591985773c65c67c357 Mon Sep 17 00:00:00 2001 From: huwenchao Date: Thu, 20 Aug 2020 00:36:57 +0800 Subject: [PATCH 03/45] refactor: use int_enum crate replace template code --- contracts/toCKB-typescript/Cargo.lock | 83 ++++++++++++++++++ contracts/toCKB-typescript/Cargo.toml | 1 + .../toCKB-typescript/src/utils/types/error.rs | 7 ++ .../src/utils/types/toCKB_cell.rs | 86 ++++++------------- 4 files changed, 115 insertions(+), 62 deletions(-) diff --git a/contracts/toCKB-typescript/Cargo.lock b/contracts/toCKB-typescript/Cargo.lock index 71c96cf..5aa23ff 100644 --- a/contracts/toCKB-typescript/Cargo.lock +++ b/contracts/toCKB-typescript/Cargo.lock @@ -48,6 +48,29 @@ dependencies = [ "ckb-standalone-types", ] +[[package]] +name = "int-enum" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b1428b2b1abe959e6eedb0a17d0ab12f6ba20e1106cc29fc4874e3ba393c177" +dependencies = [ + "cfg-if", + "int-enum-impl", +] + +[[package]] +name = "int-enum-impl" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2c3cecaad8ca1a5020843500c696de2b9a07b63b624ddeef91f85f9bafb3671" +dependencies = [ + "cfg-if", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "molecule" version = "0.6.0" @@ -57,10 +80,70 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "proc-macro-crate" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" +dependencies = [ + "toml", +] + +[[package]] +name = "proc-macro2" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04f5f085b5d71e2188cb8271e5da0161ad52c3f227a661a3c135fdf28e258b12" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "serde" +version = "1.0.115" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e54c9a88f2da7238af84b5101443f0c0d0a3bbdc455e34a5c9497b1903ed55d5" + +[[package]] +name = "syn" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e69abc24912995b3038597a7a593be5053eb0fb44f3cc5beec0deb421790c1f4" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + [[package]] name = "toCKB-typescript" version = "0.1.0" dependencies = [ "ckb-std", + "int-enum", "molecule", ] + +[[package]] +name = "toml" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a" +dependencies = [ + "serde", +] + +[[package]] +name = "unicode-xid" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" diff --git a/contracts/toCKB-typescript/Cargo.toml b/contracts/toCKB-typescript/Cargo.toml index 8490868..cd44a88 100644 --- a/contracts/toCKB-typescript/Cargo.toml +++ b/contracts/toCKB-typescript/Cargo.toml @@ -8,6 +8,7 @@ edition = "2018" [dependencies] ckb-std = "0.6.0" molecule = { version = "=0.6.0", default-features = false } +int-enum = { version = "0.4", default-features = false } [profile.release] overflow-checks = true diff --git a/contracts/toCKB-typescript/src/utils/types/error.rs b/contracts/toCKB-typescript/src/utils/types/error.rs index 433ab7c..237d4e9 100644 --- a/contracts/toCKB-typescript/src/utils/types/error.rs +++ b/contracts/toCKB-typescript/src/utils/types/error.rs @@ -1,4 +1,5 @@ use ckb_std::error::SysError; +use int_enum::{IntEnum, IntEnumError}; #[repr(i8)] pub enum Error { @@ -25,3 +26,9 @@ impl From for Error { } } } + +impl From> for Error { + fn from(_err: IntEnumError) -> Self { + Error::Encoding + } +} diff --git a/contracts/toCKB-typescript/src/utils/types/toCKB_cell.rs b/contracts/toCKB-typescript/src/utils/types/toCKB_cell.rs index 310e7e3..cfeaa2a 100644 --- a/contracts/toCKB-typescript/src/utils/types/toCKB_cell.rs +++ b/contracts/toCKB-typescript/src/utils/types/toCKB_cell.rs @@ -2,6 +2,7 @@ use super::error::Error; use super::generated::toCKB_cell_data::ToCKBCellDataReader; use ckb_std::ckb_types::bytes::Bytes; use core::result::Result; +use int_enum::IntEnum; use molecule::prelude::*; pub struct ToCKBCellDataView { @@ -20,8 +21,8 @@ impl ToCKBCellDataView { pub fn from_slice(slice: &[u8]) -> Result { ToCKBCellDataReader::verify(slice, false).map_err(|_| Error::Encoding)?; let data_reader = ToCKBCellDataReader::new_unchecked(slice); - let status = ToCKBStatus::from_byte(data_reader.status().to_entity())?; - let kind = XChainKind::from_byte(data_reader.kind().to_entity())?; + let status = ToCKBStatus::from_int(data_reader.status().to_entity().into())?; + let kind = XChainKind::from_int(data_reader.kind().to_entity().into())?; let lot_size = data_reader.lot_size().as_slice()[0]; let user_lockscript_hash = data_reader.user_lockscript_hash().to_entity().as_bytes(); let x_lock_address = data_reader.x_lock_address().to_entity().as_bytes(); @@ -50,12 +51,7 @@ impl ToCKBCellDataView { pub fn get_btc_lot_size(&self) -> Result { if let XChainKind::Btc = self.kind { - match self.lot_size { - 1 => Ok(BtcLotSize::Quarter), - 2 => Ok(BtcLotSize::Half), - 3 => Ok(BtcLotSize::Single), - _ => Err(Error::Encoding), - } + BtcLotSize::from_int(self.lot_size).map_err(|_e| Error::Encoding) } else { Err(Error::XChainMismatch) } @@ -63,15 +59,7 @@ impl ToCKBCellDataView { pub fn get_eth_lot_size(&self) -> Result { if let XChainKind::Eth = self.kind { - match self.lot_size { - 1 => Ok(EthLotSize::Quarter), - 2 => Ok(EthLotSize::Half), - 3 => Ok(EthLotSize::Single), - 4 => Ok(EthLotSize::Two), - 5 => Ok(EthLotSize::Three), - 6 => Ok(EthLotSize::Four), - _ => Err(Error::Encoding), - } + EthLotSize::from_int(self.lot_size).map_err(|_e| Error::Encoding) } else { Err(Error::XChainMismatch) } @@ -79,66 +67,40 @@ impl ToCKBCellDataView { } #[repr(u8)] +#[derive(Clone, Copy, IntEnum)] pub enum ToCKBStatus { Initial = 1, - Bonding, - Warranty, - Redeeming, - LiquidationTimeout, - LiquidationUndercollateral, - LiquidationFaultyWhenWarranty, - LiquidationFaultyWhenRedeeming, -} - -impl ToCKBStatus { - pub fn from_byte(b: Byte) -> Result { - let num = b.as_slice()[0]; - use ToCKBStatus::*; - match num { - 1 => Ok(Initial), - 2 => Ok(Bonding), - 3 => Ok(Warranty), - 4 => Ok(Redeeming), - 5 => Ok(LiquidationTimeout), - 6 => Ok(LiquidationUndercollateral), - 7 => Ok(LiquidationFaultyWhenWarranty), - 8 => Ok(LiquidationFaultyWhenRedeeming), - _ => Err(Error::Encoding), - } - } + Bonding = 2, + Warranty = 3, + Redeeming = 4, + LiquidationTimeout = 5, + LiquidationUndercollateral = 6, + LiquidationFaultyWhenWarranty = 7, + LiquidationFaultyWhenRedeeming = 8, } #[repr(u8)] +#[derive(Clone, Copy, IntEnum)] pub enum XChainKind { Btc = 1, - Eth, -} - -impl XChainKind { - pub fn from_byte(b: Byte) -> Result { - let num = b.as_slice()[0]; - use XChainKind::*; - match num { - 1 => Ok(Btc), - 2 => Ok(Eth), - _ => Err(Error::Encoding), - } - } + Eth = 2, } #[repr(u8)] +#[derive(Clone, Copy, IntEnum)] pub enum BtcLotSize { Quarter = 1, - Half, - Single, + Half = 2, + Single = 3, } #[repr(u8)] +#[derive(Clone, Copy, IntEnum)] pub enum EthLotSize { Quarter = 1, - Half, - Single, - Two, - Three, - Four, + Half = 2, + Single = 3, + Two = 4, + Three = 5, + Four = 6, } From bde44bd66c00194ec9f2266f70b76761a598d807 Mon Sep 17 00:00:00 2001 From: huwenchao Date: Fri, 21 Aug 2020 00:53:51 +0800 Subject: [PATCH 04/45] feat(MintXT): finish main logics --- contracts/toCKB-typescript/Cargo.lock | 187 ++ contracts/toCKB-typescript/Cargo.toml | 2 + .../src/switch/mint_xt/mod.rs | 228 ++- contracts/toCKB-typescript/src/switch/mod.rs | 9 +- .../toCKB-typescript/src/utils/config.rs | 3 + .../toCKB-typescript/src/utils/types/error.rs | 18 + .../utils/types/generated/toCKB_cell_data.rs | 1624 ++++++++++++++--- .../toCKB-typescript/src/utils/types/mod.rs | 1 + .../utils/types/schemas/toCKB_cell_data.mol | 19 + 9 files changed, 1838 insertions(+), 253 deletions(-) diff --git a/contracts/toCKB-typescript/Cargo.lock b/contracts/toCKB-typescript/Cargo.lock index 5aa23ff..54d25a0 100644 --- a/contracts/toCKB-typescript/Cargo.lock +++ b/contracts/toCKB-typescript/Cargo.lock @@ -1,11 +1,61 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "autocfg" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" + +[[package]] +name = "bitcoin-spv" +version = "4.0.1" +source = "git+https://github.com/huwenchao/bitcoin-spv.git?branch=rust-no-std#dc9479d07cf42c1eef97c7d7daf5565c270b6429" +dependencies = [ + "num", + "num-bigint", + "ripemd160", + "sha2", +] + +[[package]] +name = "block-buffer" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +dependencies = [ + "block-padding", + "byte-tools", + "byteorder", + "generic-array", +] + +[[package]] +name = "block-padding" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" +dependencies = [ + "byte-tools", +] + [[package]] name = "buddy-alloc" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efba9eaa9fdf9fddf408904e3dc3dc414411053ef48c06edd3aac53d2d919e0e" +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" + +[[package]] +name = "byteorder" +version = "1.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" + [[package]] name = "cc" version = "1.0.58" @@ -48,6 +98,30 @@ dependencies = [ "ckb-standalone-types", ] +[[package]] +name = "digest" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +dependencies = [ + "generic-array", +] + +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" + +[[package]] +name = "generic-array" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" +dependencies = [ + "typenum", +] + [[package]] name = "int-enum" version = "0.4.0" @@ -80,6 +154,88 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "num" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab3e176191bc4faad357e3122c4747aa098ac880e88b168f106386128736cf4a" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7f3fc75e3697059fb1bc465e3d8cca6cf92f56854f201158b3f9c77d5a3cfa0" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05ad05bd8977050b171b3f6b48175fea6e0565b7981059b486075e1026a9fb5" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6e6b7c748f995c4c29c5f5ae0248536e04a5739927c74ec0fa564805094b9f" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5b4d7360f362cfb50dde8143501e6940b22f644be75a4cc90b2d81968908138" +dependencies = [ + "autocfg", + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611" +dependencies = [ + "autocfg", +] + +[[package]] +name = "opaque-debug" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" + [[package]] name = "proc-macro-crate" version = "0.1.5" @@ -107,12 +263,35 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "ripemd160" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad5112e0dbbb87577bfbc56c42450235e3012ce336e29c5befd7807bd626da4a" +dependencies = [ + "block-buffer", + "digest", + "opaque-debug", +] + [[package]] name = "serde" version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e54c9a88f2da7238af84b5101443f0c0d0a3bbdc455e34a5c9497b1903ed55d5" +[[package]] +name = "sha2" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" +dependencies = [ + "block-buffer", + "digest", + "fake-simd", + "opaque-debug", +] + [[package]] name = "syn" version = "1.0.38" @@ -128,9 +307,11 @@ dependencies = [ name = "toCKB-typescript" version = "0.1.0" dependencies = [ + "bitcoin-spv", "ckb-std", "int-enum", "molecule", + "num", ] [[package]] @@ -142,6 +323,12 @@ dependencies = [ "serde", ] +[[package]] +name = "typenum" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" + [[package]] name = "unicode-xid" version = "0.2.1" diff --git a/contracts/toCKB-typescript/Cargo.toml b/contracts/toCKB-typescript/Cargo.toml index cd44a88..aa24d4f 100644 --- a/contracts/toCKB-typescript/Cargo.toml +++ b/contracts/toCKB-typescript/Cargo.toml @@ -9,6 +9,8 @@ edition = "2018" ckb-std = "0.6.0" molecule = { version = "=0.6.0", default-features = false } int-enum = { version = "0.4", default-features = false } +bitcoin-spv = { git = "https://github.com/huwenchao/bitcoin-spv.git", branch = "rust-no-std", default-features = false } +num = { version = "0.3", default-features = false, features = ["alloc"] } [profile.release] overflow-checks = true diff --git a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs index 13da758..275b7e6 100644 --- a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs +++ b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs @@ -1,10 +1,30 @@ use crate::switch::ToCKBCellDataTuple; -use crate::utils::types::Error; +use crate::utils::config::{SIGNER_FEE_RATE, TX_PROOF_DIFFICULTY_FACTOR}; +use crate::utils::types::{ + toCKB_cell_data::{BTCDifficultyReader, BTCSPVProofReader, MintXTWitnessReader}, + BtcLotSize, Error, ToCKBCellDataView, XChainKind, +}; +use bitcoin_spv::{ + btcspv, + types::{HeaderArray, MerkleArray, PayloadType, Vin, Vout}, + validatespv, +}; +use ckb_std::{ + ckb_constants::Source, + debug, + error::SysError, + high_level::{ + load_cell_data, load_cell_lock_hash, load_cell_type_hash, load_witness_args, QueryIter, + }, +}; use core::result::Result; +use molecule::prelude::{Entity, Reader}; +use num::bigint::BigUint; -fn verify_data(toCKB_data_tuple: &ToCKBCellDataTuple) -> Result<(), Error> { - let input_data = toCKB_data_tuple.0.as_ref().expect("should not happen"); - let output_data = toCKB_data_tuple.1.as_ref().expect("should not happen"); +fn verify_data( + input_data: &ToCKBCellDataView, + output_data: &ToCKBCellDataView, +) -> Result<(), Error> { if input_data.kind != output_data.kind || input_data.signer_lockscript_hash.as_ref() != output_data.signer_lockscript_hash.as_ref() || input_data.user_lockscript_hash.as_ref() != output_data.user_lockscript_hash.as_ref() @@ -15,7 +35,205 @@ fn verify_data(toCKB_data_tuple: &ToCKBCellDataTuple) -> Result<(), Error> { Ok(()) } +/// ensure transfer happen on XChain by verifying the spv proof +fn verify_witness(data: &ToCKBCellDataView) -> Result<(), Error> { + let witness_args = load_witness_args(0, Source::GroupInput)?.input_type(); + if witness_args.is_none() { + return Err(Error::InvalidWitness); + } + let witness_args = witness_args.to_opt().unwrap().as_bytes(); + if MintXTWitnessReader::verify(&witness_args, false).is_err() { + return Err(Error::InvalidWitness); + } + let witness = MintXTWitnessReader::new_unchecked(&witness_args); + let proof = witness.spv_proof().raw_data(); + let cell_dep_index_list = witness.cell_dep_index_list().raw_data(); + match data.kind { + XChainKind::Btc => verify_btc_witness(data, proof, cell_dep_index_list), + XChainKind::Eth => todo!(), + } +} + +fn verify_btc_witness( + data: &ToCKBCellDataView, + proof: &[u8], + cell_dep_index_list: &[u8], +) -> Result<(), Error> { + // parse difficulty + if cell_dep_index_list.len() != 1 { + return Err(Error::InvalidWitness); + } + let dep_data = load_cell_data(cell_dep_index_list[0].into(), Source::CellDep)?; + debug!("dep data is {:?}", &dep_data); + if BTCDifficultyReader::verify(&dep_data, false).is_err() { + return Err(Error::DifficultyDataInvalid); + } + let difficulty_reader = BTCDifficultyReader::new_unchecked(&dep_data); + // parse witness + if BTCSPVProofReader::verify(proof, false).is_err() { + return Err(Error::InvalidWitness); + } + let proof_reader = BTCSPVProofReader::new_unchecked(proof); + // verify btc spv + verify_btc_spv(proof_reader, difficulty_reader)?; + // verify transfer amount, to matches + let funding_output_index: u8 = proof_reader.funding_output_index().into(); + let vout = Vout::new(proof_reader.vout().raw_data())?; + let tx_out = vout.index(funding_output_index.into())?; + if let PayloadType::WPKH(wpkh) = tx_out.script_pubkey().payload()? { + // TODO: should calc and compare base58 encoding addr here + if wpkh != data.x_lock_address.as_ref() { + return Err(Error::WrongFundingAddr); + } + } else { + return Err(Error::UnsupportedFundingType); + } + let lot_size = data.get_btc_lot_size()?; + let value = tx_out.value(); + if btc_lot_size_to_u64(lot_size) != value { + return Err(Error::FundingNotEnough); + } + Ok(()) +} + +fn btc_lot_size_to_u64(lot_size: BtcLotSize) -> u64 { + match lot_size { + BtcLotSize::Single => 100_000_000, + BtcLotSize::Half => 50_000_000, + BtcLotSize::Quarter => 25_000_000, + } +} + +fn verify_btc_spv(proof: BTCSPVProofReader, difficulty: BTCDifficultyReader) -> Result<(), Error> { + if !btcspv::validate_vin(proof.vin().raw_data()) { + return Err(Error::SpvProofInvalid); + } + if !btcspv::validate_vout(proof.vout().raw_data()) { + return Err(Error::SpvProofInvalid); + } + let mut ver = [0u8; 4]; + ver.copy_from_slice(proof.version().raw_data()); + let mut lock = [0u8; 4]; + lock.copy_from_slice(proof.locktime().raw_data()); + let tx_id = validatespv::calculate_txid( + &ver, + &Vin::new(proof.vin().raw_data())?, + &Vout::new(proof.vout().raw_data())?, + &lock, + ); + if tx_id.as_ref() != proof.tx_id().raw_data() { + return Err(Error::WrongTxId); + } + + // verify difficulty + let raw_headers = proof.headers(); + let headers = HeaderArray::new(raw_headers.raw_data())?; + let observed_diff = validatespv::validate_header_chain(&headers, false)?; + let previous_diff = BigUint::from_bytes_be(difficulty.previous().raw_data()); + let current_diff = BigUint::from_bytes_be(difficulty.current().raw_data()); + let first_header_diff = headers.index(0).difficulty(); + + let req_diff = if first_header_diff == current_diff { + current_diff + } else if first_header_diff == previous_diff { + previous_diff + } else { + return Err(Error::NotAtCurrentOrPreviousDifficulty); + }; + + if observed_diff < req_diff * TX_PROOF_DIFFICULTY_FACTOR { + return Err(Error::InsufficientDifficulty); + } + + // verify tx + let header = headers.index(headers.len()); + let mut idx = [0u8; 8]; + idx.copy_from_slice(proof.index().raw_data()); + if !validatespv::prove( + tx_id, + header.tx_root(), + &MerkleArray::new(proof.intermediate_nodes().raw_data())?, + u64::from_le_bytes(idx), + ) { + return Err(Error::BadMerkleProof); + } + + Ok(()) +} + +fn verify_xt_issue(data: &ToCKBCellDataView) -> Result<(), Error> { + match data.kind { + XChainKind::Btc => verify_btc_xt_issue(data), + XChainKind::Eth => todo!(), + } +} + +fn verify_btc_xt_issue(data: &ToCKBCellDataView) -> Result<(), Error> { + // todo: change to btc_xt type hash + let btc_xt_type_hash = [0u8; 32]; + let input_xt_num = QueryIter::new(load_cell_type_hash, Source::Input) + .map(|hash_opt| hash_opt.unwrap_or_default()) + .filter(|hash| hash == &btc_xt_type_hash) + .count(); + if input_xt_num != 0 { + return Err(Error::InvalidXTInInput); + } + let mut output_index = 0; + let mut user_checked = false; + let mut signer_checked = false; + let xt_amount = btc_lot_size_to_u64(data.get_btc_lot_size()?); + loop { + let type_hash_res = load_cell_type_hash(output_index, Source::Output); + match type_hash_res { + Err(SysError::IndexOutOfBound) => break, + Err(err) => { + debug!("iter output error {:?}", err); + panic!("iter output return an error") + } + Ok(type_hash) => { + if !(type_hash.is_some() && type_hash.unwrap() == btc_xt_type_hash) { + continue; + } + let lock_hash = load_cell_lock_hash(output_index, Source::Output)?; + let cell_data = load_cell_data(output_index, Source::Output)?; + let mut amount_vec = [0u8; 8]; + amount_vec.copy_from_slice(&cell_data); + let token_amount = u64::from_le_bytes(amount_vec); + if lock_hash.as_ref() == data.user_lockscript_hash.as_ref() { + if user_checked { + return Err(Error::InvalidXTMint); + } + if token_amount != xt_amount - xt_amount * SIGNER_FEE_RATE.0 / SIGNER_FEE_RATE.1 + { + return Err(Error::InvalidXTMint); + } + user_checked = true; + } else if lock_hash.as_ref() == data.signer_lockscript_hash.as_ref() { + if signer_checked { + return Err(Error::InvalidXTMint); + } + if token_amount != xt_amount * SIGNER_FEE_RATE.0 / SIGNER_FEE_RATE.1 { + return Err(Error::InvalidXTMint); + } + signer_checked = true; + } else { + return Err(Error::InvalidXTMint); + } + output_index += 1; + } + } + } + if !(user_checked && signer_checked) { + return Err(Error::InvalidXTMint); + } + Ok(()) +} + pub fn verify(toCKB_data_tuple: &ToCKBCellDataTuple) -> Result<(), Error> { - verify_data(toCKB_data_tuple)?; + let input_data = toCKB_data_tuple.0.as_ref().expect("should not happen"); + let output_data = toCKB_data_tuple.1.as_ref().expect("should not happen"); + verify_data(input_data, output_data)?; + verify_witness(input_data)?; + verify_xt_issue(input_data)?; Ok(()) } diff --git a/contracts/toCKB-typescript/src/switch/mod.rs b/contracts/toCKB-typescript/src/switch/mod.rs index 72dd635..577749f 100644 --- a/contracts/toCKB-typescript/src/switch/mod.rs +++ b/contracts/toCKB-typescript/src/switch/mod.rs @@ -88,10 +88,13 @@ fn get_generation_tx_type(data: &ToCKBCellDataView) -> Result { } fn get_transformation_tx_type( - _input_data: &ToCKBCellDataView, - _output_data: &ToCKBCellDataView, + input_data: &ToCKBCellDataView, + output_data: &ToCKBCellDataView, ) -> Result { - unimplemented!() + match (input_data.status, output_data.status) { + (ToCKBStatus::Bonding, ToCKBStatus::Warranty) => Ok(TxType::MintXT), + _ => Err(Error::TxInvalid), + } } fn get_deletion_tx_type(_data: &ToCKBCellDataView) -> Result { diff --git a/contracts/toCKB-typescript/src/utils/config.rs b/contracts/toCKB-typescript/src/utils/config.rs index 18ef431..0d31150 100644 --- a/contracts/toCKB-typescript/src/utils/config.rs +++ b/contracts/toCKB-typescript/src/utils/config.rs @@ -1 +1,4 @@ pub const PLEDGE: u64 = 10000; +pub const TX_PROOF_DIFFICULTY_FACTOR: u8 = 6; +// default value is 2/1000 +pub const SIGNER_FEE_RATE: (u64, u64) = (2, 1000); diff --git a/contracts/toCKB-typescript/src/utils/types/error.rs b/contracts/toCKB-typescript/src/utils/types/error.rs index 287a74d..e7852b8 100644 --- a/contracts/toCKB-typescript/src/utils/types/error.rs +++ b/contracts/toCKB-typescript/src/utils/types/error.rs @@ -14,6 +14,18 @@ pub enum Error { PledgeInvalid, // MintXT Error InvalidDataChange, + InvalidWitness, + DifficultyDataInvalid, + SpvProofInvalid, + InsufficientDifficulty, + BadMerkleProof, + NotAtCurrentOrPreviousDifficulty, + WrongTxId, + FundingNotEnough, + UnsupportedFundingType, + WrongFundingAddr, + InvalidXTInInput, + InvalidXTMint, } impl From for Error { @@ -34,3 +46,9 @@ impl From> for Error { Error::Encoding } } + +impl From for Error { + fn from(_err: bitcoin_spv::types::SPVError) -> Self { + Error::SpvProofInvalid + } +} diff --git a/contracts/toCKB-typescript/src/utils/types/generated/toCKB_cell_data.rs b/contracts/toCKB-typescript/src/utils/types/generated/toCKB_cell_data.rs index 5ee6d4a..006b6dc 100644 --- a/contracts/toCKB-typescript/src/utils/types/generated/toCKB_cell_data.rs +++ b/contracts/toCKB-typescript/src/utils/types/generated/toCKB_cell_data.rs @@ -813,6 +813,410 @@ impl ::core::iter::IntoIterator for Bytes { } } #[derive(Clone)] +pub struct Byte4(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for Byte4 { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for Byte4 { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for Byte4 { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + let raw_data = hex_string(&self.raw_data()); + write!(f, "{}(0x{})", Self::NAME, raw_data) + } +} +impl ::core::default::Default for Byte4 { + fn default() -> Self { + let v: Vec = vec![0, 0, 0, 0]; + Byte4::new_unchecked(v.into()) + } +} +impl Byte4 { + pub const TOTAL_SIZE: usize = 4; + pub const ITEM_SIZE: usize = 1; + pub const ITEM_COUNT: usize = 4; + pub fn nth0(&self) -> Byte { + Byte::new_unchecked(self.0.slice(0..1)) + } + pub fn nth1(&self) -> Byte { + Byte::new_unchecked(self.0.slice(1..2)) + } + pub fn nth2(&self) -> Byte { + Byte::new_unchecked(self.0.slice(2..3)) + } + pub fn nth3(&self) -> Byte { + Byte::new_unchecked(self.0.slice(3..4)) + } + pub fn raw_data(&self) -> molecule::bytes::Bytes { + self.as_bytes() + } + pub fn as_reader<'r>(&'r self) -> Byte4Reader<'r> { + Byte4Reader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for Byte4 { + type Builder = Byte4Builder; + const NAME: &'static str = "Byte4"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + Byte4(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + Byte4Reader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + Byte4Reader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder().set([self.nth0(), self.nth1(), self.nth2(), self.nth3()]) + } +} +#[derive(Clone, Copy)] +pub struct Byte4Reader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for Byte4Reader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for Byte4Reader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for Byte4Reader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + let raw_data = hex_string(&self.raw_data()); + write!(f, "{}(0x{})", Self::NAME, raw_data) + } +} +impl<'r> Byte4Reader<'r> { + pub const TOTAL_SIZE: usize = 4; + pub const ITEM_SIZE: usize = 1; + pub const ITEM_COUNT: usize = 4; + pub fn nth0(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[0..1]) + } + pub fn nth1(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[1..2]) + } + pub fn nth2(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[2..3]) + } + pub fn nth3(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[3..4]) + } + pub fn raw_data(&self) -> &'r [u8] { + self.as_slice() + } +} +impl<'r> molecule::prelude::Reader<'r> for Byte4Reader<'r> { + type Entity = Byte4; + const NAME: &'static str = "Byte4Reader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + Byte4Reader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], _compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len != Self::TOTAL_SIZE { + return ve!(Self, TotalSizeNotMatch, Self::TOTAL_SIZE, slice_len); + } + Ok(()) + } +} +pub struct Byte4Builder(pub(crate) [Byte; 4]); +impl ::core::fmt::Debug for Byte4Builder { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:?})", Self::NAME, &self.0[..]) + } +} +impl ::core::default::Default for Byte4Builder { + fn default() -> Self { + Byte4Builder([ + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + ]) + } +} +impl Byte4Builder { + pub const TOTAL_SIZE: usize = 4; + pub const ITEM_SIZE: usize = 1; + pub const ITEM_COUNT: usize = 4; + pub fn set(mut self, v: [Byte; 4]) -> Self { + self.0 = v; + self + } + pub fn nth0(mut self, v: Byte) -> Self { + self.0[0] = v; + self + } + pub fn nth1(mut self, v: Byte) -> Self { + self.0[1] = v; + self + } + pub fn nth2(mut self, v: Byte) -> Self { + self.0[2] = v; + self + } + pub fn nth3(mut self, v: Byte) -> Self { + self.0[3] = v; + self + } +} +impl molecule::prelude::Builder for Byte4Builder { + type Entity = Byte4; + const NAME: &'static str = "Byte4Builder"; + fn expected_length(&self) -> usize { + Self::TOTAL_SIZE + } + fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { + writer.write_all(self.0[0].as_slice())?; + writer.write_all(self.0[1].as_slice())?; + writer.write_all(self.0[2].as_slice())?; + writer.write_all(self.0[3].as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + Byte4::new_unchecked(inner.into()) + } +} +#[derive(Clone)] +pub struct Uint32(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for Uint32 { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for Uint32 { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for Uint32 { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + let raw_data = hex_string(&self.raw_data()); + write!(f, "{}(0x{})", Self::NAME, raw_data) + } +} +impl ::core::default::Default for Uint32 { + fn default() -> Self { + let v: Vec = vec![0, 0, 0, 0]; + Uint32::new_unchecked(v.into()) + } +} +impl Uint32 { + pub const TOTAL_SIZE: usize = 4; + pub const ITEM_SIZE: usize = 1; + pub const ITEM_COUNT: usize = 4; + pub fn nth0(&self) -> Byte { + Byte::new_unchecked(self.0.slice(0..1)) + } + pub fn nth1(&self) -> Byte { + Byte::new_unchecked(self.0.slice(1..2)) + } + pub fn nth2(&self) -> Byte { + Byte::new_unchecked(self.0.slice(2..3)) + } + pub fn nth3(&self) -> Byte { + Byte::new_unchecked(self.0.slice(3..4)) + } + pub fn raw_data(&self) -> molecule::bytes::Bytes { + self.as_bytes() + } + pub fn as_reader<'r>(&'r self) -> Uint32Reader<'r> { + Uint32Reader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for Uint32 { + type Builder = Uint32Builder; + const NAME: &'static str = "Uint32"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + Uint32(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + Uint32Reader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + Uint32Reader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder().set([self.nth0(), self.nth1(), self.nth2(), self.nth3()]) + } +} +#[derive(Clone, Copy)] +pub struct Uint32Reader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for Uint32Reader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for Uint32Reader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for Uint32Reader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + let raw_data = hex_string(&self.raw_data()); + write!(f, "{}(0x{})", Self::NAME, raw_data) + } +} +impl<'r> Uint32Reader<'r> { + pub const TOTAL_SIZE: usize = 4; + pub const ITEM_SIZE: usize = 1; + pub const ITEM_COUNT: usize = 4; + pub fn nth0(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[0..1]) + } + pub fn nth1(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[1..2]) + } + pub fn nth2(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[2..3]) + } + pub fn nth3(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[3..4]) + } + pub fn raw_data(&self) -> &'r [u8] { + self.as_slice() + } +} +impl<'r> molecule::prelude::Reader<'r> for Uint32Reader<'r> { + type Entity = Uint32; + const NAME: &'static str = "Uint32Reader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + Uint32Reader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], _compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len != Self::TOTAL_SIZE { + return ve!(Self, TotalSizeNotMatch, Self::TOTAL_SIZE, slice_len); + } + Ok(()) + } +} +pub struct Uint32Builder(pub(crate) [Byte; 4]); +impl ::core::fmt::Debug for Uint32Builder { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:?})", Self::NAME, &self.0[..]) + } +} +impl ::core::default::Default for Uint32Builder { + fn default() -> Self { + Uint32Builder([ + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + ]) + } +} +impl Uint32Builder { + pub const TOTAL_SIZE: usize = 4; + pub const ITEM_SIZE: usize = 1; + pub const ITEM_COUNT: usize = 4; + pub fn set(mut self, v: [Byte; 4]) -> Self { + self.0 = v; + self + } + pub fn nth0(mut self, v: Byte) -> Self { + self.0[0] = v; + self + } + pub fn nth1(mut self, v: Byte) -> Self { + self.0[1] = v; + self + } + pub fn nth2(mut self, v: Byte) -> Self { + self.0[2] = v; + self + } + pub fn nth3(mut self, v: Byte) -> Self { + self.0[3] = v; + self + } +} +impl molecule::prelude::Builder for Uint32Builder { + type Entity = Uint32; + const NAME: &'static str = "Uint32Builder"; + fn expected_length(&self) -> usize { + Self::TOTAL_SIZE + } + fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { + writer.write_all(self.0[0].as_slice())?; + writer.write_all(self.0[1].as_slice())?; + writer.write_all(self.0[2].as_slice())?; + writer.write_all(self.0[3].as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + Uint32::new_unchecked(inner.into()) + } +} +#[derive(Clone)] pub struct ToCKBCellData(molecule::bytes::Bytes); impl ::core::fmt::LowerHex for ToCKBCellData { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { @@ -823,42 +1227,795 @@ impl ::core::fmt::LowerHex for ToCKBCellData { write!(f, "{}", hex_string(self.as_slice())) } } -impl ::core::fmt::Debug for ToCKBCellData { +impl ::core::fmt::Debug for ToCKBCellData { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for ToCKBCellData { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "status", self.status())?; + write!(f, ", {}: {}", "kind", self.kind())?; + write!(f, ", {}: {}", "lot_size", self.lot_size())?; + write!( + f, + ", {}: {}", + "user_lockscript_hash", + self.user_lockscript_hash() + )?; + write!(f, ", {}: {}", "x_lock_address", self.x_lock_address())?; + write!( + f, + ", {}: {}", + "signer_lockscript_hash", + self.signer_lockscript_hash() + )?; + write!(f, ", {}: {}", "x_unlock_address", self.x_unlock_address())?; + write!( + f, + ", {}: {}", + "redeemer_lockscript_hash", + self.redeemer_lockscript_hash() + )?; + write!( + f, + ", {}: {}", + "liquidation_trigger_lockscript_hash", + self.liquidation_trigger_lockscript_hash() + )?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl ::core::default::Default for ToCKBCellData { + fn default() -> Self { + let v: Vec = vec![ + 179, 0, 0, 0, 40, 0, 0, 0, 41, 0, 0, 0, 42, 0, 0, 0, 43, 0, 0, 0, 75, 0, 0, 0, 79, 0, + 0, 0, 111, 0, 0, 0, 115, 0, 0, 0, 147, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ]; + ToCKBCellData::new_unchecked(v.into()) + } +} +impl ToCKBCellData { + pub const FIELD_COUNT: usize = 9; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn status(&self) -> Byte { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + Byte::new_unchecked(self.0.slice(start..end)) + } + pub fn kind(&self) -> Byte { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + let end = molecule::unpack_number(&slice[12..]) as usize; + Byte::new_unchecked(self.0.slice(start..end)) + } + pub fn lot_size(&self) -> Byte { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[12..]) as usize; + let end = molecule::unpack_number(&slice[16..]) as usize; + Byte::new_unchecked(self.0.slice(start..end)) + } + pub fn user_lockscript_hash(&self) -> Byte32 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[16..]) as usize; + let end = molecule::unpack_number(&slice[20..]) as usize; + Byte32::new_unchecked(self.0.slice(start..end)) + } + pub fn x_lock_address(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[20..]) as usize; + let end = molecule::unpack_number(&slice[24..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } + pub fn signer_lockscript_hash(&self) -> Byte32 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[24..]) as usize; + let end = molecule::unpack_number(&slice[28..]) as usize; + Byte32::new_unchecked(self.0.slice(start..end)) + } + pub fn x_unlock_address(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[28..]) as usize; + let end = molecule::unpack_number(&slice[32..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } + pub fn redeemer_lockscript_hash(&self) -> Byte32 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[32..]) as usize; + let end = molecule::unpack_number(&slice[36..]) as usize; + Byte32::new_unchecked(self.0.slice(start..end)) + } + pub fn liquidation_trigger_lockscript_hash(&self) -> Byte32 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[36..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[40..]) as usize; + Byte32::new_unchecked(self.0.slice(start..end)) + } else { + Byte32::new_unchecked(self.0.slice(start..)) + } + } + pub fn as_reader<'r>(&'r self) -> ToCKBCellDataReader<'r> { + ToCKBCellDataReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for ToCKBCellData { + type Builder = ToCKBCellDataBuilder; + const NAME: &'static str = "ToCKBCellData"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + ToCKBCellData(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + ToCKBCellDataReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + ToCKBCellDataReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder() + .status(self.status()) + .kind(self.kind()) + .lot_size(self.lot_size()) + .user_lockscript_hash(self.user_lockscript_hash()) + .x_lock_address(self.x_lock_address()) + .signer_lockscript_hash(self.signer_lockscript_hash()) + .x_unlock_address(self.x_unlock_address()) + .redeemer_lockscript_hash(self.redeemer_lockscript_hash()) + .liquidation_trigger_lockscript_hash(self.liquidation_trigger_lockscript_hash()) + } +} +#[derive(Clone, Copy)] +pub struct ToCKBCellDataReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for ToCKBCellDataReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for ToCKBCellDataReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for ToCKBCellDataReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "status", self.status())?; + write!(f, ", {}: {}", "kind", self.kind())?; + write!(f, ", {}: {}", "lot_size", self.lot_size())?; + write!( + f, + ", {}: {}", + "user_lockscript_hash", + self.user_lockscript_hash() + )?; + write!(f, ", {}: {}", "x_lock_address", self.x_lock_address())?; + write!( + f, + ", {}: {}", + "signer_lockscript_hash", + self.signer_lockscript_hash() + )?; + write!(f, ", {}: {}", "x_unlock_address", self.x_unlock_address())?; + write!( + f, + ", {}: {}", + "redeemer_lockscript_hash", + self.redeemer_lockscript_hash() + )?; + write!( + f, + ", {}: {}", + "liquidation_trigger_lockscript_hash", + self.liquidation_trigger_lockscript_hash() + )?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl<'r> ToCKBCellDataReader<'r> { + pub const FIELD_COUNT: usize = 9; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn status(&self) -> ByteReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + ByteReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn kind(&self) -> ByteReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + let end = molecule::unpack_number(&slice[12..]) as usize; + ByteReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn lot_size(&self) -> ByteReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[12..]) as usize; + let end = molecule::unpack_number(&slice[16..]) as usize; + ByteReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn user_lockscript_hash(&self) -> Byte32Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[16..]) as usize; + let end = molecule::unpack_number(&slice[20..]) as usize; + Byte32Reader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn x_lock_address(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[20..]) as usize; + let end = molecule::unpack_number(&slice[24..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn signer_lockscript_hash(&self) -> Byte32Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[24..]) as usize; + let end = molecule::unpack_number(&slice[28..]) as usize; + Byte32Reader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn x_unlock_address(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[28..]) as usize; + let end = molecule::unpack_number(&slice[32..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn redeemer_lockscript_hash(&self) -> Byte32Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[32..]) as usize; + let end = molecule::unpack_number(&slice[36..]) as usize; + Byte32Reader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn liquidation_trigger_lockscript_hash(&self) -> Byte32Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[36..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[40..]) as usize; + Byte32Reader::new_unchecked(&self.as_slice()[start..end]) + } else { + Byte32Reader::new_unchecked(&self.as_slice()[start..]) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for ToCKBCellDataReader<'r> { + type Entity = ToCKBCellData; + const NAME: &'static str = "ToCKBCellDataReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + ToCKBCellDataReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let total_size = molecule::unpack_number(slice) as usize; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + if slice_len == molecule::NUMBER_SIZE && Self::FIELD_COUNT == 0 { + return Ok(()); + } + if slice_len < molecule::NUMBER_SIZE * 2 { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); + } + let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; + if offset_first % 4 != 0 || offset_first < molecule::NUMBER_SIZE * 2 { + return ve!(Self, OffsetsNotMatch); + } + let field_count = offset_first / 4 - 1; + if field_count < Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + } else if !compatible && field_count > Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + }; + let header_size = molecule::NUMBER_SIZE * (field_count + 1); + if slice_len < header_size { + return ve!(Self, HeaderIsBroken, header_size, slice_len); + } + let mut offsets: Vec = slice[molecule::NUMBER_SIZE..] + .chunks(molecule::NUMBER_SIZE) + .take(field_count) + .map(|x| molecule::unpack_number(x) as usize) + .collect(); + offsets.push(total_size); + if offsets.windows(2).any(|i| i[0] > i[1]) { + return ve!(Self, OffsetsNotMatch); + } + ByteReader::verify(&slice[offsets[0]..offsets[1]], compatible)?; + ByteReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; + ByteReader::verify(&slice[offsets[2]..offsets[3]], compatible)?; + Byte32Reader::verify(&slice[offsets[3]..offsets[4]], compatible)?; + BytesReader::verify(&slice[offsets[4]..offsets[5]], compatible)?; + Byte32Reader::verify(&slice[offsets[5]..offsets[6]], compatible)?; + BytesReader::verify(&slice[offsets[6]..offsets[7]], compatible)?; + Byte32Reader::verify(&slice[offsets[7]..offsets[8]], compatible)?; + Byte32Reader::verify(&slice[offsets[8]..offsets[9]], compatible)?; + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct ToCKBCellDataBuilder { + pub(crate) status: Byte, + pub(crate) kind: Byte, + pub(crate) lot_size: Byte, + pub(crate) user_lockscript_hash: Byte32, + pub(crate) x_lock_address: Bytes, + pub(crate) signer_lockscript_hash: Byte32, + pub(crate) x_unlock_address: Bytes, + pub(crate) redeemer_lockscript_hash: Byte32, + pub(crate) liquidation_trigger_lockscript_hash: Byte32, +} +impl ToCKBCellDataBuilder { + pub const FIELD_COUNT: usize = 9; + pub fn status(mut self, v: Byte) -> Self { + self.status = v; + self + } + pub fn kind(mut self, v: Byte) -> Self { + self.kind = v; + self + } + pub fn lot_size(mut self, v: Byte) -> Self { + self.lot_size = v; + self + } + pub fn user_lockscript_hash(mut self, v: Byte32) -> Self { + self.user_lockscript_hash = v; + self + } + pub fn x_lock_address(mut self, v: Bytes) -> Self { + self.x_lock_address = v; + self + } + pub fn signer_lockscript_hash(mut self, v: Byte32) -> Self { + self.signer_lockscript_hash = v; + self + } + pub fn x_unlock_address(mut self, v: Bytes) -> Self { + self.x_unlock_address = v; + self + } + pub fn redeemer_lockscript_hash(mut self, v: Byte32) -> Self { + self.redeemer_lockscript_hash = v; + self + } + pub fn liquidation_trigger_lockscript_hash(mut self, v: Byte32) -> Self { + self.liquidation_trigger_lockscript_hash = v; + self + } +} +impl molecule::prelude::Builder for ToCKBCellDataBuilder { + type Entity = ToCKBCellData; + const NAME: &'static str = "ToCKBCellDataBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) + + self.status.as_slice().len() + + self.kind.as_slice().len() + + self.lot_size.as_slice().len() + + self.user_lockscript_hash.as_slice().len() + + self.x_lock_address.as_slice().len() + + self.signer_lockscript_hash.as_slice().len() + + self.x_unlock_address.as_slice().len() + + self.redeemer_lockscript_hash.as_slice().len() + + self.liquidation_trigger_lockscript_hash.as_slice().len() + } + fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { + let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); + let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); + offsets.push(total_size); + total_size += self.status.as_slice().len(); + offsets.push(total_size); + total_size += self.kind.as_slice().len(); + offsets.push(total_size); + total_size += self.lot_size.as_slice().len(); + offsets.push(total_size); + total_size += self.user_lockscript_hash.as_slice().len(); + offsets.push(total_size); + total_size += self.x_lock_address.as_slice().len(); + offsets.push(total_size); + total_size += self.signer_lockscript_hash.as_slice().len(); + offsets.push(total_size); + total_size += self.x_unlock_address.as_slice().len(); + offsets.push(total_size); + total_size += self.redeemer_lockscript_hash.as_slice().len(); + offsets.push(total_size); + total_size += self.liquidation_trigger_lockscript_hash.as_slice().len(); + writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; + for offset in offsets.into_iter() { + writer.write_all(&molecule::pack_number(offset as molecule::Number))?; + } + writer.write_all(self.status.as_slice())?; + writer.write_all(self.kind.as_slice())?; + writer.write_all(self.lot_size.as_slice())?; + writer.write_all(self.user_lockscript_hash.as_slice())?; + writer.write_all(self.x_lock_address.as_slice())?; + writer.write_all(self.signer_lockscript_hash.as_slice())?; + writer.write_all(self.x_unlock_address.as_slice())?; + writer.write_all(self.redeemer_lockscript_hash.as_slice())?; + writer.write_all(self.liquidation_trigger_lockscript_hash.as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + ToCKBCellData::new_unchecked(inner.into()) + } +} +#[derive(Clone)] +pub struct MintXTWitness(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for MintXTWitness { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for MintXTWitness { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for MintXTWitness { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "spv_proof", self.spv_proof())?; + write!( + f, + ", {}: {}", + "cell_dep_index_list", + self.cell_dep_index_list() + )?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl ::core::default::Default for MintXTWitness { + fn default() -> Self { + let v: Vec = vec![ + 20, 0, 0, 0, 12, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ]; + MintXTWitness::new_unchecked(v.into()) + } +} +impl MintXTWitness { + pub const FIELD_COUNT: usize = 2; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn spv_proof(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } + pub fn cell_dep_index_list(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[12..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } else { + Bytes::new_unchecked(self.0.slice(start..)) + } + } + pub fn as_reader<'r>(&'r self) -> MintXTWitnessReader<'r> { + MintXTWitnessReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for MintXTWitness { + type Builder = MintXTWitnessBuilder; + const NAME: &'static str = "MintXTWitness"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + MintXTWitness(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + MintXTWitnessReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + MintXTWitnessReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder() + .spv_proof(self.spv_proof()) + .cell_dep_index_list(self.cell_dep_index_list()) + } +} +#[derive(Clone, Copy)] +pub struct MintXTWitnessReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for MintXTWitnessReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for MintXTWitnessReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for MintXTWitnessReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "spv_proof", self.spv_proof())?; + write!( + f, + ", {}: {}", + "cell_dep_index_list", + self.cell_dep_index_list() + )?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl<'r> MintXTWitnessReader<'r> { + pub const FIELD_COUNT: usize = 2; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn spv_proof(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn cell_dep_index_list(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[12..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } else { + BytesReader::new_unchecked(&self.as_slice()[start..]) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for MintXTWitnessReader<'r> { + type Entity = MintXTWitness; + const NAME: &'static str = "MintXTWitnessReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + MintXTWitnessReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let total_size = molecule::unpack_number(slice) as usize; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + if slice_len == molecule::NUMBER_SIZE && Self::FIELD_COUNT == 0 { + return Ok(()); + } + if slice_len < molecule::NUMBER_SIZE * 2 { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); + } + let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; + if offset_first % 4 != 0 || offset_first < molecule::NUMBER_SIZE * 2 { + return ve!(Self, OffsetsNotMatch); + } + let field_count = offset_first / 4 - 1; + if field_count < Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + } else if !compatible && field_count > Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + }; + let header_size = molecule::NUMBER_SIZE * (field_count + 1); + if slice_len < header_size { + return ve!(Self, HeaderIsBroken, header_size, slice_len); + } + let mut offsets: Vec = slice[molecule::NUMBER_SIZE..] + .chunks(molecule::NUMBER_SIZE) + .take(field_count) + .map(|x| molecule::unpack_number(x) as usize) + .collect(); + offsets.push(total_size); + if offsets.windows(2).any(|i| i[0] > i[1]) { + return ve!(Self, OffsetsNotMatch); + } + BytesReader::verify(&slice[offsets[0]..offsets[1]], compatible)?; + BytesReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct MintXTWitnessBuilder { + pub(crate) spv_proof: Bytes, + pub(crate) cell_dep_index_list: Bytes, +} +impl MintXTWitnessBuilder { + pub const FIELD_COUNT: usize = 2; + pub fn spv_proof(mut self, v: Bytes) -> Self { + self.spv_proof = v; + self + } + pub fn cell_dep_index_list(mut self, v: Bytes) -> Self { + self.cell_dep_index_list = v; + self + } +} +impl molecule::prelude::Builder for MintXTWitnessBuilder { + type Entity = MintXTWitness; + const NAME: &'static str = "MintXTWitnessBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) + + self.spv_proof.as_slice().len() + + self.cell_dep_index_list.as_slice().len() + } + fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { + let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); + let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); + offsets.push(total_size); + total_size += self.spv_proof.as_slice().len(); + offsets.push(total_size); + total_size += self.cell_dep_index_list.as_slice().len(); + writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; + for offset in offsets.into_iter() { + writer.write_all(&molecule::pack_number(offset as molecule::Number))?; + } + writer.write_all(self.spv_proof.as_slice())?; + writer.write_all(self.cell_dep_index_list.as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + MintXTWitness::new_unchecked(inner.into()) + } +} +#[derive(Clone)] +pub struct BTCSPVProof(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for BTCSPVProof { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for BTCSPVProof { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:#x})", Self::NAME, self) } } -impl ::core::fmt::Display for ToCKBCellData { +impl ::core::fmt::Display for BTCSPVProof { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{} {{ ", Self::NAME)?; - write!(f, "{}: {}", "status", self.status())?; - write!(f, ", {}: {}", "kind", self.kind())?; - write!(f, ", {}: {}", "lot_size", self.lot_size())?; - write!( - f, - ", {}: {}", - "user_lockscript_hash", - self.user_lockscript_hash() - )?; - write!(f, ", {}: {}", "x_lock_address", self.x_lock_address())?; - write!( - f, - ", {}: {}", - "signer_lockscript_hash", - self.signer_lockscript_hash() - )?; - write!(f, ", {}: {}", "x_unlock_address", self.x_unlock_address())?; + write!(f, "{}: {}", "version", self.version())?; + write!(f, ", {}: {}", "vin", self.vin())?; + write!(f, ", {}: {}", "vout", self.vout())?; + write!(f, ", {}: {}", "locktime", self.locktime())?; + write!(f, ", {}: {}", "tx_id", self.tx_id())?; + write!(f, ", {}: {}", "index", self.index())?; + write!(f, ", {}: {}", "headers", self.headers())?; write!( f, ", {}: {}", - "redeemer_lockscript_hash", - self.redeemer_lockscript_hash() + "intermediate_nodes", + self.intermediate_nodes() )?; write!( f, ", {}: {}", - "liquidation_trigger_lockscript_hash", - self.liquidation_trigger_lockscript_hash() + "funding_output_index", + self.funding_output_index() )?; let extra_count = self.count_extra_fields(); if extra_count != 0 { @@ -867,21 +2024,18 @@ impl ::core::fmt::Display for ToCKBCellData { write!(f, " }}") } } -impl ::core::default::Default for ToCKBCellData { +impl ::core::default::Default for BTCSPVProof { fn default() -> Self { let v: Vec = vec![ - 179, 0, 0, 0, 40, 0, 0, 0, 41, 0, 0, 0, 42, 0, 0, 0, 43, 0, 0, 0, 75, 0, 0, 0, 79, 0, - 0, 0, 111, 0, 0, 0, 115, 0, 0, 0, 147, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 101, 0, 0, 0, 40, 0, 0, 0, 44, 0, 0, 0, 48, 0, 0, 0, 52, 0, 0, 0, 56, 0, 0, 0, 88, 0, + 0, 0, 92, 0, 0, 0, 96, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]; - ToCKBCellData::new_unchecked(v.into()) + BTCSPVProof::new_unchecked(v.into()) } } -impl ToCKBCellData { +impl BTCSPVProof { pub const FIELD_COUNT: usize = 9; pub fn total_size(&self) -> usize { molecule::unpack_number(self.as_slice()) as usize @@ -899,73 +2053,73 @@ impl ToCKBCellData { pub fn has_extra_fields(&self) -> bool { Self::FIELD_COUNT != self.field_count() } - pub fn status(&self) -> Byte { + pub fn version(&self) -> Byte4 { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[4..]) as usize; let end = molecule::unpack_number(&slice[8..]) as usize; - Byte::new_unchecked(self.0.slice(start..end)) + Byte4::new_unchecked(self.0.slice(start..end)) } - pub fn kind(&self) -> Byte { + pub fn vin(&self) -> Bytes { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[8..]) as usize; let end = molecule::unpack_number(&slice[12..]) as usize; - Byte::new_unchecked(self.0.slice(start..end)) + Bytes::new_unchecked(self.0.slice(start..end)) } - pub fn lot_size(&self) -> Byte { + pub fn vout(&self) -> Bytes { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[12..]) as usize; let end = molecule::unpack_number(&slice[16..]) as usize; - Byte::new_unchecked(self.0.slice(start..end)) + Bytes::new_unchecked(self.0.slice(start..end)) } - pub fn user_lockscript_hash(&self) -> Byte32 { + pub fn locktime(&self) -> Byte4 { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[16..]) as usize; let end = molecule::unpack_number(&slice[20..]) as usize; - Byte32::new_unchecked(self.0.slice(start..end)) + Byte4::new_unchecked(self.0.slice(start..end)) } - pub fn x_lock_address(&self) -> Bytes { + pub fn tx_id(&self) -> Byte32 { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[20..]) as usize; let end = molecule::unpack_number(&slice[24..]) as usize; - Bytes::new_unchecked(self.0.slice(start..end)) + Byte32::new_unchecked(self.0.slice(start..end)) } - pub fn signer_lockscript_hash(&self) -> Byte32 { + pub fn index(&self) -> Uint32 { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[24..]) as usize; let end = molecule::unpack_number(&slice[28..]) as usize; - Byte32::new_unchecked(self.0.slice(start..end)) + Uint32::new_unchecked(self.0.slice(start..end)) } - pub fn x_unlock_address(&self) -> Bytes { + pub fn headers(&self) -> Bytes { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[28..]) as usize; let end = molecule::unpack_number(&slice[32..]) as usize; Bytes::new_unchecked(self.0.slice(start..end)) } - pub fn redeemer_lockscript_hash(&self) -> Byte32 { + pub fn intermediate_nodes(&self) -> Bytes { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[32..]) as usize; let end = molecule::unpack_number(&slice[36..]) as usize; - Byte32::new_unchecked(self.0.slice(start..end)) + Bytes::new_unchecked(self.0.slice(start..end)) } - pub fn liquidation_trigger_lockscript_hash(&self) -> Byte32 { + pub fn funding_output_index(&self) -> Byte { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[36..]) as usize; if self.has_extra_fields() { let end = molecule::unpack_number(&slice[40..]) as usize; - Byte32::new_unchecked(self.0.slice(start..end)) + Byte::new_unchecked(self.0.slice(start..end)) } else { - Byte32::new_unchecked(self.0.slice(start..)) + Byte::new_unchecked(self.0.slice(start..)) } } - pub fn as_reader<'r>(&'r self) -> ToCKBCellDataReader<'r> { - ToCKBCellDataReader::new_unchecked(self.as_slice()) + pub fn as_reader<'r>(&'r self) -> BTCSPVProofReader<'r> { + BTCSPVProofReader::new_unchecked(self.as_slice()) } } -impl molecule::prelude::Entity for ToCKBCellData { - type Builder = ToCKBCellDataBuilder; - const NAME: &'static str = "ToCKBCellData"; +impl molecule::prelude::Entity for BTCSPVProof { + type Builder = BTCSPVProofBuilder; + const NAME: &'static str = "BTCSPVProof"; fn new_unchecked(data: molecule::bytes::Bytes) -> Self { - ToCKBCellData(data) + BTCSPVProof(data) } fn as_bytes(&self) -> molecule::bytes::Bytes { self.0.clone() @@ -974,30 +2128,30 @@ impl molecule::prelude::Entity for ToCKBCellData { &self.0[..] } fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { - ToCKBCellDataReader::from_slice(slice).map(|reader| reader.to_entity()) + BTCSPVProofReader::from_slice(slice).map(|reader| reader.to_entity()) } fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { - ToCKBCellDataReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + BTCSPVProofReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) } fn new_builder() -> Self::Builder { ::core::default::Default::default() } fn as_builder(self) -> Self::Builder { Self::new_builder() - .status(self.status()) - .kind(self.kind()) - .lot_size(self.lot_size()) - .user_lockscript_hash(self.user_lockscript_hash()) - .x_lock_address(self.x_lock_address()) - .signer_lockscript_hash(self.signer_lockscript_hash()) - .x_unlock_address(self.x_unlock_address()) - .redeemer_lockscript_hash(self.redeemer_lockscript_hash()) - .liquidation_trigger_lockscript_hash(self.liquidation_trigger_lockscript_hash()) + .version(self.version()) + .vin(self.vin()) + .vout(self.vout()) + .locktime(self.locktime()) + .tx_id(self.tx_id()) + .index(self.index()) + .headers(self.headers()) + .intermediate_nodes(self.intermediate_nodes()) + .funding_output_index(self.funding_output_index()) } } #[derive(Clone, Copy)] -pub struct ToCKBCellDataReader<'r>(&'r [u8]); -impl<'r> ::core::fmt::LowerHex for ToCKBCellDataReader<'r> { +pub struct BTCSPVProofReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for BTCSPVProofReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; if f.alternate() { @@ -1006,42 +2160,32 @@ impl<'r> ::core::fmt::LowerHex for ToCKBCellDataReader<'r> { write!(f, "{}", hex_string(self.as_slice())) } } -impl<'r> ::core::fmt::Debug for ToCKBCellDataReader<'r> { +impl<'r> ::core::fmt::Debug for BTCSPVProofReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:#x})", Self::NAME, self) } } -impl<'r> ::core::fmt::Display for ToCKBCellDataReader<'r> { +impl<'r> ::core::fmt::Display for BTCSPVProofReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{} {{ ", Self::NAME)?; - write!(f, "{}: {}", "status", self.status())?; - write!(f, ", {}: {}", "kind", self.kind())?; - write!(f, ", {}: {}", "lot_size", self.lot_size())?; + write!(f, "{}: {}", "version", self.version())?; + write!(f, ", {}: {}", "vin", self.vin())?; + write!(f, ", {}: {}", "vout", self.vout())?; + write!(f, ", {}: {}", "locktime", self.locktime())?; + write!(f, ", {}: {}", "tx_id", self.tx_id())?; + write!(f, ", {}: {}", "index", self.index())?; + write!(f, ", {}: {}", "headers", self.headers())?; write!( f, ", {}: {}", - "user_lockscript_hash", - self.user_lockscript_hash() - )?; - write!(f, ", {}: {}", "x_lock_address", self.x_lock_address())?; - write!( - f, - ", {}: {}", - "signer_lockscript_hash", - self.signer_lockscript_hash() - )?; - write!(f, ", {}: {}", "x_unlock_address", self.x_unlock_address())?; - write!( - f, - ", {}: {}", - "redeemer_lockscript_hash", - self.redeemer_lockscript_hash() + "intermediate_nodes", + self.intermediate_nodes() )?; write!( f, ", {}: {}", - "liquidation_trigger_lockscript_hash", - self.liquidation_trigger_lockscript_hash() + "funding_output_index", + self.funding_output_index() )?; let extra_count = self.count_extra_fields(); if extra_count != 0 { @@ -1050,7 +2194,7 @@ impl<'r> ::core::fmt::Display for ToCKBCellDataReader<'r> { write!(f, " }}") } } -impl<'r> ToCKBCellDataReader<'r> { +impl<'r> BTCSPVProofReader<'r> { pub const FIELD_COUNT: usize = 9; pub fn total_size(&self) -> usize { molecule::unpack_number(self.as_slice()) as usize @@ -1068,73 +2212,73 @@ impl<'r> ToCKBCellDataReader<'r> { pub fn has_extra_fields(&self) -> bool { Self::FIELD_COUNT != self.field_count() } - pub fn status(&self) -> ByteReader<'r> { + pub fn version(&self) -> Byte4Reader<'r> { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[4..]) as usize; let end = molecule::unpack_number(&slice[8..]) as usize; - ByteReader::new_unchecked(&self.as_slice()[start..end]) + Byte4Reader::new_unchecked(&self.as_slice()[start..end]) } - pub fn kind(&self) -> ByteReader<'r> { + pub fn vin(&self) -> BytesReader<'r> { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[8..]) as usize; let end = molecule::unpack_number(&slice[12..]) as usize; - ByteReader::new_unchecked(&self.as_slice()[start..end]) + BytesReader::new_unchecked(&self.as_slice()[start..end]) } - pub fn lot_size(&self) -> ByteReader<'r> { + pub fn vout(&self) -> BytesReader<'r> { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[12..]) as usize; let end = molecule::unpack_number(&slice[16..]) as usize; - ByteReader::new_unchecked(&self.as_slice()[start..end]) + BytesReader::new_unchecked(&self.as_slice()[start..end]) } - pub fn user_lockscript_hash(&self) -> Byte32Reader<'r> { + pub fn locktime(&self) -> Byte4Reader<'r> { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[16..]) as usize; let end = molecule::unpack_number(&slice[20..]) as usize; - Byte32Reader::new_unchecked(&self.as_slice()[start..end]) + Byte4Reader::new_unchecked(&self.as_slice()[start..end]) } - pub fn x_lock_address(&self) -> BytesReader<'r> { + pub fn tx_id(&self) -> Byte32Reader<'r> { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[20..]) as usize; let end = molecule::unpack_number(&slice[24..]) as usize; - BytesReader::new_unchecked(&self.as_slice()[start..end]) + Byte32Reader::new_unchecked(&self.as_slice()[start..end]) } - pub fn signer_lockscript_hash(&self) -> Byte32Reader<'r> { + pub fn index(&self) -> Uint32Reader<'r> { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[24..]) as usize; let end = molecule::unpack_number(&slice[28..]) as usize; - Byte32Reader::new_unchecked(&self.as_slice()[start..end]) + Uint32Reader::new_unchecked(&self.as_slice()[start..end]) } - pub fn x_unlock_address(&self) -> BytesReader<'r> { + pub fn headers(&self) -> BytesReader<'r> { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[28..]) as usize; let end = molecule::unpack_number(&slice[32..]) as usize; BytesReader::new_unchecked(&self.as_slice()[start..end]) } - pub fn redeemer_lockscript_hash(&self) -> Byte32Reader<'r> { + pub fn intermediate_nodes(&self) -> BytesReader<'r> { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[32..]) as usize; let end = molecule::unpack_number(&slice[36..]) as usize; - Byte32Reader::new_unchecked(&self.as_slice()[start..end]) + BytesReader::new_unchecked(&self.as_slice()[start..end]) } - pub fn liquidation_trigger_lockscript_hash(&self) -> Byte32Reader<'r> { + pub fn funding_output_index(&self) -> ByteReader<'r> { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[36..]) as usize; if self.has_extra_fields() { let end = molecule::unpack_number(&slice[40..]) as usize; - Byte32Reader::new_unchecked(&self.as_slice()[start..end]) + ByteReader::new_unchecked(&self.as_slice()[start..end]) } else { - Byte32Reader::new_unchecked(&self.as_slice()[start..]) + ByteReader::new_unchecked(&self.as_slice()[start..]) } } } -impl<'r> molecule::prelude::Reader<'r> for ToCKBCellDataReader<'r> { - type Entity = ToCKBCellData; - const NAME: &'static str = "ToCKBCellDataReader"; +impl<'r> molecule::prelude::Reader<'r> for BTCSPVProofReader<'r> { + type Entity = BTCSPVProof; + const NAME: &'static str = "BTCSPVProofReader"; fn to_entity(&self) -> Self::Entity { Self::Entity::new_unchecked(self.as_slice().to_owned().into()) } fn new_unchecked(slice: &'r [u8]) -> Self { - ToCKBCellDataReader(slice) + BTCSPVProofReader(slice) } fn as_slice(&self) -> &'r [u8] { self.0 @@ -1178,130 +2322,130 @@ impl<'r> molecule::prelude::Reader<'r> for ToCKBCellDataReader<'r> { if offsets.windows(2).any(|i| i[0] > i[1]) { return ve!(Self, OffsetsNotMatch); } - ByteReader::verify(&slice[offsets[0]..offsets[1]], compatible)?; - ByteReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; - ByteReader::verify(&slice[offsets[2]..offsets[3]], compatible)?; - Byte32Reader::verify(&slice[offsets[3]..offsets[4]], compatible)?; - BytesReader::verify(&slice[offsets[4]..offsets[5]], compatible)?; - Byte32Reader::verify(&slice[offsets[5]..offsets[6]], compatible)?; + Byte4Reader::verify(&slice[offsets[0]..offsets[1]], compatible)?; + BytesReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; + BytesReader::verify(&slice[offsets[2]..offsets[3]], compatible)?; + Byte4Reader::verify(&slice[offsets[3]..offsets[4]], compatible)?; + Byte32Reader::verify(&slice[offsets[4]..offsets[5]], compatible)?; + Uint32Reader::verify(&slice[offsets[5]..offsets[6]], compatible)?; BytesReader::verify(&slice[offsets[6]..offsets[7]], compatible)?; - Byte32Reader::verify(&slice[offsets[7]..offsets[8]], compatible)?; - Byte32Reader::verify(&slice[offsets[8]..offsets[9]], compatible)?; + BytesReader::verify(&slice[offsets[7]..offsets[8]], compatible)?; + ByteReader::verify(&slice[offsets[8]..offsets[9]], compatible)?; Ok(()) } } #[derive(Debug, Default)] -pub struct ToCKBCellDataBuilder { - pub(crate) status: Byte, - pub(crate) kind: Byte, - pub(crate) lot_size: Byte, - pub(crate) user_lockscript_hash: Byte32, - pub(crate) x_lock_address: Bytes, - pub(crate) signer_lockscript_hash: Byte32, - pub(crate) x_unlock_address: Bytes, - pub(crate) redeemer_lockscript_hash: Byte32, - pub(crate) liquidation_trigger_lockscript_hash: Byte32, +pub struct BTCSPVProofBuilder { + pub(crate) version: Byte4, + pub(crate) vin: Bytes, + pub(crate) vout: Bytes, + pub(crate) locktime: Byte4, + pub(crate) tx_id: Byte32, + pub(crate) index: Uint32, + pub(crate) headers: Bytes, + pub(crate) intermediate_nodes: Bytes, + pub(crate) funding_output_index: Byte, } -impl ToCKBCellDataBuilder { +impl BTCSPVProofBuilder { pub const FIELD_COUNT: usize = 9; - pub fn status(mut self, v: Byte) -> Self { - self.status = v; + pub fn version(mut self, v: Byte4) -> Self { + self.version = v; self } - pub fn kind(mut self, v: Byte) -> Self { - self.kind = v; + pub fn vin(mut self, v: Bytes) -> Self { + self.vin = v; self } - pub fn lot_size(mut self, v: Byte) -> Self { - self.lot_size = v; + pub fn vout(mut self, v: Bytes) -> Self { + self.vout = v; self } - pub fn user_lockscript_hash(mut self, v: Byte32) -> Self { - self.user_lockscript_hash = v; + pub fn locktime(mut self, v: Byte4) -> Self { + self.locktime = v; self } - pub fn x_lock_address(mut self, v: Bytes) -> Self { - self.x_lock_address = v; + pub fn tx_id(mut self, v: Byte32) -> Self { + self.tx_id = v; self } - pub fn signer_lockscript_hash(mut self, v: Byte32) -> Self { - self.signer_lockscript_hash = v; + pub fn index(mut self, v: Uint32) -> Self { + self.index = v; self } - pub fn x_unlock_address(mut self, v: Bytes) -> Self { - self.x_unlock_address = v; + pub fn headers(mut self, v: Bytes) -> Self { + self.headers = v; self } - pub fn redeemer_lockscript_hash(mut self, v: Byte32) -> Self { - self.redeemer_lockscript_hash = v; + pub fn intermediate_nodes(mut self, v: Bytes) -> Self { + self.intermediate_nodes = v; self } - pub fn liquidation_trigger_lockscript_hash(mut self, v: Byte32) -> Self { - self.liquidation_trigger_lockscript_hash = v; + pub fn funding_output_index(mut self, v: Byte) -> Self { + self.funding_output_index = v; self } } -impl molecule::prelude::Builder for ToCKBCellDataBuilder { - type Entity = ToCKBCellData; - const NAME: &'static str = "ToCKBCellDataBuilder"; +impl molecule::prelude::Builder for BTCSPVProofBuilder { + type Entity = BTCSPVProof; + const NAME: &'static str = "BTCSPVProofBuilder"; fn expected_length(&self) -> usize { molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) - + self.status.as_slice().len() - + self.kind.as_slice().len() - + self.lot_size.as_slice().len() - + self.user_lockscript_hash.as_slice().len() - + self.x_lock_address.as_slice().len() - + self.signer_lockscript_hash.as_slice().len() - + self.x_unlock_address.as_slice().len() - + self.redeemer_lockscript_hash.as_slice().len() - + self.liquidation_trigger_lockscript_hash.as_slice().len() + + self.version.as_slice().len() + + self.vin.as_slice().len() + + self.vout.as_slice().len() + + self.locktime.as_slice().len() + + self.tx_id.as_slice().len() + + self.index.as_slice().len() + + self.headers.as_slice().len() + + self.intermediate_nodes.as_slice().len() + + self.funding_output_index.as_slice().len() } fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); offsets.push(total_size); - total_size += self.status.as_slice().len(); + total_size += self.version.as_slice().len(); offsets.push(total_size); - total_size += self.kind.as_slice().len(); + total_size += self.vin.as_slice().len(); offsets.push(total_size); - total_size += self.lot_size.as_slice().len(); + total_size += self.vout.as_slice().len(); offsets.push(total_size); - total_size += self.user_lockscript_hash.as_slice().len(); + total_size += self.locktime.as_slice().len(); offsets.push(total_size); - total_size += self.x_lock_address.as_slice().len(); + total_size += self.tx_id.as_slice().len(); offsets.push(total_size); - total_size += self.signer_lockscript_hash.as_slice().len(); + total_size += self.index.as_slice().len(); offsets.push(total_size); - total_size += self.x_unlock_address.as_slice().len(); + total_size += self.headers.as_slice().len(); offsets.push(total_size); - total_size += self.redeemer_lockscript_hash.as_slice().len(); + total_size += self.intermediate_nodes.as_slice().len(); offsets.push(total_size); - total_size += self.liquidation_trigger_lockscript_hash.as_slice().len(); + total_size += self.funding_output_index.as_slice().len(); writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; for offset in offsets.into_iter() { writer.write_all(&molecule::pack_number(offset as molecule::Number))?; } - writer.write_all(self.status.as_slice())?; - writer.write_all(self.kind.as_slice())?; - writer.write_all(self.lot_size.as_slice())?; - writer.write_all(self.user_lockscript_hash.as_slice())?; - writer.write_all(self.x_lock_address.as_slice())?; - writer.write_all(self.signer_lockscript_hash.as_slice())?; - writer.write_all(self.x_unlock_address.as_slice())?; - writer.write_all(self.redeemer_lockscript_hash.as_slice())?; - writer.write_all(self.liquidation_trigger_lockscript_hash.as_slice())?; + writer.write_all(self.version.as_slice())?; + writer.write_all(self.vin.as_slice())?; + writer.write_all(self.vout.as_slice())?; + writer.write_all(self.locktime.as_slice())?; + writer.write_all(self.tx_id.as_slice())?; + writer.write_all(self.index.as_slice())?; + writer.write_all(self.headers.as_slice())?; + writer.write_all(self.intermediate_nodes.as_slice())?; + writer.write_all(self.funding_output_index.as_slice())?; Ok(()) } fn build(&self) -> Self::Entity { let mut inner = Vec::with_capacity(self.expected_length()); self.write(&mut inner) .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); - ToCKBCellData::new_unchecked(inner.into()) + BTCSPVProof::new_unchecked(inner.into()) } } #[derive(Clone)] -pub struct MintXTWitness(molecule::bytes::Bytes); -impl ::core::fmt::LowerHex for MintXTWitness { +pub struct BTCDifficulty(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for BTCDifficulty { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; if f.alternate() { @@ -1310,21 +2454,16 @@ impl ::core::fmt::LowerHex for MintXTWitness { write!(f, "{}", hex_string(self.as_slice())) } } -impl ::core::fmt::Debug for MintXTWitness { +impl ::core::fmt::Debug for BTCDifficulty { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:#x})", Self::NAME, self) } } -impl ::core::fmt::Display for MintXTWitness { +impl ::core::fmt::Display for BTCDifficulty { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{} {{ ", Self::NAME)?; - write!(f, "{}: {}", "spv_proof", self.spv_proof())?; - write!( - f, - ", {}: {}", - "cell_dep_index_list", - self.cell_dep_index_list() - )?; + write!(f, "{}: {}", "current", self.current())?; + write!(f, ", {}: {}", "previous", self.previous())?; let extra_count = self.count_extra_fields(); if extra_count != 0 { write!(f, ", .. ({} fields)", extra_count)?; @@ -1332,15 +2471,15 @@ impl ::core::fmt::Display for MintXTWitness { write!(f, " }}") } } -impl ::core::default::Default for MintXTWitness { +impl ::core::default::Default for BTCDifficulty { fn default() -> Self { let v: Vec = vec![ 20, 0, 0, 0, 12, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]; - MintXTWitness::new_unchecked(v.into()) + BTCDifficulty::new_unchecked(v.into()) } } -impl MintXTWitness { +impl BTCDifficulty { pub const FIELD_COUNT: usize = 2; pub fn total_size(&self) -> usize { molecule::unpack_number(self.as_slice()) as usize @@ -1358,13 +2497,13 @@ impl MintXTWitness { pub fn has_extra_fields(&self) -> bool { Self::FIELD_COUNT != self.field_count() } - pub fn spv_proof(&self) -> Bytes { + pub fn current(&self) -> Bytes { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[4..]) as usize; let end = molecule::unpack_number(&slice[8..]) as usize; Bytes::new_unchecked(self.0.slice(start..end)) } - pub fn cell_dep_index_list(&self) -> Bytes { + pub fn previous(&self) -> Bytes { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[8..]) as usize; if self.has_extra_fields() { @@ -1374,15 +2513,15 @@ impl MintXTWitness { Bytes::new_unchecked(self.0.slice(start..)) } } - pub fn as_reader<'r>(&'r self) -> MintXTWitnessReader<'r> { - MintXTWitnessReader::new_unchecked(self.as_slice()) + pub fn as_reader<'r>(&'r self) -> BTCDifficultyReader<'r> { + BTCDifficultyReader::new_unchecked(self.as_slice()) } } -impl molecule::prelude::Entity for MintXTWitness { - type Builder = MintXTWitnessBuilder; - const NAME: &'static str = "MintXTWitness"; +impl molecule::prelude::Entity for BTCDifficulty { + type Builder = BTCDifficultyBuilder; + const NAME: &'static str = "BTCDifficulty"; fn new_unchecked(data: molecule::bytes::Bytes) -> Self { - MintXTWitness(data) + BTCDifficulty(data) } fn as_bytes(&self) -> molecule::bytes::Bytes { self.0.clone() @@ -1391,23 +2530,23 @@ impl molecule::prelude::Entity for MintXTWitness { &self.0[..] } fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { - MintXTWitnessReader::from_slice(slice).map(|reader| reader.to_entity()) + BTCDifficultyReader::from_slice(slice).map(|reader| reader.to_entity()) } fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { - MintXTWitnessReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + BTCDifficultyReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) } fn new_builder() -> Self::Builder { ::core::default::Default::default() } fn as_builder(self) -> Self::Builder { Self::new_builder() - .spv_proof(self.spv_proof()) - .cell_dep_index_list(self.cell_dep_index_list()) + .current(self.current()) + .previous(self.previous()) } } #[derive(Clone, Copy)] -pub struct MintXTWitnessReader<'r>(&'r [u8]); -impl<'r> ::core::fmt::LowerHex for MintXTWitnessReader<'r> { +pub struct BTCDifficultyReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for BTCDifficultyReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; if f.alternate() { @@ -1416,21 +2555,16 @@ impl<'r> ::core::fmt::LowerHex for MintXTWitnessReader<'r> { write!(f, "{}", hex_string(self.as_slice())) } } -impl<'r> ::core::fmt::Debug for MintXTWitnessReader<'r> { +impl<'r> ::core::fmt::Debug for BTCDifficultyReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:#x})", Self::NAME, self) } } -impl<'r> ::core::fmt::Display for MintXTWitnessReader<'r> { +impl<'r> ::core::fmt::Display for BTCDifficultyReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{} {{ ", Self::NAME)?; - write!(f, "{}: {}", "spv_proof", self.spv_proof())?; - write!( - f, - ", {}: {}", - "cell_dep_index_list", - self.cell_dep_index_list() - )?; + write!(f, "{}: {}", "current", self.current())?; + write!(f, ", {}: {}", "previous", self.previous())?; let extra_count = self.count_extra_fields(); if extra_count != 0 { write!(f, ", .. ({} fields)", extra_count)?; @@ -1438,7 +2572,7 @@ impl<'r> ::core::fmt::Display for MintXTWitnessReader<'r> { write!(f, " }}") } } -impl<'r> MintXTWitnessReader<'r> { +impl<'r> BTCDifficultyReader<'r> { pub const FIELD_COUNT: usize = 2; pub fn total_size(&self) -> usize { molecule::unpack_number(self.as_slice()) as usize @@ -1456,13 +2590,13 @@ impl<'r> MintXTWitnessReader<'r> { pub fn has_extra_fields(&self) -> bool { Self::FIELD_COUNT != self.field_count() } - pub fn spv_proof(&self) -> BytesReader<'r> { + pub fn current(&self) -> BytesReader<'r> { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[4..]) as usize; let end = molecule::unpack_number(&slice[8..]) as usize; BytesReader::new_unchecked(&self.as_slice()[start..end]) } - pub fn cell_dep_index_list(&self) -> BytesReader<'r> { + pub fn previous(&self) -> BytesReader<'r> { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[8..]) as usize; if self.has_extra_fields() { @@ -1473,14 +2607,14 @@ impl<'r> MintXTWitnessReader<'r> { } } } -impl<'r> molecule::prelude::Reader<'r> for MintXTWitnessReader<'r> { - type Entity = MintXTWitness; - const NAME: &'static str = "MintXTWitnessReader"; +impl<'r> molecule::prelude::Reader<'r> for BTCDifficultyReader<'r> { + type Entity = BTCDifficulty; + const NAME: &'static str = "BTCDifficultyReader"; fn to_entity(&self) -> Self::Entity { Self::Entity::new_unchecked(self.as_slice().to_owned().into()) } fn new_unchecked(slice: &'r [u8]) -> Self { - MintXTWitnessReader(slice) + BTCDifficultyReader(slice) } fn as_slice(&self) -> &'r [u8] { self.0 @@ -1530,48 +2664,48 @@ impl<'r> molecule::prelude::Reader<'r> for MintXTWitnessReader<'r> { } } #[derive(Debug, Default)] -pub struct MintXTWitnessBuilder { - pub(crate) spv_proof: Bytes, - pub(crate) cell_dep_index_list: Bytes, +pub struct BTCDifficultyBuilder { + pub(crate) current: Bytes, + pub(crate) previous: Bytes, } -impl MintXTWitnessBuilder { +impl BTCDifficultyBuilder { pub const FIELD_COUNT: usize = 2; - pub fn spv_proof(mut self, v: Bytes) -> Self { - self.spv_proof = v; + pub fn current(mut self, v: Bytes) -> Self { + self.current = v; self } - pub fn cell_dep_index_list(mut self, v: Bytes) -> Self { - self.cell_dep_index_list = v; + pub fn previous(mut self, v: Bytes) -> Self { + self.previous = v; self } } -impl molecule::prelude::Builder for MintXTWitnessBuilder { - type Entity = MintXTWitness; - const NAME: &'static str = "MintXTWitnessBuilder"; +impl molecule::prelude::Builder for BTCDifficultyBuilder { + type Entity = BTCDifficulty; + const NAME: &'static str = "BTCDifficultyBuilder"; fn expected_length(&self) -> usize { molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) - + self.spv_proof.as_slice().len() - + self.cell_dep_index_list.as_slice().len() + + self.current.as_slice().len() + + self.previous.as_slice().len() } fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); offsets.push(total_size); - total_size += self.spv_proof.as_slice().len(); + total_size += self.current.as_slice().len(); offsets.push(total_size); - total_size += self.cell_dep_index_list.as_slice().len(); + total_size += self.previous.as_slice().len(); writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; for offset in offsets.into_iter() { writer.write_all(&molecule::pack_number(offset as molecule::Number))?; } - writer.write_all(self.spv_proof.as_slice())?; - writer.write_all(self.cell_dep_index_list.as_slice())?; + writer.write_all(self.current.as_slice())?; + writer.write_all(self.previous.as_slice())?; Ok(()) } fn build(&self) -> Self::Entity { let mut inner = Vec::with_capacity(self.expected_length()); self.write(&mut inner) .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); - MintXTWitness::new_unchecked(inner.into()) + BTCDifficulty::new_unchecked(inner.into()) } } diff --git a/contracts/toCKB-typescript/src/utils/types/mod.rs b/contracts/toCKB-typescript/src/utils/types/mod.rs index 1528eb6..71ef2e8 100644 --- a/contracts/toCKB-typescript/src/utils/types/mod.rs +++ b/contracts/toCKB-typescript/src/utils/types/mod.rs @@ -3,4 +3,5 @@ mod generated; mod toCKB_cell; pub use error::Error; +pub use generated::toCKB_cell_data; pub use toCKB_cell::*; diff --git a/contracts/toCKB-typescript/src/utils/types/schemas/toCKB_cell_data.mol b/contracts/toCKB-typescript/src/utils/types/schemas/toCKB_cell_data.mol index b52e9f9..8c47ad7 100644 --- a/contracts/toCKB-typescript/src/utils/types/schemas/toCKB_cell_data.mol +++ b/contracts/toCKB-typescript/src/utils/types/schemas/toCKB_cell_data.mol @@ -1,5 +1,7 @@ array Byte32 [byte; 32]; vector Bytes ; +array Byte4 [byte; 4]; +array Uint32 [byte; 4]; table ToCKBCellData { status: byte, @@ -17,3 +19,20 @@ table MintXTWitness { spv_proof: Bytes, cell_dep_index_list: Bytes, } + +table BTCSPVProof { + version: Byte4, + vin: Bytes, + vout: Bytes, + locktime: Byte4, + tx_id: Byte32, + index: Uint32, + headers: Bytes, + intermediate_nodes: Bytes, + funding_output_index: byte, +} + +table BTCDifficulty { + current: Bytes, + previous: Bytes, +} From 8a627004e7c28d1c3929be6edfc1a4fc247e7e45 Mon Sep 17 00:00:00 2001 From: huwenchao Date: Fri, 21 Aug 2020 01:08:15 +0800 Subject: [PATCH 05/45] fix: ambiguous name error --- contracts/toCKB-typescript/src/switch/mod.rs | 32 +++++++++----------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/contracts/toCKB-typescript/src/switch/mod.rs b/contracts/toCKB-typescript/src/switch/mod.rs index 62aeee1..116146e 100644 --- a/contracts/toCKB-typescript/src/switch/mod.rs +++ b/contracts/toCKB-typescript/src/switch/mod.rs @@ -92,37 +92,35 @@ fn get_transformation_tx_type( output_data: &ToCKBCellDataView, ) -> Result { use ToCKBStatus::*; - use TxType::*; let status_transformation = (input_data.status, output_data.status); match status_transformation { - (Initial, Bonded) => Ok(Bonding), - (Bonded, Warranty) => Ok(MintXT), + (Initial, Bonded) => Ok(TxType::Bonding), + (Bonded, Warranty) => Ok(TxType::MintXT), (Warranty, Redeeming) => { if let 0 = load_input_since(0, Source::GroupInput)? { - Ok(PretermRedeem) + Ok(TxType::PretermRedeem) } else { - Ok(AttermRedeem) + Ok(TxType::AttermRedeem) } } - (Redeeming, SignerTimeout) => Ok(LiquidationSignerTimeout), - (Warranty, Undercollateral) => Ok(LiquidationUndercollateral), - (Warranty, FaultyWhenWarranty) => Ok(LiquidationFaultyWhenWarranty), - (Redeeming, FaultyWhenRedeeming) => Ok(LiquidationFaultyWhenRedeeming), + (Redeeming, SignerTimeout) => Ok(TxType::LiquidationSignerTimeout), + (Warranty, Undercollateral) => Ok(TxType::LiquidationUndercollateral), + (Warranty, FaultyWhenWarranty) => Ok(TxType::LiquidationFaultyWhenWarranty), + (Redeeming, FaultyWhenRedeeming) => Ok(TxType::LiquidationFaultyWhenRedeeming), _ => Err(Error::TxInvalid), } } fn get_deletion_tx_type(data: &ToCKBCellDataView) -> Result { use ToCKBStatus::*; - use TxType::*; match data.status { - Initial => Ok(WithdrawPledge), - Bonded => Ok(WithdrawPledgeAndCollateral), - Redeeming => Ok(WithdrawCollateral), - SignerTimeout => Ok(AuctionSignerTimeout), - Undercollateral => Ok(AuctionUnderCollateral), - FaultyWhenWarranty => Ok(AuctionFaultyWhenWarranty), - FaultyWhenRedeeming => Ok(AuctionFaultyWhenRedeeming), + Initial => Ok(TxType::WithdrawPledge), + Bonded => Ok(TxType::WithdrawPledgeAndCollateral), + Redeeming => Ok(TxType::WithdrawCollateral), + SignerTimeout => Ok(TxType::AuctionSignerTimeout), + Undercollateral => Ok(TxType::AuctionUnderCollateral), + FaultyWhenWarranty => Ok(TxType::AuctionFaultyWhenWarranty), + FaultyWhenRedeeming => Ok(TxType::AuctionFaultyWhenRedeeming), _ => Err(Error::TxInvalid), } } From 769ff277a08704724585b68912a308aa7e3cb725 Mon Sep 17 00:00:00 2001 From: huwenchao Date: Fri, 21 Aug 2020 01:19:55 +0800 Subject: [PATCH 06/45] fix: merge error --- .../toCKB-typescript/src/utils/types/toCKB_cell.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/contracts/toCKB-typescript/src/utils/types/toCKB_cell.rs b/contracts/toCKB-typescript/src/utils/types/toCKB_cell.rs index 037ff9e..a6b94cf 100644 --- a/contracts/toCKB-typescript/src/utils/types/toCKB_cell.rs +++ b/contracts/toCKB-typescript/src/utils/types/toCKB_cell.rs @@ -8,7 +8,7 @@ use molecule::prelude::*; pub struct ToCKBCellDataView { pub status: ToCKBStatus, pub kind: XChainKind, - pub lot_size: u8, + lot_size: u8, pub user_lockscript_hash: Bytes, pub x_lock_address: Bytes, pub signer_lockscript_hash: Bytes, @@ -67,16 +67,16 @@ impl ToCKBCellDataView { } #[repr(u8)] -#[derive(Clone, Copy, IntEnum, PartialEq)] +#[derive(Clone, Copy, IntEnum)] pub enum ToCKBStatus { Initial = 1, - Bonding = 2, + Bonded = 2, Warranty = 3, Redeeming = 4, - LiquidationTimeout = 5, - LiquidationUndercollateral = 6, - LiquidationFaultyWhenWarranty = 7, - LiquidationFaultyWhenRedeeming = 8, + SignerTimeout = 5, + Undercollateral = 6, + FaultyWhenWarranty = 7, + FaultyWhenRedeeming = 8, } #[repr(u8)] From cb6781b5b209b3805d8cc3251a258c3236ef3dea Mon Sep 17 00:00:00 2001 From: huwenchao Date: Fri, 21 Aug 2020 01:20:53 +0800 Subject: [PATCH 07/45] chore: update makefile --- Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 77d397d..b20cf25 100644 --- a/Makefile +++ b/Makefile @@ -5,4 +5,6 @@ schema: moleculec --language rust --schema-file contracts/toCKB-typescript/src/utils/types/schemas/toCKB_cell_data.mol > contracts/toCKB-typescript/src/utils/types/generated/toCKB_cell_data.rs fmt: - cd contracts/toCKB-typescript && cargo fmt \ No newline at end of file + cd contracts/toCKB-typescript && cargo fmt + +.PHONY: schema fmt watch From 12c6dfb6652868cab355fd341925c0ee3982e73a Mon Sep 17 00:00:00 2001 From: huwenchao Date: Fri, 21 Aug 2020 18:06:18 +0800 Subject: [PATCH 08/45] chore: remove useless refactor --- .../src/switch/deposit_request/mod.rs | 12 ++----- contracts/toCKB-typescript/src/switch/mod.rs | 32 ++++++++++--------- 2 files changed, 20 insertions(+), 24 deletions(-) diff --git a/contracts/toCKB-typescript/src/switch/deposit_request/mod.rs b/contracts/toCKB-typescript/src/switch/deposit_request/mod.rs index bb5ae82..44dcc94 100644 --- a/contracts/toCKB-typescript/src/switch/deposit_request/mod.rs +++ b/contracts/toCKB-typescript/src/switch/deposit_request/mod.rs @@ -1,7 +1,7 @@ use crate::switch::ToCKBCellDataTuple; use crate::utils::{ config::PLEDGE, - types::{Error, ToCKBCellDataView, XChainKind}, + types::{Error, ToCKBCellDataView}, }; use ckb_std::{ckb_constants::Source, high_level::load_cell_capacity}; use core::result::Result; @@ -24,14 +24,8 @@ fn verify_capacity() -> Result<(), Error> { } fn verify_lot_size(toCKB_data: &ToCKBCellDataView) -> Result<(), Error> { - if let XChainKind::Btc = toCKB_data.kind { - if toCKB_data.get_btc_lot_size().is_err() { - return Err(Error::LotSizeInvalid); - } - } else { - if toCKB_data.get_eth_lot_size().is_err() { - return Err(Error::LotSizeInvalid); - } + if toCKB_data.get_btc_lot_size().is_err() && toCKB_data.get_eth_lot_size().is_err() { + return Err(Error::LotSizeInvalid); } Ok(()) } diff --git a/contracts/toCKB-typescript/src/switch/mod.rs b/contracts/toCKB-typescript/src/switch/mod.rs index 116146e..62aeee1 100644 --- a/contracts/toCKB-typescript/src/switch/mod.rs +++ b/contracts/toCKB-typescript/src/switch/mod.rs @@ -92,35 +92,37 @@ fn get_transformation_tx_type( output_data: &ToCKBCellDataView, ) -> Result { use ToCKBStatus::*; + use TxType::*; let status_transformation = (input_data.status, output_data.status); match status_transformation { - (Initial, Bonded) => Ok(TxType::Bonding), - (Bonded, Warranty) => Ok(TxType::MintXT), + (Initial, Bonded) => Ok(Bonding), + (Bonded, Warranty) => Ok(MintXT), (Warranty, Redeeming) => { if let 0 = load_input_since(0, Source::GroupInput)? { - Ok(TxType::PretermRedeem) + Ok(PretermRedeem) } else { - Ok(TxType::AttermRedeem) + Ok(AttermRedeem) } } - (Redeeming, SignerTimeout) => Ok(TxType::LiquidationSignerTimeout), - (Warranty, Undercollateral) => Ok(TxType::LiquidationUndercollateral), - (Warranty, FaultyWhenWarranty) => Ok(TxType::LiquidationFaultyWhenWarranty), - (Redeeming, FaultyWhenRedeeming) => Ok(TxType::LiquidationFaultyWhenRedeeming), + (Redeeming, SignerTimeout) => Ok(LiquidationSignerTimeout), + (Warranty, Undercollateral) => Ok(LiquidationUndercollateral), + (Warranty, FaultyWhenWarranty) => Ok(LiquidationFaultyWhenWarranty), + (Redeeming, FaultyWhenRedeeming) => Ok(LiquidationFaultyWhenRedeeming), _ => Err(Error::TxInvalid), } } fn get_deletion_tx_type(data: &ToCKBCellDataView) -> Result { use ToCKBStatus::*; + use TxType::*; match data.status { - Initial => Ok(TxType::WithdrawPledge), - Bonded => Ok(TxType::WithdrawPledgeAndCollateral), - Redeeming => Ok(TxType::WithdrawCollateral), - SignerTimeout => Ok(TxType::AuctionSignerTimeout), - Undercollateral => Ok(TxType::AuctionUnderCollateral), - FaultyWhenWarranty => Ok(TxType::AuctionFaultyWhenWarranty), - FaultyWhenRedeeming => Ok(TxType::AuctionFaultyWhenRedeeming), + Initial => Ok(WithdrawPledge), + Bonded => Ok(WithdrawPledgeAndCollateral), + Redeeming => Ok(WithdrawCollateral), + SignerTimeout => Ok(AuctionSignerTimeout), + Undercollateral => Ok(AuctionUnderCollateral), + FaultyWhenWarranty => Ok(AuctionFaultyWhenWarranty), + FaultyWhenRedeeming => Ok(AuctionFaultyWhenRedeeming), _ => Err(Error::TxInvalid), } } From e6acecbae81bd4820c1ef0b99bb9a1494a607daa Mon Sep 17 00:00:00 2001 From: huwenchao Date: Fri, 21 Aug 2020 18:10:45 +0800 Subject: [PATCH 09/45] fix: change udt amount unit to u128 --- contracts/toCKB-typescript/src/switch/mint_xt/mod.rs | 10 +++++----- contracts/toCKB-typescript/src/utils/config.rs | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs index 275b7e6..3a413fa 100644 --- a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs +++ b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs @@ -90,13 +90,13 @@ fn verify_btc_witness( } let lot_size = data.get_btc_lot_size()?; let value = tx_out.value(); - if btc_lot_size_to_u64(lot_size) != value { + if btc_lot_size_to_u128(lot_size) != value as u128 { return Err(Error::FundingNotEnough); } Ok(()) } -fn btc_lot_size_to_u64(lot_size: BtcLotSize) -> u64 { +fn btc_lot_size_to_u128(lot_size: BtcLotSize) -> u128 { match lot_size { BtcLotSize::Single => 100_000_000, BtcLotSize::Half => 50_000_000, @@ -181,7 +181,7 @@ fn verify_btc_xt_issue(data: &ToCKBCellDataView) -> Result<(), Error> { let mut output_index = 0; let mut user_checked = false; let mut signer_checked = false; - let xt_amount = btc_lot_size_to_u64(data.get_btc_lot_size()?); + let xt_amount = btc_lot_size_to_u128(data.get_btc_lot_size()?); loop { let type_hash_res = load_cell_type_hash(output_index, Source::Output); match type_hash_res { @@ -196,9 +196,9 @@ fn verify_btc_xt_issue(data: &ToCKBCellDataView) -> Result<(), Error> { } let lock_hash = load_cell_lock_hash(output_index, Source::Output)?; let cell_data = load_cell_data(output_index, Source::Output)?; - let mut amount_vec = [0u8; 8]; + let mut amount_vec = [0u8; 16]; amount_vec.copy_from_slice(&cell_data); - let token_amount = u64::from_le_bytes(amount_vec); + let token_amount = u128::from_le_bytes(amount_vec); if lock_hash.as_ref() == data.user_lockscript_hash.as_ref() { if user_checked { return Err(Error::InvalidXTMint); diff --git a/contracts/toCKB-typescript/src/utils/config.rs b/contracts/toCKB-typescript/src/utils/config.rs index 0d31150..d00aa94 100644 --- a/contracts/toCKB-typescript/src/utils/config.rs +++ b/contracts/toCKB-typescript/src/utils/config.rs @@ -1,4 +1,4 @@ pub const PLEDGE: u64 = 10000; pub const TX_PROOF_DIFFICULTY_FACTOR: u8 = 6; // default value is 2/1000 -pub const SIGNER_FEE_RATE: (u64, u64) = (2, 1000); +pub const SIGNER_FEE_RATE: (u128, u128) = (2, 1000); From b24a0b9fbc00cb3e5d33beca5738628508063c52 Mon Sep 17 00:00:00 2001 From: huwenchao Date: Fri, 21 Aug 2020 18:45:51 +0800 Subject: [PATCH 10/45] refactor: split mol to multiple files --- Makefile | 3 + .../src/switch/mint_xt/mod.rs | 3 +- .../src/utils/types/generated/mod.rs | 3 + .../utils/types/generated/toCKB_cell_data.rs | 2780 ++--------------- .../toCKB-typescript/src/utils/types/mod.rs | 2 +- .../utils/types/schemas/toCKB_cell_data.mol | 26 +- 6 files changed, 290 insertions(+), 2527 deletions(-) diff --git a/Makefile b/Makefile index b20cf25..4c64e92 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,10 @@ watch: watchexec -w contracts/toCKB-typescript/src -- 'make fmt && capsule build' schema: + moleculec --language rust --schema-file contracts/toCKB-typescript/src/utils/types/schemas/basic.mol > contracts/toCKB-typescript/src/utils/types/generated/basic.rs moleculec --language rust --schema-file contracts/toCKB-typescript/src/utils/types/schemas/toCKB_cell_data.mol > contracts/toCKB-typescript/src/utils/types/generated/toCKB_cell_data.rs + moleculec --language rust --schema-file contracts/toCKB-typescript/src/utils/types/schemas/btc_difficulty.mol > contracts/toCKB-typescript/src/utils/types/generated/btc_difficulty.rs + moleculec --language rust --schema-file contracts/toCKB-typescript/src/utils/types/schemas/mint_xt_witness.mol > contracts/toCKB-typescript/src/utils/types/generated/mint_xt_witness.rs fmt: cd contracts/toCKB-typescript && cargo fmt diff --git a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs index 3a413fa..4195a32 100644 --- a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs +++ b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs @@ -1,7 +1,8 @@ use crate::switch::ToCKBCellDataTuple; use crate::utils::config::{SIGNER_FEE_RATE, TX_PROOF_DIFFICULTY_FACTOR}; use crate::utils::types::{ - toCKB_cell_data::{BTCDifficultyReader, BTCSPVProofReader, MintXTWitnessReader}, + btc_difficulty::BTCDifficultyReader, + mint_xt_witness::{BTCSPVProofReader, MintXTWitnessReader}, BtcLotSize, Error, ToCKBCellDataView, XChainKind, }; use bitcoin_spv::{ diff --git a/contracts/toCKB-typescript/src/utils/types/generated/mod.rs b/contracts/toCKB-typescript/src/utils/types/generated/mod.rs index b42970a..4e0fab0 100644 --- a/contracts/toCKB-typescript/src/utils/types/generated/mod.rs +++ b/contracts/toCKB-typescript/src/utils/types/generated/mod.rs @@ -1 +1,4 @@ +pub mod basic; +pub mod btc_difficulty; +pub mod mint_xt_witness; pub mod toCKB_cell_data; diff --git a/contracts/toCKB-typescript/src/utils/types/generated/toCKB_cell_data.rs b/contracts/toCKB-typescript/src/utils/types/generated/toCKB_cell_data.rs index 006b6dc..3f7ca47 100644 --- a/contracts/toCKB-typescript/src/utils/types/generated/toCKB_cell_data.rs +++ b/contracts/toCKB-typescript/src/utils/types/generated/toCKB_cell_data.rs @@ -1,2157 +1,10 @@ // Generated by Molecule 0.6.0 +use super::basic::*; use molecule::prelude::*; #[derive(Clone)] -pub struct Byte32(molecule::bytes::Bytes); -impl ::core::fmt::LowerHex for Byte32 { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl ::core::fmt::Debug for Byte32 { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl ::core::fmt::Display for Byte32 { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - let raw_data = hex_string(&self.raw_data()); - write!(f, "{}(0x{})", Self::NAME, raw_data) - } -} -impl ::core::default::Default for Byte32 { - fn default() -> Self { - let v: Vec = vec![ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, - ]; - Byte32::new_unchecked(v.into()) - } -} -impl Byte32 { - pub const TOTAL_SIZE: usize = 32; - pub const ITEM_SIZE: usize = 1; - pub const ITEM_COUNT: usize = 32; - pub fn nth0(&self) -> Byte { - Byte::new_unchecked(self.0.slice(0..1)) - } - pub fn nth1(&self) -> Byte { - Byte::new_unchecked(self.0.slice(1..2)) - } - pub fn nth2(&self) -> Byte { - Byte::new_unchecked(self.0.slice(2..3)) - } - pub fn nth3(&self) -> Byte { - Byte::new_unchecked(self.0.slice(3..4)) - } - pub fn nth4(&self) -> Byte { - Byte::new_unchecked(self.0.slice(4..5)) - } - pub fn nth5(&self) -> Byte { - Byte::new_unchecked(self.0.slice(5..6)) - } - pub fn nth6(&self) -> Byte { - Byte::new_unchecked(self.0.slice(6..7)) - } - pub fn nth7(&self) -> Byte { - Byte::new_unchecked(self.0.slice(7..8)) - } - pub fn nth8(&self) -> Byte { - Byte::new_unchecked(self.0.slice(8..9)) - } - pub fn nth9(&self) -> Byte { - Byte::new_unchecked(self.0.slice(9..10)) - } - pub fn nth10(&self) -> Byte { - Byte::new_unchecked(self.0.slice(10..11)) - } - pub fn nth11(&self) -> Byte { - Byte::new_unchecked(self.0.slice(11..12)) - } - pub fn nth12(&self) -> Byte { - Byte::new_unchecked(self.0.slice(12..13)) - } - pub fn nth13(&self) -> Byte { - Byte::new_unchecked(self.0.slice(13..14)) - } - pub fn nth14(&self) -> Byte { - Byte::new_unchecked(self.0.slice(14..15)) - } - pub fn nth15(&self) -> Byte { - Byte::new_unchecked(self.0.slice(15..16)) - } - pub fn nth16(&self) -> Byte { - Byte::new_unchecked(self.0.slice(16..17)) - } - pub fn nth17(&self) -> Byte { - Byte::new_unchecked(self.0.slice(17..18)) - } - pub fn nth18(&self) -> Byte { - Byte::new_unchecked(self.0.slice(18..19)) - } - pub fn nth19(&self) -> Byte { - Byte::new_unchecked(self.0.slice(19..20)) - } - pub fn nth20(&self) -> Byte { - Byte::new_unchecked(self.0.slice(20..21)) - } - pub fn nth21(&self) -> Byte { - Byte::new_unchecked(self.0.slice(21..22)) - } - pub fn nth22(&self) -> Byte { - Byte::new_unchecked(self.0.slice(22..23)) - } - pub fn nth23(&self) -> Byte { - Byte::new_unchecked(self.0.slice(23..24)) - } - pub fn nth24(&self) -> Byte { - Byte::new_unchecked(self.0.slice(24..25)) - } - pub fn nth25(&self) -> Byte { - Byte::new_unchecked(self.0.slice(25..26)) - } - pub fn nth26(&self) -> Byte { - Byte::new_unchecked(self.0.slice(26..27)) - } - pub fn nth27(&self) -> Byte { - Byte::new_unchecked(self.0.slice(27..28)) - } - pub fn nth28(&self) -> Byte { - Byte::new_unchecked(self.0.slice(28..29)) - } - pub fn nth29(&self) -> Byte { - Byte::new_unchecked(self.0.slice(29..30)) - } - pub fn nth30(&self) -> Byte { - Byte::new_unchecked(self.0.slice(30..31)) - } - pub fn nth31(&self) -> Byte { - Byte::new_unchecked(self.0.slice(31..32)) - } - pub fn raw_data(&self) -> molecule::bytes::Bytes { - self.as_bytes() - } - pub fn as_reader<'r>(&'r self) -> Byte32Reader<'r> { - Byte32Reader::new_unchecked(self.as_slice()) - } -} -impl molecule::prelude::Entity for Byte32 { - type Builder = Byte32Builder; - const NAME: &'static str = "Byte32"; - fn new_unchecked(data: molecule::bytes::Bytes) -> Self { - Byte32(data) - } - fn as_bytes(&self) -> molecule::bytes::Bytes { - self.0.clone() - } - fn as_slice(&self) -> &[u8] { - &self.0[..] - } - fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { - Byte32Reader::from_slice(slice).map(|reader| reader.to_entity()) - } - fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { - Byte32Reader::from_compatible_slice(slice).map(|reader| reader.to_entity()) - } - fn new_builder() -> Self::Builder { - ::core::default::Default::default() - } - fn as_builder(self) -> Self::Builder { - Self::new_builder().set([ - self.nth0(), - self.nth1(), - self.nth2(), - self.nth3(), - self.nth4(), - self.nth5(), - self.nth6(), - self.nth7(), - self.nth8(), - self.nth9(), - self.nth10(), - self.nth11(), - self.nth12(), - self.nth13(), - self.nth14(), - self.nth15(), - self.nth16(), - self.nth17(), - self.nth18(), - self.nth19(), - self.nth20(), - self.nth21(), - self.nth22(), - self.nth23(), - self.nth24(), - self.nth25(), - self.nth26(), - self.nth27(), - self.nth28(), - self.nth29(), - self.nth30(), - self.nth31(), - ]) - } -} -#[derive(Clone, Copy)] -pub struct Byte32Reader<'r>(&'r [u8]); -impl<'r> ::core::fmt::LowerHex for Byte32Reader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl<'r> ::core::fmt::Debug for Byte32Reader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl<'r> ::core::fmt::Display for Byte32Reader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - let raw_data = hex_string(&self.raw_data()); - write!(f, "{}(0x{})", Self::NAME, raw_data) - } -} -impl<'r> Byte32Reader<'r> { - pub const TOTAL_SIZE: usize = 32; - pub const ITEM_SIZE: usize = 1; - pub const ITEM_COUNT: usize = 32; - pub fn nth0(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[0..1]) - } - pub fn nth1(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[1..2]) - } - pub fn nth2(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[2..3]) - } - pub fn nth3(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[3..4]) - } - pub fn nth4(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[4..5]) - } - pub fn nth5(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[5..6]) - } - pub fn nth6(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[6..7]) - } - pub fn nth7(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[7..8]) - } - pub fn nth8(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[8..9]) - } - pub fn nth9(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[9..10]) - } - pub fn nth10(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[10..11]) - } - pub fn nth11(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[11..12]) - } - pub fn nth12(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[12..13]) - } - pub fn nth13(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[13..14]) - } - pub fn nth14(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[14..15]) - } - pub fn nth15(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[15..16]) - } - pub fn nth16(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[16..17]) - } - pub fn nth17(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[17..18]) - } - pub fn nth18(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[18..19]) - } - pub fn nth19(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[19..20]) - } - pub fn nth20(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[20..21]) - } - pub fn nth21(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[21..22]) - } - pub fn nth22(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[22..23]) - } - pub fn nth23(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[23..24]) - } - pub fn nth24(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[24..25]) - } - pub fn nth25(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[25..26]) - } - pub fn nth26(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[26..27]) - } - pub fn nth27(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[27..28]) - } - pub fn nth28(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[28..29]) - } - pub fn nth29(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[29..30]) - } - pub fn nth30(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[30..31]) - } - pub fn nth31(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[31..32]) - } - pub fn raw_data(&self) -> &'r [u8] { - self.as_slice() - } -} -impl<'r> molecule::prelude::Reader<'r> for Byte32Reader<'r> { - type Entity = Byte32; - const NAME: &'static str = "Byte32Reader"; - fn to_entity(&self) -> Self::Entity { - Self::Entity::new_unchecked(self.as_slice().to_owned().into()) - } - fn new_unchecked(slice: &'r [u8]) -> Self { - Byte32Reader(slice) - } - fn as_slice(&self) -> &'r [u8] { - self.0 - } - fn verify(slice: &[u8], _compatible: bool) -> molecule::error::VerificationResult<()> { - use molecule::verification_error as ve; - let slice_len = slice.len(); - if slice_len != Self::TOTAL_SIZE { - return ve!(Self, TotalSizeNotMatch, Self::TOTAL_SIZE, slice_len); - } - Ok(()) - } -} -pub struct Byte32Builder(pub(crate) [Byte; 32]); -impl ::core::fmt::Debug for Byte32Builder { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:?})", Self::NAME, &self.0[..]) - } -} -impl ::core::default::Default for Byte32Builder { - fn default() -> Self { - Byte32Builder([ - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - ]) - } -} -impl Byte32Builder { - pub const TOTAL_SIZE: usize = 32; - pub const ITEM_SIZE: usize = 1; - pub const ITEM_COUNT: usize = 32; - pub fn set(mut self, v: [Byte; 32]) -> Self { - self.0 = v; - self - } - pub fn nth0(mut self, v: Byte) -> Self { - self.0[0] = v; - self - } - pub fn nth1(mut self, v: Byte) -> Self { - self.0[1] = v; - self - } - pub fn nth2(mut self, v: Byte) -> Self { - self.0[2] = v; - self - } - pub fn nth3(mut self, v: Byte) -> Self { - self.0[3] = v; - self - } - pub fn nth4(mut self, v: Byte) -> Self { - self.0[4] = v; - self - } - pub fn nth5(mut self, v: Byte) -> Self { - self.0[5] = v; - self - } - pub fn nth6(mut self, v: Byte) -> Self { - self.0[6] = v; - self - } - pub fn nth7(mut self, v: Byte) -> Self { - self.0[7] = v; - self - } - pub fn nth8(mut self, v: Byte) -> Self { - self.0[8] = v; - self - } - pub fn nth9(mut self, v: Byte) -> Self { - self.0[9] = v; - self - } - pub fn nth10(mut self, v: Byte) -> Self { - self.0[10] = v; - self - } - pub fn nth11(mut self, v: Byte) -> Self { - self.0[11] = v; - self - } - pub fn nth12(mut self, v: Byte) -> Self { - self.0[12] = v; - self - } - pub fn nth13(mut self, v: Byte) -> Self { - self.0[13] = v; - self - } - pub fn nth14(mut self, v: Byte) -> Self { - self.0[14] = v; - self - } - pub fn nth15(mut self, v: Byte) -> Self { - self.0[15] = v; - self - } - pub fn nth16(mut self, v: Byte) -> Self { - self.0[16] = v; - self - } - pub fn nth17(mut self, v: Byte) -> Self { - self.0[17] = v; - self - } - pub fn nth18(mut self, v: Byte) -> Self { - self.0[18] = v; - self - } - pub fn nth19(mut self, v: Byte) -> Self { - self.0[19] = v; - self - } - pub fn nth20(mut self, v: Byte) -> Self { - self.0[20] = v; - self - } - pub fn nth21(mut self, v: Byte) -> Self { - self.0[21] = v; - self - } - pub fn nth22(mut self, v: Byte) -> Self { - self.0[22] = v; - self - } - pub fn nth23(mut self, v: Byte) -> Self { - self.0[23] = v; - self - } - pub fn nth24(mut self, v: Byte) -> Self { - self.0[24] = v; - self - } - pub fn nth25(mut self, v: Byte) -> Self { - self.0[25] = v; - self - } - pub fn nth26(mut self, v: Byte) -> Self { - self.0[26] = v; - self - } - pub fn nth27(mut self, v: Byte) -> Self { - self.0[27] = v; - self - } - pub fn nth28(mut self, v: Byte) -> Self { - self.0[28] = v; - self - } - pub fn nth29(mut self, v: Byte) -> Self { - self.0[29] = v; - self - } - pub fn nth30(mut self, v: Byte) -> Self { - self.0[30] = v; - self - } - pub fn nth31(mut self, v: Byte) -> Self { - self.0[31] = v; - self - } -} -impl molecule::prelude::Builder for Byte32Builder { - type Entity = Byte32; - const NAME: &'static str = "Byte32Builder"; - fn expected_length(&self) -> usize { - Self::TOTAL_SIZE - } - fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { - writer.write_all(self.0[0].as_slice())?; - writer.write_all(self.0[1].as_slice())?; - writer.write_all(self.0[2].as_slice())?; - writer.write_all(self.0[3].as_slice())?; - writer.write_all(self.0[4].as_slice())?; - writer.write_all(self.0[5].as_slice())?; - writer.write_all(self.0[6].as_slice())?; - writer.write_all(self.0[7].as_slice())?; - writer.write_all(self.0[8].as_slice())?; - writer.write_all(self.0[9].as_slice())?; - writer.write_all(self.0[10].as_slice())?; - writer.write_all(self.0[11].as_slice())?; - writer.write_all(self.0[12].as_slice())?; - writer.write_all(self.0[13].as_slice())?; - writer.write_all(self.0[14].as_slice())?; - writer.write_all(self.0[15].as_slice())?; - writer.write_all(self.0[16].as_slice())?; - writer.write_all(self.0[17].as_slice())?; - writer.write_all(self.0[18].as_slice())?; - writer.write_all(self.0[19].as_slice())?; - writer.write_all(self.0[20].as_slice())?; - writer.write_all(self.0[21].as_slice())?; - writer.write_all(self.0[22].as_slice())?; - writer.write_all(self.0[23].as_slice())?; - writer.write_all(self.0[24].as_slice())?; - writer.write_all(self.0[25].as_slice())?; - writer.write_all(self.0[26].as_slice())?; - writer.write_all(self.0[27].as_slice())?; - writer.write_all(self.0[28].as_slice())?; - writer.write_all(self.0[29].as_slice())?; - writer.write_all(self.0[30].as_slice())?; - writer.write_all(self.0[31].as_slice())?; - Ok(()) - } - fn build(&self) -> Self::Entity { - let mut inner = Vec::with_capacity(self.expected_length()); - self.write(&mut inner) - .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); - Byte32::new_unchecked(inner.into()) - } -} -#[derive(Clone)] -pub struct Bytes(molecule::bytes::Bytes); -impl ::core::fmt::LowerHex for Bytes { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl ::core::fmt::Debug for Bytes { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl ::core::fmt::Display for Bytes { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - let raw_data = hex_string(&self.raw_data()); - write!(f, "{}(0x{})", Self::NAME, raw_data) - } -} -impl ::core::default::Default for Bytes { - fn default() -> Self { - let v: Vec = vec![0, 0, 0, 0]; - Bytes::new_unchecked(v.into()) - } -} -impl Bytes { - pub const ITEM_SIZE: usize = 1; - pub fn total_size(&self) -> usize { - molecule::NUMBER_SIZE * (self.item_count() + 1) - } - pub fn item_count(&self) -> usize { - molecule::unpack_number(self.as_slice()) as usize - } - pub fn len(&self) -> usize { - self.item_count() - } - pub fn is_empty(&self) -> bool { - self.len() == 0 - } - pub fn get(&self, idx: usize) -> Option { - if idx >= self.len() { - None - } else { - Some(self.get_unchecked(idx)) - } - } - pub fn get_unchecked(&self, idx: usize) -> Byte { - let start = molecule::NUMBER_SIZE + Self::ITEM_SIZE * idx; - let end = start + Self::ITEM_SIZE; - Byte::new_unchecked(self.0.slice(start..end)) - } - pub fn raw_data(&self) -> molecule::bytes::Bytes { - self.0.slice(molecule::NUMBER_SIZE..) - } - pub fn as_reader<'r>(&'r self) -> BytesReader<'r> { - BytesReader::new_unchecked(self.as_slice()) - } -} -impl molecule::prelude::Entity for Bytes { - type Builder = BytesBuilder; - const NAME: &'static str = "Bytes"; - fn new_unchecked(data: molecule::bytes::Bytes) -> Self { - Bytes(data) - } - fn as_bytes(&self) -> molecule::bytes::Bytes { - self.0.clone() - } - fn as_slice(&self) -> &[u8] { - &self.0[..] - } - fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { - BytesReader::from_slice(slice).map(|reader| reader.to_entity()) - } - fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { - BytesReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) - } - fn new_builder() -> Self::Builder { - ::core::default::Default::default() - } - fn as_builder(self) -> Self::Builder { - Self::new_builder().extend(self.into_iter()) - } -} -#[derive(Clone, Copy)] -pub struct BytesReader<'r>(&'r [u8]); -impl<'r> ::core::fmt::LowerHex for BytesReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl<'r> ::core::fmt::Debug for BytesReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl<'r> ::core::fmt::Display for BytesReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - let raw_data = hex_string(&self.raw_data()); - write!(f, "{}(0x{})", Self::NAME, raw_data) - } -} -impl<'r> BytesReader<'r> { - pub const ITEM_SIZE: usize = 1; - pub fn total_size(&self) -> usize { - molecule::NUMBER_SIZE * (self.item_count() + 1) - } - pub fn item_count(&self) -> usize { - molecule::unpack_number(self.as_slice()) as usize - } - pub fn len(&self) -> usize { - self.item_count() - } - pub fn is_empty(&self) -> bool { - self.len() == 0 - } - pub fn get(&self, idx: usize) -> Option> { - if idx >= self.len() { - None - } else { - Some(self.get_unchecked(idx)) - } - } - pub fn get_unchecked(&self, idx: usize) -> ByteReader<'r> { - let start = molecule::NUMBER_SIZE + Self::ITEM_SIZE * idx; - let end = start + Self::ITEM_SIZE; - ByteReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn raw_data(&self) -> &'r [u8] { - &self.as_slice()[molecule::NUMBER_SIZE..] - } -} -impl<'r> molecule::prelude::Reader<'r> for BytesReader<'r> { - type Entity = Bytes; - const NAME: &'static str = "BytesReader"; - fn to_entity(&self) -> Self::Entity { - Self::Entity::new_unchecked(self.as_slice().to_owned().into()) - } - fn new_unchecked(slice: &'r [u8]) -> Self { - BytesReader(slice) - } - fn as_slice(&self) -> &'r [u8] { - self.0 - } - fn verify(slice: &[u8], _compatible: bool) -> molecule::error::VerificationResult<()> { - use molecule::verification_error as ve; - let slice_len = slice.len(); - if slice_len < molecule::NUMBER_SIZE { - return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); - } - let item_count = molecule::unpack_number(slice) as usize; - if item_count == 0 { - if slice_len != molecule::NUMBER_SIZE { - return ve!(Self, TotalSizeNotMatch, molecule::NUMBER_SIZE, slice_len); - } - return Ok(()); - } - let total_size = molecule::NUMBER_SIZE + Self::ITEM_SIZE * item_count; - if slice_len != total_size { - return ve!(Self, TotalSizeNotMatch, total_size, slice_len); - } - Ok(()) - } -} -#[derive(Debug, Default)] -pub struct BytesBuilder(pub(crate) Vec); -impl BytesBuilder { - pub const ITEM_SIZE: usize = 1; - pub fn set(mut self, v: Vec) -> Self { - self.0 = v; - self - } - pub fn push(mut self, v: Byte) -> Self { - self.0.push(v); - self - } - pub fn extend>(mut self, iter: T) -> Self { - for elem in iter { - self.0.push(elem); - } - self - } -} -impl molecule::prelude::Builder for BytesBuilder { - type Entity = Bytes; - const NAME: &'static str = "BytesBuilder"; - fn expected_length(&self) -> usize { - molecule::NUMBER_SIZE + Self::ITEM_SIZE * self.0.len() - } - fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { - writer.write_all(&molecule::pack_number(self.0.len() as molecule::Number))?; - for inner in &self.0[..] { - writer.write_all(inner.as_slice())?; - } - Ok(()) - } - fn build(&self) -> Self::Entity { - let mut inner = Vec::with_capacity(self.expected_length()); - self.write(&mut inner) - .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); - Bytes::new_unchecked(inner.into()) - } -} -pub struct BytesIterator(Bytes, usize, usize); -impl ::core::iter::Iterator for BytesIterator { - type Item = Byte; - fn next(&mut self) -> Option { - if self.1 >= self.2 { - None - } else { - let ret = self.0.get_unchecked(self.1); - self.1 += 1; - Some(ret) - } - } -} -impl ::core::iter::ExactSizeIterator for BytesIterator { - fn len(&self) -> usize { - self.2 - self.1 - } -} -impl ::core::iter::IntoIterator for Bytes { - type Item = Byte; - type IntoIter = BytesIterator; - fn into_iter(self) -> Self::IntoIter { - let len = self.len(); - BytesIterator(self, 0, len) - } -} -#[derive(Clone)] -pub struct Byte4(molecule::bytes::Bytes); -impl ::core::fmt::LowerHex for Byte4 { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl ::core::fmt::Debug for Byte4 { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl ::core::fmt::Display for Byte4 { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - let raw_data = hex_string(&self.raw_data()); - write!(f, "{}(0x{})", Self::NAME, raw_data) - } -} -impl ::core::default::Default for Byte4 { - fn default() -> Self { - let v: Vec = vec![0, 0, 0, 0]; - Byte4::new_unchecked(v.into()) - } -} -impl Byte4 { - pub const TOTAL_SIZE: usize = 4; - pub const ITEM_SIZE: usize = 1; - pub const ITEM_COUNT: usize = 4; - pub fn nth0(&self) -> Byte { - Byte::new_unchecked(self.0.slice(0..1)) - } - pub fn nth1(&self) -> Byte { - Byte::new_unchecked(self.0.slice(1..2)) - } - pub fn nth2(&self) -> Byte { - Byte::new_unchecked(self.0.slice(2..3)) - } - pub fn nth3(&self) -> Byte { - Byte::new_unchecked(self.0.slice(3..4)) - } - pub fn raw_data(&self) -> molecule::bytes::Bytes { - self.as_bytes() - } - pub fn as_reader<'r>(&'r self) -> Byte4Reader<'r> { - Byte4Reader::new_unchecked(self.as_slice()) - } -} -impl molecule::prelude::Entity for Byte4 { - type Builder = Byte4Builder; - const NAME: &'static str = "Byte4"; - fn new_unchecked(data: molecule::bytes::Bytes) -> Self { - Byte4(data) - } - fn as_bytes(&self) -> molecule::bytes::Bytes { - self.0.clone() - } - fn as_slice(&self) -> &[u8] { - &self.0[..] - } - fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { - Byte4Reader::from_slice(slice).map(|reader| reader.to_entity()) - } - fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { - Byte4Reader::from_compatible_slice(slice).map(|reader| reader.to_entity()) - } - fn new_builder() -> Self::Builder { - ::core::default::Default::default() - } - fn as_builder(self) -> Self::Builder { - Self::new_builder().set([self.nth0(), self.nth1(), self.nth2(), self.nth3()]) - } -} -#[derive(Clone, Copy)] -pub struct Byte4Reader<'r>(&'r [u8]); -impl<'r> ::core::fmt::LowerHex for Byte4Reader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl<'r> ::core::fmt::Debug for Byte4Reader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl<'r> ::core::fmt::Display for Byte4Reader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - let raw_data = hex_string(&self.raw_data()); - write!(f, "{}(0x{})", Self::NAME, raw_data) - } -} -impl<'r> Byte4Reader<'r> { - pub const TOTAL_SIZE: usize = 4; - pub const ITEM_SIZE: usize = 1; - pub const ITEM_COUNT: usize = 4; - pub fn nth0(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[0..1]) - } - pub fn nth1(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[1..2]) - } - pub fn nth2(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[2..3]) - } - pub fn nth3(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[3..4]) - } - pub fn raw_data(&self) -> &'r [u8] { - self.as_slice() - } -} -impl<'r> molecule::prelude::Reader<'r> for Byte4Reader<'r> { - type Entity = Byte4; - const NAME: &'static str = "Byte4Reader"; - fn to_entity(&self) -> Self::Entity { - Self::Entity::new_unchecked(self.as_slice().to_owned().into()) - } - fn new_unchecked(slice: &'r [u8]) -> Self { - Byte4Reader(slice) - } - fn as_slice(&self) -> &'r [u8] { - self.0 - } - fn verify(slice: &[u8], _compatible: bool) -> molecule::error::VerificationResult<()> { - use molecule::verification_error as ve; - let slice_len = slice.len(); - if slice_len != Self::TOTAL_SIZE { - return ve!(Self, TotalSizeNotMatch, Self::TOTAL_SIZE, slice_len); - } - Ok(()) - } -} -pub struct Byte4Builder(pub(crate) [Byte; 4]); -impl ::core::fmt::Debug for Byte4Builder { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:?})", Self::NAME, &self.0[..]) - } -} -impl ::core::default::Default for Byte4Builder { - fn default() -> Self { - Byte4Builder([ - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - ]) - } -} -impl Byte4Builder { - pub const TOTAL_SIZE: usize = 4; - pub const ITEM_SIZE: usize = 1; - pub const ITEM_COUNT: usize = 4; - pub fn set(mut self, v: [Byte; 4]) -> Self { - self.0 = v; - self - } - pub fn nth0(mut self, v: Byte) -> Self { - self.0[0] = v; - self - } - pub fn nth1(mut self, v: Byte) -> Self { - self.0[1] = v; - self - } - pub fn nth2(mut self, v: Byte) -> Self { - self.0[2] = v; - self - } - pub fn nth3(mut self, v: Byte) -> Self { - self.0[3] = v; - self - } -} -impl molecule::prelude::Builder for Byte4Builder { - type Entity = Byte4; - const NAME: &'static str = "Byte4Builder"; - fn expected_length(&self) -> usize { - Self::TOTAL_SIZE - } - fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { - writer.write_all(self.0[0].as_slice())?; - writer.write_all(self.0[1].as_slice())?; - writer.write_all(self.0[2].as_slice())?; - writer.write_all(self.0[3].as_slice())?; - Ok(()) - } - fn build(&self) -> Self::Entity { - let mut inner = Vec::with_capacity(self.expected_length()); - self.write(&mut inner) - .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); - Byte4::new_unchecked(inner.into()) - } -} -#[derive(Clone)] -pub struct Uint32(molecule::bytes::Bytes); -impl ::core::fmt::LowerHex for Uint32 { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl ::core::fmt::Debug for Uint32 { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl ::core::fmt::Display for Uint32 { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - let raw_data = hex_string(&self.raw_data()); - write!(f, "{}(0x{})", Self::NAME, raw_data) - } -} -impl ::core::default::Default for Uint32 { - fn default() -> Self { - let v: Vec = vec![0, 0, 0, 0]; - Uint32::new_unchecked(v.into()) - } -} -impl Uint32 { - pub const TOTAL_SIZE: usize = 4; - pub const ITEM_SIZE: usize = 1; - pub const ITEM_COUNT: usize = 4; - pub fn nth0(&self) -> Byte { - Byte::new_unchecked(self.0.slice(0..1)) - } - pub fn nth1(&self) -> Byte { - Byte::new_unchecked(self.0.slice(1..2)) - } - pub fn nth2(&self) -> Byte { - Byte::new_unchecked(self.0.slice(2..3)) - } - pub fn nth3(&self) -> Byte { - Byte::new_unchecked(self.0.slice(3..4)) - } - pub fn raw_data(&self) -> molecule::bytes::Bytes { - self.as_bytes() - } - pub fn as_reader<'r>(&'r self) -> Uint32Reader<'r> { - Uint32Reader::new_unchecked(self.as_slice()) - } -} -impl molecule::prelude::Entity for Uint32 { - type Builder = Uint32Builder; - const NAME: &'static str = "Uint32"; - fn new_unchecked(data: molecule::bytes::Bytes) -> Self { - Uint32(data) - } - fn as_bytes(&self) -> molecule::bytes::Bytes { - self.0.clone() - } - fn as_slice(&self) -> &[u8] { - &self.0[..] - } - fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { - Uint32Reader::from_slice(slice).map(|reader| reader.to_entity()) - } - fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { - Uint32Reader::from_compatible_slice(slice).map(|reader| reader.to_entity()) - } - fn new_builder() -> Self::Builder { - ::core::default::Default::default() - } - fn as_builder(self) -> Self::Builder { - Self::new_builder().set([self.nth0(), self.nth1(), self.nth2(), self.nth3()]) - } -} -#[derive(Clone, Copy)] -pub struct Uint32Reader<'r>(&'r [u8]); -impl<'r> ::core::fmt::LowerHex for Uint32Reader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl<'r> ::core::fmt::Debug for Uint32Reader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl<'r> ::core::fmt::Display for Uint32Reader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - let raw_data = hex_string(&self.raw_data()); - write!(f, "{}(0x{})", Self::NAME, raw_data) - } -} -impl<'r> Uint32Reader<'r> { - pub const TOTAL_SIZE: usize = 4; - pub const ITEM_SIZE: usize = 1; - pub const ITEM_COUNT: usize = 4; - pub fn nth0(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[0..1]) - } - pub fn nth1(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[1..2]) - } - pub fn nth2(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[2..3]) - } - pub fn nth3(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[3..4]) - } - pub fn raw_data(&self) -> &'r [u8] { - self.as_slice() - } -} -impl<'r> molecule::prelude::Reader<'r> for Uint32Reader<'r> { - type Entity = Uint32; - const NAME: &'static str = "Uint32Reader"; - fn to_entity(&self) -> Self::Entity { - Self::Entity::new_unchecked(self.as_slice().to_owned().into()) - } - fn new_unchecked(slice: &'r [u8]) -> Self { - Uint32Reader(slice) - } - fn as_slice(&self) -> &'r [u8] { - self.0 - } - fn verify(slice: &[u8], _compatible: bool) -> molecule::error::VerificationResult<()> { - use molecule::verification_error as ve; - let slice_len = slice.len(); - if slice_len != Self::TOTAL_SIZE { - return ve!(Self, TotalSizeNotMatch, Self::TOTAL_SIZE, slice_len); - } - Ok(()) - } -} -pub struct Uint32Builder(pub(crate) [Byte; 4]); -impl ::core::fmt::Debug for Uint32Builder { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:?})", Self::NAME, &self.0[..]) - } -} -impl ::core::default::Default for Uint32Builder { - fn default() -> Self { - Uint32Builder([ - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - ]) - } -} -impl Uint32Builder { - pub const TOTAL_SIZE: usize = 4; - pub const ITEM_SIZE: usize = 1; - pub const ITEM_COUNT: usize = 4; - pub fn set(mut self, v: [Byte; 4]) -> Self { - self.0 = v; - self - } - pub fn nth0(mut self, v: Byte) -> Self { - self.0[0] = v; - self - } - pub fn nth1(mut self, v: Byte) -> Self { - self.0[1] = v; - self - } - pub fn nth2(mut self, v: Byte) -> Self { - self.0[2] = v; - self - } - pub fn nth3(mut self, v: Byte) -> Self { - self.0[3] = v; - self - } -} -impl molecule::prelude::Builder for Uint32Builder { - type Entity = Uint32; - const NAME: &'static str = "Uint32Builder"; - fn expected_length(&self) -> usize { - Self::TOTAL_SIZE - } - fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { - writer.write_all(self.0[0].as_slice())?; - writer.write_all(self.0[1].as_slice())?; - writer.write_all(self.0[2].as_slice())?; - writer.write_all(self.0[3].as_slice())?; - Ok(()) - } - fn build(&self) -> Self::Entity { - let mut inner = Vec::with_capacity(self.expected_length()); - self.write(&mut inner) - .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); - Uint32::new_unchecked(inner.into()) - } -} -#[derive(Clone)] -pub struct ToCKBCellData(molecule::bytes::Bytes); -impl ::core::fmt::LowerHex for ToCKBCellData { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl ::core::fmt::Debug for ToCKBCellData { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl ::core::fmt::Display for ToCKBCellData { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{} {{ ", Self::NAME)?; - write!(f, "{}: {}", "status", self.status())?; - write!(f, ", {}: {}", "kind", self.kind())?; - write!(f, ", {}: {}", "lot_size", self.lot_size())?; - write!( - f, - ", {}: {}", - "user_lockscript_hash", - self.user_lockscript_hash() - )?; - write!(f, ", {}: {}", "x_lock_address", self.x_lock_address())?; - write!( - f, - ", {}: {}", - "signer_lockscript_hash", - self.signer_lockscript_hash() - )?; - write!(f, ", {}: {}", "x_unlock_address", self.x_unlock_address())?; - write!( - f, - ", {}: {}", - "redeemer_lockscript_hash", - self.redeemer_lockscript_hash() - )?; - write!( - f, - ", {}: {}", - "liquidation_trigger_lockscript_hash", - self.liquidation_trigger_lockscript_hash() - )?; - let extra_count = self.count_extra_fields(); - if extra_count != 0 { - write!(f, ", .. ({} fields)", extra_count)?; - } - write!(f, " }}") - } -} -impl ::core::default::Default for ToCKBCellData { - fn default() -> Self { - let v: Vec = vec![ - 179, 0, 0, 0, 40, 0, 0, 0, 41, 0, 0, 0, 42, 0, 0, 0, 43, 0, 0, 0, 75, 0, 0, 0, 79, 0, - 0, 0, 111, 0, 0, 0, 115, 0, 0, 0, 147, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ]; - ToCKBCellData::new_unchecked(v.into()) - } -} -impl ToCKBCellData { - pub const FIELD_COUNT: usize = 9; - pub fn total_size(&self) -> usize { - molecule::unpack_number(self.as_slice()) as usize - } - pub fn field_count(&self) -> usize { - if self.total_size() == molecule::NUMBER_SIZE { - 0 - } else { - (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 - } - } - pub fn count_extra_fields(&self) -> usize { - self.field_count() - Self::FIELD_COUNT - } - pub fn has_extra_fields(&self) -> bool { - Self::FIELD_COUNT != self.field_count() - } - pub fn status(&self) -> Byte { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[4..]) as usize; - let end = molecule::unpack_number(&slice[8..]) as usize; - Byte::new_unchecked(self.0.slice(start..end)) - } - pub fn kind(&self) -> Byte { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[8..]) as usize; - let end = molecule::unpack_number(&slice[12..]) as usize; - Byte::new_unchecked(self.0.slice(start..end)) - } - pub fn lot_size(&self) -> Byte { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[12..]) as usize; - let end = molecule::unpack_number(&slice[16..]) as usize; - Byte::new_unchecked(self.0.slice(start..end)) - } - pub fn user_lockscript_hash(&self) -> Byte32 { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[16..]) as usize; - let end = molecule::unpack_number(&slice[20..]) as usize; - Byte32::new_unchecked(self.0.slice(start..end)) - } - pub fn x_lock_address(&self) -> Bytes { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[20..]) as usize; - let end = molecule::unpack_number(&slice[24..]) as usize; - Bytes::new_unchecked(self.0.slice(start..end)) - } - pub fn signer_lockscript_hash(&self) -> Byte32 { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[24..]) as usize; - let end = molecule::unpack_number(&slice[28..]) as usize; - Byte32::new_unchecked(self.0.slice(start..end)) - } - pub fn x_unlock_address(&self) -> Bytes { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[28..]) as usize; - let end = molecule::unpack_number(&slice[32..]) as usize; - Bytes::new_unchecked(self.0.slice(start..end)) - } - pub fn redeemer_lockscript_hash(&self) -> Byte32 { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[32..]) as usize; - let end = molecule::unpack_number(&slice[36..]) as usize; - Byte32::new_unchecked(self.0.slice(start..end)) - } - pub fn liquidation_trigger_lockscript_hash(&self) -> Byte32 { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[36..]) as usize; - if self.has_extra_fields() { - let end = molecule::unpack_number(&slice[40..]) as usize; - Byte32::new_unchecked(self.0.slice(start..end)) - } else { - Byte32::new_unchecked(self.0.slice(start..)) - } - } - pub fn as_reader<'r>(&'r self) -> ToCKBCellDataReader<'r> { - ToCKBCellDataReader::new_unchecked(self.as_slice()) - } -} -impl molecule::prelude::Entity for ToCKBCellData { - type Builder = ToCKBCellDataBuilder; - const NAME: &'static str = "ToCKBCellData"; - fn new_unchecked(data: molecule::bytes::Bytes) -> Self { - ToCKBCellData(data) - } - fn as_bytes(&self) -> molecule::bytes::Bytes { - self.0.clone() - } - fn as_slice(&self) -> &[u8] { - &self.0[..] - } - fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { - ToCKBCellDataReader::from_slice(slice).map(|reader| reader.to_entity()) - } - fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { - ToCKBCellDataReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) - } - fn new_builder() -> Self::Builder { - ::core::default::Default::default() - } - fn as_builder(self) -> Self::Builder { - Self::new_builder() - .status(self.status()) - .kind(self.kind()) - .lot_size(self.lot_size()) - .user_lockscript_hash(self.user_lockscript_hash()) - .x_lock_address(self.x_lock_address()) - .signer_lockscript_hash(self.signer_lockscript_hash()) - .x_unlock_address(self.x_unlock_address()) - .redeemer_lockscript_hash(self.redeemer_lockscript_hash()) - .liquidation_trigger_lockscript_hash(self.liquidation_trigger_lockscript_hash()) - } -} -#[derive(Clone, Copy)] -pub struct ToCKBCellDataReader<'r>(&'r [u8]); -impl<'r> ::core::fmt::LowerHex for ToCKBCellDataReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl<'r> ::core::fmt::Debug for ToCKBCellDataReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl<'r> ::core::fmt::Display for ToCKBCellDataReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{} {{ ", Self::NAME)?; - write!(f, "{}: {}", "status", self.status())?; - write!(f, ", {}: {}", "kind", self.kind())?; - write!(f, ", {}: {}", "lot_size", self.lot_size())?; - write!( - f, - ", {}: {}", - "user_lockscript_hash", - self.user_lockscript_hash() - )?; - write!(f, ", {}: {}", "x_lock_address", self.x_lock_address())?; - write!( - f, - ", {}: {}", - "signer_lockscript_hash", - self.signer_lockscript_hash() - )?; - write!(f, ", {}: {}", "x_unlock_address", self.x_unlock_address())?; - write!( - f, - ", {}: {}", - "redeemer_lockscript_hash", - self.redeemer_lockscript_hash() - )?; - write!( - f, - ", {}: {}", - "liquidation_trigger_lockscript_hash", - self.liquidation_trigger_lockscript_hash() - )?; - let extra_count = self.count_extra_fields(); - if extra_count != 0 { - write!(f, ", .. ({} fields)", extra_count)?; - } - write!(f, " }}") - } -} -impl<'r> ToCKBCellDataReader<'r> { - pub const FIELD_COUNT: usize = 9; - pub fn total_size(&self) -> usize { - molecule::unpack_number(self.as_slice()) as usize - } - pub fn field_count(&self) -> usize { - if self.total_size() == molecule::NUMBER_SIZE { - 0 - } else { - (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 - } - } - pub fn count_extra_fields(&self) -> usize { - self.field_count() - Self::FIELD_COUNT - } - pub fn has_extra_fields(&self) -> bool { - Self::FIELD_COUNT != self.field_count() - } - pub fn status(&self) -> ByteReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[4..]) as usize; - let end = molecule::unpack_number(&slice[8..]) as usize; - ByteReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn kind(&self) -> ByteReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[8..]) as usize; - let end = molecule::unpack_number(&slice[12..]) as usize; - ByteReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn lot_size(&self) -> ByteReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[12..]) as usize; - let end = molecule::unpack_number(&slice[16..]) as usize; - ByteReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn user_lockscript_hash(&self) -> Byte32Reader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[16..]) as usize; - let end = molecule::unpack_number(&slice[20..]) as usize; - Byte32Reader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn x_lock_address(&self) -> BytesReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[20..]) as usize; - let end = molecule::unpack_number(&slice[24..]) as usize; - BytesReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn signer_lockscript_hash(&self) -> Byte32Reader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[24..]) as usize; - let end = molecule::unpack_number(&slice[28..]) as usize; - Byte32Reader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn x_unlock_address(&self) -> BytesReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[28..]) as usize; - let end = molecule::unpack_number(&slice[32..]) as usize; - BytesReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn redeemer_lockscript_hash(&self) -> Byte32Reader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[32..]) as usize; - let end = molecule::unpack_number(&slice[36..]) as usize; - Byte32Reader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn liquidation_trigger_lockscript_hash(&self) -> Byte32Reader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[36..]) as usize; - if self.has_extra_fields() { - let end = molecule::unpack_number(&slice[40..]) as usize; - Byte32Reader::new_unchecked(&self.as_slice()[start..end]) - } else { - Byte32Reader::new_unchecked(&self.as_slice()[start..]) - } - } -} -impl<'r> molecule::prelude::Reader<'r> for ToCKBCellDataReader<'r> { - type Entity = ToCKBCellData; - const NAME: &'static str = "ToCKBCellDataReader"; - fn to_entity(&self) -> Self::Entity { - Self::Entity::new_unchecked(self.as_slice().to_owned().into()) - } - fn new_unchecked(slice: &'r [u8]) -> Self { - ToCKBCellDataReader(slice) - } - fn as_slice(&self) -> &'r [u8] { - self.0 - } - fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { - use molecule::verification_error as ve; - let slice_len = slice.len(); - if slice_len < molecule::NUMBER_SIZE { - return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); - } - let total_size = molecule::unpack_number(slice) as usize; - if slice_len != total_size { - return ve!(Self, TotalSizeNotMatch, total_size, slice_len); - } - if slice_len == molecule::NUMBER_SIZE && Self::FIELD_COUNT == 0 { - return Ok(()); - } - if slice_len < molecule::NUMBER_SIZE * 2 { - return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); - } - let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; - if offset_first % 4 != 0 || offset_first < molecule::NUMBER_SIZE * 2 { - return ve!(Self, OffsetsNotMatch); - } - let field_count = offset_first / 4 - 1; - if field_count < Self::FIELD_COUNT { - return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); - } else if !compatible && field_count > Self::FIELD_COUNT { - return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); - }; - let header_size = molecule::NUMBER_SIZE * (field_count + 1); - if slice_len < header_size { - return ve!(Self, HeaderIsBroken, header_size, slice_len); - } - let mut offsets: Vec = slice[molecule::NUMBER_SIZE..] - .chunks(molecule::NUMBER_SIZE) - .take(field_count) - .map(|x| molecule::unpack_number(x) as usize) - .collect(); - offsets.push(total_size); - if offsets.windows(2).any(|i| i[0] > i[1]) { - return ve!(Self, OffsetsNotMatch); - } - ByteReader::verify(&slice[offsets[0]..offsets[1]], compatible)?; - ByteReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; - ByteReader::verify(&slice[offsets[2]..offsets[3]], compatible)?; - Byte32Reader::verify(&slice[offsets[3]..offsets[4]], compatible)?; - BytesReader::verify(&slice[offsets[4]..offsets[5]], compatible)?; - Byte32Reader::verify(&slice[offsets[5]..offsets[6]], compatible)?; - BytesReader::verify(&slice[offsets[6]..offsets[7]], compatible)?; - Byte32Reader::verify(&slice[offsets[7]..offsets[8]], compatible)?; - Byte32Reader::verify(&slice[offsets[8]..offsets[9]], compatible)?; - Ok(()) - } -} -#[derive(Debug, Default)] -pub struct ToCKBCellDataBuilder { - pub(crate) status: Byte, - pub(crate) kind: Byte, - pub(crate) lot_size: Byte, - pub(crate) user_lockscript_hash: Byte32, - pub(crate) x_lock_address: Bytes, - pub(crate) signer_lockscript_hash: Byte32, - pub(crate) x_unlock_address: Bytes, - pub(crate) redeemer_lockscript_hash: Byte32, - pub(crate) liquidation_trigger_lockscript_hash: Byte32, -} -impl ToCKBCellDataBuilder { - pub const FIELD_COUNT: usize = 9; - pub fn status(mut self, v: Byte) -> Self { - self.status = v; - self - } - pub fn kind(mut self, v: Byte) -> Self { - self.kind = v; - self - } - pub fn lot_size(mut self, v: Byte) -> Self { - self.lot_size = v; - self - } - pub fn user_lockscript_hash(mut self, v: Byte32) -> Self { - self.user_lockscript_hash = v; - self - } - pub fn x_lock_address(mut self, v: Bytes) -> Self { - self.x_lock_address = v; - self - } - pub fn signer_lockscript_hash(mut self, v: Byte32) -> Self { - self.signer_lockscript_hash = v; - self - } - pub fn x_unlock_address(mut self, v: Bytes) -> Self { - self.x_unlock_address = v; - self - } - pub fn redeemer_lockscript_hash(mut self, v: Byte32) -> Self { - self.redeemer_lockscript_hash = v; - self - } - pub fn liquidation_trigger_lockscript_hash(mut self, v: Byte32) -> Self { - self.liquidation_trigger_lockscript_hash = v; - self - } -} -impl molecule::prelude::Builder for ToCKBCellDataBuilder { - type Entity = ToCKBCellData; - const NAME: &'static str = "ToCKBCellDataBuilder"; - fn expected_length(&self) -> usize { - molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) - + self.status.as_slice().len() - + self.kind.as_slice().len() - + self.lot_size.as_slice().len() - + self.user_lockscript_hash.as_slice().len() - + self.x_lock_address.as_slice().len() - + self.signer_lockscript_hash.as_slice().len() - + self.x_unlock_address.as_slice().len() - + self.redeemer_lockscript_hash.as_slice().len() - + self.liquidation_trigger_lockscript_hash.as_slice().len() - } - fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { - let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); - let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); - offsets.push(total_size); - total_size += self.status.as_slice().len(); - offsets.push(total_size); - total_size += self.kind.as_slice().len(); - offsets.push(total_size); - total_size += self.lot_size.as_slice().len(); - offsets.push(total_size); - total_size += self.user_lockscript_hash.as_slice().len(); - offsets.push(total_size); - total_size += self.x_lock_address.as_slice().len(); - offsets.push(total_size); - total_size += self.signer_lockscript_hash.as_slice().len(); - offsets.push(total_size); - total_size += self.x_unlock_address.as_slice().len(); - offsets.push(total_size); - total_size += self.redeemer_lockscript_hash.as_slice().len(); - offsets.push(total_size); - total_size += self.liquidation_trigger_lockscript_hash.as_slice().len(); - writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; - for offset in offsets.into_iter() { - writer.write_all(&molecule::pack_number(offset as molecule::Number))?; - } - writer.write_all(self.status.as_slice())?; - writer.write_all(self.kind.as_slice())?; - writer.write_all(self.lot_size.as_slice())?; - writer.write_all(self.user_lockscript_hash.as_slice())?; - writer.write_all(self.x_lock_address.as_slice())?; - writer.write_all(self.signer_lockscript_hash.as_slice())?; - writer.write_all(self.x_unlock_address.as_slice())?; - writer.write_all(self.redeemer_lockscript_hash.as_slice())?; - writer.write_all(self.liquidation_trigger_lockscript_hash.as_slice())?; - Ok(()) - } - fn build(&self) -> Self::Entity { - let mut inner = Vec::with_capacity(self.expected_length()); - self.write(&mut inner) - .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); - ToCKBCellData::new_unchecked(inner.into()) - } -} -#[derive(Clone)] -pub struct MintXTWitness(molecule::bytes::Bytes); -impl ::core::fmt::LowerHex for MintXTWitness { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl ::core::fmt::Debug for MintXTWitness { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl ::core::fmt::Display for MintXTWitness { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{} {{ ", Self::NAME)?; - write!(f, "{}: {}", "spv_proof", self.spv_proof())?; - write!( - f, - ", {}: {}", - "cell_dep_index_list", - self.cell_dep_index_list() - )?; - let extra_count = self.count_extra_fields(); - if extra_count != 0 { - write!(f, ", .. ({} fields)", extra_count)?; - } - write!(f, " }}") - } -} -impl ::core::default::Default for MintXTWitness { - fn default() -> Self { - let v: Vec = vec![ - 20, 0, 0, 0, 12, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ]; - MintXTWitness::new_unchecked(v.into()) - } -} -impl MintXTWitness { - pub const FIELD_COUNT: usize = 2; - pub fn total_size(&self) -> usize { - molecule::unpack_number(self.as_slice()) as usize - } - pub fn field_count(&self) -> usize { - if self.total_size() == molecule::NUMBER_SIZE { - 0 - } else { - (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 - } - } - pub fn count_extra_fields(&self) -> usize { - self.field_count() - Self::FIELD_COUNT - } - pub fn has_extra_fields(&self) -> bool { - Self::FIELD_COUNT != self.field_count() - } - pub fn spv_proof(&self) -> Bytes { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[4..]) as usize; - let end = molecule::unpack_number(&slice[8..]) as usize; - Bytes::new_unchecked(self.0.slice(start..end)) - } - pub fn cell_dep_index_list(&self) -> Bytes { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[8..]) as usize; - if self.has_extra_fields() { - let end = molecule::unpack_number(&slice[12..]) as usize; - Bytes::new_unchecked(self.0.slice(start..end)) - } else { - Bytes::new_unchecked(self.0.slice(start..)) - } - } - pub fn as_reader<'r>(&'r self) -> MintXTWitnessReader<'r> { - MintXTWitnessReader::new_unchecked(self.as_slice()) - } -} -impl molecule::prelude::Entity for MintXTWitness { - type Builder = MintXTWitnessBuilder; - const NAME: &'static str = "MintXTWitness"; - fn new_unchecked(data: molecule::bytes::Bytes) -> Self { - MintXTWitness(data) - } - fn as_bytes(&self) -> molecule::bytes::Bytes { - self.0.clone() - } - fn as_slice(&self) -> &[u8] { - &self.0[..] - } - fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { - MintXTWitnessReader::from_slice(slice).map(|reader| reader.to_entity()) - } - fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { - MintXTWitnessReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) - } - fn new_builder() -> Self::Builder { - ::core::default::Default::default() - } - fn as_builder(self) -> Self::Builder { - Self::new_builder() - .spv_proof(self.spv_proof()) - .cell_dep_index_list(self.cell_dep_index_list()) - } -} -#[derive(Clone, Copy)] -pub struct MintXTWitnessReader<'r>(&'r [u8]); -impl<'r> ::core::fmt::LowerHex for MintXTWitnessReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl<'r> ::core::fmt::Debug for MintXTWitnessReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl<'r> ::core::fmt::Display for MintXTWitnessReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{} {{ ", Self::NAME)?; - write!(f, "{}: {}", "spv_proof", self.spv_proof())?; - write!( - f, - ", {}: {}", - "cell_dep_index_list", - self.cell_dep_index_list() - )?; - let extra_count = self.count_extra_fields(); - if extra_count != 0 { - write!(f, ", .. ({} fields)", extra_count)?; - } - write!(f, " }}") - } -} -impl<'r> MintXTWitnessReader<'r> { - pub const FIELD_COUNT: usize = 2; - pub fn total_size(&self) -> usize { - molecule::unpack_number(self.as_slice()) as usize - } - pub fn field_count(&self) -> usize { - if self.total_size() == molecule::NUMBER_SIZE { - 0 - } else { - (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 - } - } - pub fn count_extra_fields(&self) -> usize { - self.field_count() - Self::FIELD_COUNT - } - pub fn has_extra_fields(&self) -> bool { - Self::FIELD_COUNT != self.field_count() - } - pub fn spv_proof(&self) -> BytesReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[4..]) as usize; - let end = molecule::unpack_number(&slice[8..]) as usize; - BytesReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn cell_dep_index_list(&self) -> BytesReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[8..]) as usize; - if self.has_extra_fields() { - let end = molecule::unpack_number(&slice[12..]) as usize; - BytesReader::new_unchecked(&self.as_slice()[start..end]) - } else { - BytesReader::new_unchecked(&self.as_slice()[start..]) - } - } -} -impl<'r> molecule::prelude::Reader<'r> for MintXTWitnessReader<'r> { - type Entity = MintXTWitness; - const NAME: &'static str = "MintXTWitnessReader"; - fn to_entity(&self) -> Self::Entity { - Self::Entity::new_unchecked(self.as_slice().to_owned().into()) - } - fn new_unchecked(slice: &'r [u8]) -> Self { - MintXTWitnessReader(slice) - } - fn as_slice(&self) -> &'r [u8] { - self.0 - } - fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { - use molecule::verification_error as ve; - let slice_len = slice.len(); - if slice_len < molecule::NUMBER_SIZE { - return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); - } - let total_size = molecule::unpack_number(slice) as usize; - if slice_len != total_size { - return ve!(Self, TotalSizeNotMatch, total_size, slice_len); - } - if slice_len == molecule::NUMBER_SIZE && Self::FIELD_COUNT == 0 { - return Ok(()); - } - if slice_len < molecule::NUMBER_SIZE * 2 { - return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); - } - let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; - if offset_first % 4 != 0 || offset_first < molecule::NUMBER_SIZE * 2 { - return ve!(Self, OffsetsNotMatch); - } - let field_count = offset_first / 4 - 1; - if field_count < Self::FIELD_COUNT { - return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); - } else if !compatible && field_count > Self::FIELD_COUNT { - return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); - }; - let header_size = molecule::NUMBER_SIZE * (field_count + 1); - if slice_len < header_size { - return ve!(Self, HeaderIsBroken, header_size, slice_len); - } - let mut offsets: Vec = slice[molecule::NUMBER_SIZE..] - .chunks(molecule::NUMBER_SIZE) - .take(field_count) - .map(|x| molecule::unpack_number(x) as usize) - .collect(); - offsets.push(total_size); - if offsets.windows(2).any(|i| i[0] > i[1]) { - return ve!(Self, OffsetsNotMatch); - } - BytesReader::verify(&slice[offsets[0]..offsets[1]], compatible)?; - BytesReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; - Ok(()) - } -} -#[derive(Debug, Default)] -pub struct MintXTWitnessBuilder { - pub(crate) spv_proof: Bytes, - pub(crate) cell_dep_index_list: Bytes, -} -impl MintXTWitnessBuilder { - pub const FIELD_COUNT: usize = 2; - pub fn spv_proof(mut self, v: Bytes) -> Self { - self.spv_proof = v; - self - } - pub fn cell_dep_index_list(mut self, v: Bytes) -> Self { - self.cell_dep_index_list = v; - self - } -} -impl molecule::prelude::Builder for MintXTWitnessBuilder { - type Entity = MintXTWitness; - const NAME: &'static str = "MintXTWitnessBuilder"; - fn expected_length(&self) -> usize { - molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) - + self.spv_proof.as_slice().len() - + self.cell_dep_index_list.as_slice().len() - } - fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { - let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); - let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); - offsets.push(total_size); - total_size += self.spv_proof.as_slice().len(); - offsets.push(total_size); - total_size += self.cell_dep_index_list.as_slice().len(); - writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; - for offset in offsets.into_iter() { - writer.write_all(&molecule::pack_number(offset as molecule::Number))?; - } - writer.write_all(self.spv_proof.as_slice())?; - writer.write_all(self.cell_dep_index_list.as_slice())?; - Ok(()) - } - fn build(&self) -> Self::Entity { - let mut inner = Vec::with_capacity(self.expected_length()); - self.write(&mut inner) - .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); - MintXTWitness::new_unchecked(inner.into()) - } -} -#[derive(Clone)] -pub struct BTCSPVProof(molecule::bytes::Bytes); -impl ::core::fmt::LowerHex for BTCSPVProof { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl ::core::fmt::Debug for BTCSPVProof { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl ::core::fmt::Display for BTCSPVProof { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{} {{ ", Self::NAME)?; - write!(f, "{}: {}", "version", self.version())?; - write!(f, ", {}: {}", "vin", self.vin())?; - write!(f, ", {}: {}", "vout", self.vout())?; - write!(f, ", {}: {}", "locktime", self.locktime())?; - write!(f, ", {}: {}", "tx_id", self.tx_id())?; - write!(f, ", {}: {}", "index", self.index())?; - write!(f, ", {}: {}", "headers", self.headers())?; - write!( - f, - ", {}: {}", - "intermediate_nodes", - self.intermediate_nodes() - )?; - write!( - f, - ", {}: {}", - "funding_output_index", - self.funding_output_index() - )?; - let extra_count = self.count_extra_fields(); - if extra_count != 0 { - write!(f, ", .. ({} fields)", extra_count)?; - } - write!(f, " }}") - } -} -impl ::core::default::Default for BTCSPVProof { - fn default() -> Self { - let v: Vec = vec![ - 101, 0, 0, 0, 40, 0, 0, 0, 44, 0, 0, 0, 48, 0, 0, 0, 52, 0, 0, 0, 56, 0, 0, 0, 88, 0, - 0, 0, 92, 0, 0, 0, 96, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ]; - BTCSPVProof::new_unchecked(v.into()) - } -} -impl BTCSPVProof { - pub const FIELD_COUNT: usize = 9; - pub fn total_size(&self) -> usize { - molecule::unpack_number(self.as_slice()) as usize - } - pub fn field_count(&self) -> usize { - if self.total_size() == molecule::NUMBER_SIZE { - 0 - } else { - (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 - } - } - pub fn count_extra_fields(&self) -> usize { - self.field_count() - Self::FIELD_COUNT - } - pub fn has_extra_fields(&self) -> bool { - Self::FIELD_COUNT != self.field_count() - } - pub fn version(&self) -> Byte4 { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[4..]) as usize; - let end = molecule::unpack_number(&slice[8..]) as usize; - Byte4::new_unchecked(self.0.slice(start..end)) - } - pub fn vin(&self) -> Bytes { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[8..]) as usize; - let end = molecule::unpack_number(&slice[12..]) as usize; - Bytes::new_unchecked(self.0.slice(start..end)) - } - pub fn vout(&self) -> Bytes { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[12..]) as usize; - let end = molecule::unpack_number(&slice[16..]) as usize; - Bytes::new_unchecked(self.0.slice(start..end)) - } - pub fn locktime(&self) -> Byte4 { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[16..]) as usize; - let end = molecule::unpack_number(&slice[20..]) as usize; - Byte4::new_unchecked(self.0.slice(start..end)) - } - pub fn tx_id(&self) -> Byte32 { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[20..]) as usize; - let end = molecule::unpack_number(&slice[24..]) as usize; - Byte32::new_unchecked(self.0.slice(start..end)) - } - pub fn index(&self) -> Uint32 { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[24..]) as usize; - let end = molecule::unpack_number(&slice[28..]) as usize; - Uint32::new_unchecked(self.0.slice(start..end)) - } - pub fn headers(&self) -> Bytes { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[28..]) as usize; - let end = molecule::unpack_number(&slice[32..]) as usize; - Bytes::new_unchecked(self.0.slice(start..end)) - } - pub fn intermediate_nodes(&self) -> Bytes { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[32..]) as usize; - let end = molecule::unpack_number(&slice[36..]) as usize; - Bytes::new_unchecked(self.0.slice(start..end)) - } - pub fn funding_output_index(&self) -> Byte { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[36..]) as usize; - if self.has_extra_fields() { - let end = molecule::unpack_number(&slice[40..]) as usize; - Byte::new_unchecked(self.0.slice(start..end)) - } else { - Byte::new_unchecked(self.0.slice(start..)) - } - } - pub fn as_reader<'r>(&'r self) -> BTCSPVProofReader<'r> { - BTCSPVProofReader::new_unchecked(self.as_slice()) - } -} -impl molecule::prelude::Entity for BTCSPVProof { - type Builder = BTCSPVProofBuilder; - const NAME: &'static str = "BTCSPVProof"; - fn new_unchecked(data: molecule::bytes::Bytes) -> Self { - BTCSPVProof(data) - } - fn as_bytes(&self) -> molecule::bytes::Bytes { - self.0.clone() - } - fn as_slice(&self) -> &[u8] { - &self.0[..] - } - fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { - BTCSPVProofReader::from_slice(slice).map(|reader| reader.to_entity()) - } - fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { - BTCSPVProofReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) - } - fn new_builder() -> Self::Builder { - ::core::default::Default::default() - } - fn as_builder(self) -> Self::Builder { - Self::new_builder() - .version(self.version()) - .vin(self.vin()) - .vout(self.vout()) - .locktime(self.locktime()) - .tx_id(self.tx_id()) - .index(self.index()) - .headers(self.headers()) - .intermediate_nodes(self.intermediate_nodes()) - .funding_output_index(self.funding_output_index()) - } -} -#[derive(Clone, Copy)] -pub struct BTCSPVProofReader<'r>(&'r [u8]); -impl<'r> ::core::fmt::LowerHex for BTCSPVProofReader<'r> { +pub struct ToCKBCellData(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for ToCKBCellData { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; if f.alternate() { @@ -2160,32 +13,42 @@ impl<'r> ::core::fmt::LowerHex for BTCSPVProofReader<'r> { write!(f, "{}", hex_string(self.as_slice())) } } -impl<'r> ::core::fmt::Debug for BTCSPVProofReader<'r> { +impl ::core::fmt::Debug for ToCKBCellData { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:#x})", Self::NAME, self) } } -impl<'r> ::core::fmt::Display for BTCSPVProofReader<'r> { +impl ::core::fmt::Display for ToCKBCellData { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{} {{ ", Self::NAME)?; - write!(f, "{}: {}", "version", self.version())?; - write!(f, ", {}: {}", "vin", self.vin())?; - write!(f, ", {}: {}", "vout", self.vout())?; - write!(f, ", {}: {}", "locktime", self.locktime())?; - write!(f, ", {}: {}", "tx_id", self.tx_id())?; - write!(f, ", {}: {}", "index", self.index())?; - write!(f, ", {}: {}", "headers", self.headers())?; + write!(f, "{}: {}", "status", self.status())?; + write!(f, ", {}: {}", "kind", self.kind())?; + write!(f, ", {}: {}", "lot_size", self.lot_size())?; write!( f, ", {}: {}", - "intermediate_nodes", - self.intermediate_nodes() + "user_lockscript_hash", + self.user_lockscript_hash() )?; + write!(f, ", {}: {}", "x_lock_address", self.x_lock_address())?; write!( f, ", {}: {}", - "funding_output_index", - self.funding_output_index() + "signer_lockscript_hash", + self.signer_lockscript_hash() + )?; + write!(f, ", {}: {}", "x_unlock_address", self.x_unlock_address())?; + write!( + f, + ", {}: {}", + "redeemer_lockscript_hash", + self.redeemer_lockscript_hash() + )?; + write!( + f, + ", {}: {}", + "liquidation_trigger_lockscript_hash", + self.liquidation_trigger_lockscript_hash() )?; let extra_count = self.count_extra_fields(); if extra_count != 0 { @@ -2194,293 +57,22 @@ impl<'r> ::core::fmt::Display for BTCSPVProofReader<'r> { write!(f, " }}") } } -impl<'r> BTCSPVProofReader<'r> { - pub const FIELD_COUNT: usize = 9; - pub fn total_size(&self) -> usize { - molecule::unpack_number(self.as_slice()) as usize - } - pub fn field_count(&self) -> usize { - if self.total_size() == molecule::NUMBER_SIZE { - 0 - } else { - (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 - } - } - pub fn count_extra_fields(&self) -> usize { - self.field_count() - Self::FIELD_COUNT - } - pub fn has_extra_fields(&self) -> bool { - Self::FIELD_COUNT != self.field_count() - } - pub fn version(&self) -> Byte4Reader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[4..]) as usize; - let end = molecule::unpack_number(&slice[8..]) as usize; - Byte4Reader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn vin(&self) -> BytesReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[8..]) as usize; - let end = molecule::unpack_number(&slice[12..]) as usize; - BytesReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn vout(&self) -> BytesReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[12..]) as usize; - let end = molecule::unpack_number(&slice[16..]) as usize; - BytesReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn locktime(&self) -> Byte4Reader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[16..]) as usize; - let end = molecule::unpack_number(&slice[20..]) as usize; - Byte4Reader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn tx_id(&self) -> Byte32Reader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[20..]) as usize; - let end = molecule::unpack_number(&slice[24..]) as usize; - Byte32Reader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn index(&self) -> Uint32Reader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[24..]) as usize; - let end = molecule::unpack_number(&slice[28..]) as usize; - Uint32Reader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn headers(&self) -> BytesReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[28..]) as usize; - let end = molecule::unpack_number(&slice[32..]) as usize; - BytesReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn intermediate_nodes(&self) -> BytesReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[32..]) as usize; - let end = molecule::unpack_number(&slice[36..]) as usize; - BytesReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn funding_output_index(&self) -> ByteReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[36..]) as usize; - if self.has_extra_fields() { - let end = molecule::unpack_number(&slice[40..]) as usize; - ByteReader::new_unchecked(&self.as_slice()[start..end]) - } else { - ByteReader::new_unchecked(&self.as_slice()[start..]) - } - } -} -impl<'r> molecule::prelude::Reader<'r> for BTCSPVProofReader<'r> { - type Entity = BTCSPVProof; - const NAME: &'static str = "BTCSPVProofReader"; - fn to_entity(&self) -> Self::Entity { - Self::Entity::new_unchecked(self.as_slice().to_owned().into()) - } - fn new_unchecked(slice: &'r [u8]) -> Self { - BTCSPVProofReader(slice) - } - fn as_slice(&self) -> &'r [u8] { - self.0 - } - fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { - use molecule::verification_error as ve; - let slice_len = slice.len(); - if slice_len < molecule::NUMBER_SIZE { - return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); - } - let total_size = molecule::unpack_number(slice) as usize; - if slice_len != total_size { - return ve!(Self, TotalSizeNotMatch, total_size, slice_len); - } - if slice_len == molecule::NUMBER_SIZE && Self::FIELD_COUNT == 0 { - return Ok(()); - } - if slice_len < molecule::NUMBER_SIZE * 2 { - return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); - } - let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; - if offset_first % 4 != 0 || offset_first < molecule::NUMBER_SIZE * 2 { - return ve!(Self, OffsetsNotMatch); - } - let field_count = offset_first / 4 - 1; - if field_count < Self::FIELD_COUNT { - return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); - } else if !compatible && field_count > Self::FIELD_COUNT { - return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); - }; - let header_size = molecule::NUMBER_SIZE * (field_count + 1); - if slice_len < header_size { - return ve!(Self, HeaderIsBroken, header_size, slice_len); - } - let mut offsets: Vec = slice[molecule::NUMBER_SIZE..] - .chunks(molecule::NUMBER_SIZE) - .take(field_count) - .map(|x| molecule::unpack_number(x) as usize) - .collect(); - offsets.push(total_size); - if offsets.windows(2).any(|i| i[0] > i[1]) { - return ve!(Self, OffsetsNotMatch); - } - Byte4Reader::verify(&slice[offsets[0]..offsets[1]], compatible)?; - BytesReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; - BytesReader::verify(&slice[offsets[2]..offsets[3]], compatible)?; - Byte4Reader::verify(&slice[offsets[3]..offsets[4]], compatible)?; - Byte32Reader::verify(&slice[offsets[4]..offsets[5]], compatible)?; - Uint32Reader::verify(&slice[offsets[5]..offsets[6]], compatible)?; - BytesReader::verify(&slice[offsets[6]..offsets[7]], compatible)?; - BytesReader::verify(&slice[offsets[7]..offsets[8]], compatible)?; - ByteReader::verify(&slice[offsets[8]..offsets[9]], compatible)?; - Ok(()) - } -} -#[derive(Debug, Default)] -pub struct BTCSPVProofBuilder { - pub(crate) version: Byte4, - pub(crate) vin: Bytes, - pub(crate) vout: Bytes, - pub(crate) locktime: Byte4, - pub(crate) tx_id: Byte32, - pub(crate) index: Uint32, - pub(crate) headers: Bytes, - pub(crate) intermediate_nodes: Bytes, - pub(crate) funding_output_index: Byte, -} -impl BTCSPVProofBuilder { - pub const FIELD_COUNT: usize = 9; - pub fn version(mut self, v: Byte4) -> Self { - self.version = v; - self - } - pub fn vin(mut self, v: Bytes) -> Self { - self.vin = v; - self - } - pub fn vout(mut self, v: Bytes) -> Self { - self.vout = v; - self - } - pub fn locktime(mut self, v: Byte4) -> Self { - self.locktime = v; - self - } - pub fn tx_id(mut self, v: Byte32) -> Self { - self.tx_id = v; - self - } - pub fn index(mut self, v: Uint32) -> Self { - self.index = v; - self - } - pub fn headers(mut self, v: Bytes) -> Self { - self.headers = v; - self - } - pub fn intermediate_nodes(mut self, v: Bytes) -> Self { - self.intermediate_nodes = v; - self - } - pub fn funding_output_index(mut self, v: Byte) -> Self { - self.funding_output_index = v; - self - } -} -impl molecule::prelude::Builder for BTCSPVProofBuilder { - type Entity = BTCSPVProof; - const NAME: &'static str = "BTCSPVProofBuilder"; - fn expected_length(&self) -> usize { - molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) - + self.version.as_slice().len() - + self.vin.as_slice().len() - + self.vout.as_slice().len() - + self.locktime.as_slice().len() - + self.tx_id.as_slice().len() - + self.index.as_slice().len() - + self.headers.as_slice().len() - + self.intermediate_nodes.as_slice().len() - + self.funding_output_index.as_slice().len() - } - fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { - let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); - let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); - offsets.push(total_size); - total_size += self.version.as_slice().len(); - offsets.push(total_size); - total_size += self.vin.as_slice().len(); - offsets.push(total_size); - total_size += self.vout.as_slice().len(); - offsets.push(total_size); - total_size += self.locktime.as_slice().len(); - offsets.push(total_size); - total_size += self.tx_id.as_slice().len(); - offsets.push(total_size); - total_size += self.index.as_slice().len(); - offsets.push(total_size); - total_size += self.headers.as_slice().len(); - offsets.push(total_size); - total_size += self.intermediate_nodes.as_slice().len(); - offsets.push(total_size); - total_size += self.funding_output_index.as_slice().len(); - writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; - for offset in offsets.into_iter() { - writer.write_all(&molecule::pack_number(offset as molecule::Number))?; - } - writer.write_all(self.version.as_slice())?; - writer.write_all(self.vin.as_slice())?; - writer.write_all(self.vout.as_slice())?; - writer.write_all(self.locktime.as_slice())?; - writer.write_all(self.tx_id.as_slice())?; - writer.write_all(self.index.as_slice())?; - writer.write_all(self.headers.as_slice())?; - writer.write_all(self.intermediate_nodes.as_slice())?; - writer.write_all(self.funding_output_index.as_slice())?; - Ok(()) - } - fn build(&self) -> Self::Entity { - let mut inner = Vec::with_capacity(self.expected_length()); - self.write(&mut inner) - .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); - BTCSPVProof::new_unchecked(inner.into()) - } -} -#[derive(Clone)] -pub struct BTCDifficulty(molecule::bytes::Bytes); -impl ::core::fmt::LowerHex for BTCDifficulty { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl ::core::fmt::Debug for BTCDifficulty { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl ::core::fmt::Display for BTCDifficulty { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{} {{ ", Self::NAME)?; - write!(f, "{}: {}", "current", self.current())?; - write!(f, ", {}: {}", "previous", self.previous())?; - let extra_count = self.count_extra_fields(); - if extra_count != 0 { - write!(f, ", .. ({} fields)", extra_count)?; - } - write!(f, " }}") - } -} -impl ::core::default::Default for BTCDifficulty { +impl ::core::default::Default for ToCKBCellData { fn default() -> Self { let v: Vec = vec![ - 20, 0, 0, 0, 12, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 179, 0, 0, 0, 40, 0, 0, 0, 41, 0, 0, 0, 42, 0, 0, 0, 43, 0, 0, 0, 75, 0, 0, 0, 79, 0, + 0, 0, 111, 0, 0, 0, 115, 0, 0, 0, 147, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]; - BTCDifficulty::new_unchecked(v.into()) + ToCKBCellData::new_unchecked(v.into()) } } -impl BTCDifficulty { - pub const FIELD_COUNT: usize = 2; +impl ToCKBCellData { + pub const FIELD_COUNT: usize = 9; pub fn total_size(&self) -> usize { molecule::unpack_number(self.as_slice()) as usize } @@ -2497,31 +89,73 @@ impl BTCDifficulty { pub fn has_extra_fields(&self) -> bool { Self::FIELD_COUNT != self.field_count() } - pub fn current(&self) -> Bytes { + pub fn status(&self) -> Byte { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[4..]) as usize; let end = molecule::unpack_number(&slice[8..]) as usize; - Bytes::new_unchecked(self.0.slice(start..end)) + Byte::new_unchecked(self.0.slice(start..end)) } - pub fn previous(&self) -> Bytes { + pub fn kind(&self) -> Byte { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[8..]) as usize; + let end = molecule::unpack_number(&slice[12..]) as usize; + Byte::new_unchecked(self.0.slice(start..end)) + } + pub fn lot_size(&self) -> Byte { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[12..]) as usize; + let end = molecule::unpack_number(&slice[16..]) as usize; + Byte::new_unchecked(self.0.slice(start..end)) + } + pub fn user_lockscript_hash(&self) -> Byte32 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[16..]) as usize; + let end = molecule::unpack_number(&slice[20..]) as usize; + Byte32::new_unchecked(self.0.slice(start..end)) + } + pub fn x_lock_address(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[20..]) as usize; + let end = molecule::unpack_number(&slice[24..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } + pub fn signer_lockscript_hash(&self) -> Byte32 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[24..]) as usize; + let end = molecule::unpack_number(&slice[28..]) as usize; + Byte32::new_unchecked(self.0.slice(start..end)) + } + pub fn x_unlock_address(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[28..]) as usize; + let end = molecule::unpack_number(&slice[32..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } + pub fn redeemer_lockscript_hash(&self) -> Byte32 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[32..]) as usize; + let end = molecule::unpack_number(&slice[36..]) as usize; + Byte32::new_unchecked(self.0.slice(start..end)) + } + pub fn liquidation_trigger_lockscript_hash(&self) -> Byte32 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[36..]) as usize; if self.has_extra_fields() { - let end = molecule::unpack_number(&slice[12..]) as usize; - Bytes::new_unchecked(self.0.slice(start..end)) + let end = molecule::unpack_number(&slice[40..]) as usize; + Byte32::new_unchecked(self.0.slice(start..end)) } else { - Bytes::new_unchecked(self.0.slice(start..)) + Byte32::new_unchecked(self.0.slice(start..)) } } - pub fn as_reader<'r>(&'r self) -> BTCDifficultyReader<'r> { - BTCDifficultyReader::new_unchecked(self.as_slice()) + pub fn as_reader<'r>(&'r self) -> ToCKBCellDataReader<'r> { + ToCKBCellDataReader::new_unchecked(self.as_slice()) } } -impl molecule::prelude::Entity for BTCDifficulty { - type Builder = BTCDifficultyBuilder; - const NAME: &'static str = "BTCDifficulty"; +impl molecule::prelude::Entity for ToCKBCellData { + type Builder = ToCKBCellDataBuilder; + const NAME: &'static str = "ToCKBCellData"; fn new_unchecked(data: molecule::bytes::Bytes) -> Self { - BTCDifficulty(data) + ToCKBCellData(data) } fn as_bytes(&self) -> molecule::bytes::Bytes { self.0.clone() @@ -2530,23 +164,30 @@ impl molecule::prelude::Entity for BTCDifficulty { &self.0[..] } fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { - BTCDifficultyReader::from_slice(slice).map(|reader| reader.to_entity()) + ToCKBCellDataReader::from_slice(slice).map(|reader| reader.to_entity()) } fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { - BTCDifficultyReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + ToCKBCellDataReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) } fn new_builder() -> Self::Builder { ::core::default::Default::default() } fn as_builder(self) -> Self::Builder { Self::new_builder() - .current(self.current()) - .previous(self.previous()) + .status(self.status()) + .kind(self.kind()) + .lot_size(self.lot_size()) + .user_lockscript_hash(self.user_lockscript_hash()) + .x_lock_address(self.x_lock_address()) + .signer_lockscript_hash(self.signer_lockscript_hash()) + .x_unlock_address(self.x_unlock_address()) + .redeemer_lockscript_hash(self.redeemer_lockscript_hash()) + .liquidation_trigger_lockscript_hash(self.liquidation_trigger_lockscript_hash()) } } #[derive(Clone, Copy)] -pub struct BTCDifficultyReader<'r>(&'r [u8]); -impl<'r> ::core::fmt::LowerHex for BTCDifficultyReader<'r> { +pub struct ToCKBCellDataReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for ToCKBCellDataReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; if f.alternate() { @@ -2555,16 +196,43 @@ impl<'r> ::core::fmt::LowerHex for BTCDifficultyReader<'r> { write!(f, "{}", hex_string(self.as_slice())) } } -impl<'r> ::core::fmt::Debug for BTCDifficultyReader<'r> { +impl<'r> ::core::fmt::Debug for ToCKBCellDataReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:#x})", Self::NAME, self) } } -impl<'r> ::core::fmt::Display for BTCDifficultyReader<'r> { +impl<'r> ::core::fmt::Display for ToCKBCellDataReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{} {{ ", Self::NAME)?; - write!(f, "{}: {}", "current", self.current())?; - write!(f, ", {}: {}", "previous", self.previous())?; + write!(f, "{}: {}", "status", self.status())?; + write!(f, ", {}: {}", "kind", self.kind())?; + write!(f, ", {}: {}", "lot_size", self.lot_size())?; + write!( + f, + ", {}: {}", + "user_lockscript_hash", + self.user_lockscript_hash() + )?; + write!(f, ", {}: {}", "x_lock_address", self.x_lock_address())?; + write!( + f, + ", {}: {}", + "signer_lockscript_hash", + self.signer_lockscript_hash() + )?; + write!(f, ", {}: {}", "x_unlock_address", self.x_unlock_address())?; + write!( + f, + ", {}: {}", + "redeemer_lockscript_hash", + self.redeemer_lockscript_hash() + )?; + write!( + f, + ", {}: {}", + "liquidation_trigger_lockscript_hash", + self.liquidation_trigger_lockscript_hash() + )?; let extra_count = self.count_extra_fields(); if extra_count != 0 { write!(f, ", .. ({} fields)", extra_count)?; @@ -2572,8 +240,8 @@ impl<'r> ::core::fmt::Display for BTCDifficultyReader<'r> { write!(f, " }}") } } -impl<'r> BTCDifficultyReader<'r> { - pub const FIELD_COUNT: usize = 2; +impl<'r> ToCKBCellDataReader<'r> { + pub const FIELD_COUNT: usize = 9; pub fn total_size(&self) -> usize { molecule::unpack_number(self.as_slice()) as usize } @@ -2590,31 +258,73 @@ impl<'r> BTCDifficultyReader<'r> { pub fn has_extra_fields(&self) -> bool { Self::FIELD_COUNT != self.field_count() } - pub fn current(&self) -> BytesReader<'r> { + pub fn status(&self) -> ByteReader<'r> { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[4..]) as usize; let end = molecule::unpack_number(&slice[8..]) as usize; - BytesReader::new_unchecked(&self.as_slice()[start..end]) + ByteReader::new_unchecked(&self.as_slice()[start..end]) } - pub fn previous(&self) -> BytesReader<'r> { + pub fn kind(&self) -> ByteReader<'r> { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[8..]) as usize; + let end = molecule::unpack_number(&slice[12..]) as usize; + ByteReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn lot_size(&self) -> ByteReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[12..]) as usize; + let end = molecule::unpack_number(&slice[16..]) as usize; + ByteReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn user_lockscript_hash(&self) -> Byte32Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[16..]) as usize; + let end = molecule::unpack_number(&slice[20..]) as usize; + Byte32Reader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn x_lock_address(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[20..]) as usize; + let end = molecule::unpack_number(&slice[24..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn signer_lockscript_hash(&self) -> Byte32Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[24..]) as usize; + let end = molecule::unpack_number(&slice[28..]) as usize; + Byte32Reader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn x_unlock_address(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[28..]) as usize; + let end = molecule::unpack_number(&slice[32..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn redeemer_lockscript_hash(&self) -> Byte32Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[32..]) as usize; + let end = molecule::unpack_number(&slice[36..]) as usize; + Byte32Reader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn liquidation_trigger_lockscript_hash(&self) -> Byte32Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[36..]) as usize; if self.has_extra_fields() { - let end = molecule::unpack_number(&slice[12..]) as usize; - BytesReader::new_unchecked(&self.as_slice()[start..end]) + let end = molecule::unpack_number(&slice[40..]) as usize; + Byte32Reader::new_unchecked(&self.as_slice()[start..end]) } else { - BytesReader::new_unchecked(&self.as_slice()[start..]) + Byte32Reader::new_unchecked(&self.as_slice()[start..]) } } } -impl<'r> molecule::prelude::Reader<'r> for BTCDifficultyReader<'r> { - type Entity = BTCDifficulty; - const NAME: &'static str = "BTCDifficultyReader"; +impl<'r> molecule::prelude::Reader<'r> for ToCKBCellDataReader<'r> { + type Entity = ToCKBCellData; + const NAME: &'static str = "ToCKBCellDataReader"; fn to_entity(&self) -> Self::Entity { Self::Entity::new_unchecked(self.as_slice().to_owned().into()) } fn new_unchecked(slice: &'r [u8]) -> Self { - BTCDifficultyReader(slice) + ToCKBCellDataReader(slice) } fn as_slice(&self) -> &'r [u8] { self.0 @@ -2658,54 +368,124 @@ impl<'r> molecule::prelude::Reader<'r> for BTCDifficultyReader<'r> { if offsets.windows(2).any(|i| i[0] > i[1]) { return ve!(Self, OffsetsNotMatch); } - BytesReader::verify(&slice[offsets[0]..offsets[1]], compatible)?; - BytesReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; + ByteReader::verify(&slice[offsets[0]..offsets[1]], compatible)?; + ByteReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; + ByteReader::verify(&slice[offsets[2]..offsets[3]], compatible)?; + Byte32Reader::verify(&slice[offsets[3]..offsets[4]], compatible)?; + BytesReader::verify(&slice[offsets[4]..offsets[5]], compatible)?; + Byte32Reader::verify(&slice[offsets[5]..offsets[6]], compatible)?; + BytesReader::verify(&slice[offsets[6]..offsets[7]], compatible)?; + Byte32Reader::verify(&slice[offsets[7]..offsets[8]], compatible)?; + Byte32Reader::verify(&slice[offsets[8]..offsets[9]], compatible)?; Ok(()) } } #[derive(Debug, Default)] -pub struct BTCDifficultyBuilder { - pub(crate) current: Bytes, - pub(crate) previous: Bytes, +pub struct ToCKBCellDataBuilder { + pub(crate) status: Byte, + pub(crate) kind: Byte, + pub(crate) lot_size: Byte, + pub(crate) user_lockscript_hash: Byte32, + pub(crate) x_lock_address: Bytes, + pub(crate) signer_lockscript_hash: Byte32, + pub(crate) x_unlock_address: Bytes, + pub(crate) redeemer_lockscript_hash: Byte32, + pub(crate) liquidation_trigger_lockscript_hash: Byte32, } -impl BTCDifficultyBuilder { - pub const FIELD_COUNT: usize = 2; - pub fn current(mut self, v: Bytes) -> Self { - self.current = v; +impl ToCKBCellDataBuilder { + pub const FIELD_COUNT: usize = 9; + pub fn status(mut self, v: Byte) -> Self { + self.status = v; + self + } + pub fn kind(mut self, v: Byte) -> Self { + self.kind = v; self } - pub fn previous(mut self, v: Bytes) -> Self { - self.previous = v; + pub fn lot_size(mut self, v: Byte) -> Self { + self.lot_size = v; + self + } + pub fn user_lockscript_hash(mut self, v: Byte32) -> Self { + self.user_lockscript_hash = v; + self + } + pub fn x_lock_address(mut self, v: Bytes) -> Self { + self.x_lock_address = v; + self + } + pub fn signer_lockscript_hash(mut self, v: Byte32) -> Self { + self.signer_lockscript_hash = v; + self + } + pub fn x_unlock_address(mut self, v: Bytes) -> Self { + self.x_unlock_address = v; + self + } + pub fn redeemer_lockscript_hash(mut self, v: Byte32) -> Self { + self.redeemer_lockscript_hash = v; + self + } + pub fn liquidation_trigger_lockscript_hash(mut self, v: Byte32) -> Self { + self.liquidation_trigger_lockscript_hash = v; self } } -impl molecule::prelude::Builder for BTCDifficultyBuilder { - type Entity = BTCDifficulty; - const NAME: &'static str = "BTCDifficultyBuilder"; +impl molecule::prelude::Builder for ToCKBCellDataBuilder { + type Entity = ToCKBCellData; + const NAME: &'static str = "ToCKBCellDataBuilder"; fn expected_length(&self) -> usize { molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) - + self.current.as_slice().len() - + self.previous.as_slice().len() + + self.status.as_slice().len() + + self.kind.as_slice().len() + + self.lot_size.as_slice().len() + + self.user_lockscript_hash.as_slice().len() + + self.x_lock_address.as_slice().len() + + self.signer_lockscript_hash.as_slice().len() + + self.x_unlock_address.as_slice().len() + + self.redeemer_lockscript_hash.as_slice().len() + + self.liquidation_trigger_lockscript_hash.as_slice().len() } fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); offsets.push(total_size); - total_size += self.current.as_slice().len(); + total_size += self.status.as_slice().len(); + offsets.push(total_size); + total_size += self.kind.as_slice().len(); + offsets.push(total_size); + total_size += self.lot_size.as_slice().len(); + offsets.push(total_size); + total_size += self.user_lockscript_hash.as_slice().len(); + offsets.push(total_size); + total_size += self.x_lock_address.as_slice().len(); + offsets.push(total_size); + total_size += self.signer_lockscript_hash.as_slice().len(); + offsets.push(total_size); + total_size += self.x_unlock_address.as_slice().len(); + offsets.push(total_size); + total_size += self.redeemer_lockscript_hash.as_slice().len(); offsets.push(total_size); - total_size += self.previous.as_slice().len(); + total_size += self.liquidation_trigger_lockscript_hash.as_slice().len(); writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; for offset in offsets.into_iter() { writer.write_all(&molecule::pack_number(offset as molecule::Number))?; } - writer.write_all(self.current.as_slice())?; - writer.write_all(self.previous.as_slice())?; + writer.write_all(self.status.as_slice())?; + writer.write_all(self.kind.as_slice())?; + writer.write_all(self.lot_size.as_slice())?; + writer.write_all(self.user_lockscript_hash.as_slice())?; + writer.write_all(self.x_lock_address.as_slice())?; + writer.write_all(self.signer_lockscript_hash.as_slice())?; + writer.write_all(self.x_unlock_address.as_slice())?; + writer.write_all(self.redeemer_lockscript_hash.as_slice())?; + writer.write_all(self.liquidation_trigger_lockscript_hash.as_slice())?; Ok(()) } fn build(&self) -> Self::Entity { let mut inner = Vec::with_capacity(self.expected_length()); self.write(&mut inner) .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); - BTCDifficulty::new_unchecked(inner.into()) + ToCKBCellData::new_unchecked(inner.into()) } } diff --git a/contracts/toCKB-typescript/src/utils/types/mod.rs b/contracts/toCKB-typescript/src/utils/types/mod.rs index 71ef2e8..2c9d9d5 100644 --- a/contracts/toCKB-typescript/src/utils/types/mod.rs +++ b/contracts/toCKB-typescript/src/utils/types/mod.rs @@ -3,5 +3,5 @@ mod generated; mod toCKB_cell; pub use error::Error; -pub use generated::toCKB_cell_data; +pub use generated::{basic, btc_difficulty, mint_xt_witness, toCKB_cell_data}; pub use toCKB_cell::*; diff --git a/contracts/toCKB-typescript/src/utils/types/schemas/toCKB_cell_data.mol b/contracts/toCKB-typescript/src/utils/types/schemas/toCKB_cell_data.mol index 8c47ad7..1033607 100644 --- a/contracts/toCKB-typescript/src/utils/types/schemas/toCKB_cell_data.mol +++ b/contracts/toCKB-typescript/src/utils/types/schemas/toCKB_cell_data.mol @@ -1,7 +1,4 @@ -array Byte32 [byte; 32]; -vector Bytes ; -array Byte4 [byte; 4]; -array Uint32 [byte; 4]; +import basic; table ToCKBCellData { status: byte, @@ -15,24 +12,3 @@ table ToCKBCellData { liquidation_trigger_lockscript_hash: Byte32, } -table MintXTWitness { - spv_proof: Bytes, - cell_dep_index_list: Bytes, -} - -table BTCSPVProof { - version: Byte4, - vin: Bytes, - vout: Bytes, - locktime: Byte4, - tx_id: Byte32, - index: Uint32, - headers: Bytes, - intermediate_nodes: Bytes, - funding_output_index: byte, -} - -table BTCDifficulty { - current: Bytes, - previous: Bytes, -} From 79b148dd9c31edfb95c8ab5c28de385b5f607a62 Mon Sep 17 00:00:00 2001 From: huwenchao Date: Fri, 21 Aug 2020 18:46:15 +0800 Subject: [PATCH 11/45] refactor: split mol to multiple files 2 --- .../src/utils/types/generated/basic.rs | 1218 +++++++++++++++++ .../utils/types/generated/btc_difficulty.rs | 270 ++++ .../utils/types/generated/mint_xt_witness.rs | 744 ++++++++++ .../src/utils/types/schemas/basic.mol | 4 + .../utils/types/schemas/btc_difficulty.mol | 6 + .../utils/types/schemas/mint_xt_witness.mol | 18 + 6 files changed, 2260 insertions(+) create mode 100644 contracts/toCKB-typescript/src/utils/types/generated/basic.rs create mode 100644 contracts/toCKB-typescript/src/utils/types/generated/btc_difficulty.rs create mode 100644 contracts/toCKB-typescript/src/utils/types/generated/mint_xt_witness.rs create mode 100644 contracts/toCKB-typescript/src/utils/types/schemas/basic.mol create mode 100644 contracts/toCKB-typescript/src/utils/types/schemas/btc_difficulty.mol create mode 100644 contracts/toCKB-typescript/src/utils/types/schemas/mint_xt_witness.mol diff --git a/contracts/toCKB-typescript/src/utils/types/generated/basic.rs b/contracts/toCKB-typescript/src/utils/types/generated/basic.rs new file mode 100644 index 0000000..811ef95 --- /dev/null +++ b/contracts/toCKB-typescript/src/utils/types/generated/basic.rs @@ -0,0 +1,1218 @@ +// Generated by Molecule 0.6.0 + +use molecule::prelude::*; +#[derive(Clone)] +pub struct Byte32(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for Byte32 { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for Byte32 { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for Byte32 { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + let raw_data = hex_string(&self.raw_data()); + write!(f, "{}(0x{})", Self::NAME, raw_data) + } +} +impl ::core::default::Default for Byte32 { + fn default() -> Self { + let v: Vec = vec![ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, + ]; + Byte32::new_unchecked(v.into()) + } +} +impl Byte32 { + pub const TOTAL_SIZE: usize = 32; + pub const ITEM_SIZE: usize = 1; + pub const ITEM_COUNT: usize = 32; + pub fn nth0(&self) -> Byte { + Byte::new_unchecked(self.0.slice(0..1)) + } + pub fn nth1(&self) -> Byte { + Byte::new_unchecked(self.0.slice(1..2)) + } + pub fn nth2(&self) -> Byte { + Byte::new_unchecked(self.0.slice(2..3)) + } + pub fn nth3(&self) -> Byte { + Byte::new_unchecked(self.0.slice(3..4)) + } + pub fn nth4(&self) -> Byte { + Byte::new_unchecked(self.0.slice(4..5)) + } + pub fn nth5(&self) -> Byte { + Byte::new_unchecked(self.0.slice(5..6)) + } + pub fn nth6(&self) -> Byte { + Byte::new_unchecked(self.0.slice(6..7)) + } + pub fn nth7(&self) -> Byte { + Byte::new_unchecked(self.0.slice(7..8)) + } + pub fn nth8(&self) -> Byte { + Byte::new_unchecked(self.0.slice(8..9)) + } + pub fn nth9(&self) -> Byte { + Byte::new_unchecked(self.0.slice(9..10)) + } + pub fn nth10(&self) -> Byte { + Byte::new_unchecked(self.0.slice(10..11)) + } + pub fn nth11(&self) -> Byte { + Byte::new_unchecked(self.0.slice(11..12)) + } + pub fn nth12(&self) -> Byte { + Byte::new_unchecked(self.0.slice(12..13)) + } + pub fn nth13(&self) -> Byte { + Byte::new_unchecked(self.0.slice(13..14)) + } + pub fn nth14(&self) -> Byte { + Byte::new_unchecked(self.0.slice(14..15)) + } + pub fn nth15(&self) -> Byte { + Byte::new_unchecked(self.0.slice(15..16)) + } + pub fn nth16(&self) -> Byte { + Byte::new_unchecked(self.0.slice(16..17)) + } + pub fn nth17(&self) -> Byte { + Byte::new_unchecked(self.0.slice(17..18)) + } + pub fn nth18(&self) -> Byte { + Byte::new_unchecked(self.0.slice(18..19)) + } + pub fn nth19(&self) -> Byte { + Byte::new_unchecked(self.0.slice(19..20)) + } + pub fn nth20(&self) -> Byte { + Byte::new_unchecked(self.0.slice(20..21)) + } + pub fn nth21(&self) -> Byte { + Byte::new_unchecked(self.0.slice(21..22)) + } + pub fn nth22(&self) -> Byte { + Byte::new_unchecked(self.0.slice(22..23)) + } + pub fn nth23(&self) -> Byte { + Byte::new_unchecked(self.0.slice(23..24)) + } + pub fn nth24(&self) -> Byte { + Byte::new_unchecked(self.0.slice(24..25)) + } + pub fn nth25(&self) -> Byte { + Byte::new_unchecked(self.0.slice(25..26)) + } + pub fn nth26(&self) -> Byte { + Byte::new_unchecked(self.0.slice(26..27)) + } + pub fn nth27(&self) -> Byte { + Byte::new_unchecked(self.0.slice(27..28)) + } + pub fn nth28(&self) -> Byte { + Byte::new_unchecked(self.0.slice(28..29)) + } + pub fn nth29(&self) -> Byte { + Byte::new_unchecked(self.0.slice(29..30)) + } + pub fn nth30(&self) -> Byte { + Byte::new_unchecked(self.0.slice(30..31)) + } + pub fn nth31(&self) -> Byte { + Byte::new_unchecked(self.0.slice(31..32)) + } + pub fn raw_data(&self) -> molecule::bytes::Bytes { + self.as_bytes() + } + pub fn as_reader<'r>(&'r self) -> Byte32Reader<'r> { + Byte32Reader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for Byte32 { + type Builder = Byte32Builder; + const NAME: &'static str = "Byte32"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + Byte32(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + Byte32Reader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + Byte32Reader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder().set([ + self.nth0(), + self.nth1(), + self.nth2(), + self.nth3(), + self.nth4(), + self.nth5(), + self.nth6(), + self.nth7(), + self.nth8(), + self.nth9(), + self.nth10(), + self.nth11(), + self.nth12(), + self.nth13(), + self.nth14(), + self.nth15(), + self.nth16(), + self.nth17(), + self.nth18(), + self.nth19(), + self.nth20(), + self.nth21(), + self.nth22(), + self.nth23(), + self.nth24(), + self.nth25(), + self.nth26(), + self.nth27(), + self.nth28(), + self.nth29(), + self.nth30(), + self.nth31(), + ]) + } +} +#[derive(Clone, Copy)] +pub struct Byte32Reader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for Byte32Reader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for Byte32Reader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for Byte32Reader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + let raw_data = hex_string(&self.raw_data()); + write!(f, "{}(0x{})", Self::NAME, raw_data) + } +} +impl<'r> Byte32Reader<'r> { + pub const TOTAL_SIZE: usize = 32; + pub const ITEM_SIZE: usize = 1; + pub const ITEM_COUNT: usize = 32; + pub fn nth0(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[0..1]) + } + pub fn nth1(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[1..2]) + } + pub fn nth2(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[2..3]) + } + pub fn nth3(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[3..4]) + } + pub fn nth4(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[4..5]) + } + pub fn nth5(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[5..6]) + } + pub fn nth6(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[6..7]) + } + pub fn nth7(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[7..8]) + } + pub fn nth8(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[8..9]) + } + pub fn nth9(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[9..10]) + } + pub fn nth10(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[10..11]) + } + pub fn nth11(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[11..12]) + } + pub fn nth12(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[12..13]) + } + pub fn nth13(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[13..14]) + } + pub fn nth14(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[14..15]) + } + pub fn nth15(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[15..16]) + } + pub fn nth16(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[16..17]) + } + pub fn nth17(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[17..18]) + } + pub fn nth18(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[18..19]) + } + pub fn nth19(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[19..20]) + } + pub fn nth20(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[20..21]) + } + pub fn nth21(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[21..22]) + } + pub fn nth22(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[22..23]) + } + pub fn nth23(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[23..24]) + } + pub fn nth24(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[24..25]) + } + pub fn nth25(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[25..26]) + } + pub fn nth26(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[26..27]) + } + pub fn nth27(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[27..28]) + } + pub fn nth28(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[28..29]) + } + pub fn nth29(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[29..30]) + } + pub fn nth30(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[30..31]) + } + pub fn nth31(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[31..32]) + } + pub fn raw_data(&self) -> &'r [u8] { + self.as_slice() + } +} +impl<'r> molecule::prelude::Reader<'r> for Byte32Reader<'r> { + type Entity = Byte32; + const NAME: &'static str = "Byte32Reader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + Byte32Reader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], _compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len != Self::TOTAL_SIZE { + return ve!(Self, TotalSizeNotMatch, Self::TOTAL_SIZE, slice_len); + } + Ok(()) + } +} +pub struct Byte32Builder(pub(crate) [Byte; 32]); +impl ::core::fmt::Debug for Byte32Builder { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:?})", Self::NAME, &self.0[..]) + } +} +impl ::core::default::Default for Byte32Builder { + fn default() -> Self { + Byte32Builder([ + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + ]) + } +} +impl Byte32Builder { + pub const TOTAL_SIZE: usize = 32; + pub const ITEM_SIZE: usize = 1; + pub const ITEM_COUNT: usize = 32; + pub fn set(mut self, v: [Byte; 32]) -> Self { + self.0 = v; + self + } + pub fn nth0(mut self, v: Byte) -> Self { + self.0[0] = v; + self + } + pub fn nth1(mut self, v: Byte) -> Self { + self.0[1] = v; + self + } + pub fn nth2(mut self, v: Byte) -> Self { + self.0[2] = v; + self + } + pub fn nth3(mut self, v: Byte) -> Self { + self.0[3] = v; + self + } + pub fn nth4(mut self, v: Byte) -> Self { + self.0[4] = v; + self + } + pub fn nth5(mut self, v: Byte) -> Self { + self.0[5] = v; + self + } + pub fn nth6(mut self, v: Byte) -> Self { + self.0[6] = v; + self + } + pub fn nth7(mut self, v: Byte) -> Self { + self.0[7] = v; + self + } + pub fn nth8(mut self, v: Byte) -> Self { + self.0[8] = v; + self + } + pub fn nth9(mut self, v: Byte) -> Self { + self.0[9] = v; + self + } + pub fn nth10(mut self, v: Byte) -> Self { + self.0[10] = v; + self + } + pub fn nth11(mut self, v: Byte) -> Self { + self.0[11] = v; + self + } + pub fn nth12(mut self, v: Byte) -> Self { + self.0[12] = v; + self + } + pub fn nth13(mut self, v: Byte) -> Self { + self.0[13] = v; + self + } + pub fn nth14(mut self, v: Byte) -> Self { + self.0[14] = v; + self + } + pub fn nth15(mut self, v: Byte) -> Self { + self.0[15] = v; + self + } + pub fn nth16(mut self, v: Byte) -> Self { + self.0[16] = v; + self + } + pub fn nth17(mut self, v: Byte) -> Self { + self.0[17] = v; + self + } + pub fn nth18(mut self, v: Byte) -> Self { + self.0[18] = v; + self + } + pub fn nth19(mut self, v: Byte) -> Self { + self.0[19] = v; + self + } + pub fn nth20(mut self, v: Byte) -> Self { + self.0[20] = v; + self + } + pub fn nth21(mut self, v: Byte) -> Self { + self.0[21] = v; + self + } + pub fn nth22(mut self, v: Byte) -> Self { + self.0[22] = v; + self + } + pub fn nth23(mut self, v: Byte) -> Self { + self.0[23] = v; + self + } + pub fn nth24(mut self, v: Byte) -> Self { + self.0[24] = v; + self + } + pub fn nth25(mut self, v: Byte) -> Self { + self.0[25] = v; + self + } + pub fn nth26(mut self, v: Byte) -> Self { + self.0[26] = v; + self + } + pub fn nth27(mut self, v: Byte) -> Self { + self.0[27] = v; + self + } + pub fn nth28(mut self, v: Byte) -> Self { + self.0[28] = v; + self + } + pub fn nth29(mut self, v: Byte) -> Self { + self.0[29] = v; + self + } + pub fn nth30(mut self, v: Byte) -> Self { + self.0[30] = v; + self + } + pub fn nth31(mut self, v: Byte) -> Self { + self.0[31] = v; + self + } +} +impl molecule::prelude::Builder for Byte32Builder { + type Entity = Byte32; + const NAME: &'static str = "Byte32Builder"; + fn expected_length(&self) -> usize { + Self::TOTAL_SIZE + } + fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { + writer.write_all(self.0[0].as_slice())?; + writer.write_all(self.0[1].as_slice())?; + writer.write_all(self.0[2].as_slice())?; + writer.write_all(self.0[3].as_slice())?; + writer.write_all(self.0[4].as_slice())?; + writer.write_all(self.0[5].as_slice())?; + writer.write_all(self.0[6].as_slice())?; + writer.write_all(self.0[7].as_slice())?; + writer.write_all(self.0[8].as_slice())?; + writer.write_all(self.0[9].as_slice())?; + writer.write_all(self.0[10].as_slice())?; + writer.write_all(self.0[11].as_slice())?; + writer.write_all(self.0[12].as_slice())?; + writer.write_all(self.0[13].as_slice())?; + writer.write_all(self.0[14].as_slice())?; + writer.write_all(self.0[15].as_slice())?; + writer.write_all(self.0[16].as_slice())?; + writer.write_all(self.0[17].as_slice())?; + writer.write_all(self.0[18].as_slice())?; + writer.write_all(self.0[19].as_slice())?; + writer.write_all(self.0[20].as_slice())?; + writer.write_all(self.0[21].as_slice())?; + writer.write_all(self.0[22].as_slice())?; + writer.write_all(self.0[23].as_slice())?; + writer.write_all(self.0[24].as_slice())?; + writer.write_all(self.0[25].as_slice())?; + writer.write_all(self.0[26].as_slice())?; + writer.write_all(self.0[27].as_slice())?; + writer.write_all(self.0[28].as_slice())?; + writer.write_all(self.0[29].as_slice())?; + writer.write_all(self.0[30].as_slice())?; + writer.write_all(self.0[31].as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + Byte32::new_unchecked(inner.into()) + } +} +#[derive(Clone)] +pub struct Bytes(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for Bytes { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for Bytes { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for Bytes { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + let raw_data = hex_string(&self.raw_data()); + write!(f, "{}(0x{})", Self::NAME, raw_data) + } +} +impl ::core::default::Default for Bytes { + fn default() -> Self { + let v: Vec = vec![0, 0, 0, 0]; + Bytes::new_unchecked(v.into()) + } +} +impl Bytes { + pub const ITEM_SIZE: usize = 1; + pub fn total_size(&self) -> usize { + molecule::NUMBER_SIZE * (self.item_count() + 1) + } + pub fn item_count(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn len(&self) -> usize { + self.item_count() + } + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + pub fn get(&self, idx: usize) -> Option { + if idx >= self.len() { + None + } else { + Some(self.get_unchecked(idx)) + } + } + pub fn get_unchecked(&self, idx: usize) -> Byte { + let start = molecule::NUMBER_SIZE + Self::ITEM_SIZE * idx; + let end = start + Self::ITEM_SIZE; + Byte::new_unchecked(self.0.slice(start..end)) + } + pub fn raw_data(&self) -> molecule::bytes::Bytes { + self.0.slice(molecule::NUMBER_SIZE..) + } + pub fn as_reader<'r>(&'r self) -> BytesReader<'r> { + BytesReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for Bytes { + type Builder = BytesBuilder; + const NAME: &'static str = "Bytes"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + Bytes(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + BytesReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + BytesReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder().extend(self.into_iter()) + } +} +#[derive(Clone, Copy)] +pub struct BytesReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for BytesReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for BytesReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for BytesReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + let raw_data = hex_string(&self.raw_data()); + write!(f, "{}(0x{})", Self::NAME, raw_data) + } +} +impl<'r> BytesReader<'r> { + pub const ITEM_SIZE: usize = 1; + pub fn total_size(&self) -> usize { + molecule::NUMBER_SIZE * (self.item_count() + 1) + } + pub fn item_count(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn len(&self) -> usize { + self.item_count() + } + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + pub fn get(&self, idx: usize) -> Option> { + if idx >= self.len() { + None + } else { + Some(self.get_unchecked(idx)) + } + } + pub fn get_unchecked(&self, idx: usize) -> ByteReader<'r> { + let start = molecule::NUMBER_SIZE + Self::ITEM_SIZE * idx; + let end = start + Self::ITEM_SIZE; + ByteReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn raw_data(&self) -> &'r [u8] { + &self.as_slice()[molecule::NUMBER_SIZE..] + } +} +impl<'r> molecule::prelude::Reader<'r> for BytesReader<'r> { + type Entity = Bytes; + const NAME: &'static str = "BytesReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + BytesReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], _compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let item_count = molecule::unpack_number(slice) as usize; + if item_count == 0 { + if slice_len != molecule::NUMBER_SIZE { + return ve!(Self, TotalSizeNotMatch, molecule::NUMBER_SIZE, slice_len); + } + return Ok(()); + } + let total_size = molecule::NUMBER_SIZE + Self::ITEM_SIZE * item_count; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct BytesBuilder(pub(crate) Vec); +impl BytesBuilder { + pub const ITEM_SIZE: usize = 1; + pub fn set(mut self, v: Vec) -> Self { + self.0 = v; + self + } + pub fn push(mut self, v: Byte) -> Self { + self.0.push(v); + self + } + pub fn extend>(mut self, iter: T) -> Self { + for elem in iter { + self.0.push(elem); + } + self + } +} +impl molecule::prelude::Builder for BytesBuilder { + type Entity = Bytes; + const NAME: &'static str = "BytesBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE + Self::ITEM_SIZE * self.0.len() + } + fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { + writer.write_all(&molecule::pack_number(self.0.len() as molecule::Number))?; + for inner in &self.0[..] { + writer.write_all(inner.as_slice())?; + } + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + Bytes::new_unchecked(inner.into()) + } +} +pub struct BytesIterator(Bytes, usize, usize); +impl ::core::iter::Iterator for BytesIterator { + type Item = Byte; + fn next(&mut self) -> Option { + if self.1 >= self.2 { + None + } else { + let ret = self.0.get_unchecked(self.1); + self.1 += 1; + Some(ret) + } + } +} +impl ::core::iter::ExactSizeIterator for BytesIterator { + fn len(&self) -> usize { + self.2 - self.1 + } +} +impl ::core::iter::IntoIterator for Bytes { + type Item = Byte; + type IntoIter = BytesIterator; + fn into_iter(self) -> Self::IntoIter { + let len = self.len(); + BytesIterator(self, 0, len) + } +} +#[derive(Clone)] +pub struct Byte4(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for Byte4 { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for Byte4 { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for Byte4 { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + let raw_data = hex_string(&self.raw_data()); + write!(f, "{}(0x{})", Self::NAME, raw_data) + } +} +impl ::core::default::Default for Byte4 { + fn default() -> Self { + let v: Vec = vec![0, 0, 0, 0]; + Byte4::new_unchecked(v.into()) + } +} +impl Byte4 { + pub const TOTAL_SIZE: usize = 4; + pub const ITEM_SIZE: usize = 1; + pub const ITEM_COUNT: usize = 4; + pub fn nth0(&self) -> Byte { + Byte::new_unchecked(self.0.slice(0..1)) + } + pub fn nth1(&self) -> Byte { + Byte::new_unchecked(self.0.slice(1..2)) + } + pub fn nth2(&self) -> Byte { + Byte::new_unchecked(self.0.slice(2..3)) + } + pub fn nth3(&self) -> Byte { + Byte::new_unchecked(self.0.slice(3..4)) + } + pub fn raw_data(&self) -> molecule::bytes::Bytes { + self.as_bytes() + } + pub fn as_reader<'r>(&'r self) -> Byte4Reader<'r> { + Byte4Reader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for Byte4 { + type Builder = Byte4Builder; + const NAME: &'static str = "Byte4"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + Byte4(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + Byte4Reader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + Byte4Reader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder().set([self.nth0(), self.nth1(), self.nth2(), self.nth3()]) + } +} +#[derive(Clone, Copy)] +pub struct Byte4Reader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for Byte4Reader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for Byte4Reader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for Byte4Reader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + let raw_data = hex_string(&self.raw_data()); + write!(f, "{}(0x{})", Self::NAME, raw_data) + } +} +impl<'r> Byte4Reader<'r> { + pub const TOTAL_SIZE: usize = 4; + pub const ITEM_SIZE: usize = 1; + pub const ITEM_COUNT: usize = 4; + pub fn nth0(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[0..1]) + } + pub fn nth1(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[1..2]) + } + pub fn nth2(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[2..3]) + } + pub fn nth3(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[3..4]) + } + pub fn raw_data(&self) -> &'r [u8] { + self.as_slice() + } +} +impl<'r> molecule::prelude::Reader<'r> for Byte4Reader<'r> { + type Entity = Byte4; + const NAME: &'static str = "Byte4Reader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + Byte4Reader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], _compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len != Self::TOTAL_SIZE { + return ve!(Self, TotalSizeNotMatch, Self::TOTAL_SIZE, slice_len); + } + Ok(()) + } +} +pub struct Byte4Builder(pub(crate) [Byte; 4]); +impl ::core::fmt::Debug for Byte4Builder { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:?})", Self::NAME, &self.0[..]) + } +} +impl ::core::default::Default for Byte4Builder { + fn default() -> Self { + Byte4Builder([ + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + ]) + } +} +impl Byte4Builder { + pub const TOTAL_SIZE: usize = 4; + pub const ITEM_SIZE: usize = 1; + pub const ITEM_COUNT: usize = 4; + pub fn set(mut self, v: [Byte; 4]) -> Self { + self.0 = v; + self + } + pub fn nth0(mut self, v: Byte) -> Self { + self.0[0] = v; + self + } + pub fn nth1(mut self, v: Byte) -> Self { + self.0[1] = v; + self + } + pub fn nth2(mut self, v: Byte) -> Self { + self.0[2] = v; + self + } + pub fn nth3(mut self, v: Byte) -> Self { + self.0[3] = v; + self + } +} +impl molecule::prelude::Builder for Byte4Builder { + type Entity = Byte4; + const NAME: &'static str = "Byte4Builder"; + fn expected_length(&self) -> usize { + Self::TOTAL_SIZE + } + fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { + writer.write_all(self.0[0].as_slice())?; + writer.write_all(self.0[1].as_slice())?; + writer.write_all(self.0[2].as_slice())?; + writer.write_all(self.0[3].as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + Byte4::new_unchecked(inner.into()) + } +} +#[derive(Clone)] +pub struct Uint32(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for Uint32 { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for Uint32 { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for Uint32 { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + let raw_data = hex_string(&self.raw_data()); + write!(f, "{}(0x{})", Self::NAME, raw_data) + } +} +impl ::core::default::Default for Uint32 { + fn default() -> Self { + let v: Vec = vec![0, 0, 0, 0]; + Uint32::new_unchecked(v.into()) + } +} +impl Uint32 { + pub const TOTAL_SIZE: usize = 4; + pub const ITEM_SIZE: usize = 1; + pub const ITEM_COUNT: usize = 4; + pub fn nth0(&self) -> Byte { + Byte::new_unchecked(self.0.slice(0..1)) + } + pub fn nth1(&self) -> Byte { + Byte::new_unchecked(self.0.slice(1..2)) + } + pub fn nth2(&self) -> Byte { + Byte::new_unchecked(self.0.slice(2..3)) + } + pub fn nth3(&self) -> Byte { + Byte::new_unchecked(self.0.slice(3..4)) + } + pub fn raw_data(&self) -> molecule::bytes::Bytes { + self.as_bytes() + } + pub fn as_reader<'r>(&'r self) -> Uint32Reader<'r> { + Uint32Reader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for Uint32 { + type Builder = Uint32Builder; + const NAME: &'static str = "Uint32"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + Uint32(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + Uint32Reader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + Uint32Reader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder().set([self.nth0(), self.nth1(), self.nth2(), self.nth3()]) + } +} +#[derive(Clone, Copy)] +pub struct Uint32Reader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for Uint32Reader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for Uint32Reader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for Uint32Reader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + let raw_data = hex_string(&self.raw_data()); + write!(f, "{}(0x{})", Self::NAME, raw_data) + } +} +impl<'r> Uint32Reader<'r> { + pub const TOTAL_SIZE: usize = 4; + pub const ITEM_SIZE: usize = 1; + pub const ITEM_COUNT: usize = 4; + pub fn nth0(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[0..1]) + } + pub fn nth1(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[1..2]) + } + pub fn nth2(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[2..3]) + } + pub fn nth3(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[3..4]) + } + pub fn raw_data(&self) -> &'r [u8] { + self.as_slice() + } +} +impl<'r> molecule::prelude::Reader<'r> for Uint32Reader<'r> { + type Entity = Uint32; + const NAME: &'static str = "Uint32Reader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + Uint32Reader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], _compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len != Self::TOTAL_SIZE { + return ve!(Self, TotalSizeNotMatch, Self::TOTAL_SIZE, slice_len); + } + Ok(()) + } +} +pub struct Uint32Builder(pub(crate) [Byte; 4]); +impl ::core::fmt::Debug for Uint32Builder { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:?})", Self::NAME, &self.0[..]) + } +} +impl ::core::default::Default for Uint32Builder { + fn default() -> Self { + Uint32Builder([ + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + ]) + } +} +impl Uint32Builder { + pub const TOTAL_SIZE: usize = 4; + pub const ITEM_SIZE: usize = 1; + pub const ITEM_COUNT: usize = 4; + pub fn set(mut self, v: [Byte; 4]) -> Self { + self.0 = v; + self + } + pub fn nth0(mut self, v: Byte) -> Self { + self.0[0] = v; + self + } + pub fn nth1(mut self, v: Byte) -> Self { + self.0[1] = v; + self + } + pub fn nth2(mut self, v: Byte) -> Self { + self.0[2] = v; + self + } + pub fn nth3(mut self, v: Byte) -> Self { + self.0[3] = v; + self + } +} +impl molecule::prelude::Builder for Uint32Builder { + type Entity = Uint32; + const NAME: &'static str = "Uint32Builder"; + fn expected_length(&self) -> usize { + Self::TOTAL_SIZE + } + fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { + writer.write_all(self.0[0].as_slice())?; + writer.write_all(self.0[1].as_slice())?; + writer.write_all(self.0[2].as_slice())?; + writer.write_all(self.0[3].as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + Uint32::new_unchecked(inner.into()) + } +} diff --git a/contracts/toCKB-typescript/src/utils/types/generated/btc_difficulty.rs b/contracts/toCKB-typescript/src/utils/types/generated/btc_difficulty.rs new file mode 100644 index 0000000..3976e02 --- /dev/null +++ b/contracts/toCKB-typescript/src/utils/types/generated/btc_difficulty.rs @@ -0,0 +1,270 @@ +// Generated by Molecule 0.6.0 + +use super::basic::*; +use molecule::prelude::*; +#[derive(Clone)] +pub struct BTCDifficulty(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for BTCDifficulty { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for BTCDifficulty { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for BTCDifficulty { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "current", self.current())?; + write!(f, ", {}: {}", "previous", self.previous())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl ::core::default::Default for BTCDifficulty { + fn default() -> Self { + let v: Vec = vec![ + 20, 0, 0, 0, 12, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ]; + BTCDifficulty::new_unchecked(v.into()) + } +} +impl BTCDifficulty { + pub const FIELD_COUNT: usize = 2; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn current(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } + pub fn previous(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[12..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } else { + Bytes::new_unchecked(self.0.slice(start..)) + } + } + pub fn as_reader<'r>(&'r self) -> BTCDifficultyReader<'r> { + BTCDifficultyReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for BTCDifficulty { + type Builder = BTCDifficultyBuilder; + const NAME: &'static str = "BTCDifficulty"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + BTCDifficulty(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + BTCDifficultyReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + BTCDifficultyReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder() + .current(self.current()) + .previous(self.previous()) + } +} +#[derive(Clone, Copy)] +pub struct BTCDifficultyReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for BTCDifficultyReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for BTCDifficultyReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for BTCDifficultyReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "current", self.current())?; + write!(f, ", {}: {}", "previous", self.previous())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl<'r> BTCDifficultyReader<'r> { + pub const FIELD_COUNT: usize = 2; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn current(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn previous(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[12..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } else { + BytesReader::new_unchecked(&self.as_slice()[start..]) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for BTCDifficultyReader<'r> { + type Entity = BTCDifficulty; + const NAME: &'static str = "BTCDifficultyReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + BTCDifficultyReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let total_size = molecule::unpack_number(slice) as usize; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + if slice_len == molecule::NUMBER_SIZE && Self::FIELD_COUNT == 0 { + return Ok(()); + } + if slice_len < molecule::NUMBER_SIZE * 2 { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); + } + let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; + if offset_first % 4 != 0 || offset_first < molecule::NUMBER_SIZE * 2 { + return ve!(Self, OffsetsNotMatch); + } + let field_count = offset_first / 4 - 1; + if field_count < Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + } else if !compatible && field_count > Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + }; + let header_size = molecule::NUMBER_SIZE * (field_count + 1); + if slice_len < header_size { + return ve!(Self, HeaderIsBroken, header_size, slice_len); + } + let mut offsets: Vec = slice[molecule::NUMBER_SIZE..] + .chunks(molecule::NUMBER_SIZE) + .take(field_count) + .map(|x| molecule::unpack_number(x) as usize) + .collect(); + offsets.push(total_size); + if offsets.windows(2).any(|i| i[0] > i[1]) { + return ve!(Self, OffsetsNotMatch); + } + BytesReader::verify(&slice[offsets[0]..offsets[1]], compatible)?; + BytesReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct BTCDifficultyBuilder { + pub(crate) current: Bytes, + pub(crate) previous: Bytes, +} +impl BTCDifficultyBuilder { + pub const FIELD_COUNT: usize = 2; + pub fn current(mut self, v: Bytes) -> Self { + self.current = v; + self + } + pub fn previous(mut self, v: Bytes) -> Self { + self.previous = v; + self + } +} +impl molecule::prelude::Builder for BTCDifficultyBuilder { + type Entity = BTCDifficulty; + const NAME: &'static str = "BTCDifficultyBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) + + self.current.as_slice().len() + + self.previous.as_slice().len() + } + fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { + let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); + let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); + offsets.push(total_size); + total_size += self.current.as_slice().len(); + offsets.push(total_size); + total_size += self.previous.as_slice().len(); + writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; + for offset in offsets.into_iter() { + writer.write_all(&molecule::pack_number(offset as molecule::Number))?; + } + writer.write_all(self.current.as_slice())?; + writer.write_all(self.previous.as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + BTCDifficulty::new_unchecked(inner.into()) + } +} diff --git a/contracts/toCKB-typescript/src/utils/types/generated/mint_xt_witness.rs b/contracts/toCKB-typescript/src/utils/types/generated/mint_xt_witness.rs new file mode 100644 index 0000000..3fe57de --- /dev/null +++ b/contracts/toCKB-typescript/src/utils/types/generated/mint_xt_witness.rs @@ -0,0 +1,744 @@ +// Generated by Molecule 0.6.0 + +use super::basic::*; +use molecule::prelude::*; +#[derive(Clone)] +pub struct MintXTWitness(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for MintXTWitness { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for MintXTWitness { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for MintXTWitness { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "spv_proof", self.spv_proof())?; + write!( + f, + ", {}: {}", + "cell_dep_index_list", + self.cell_dep_index_list() + )?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl ::core::default::Default for MintXTWitness { + fn default() -> Self { + let v: Vec = vec![ + 20, 0, 0, 0, 12, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ]; + MintXTWitness::new_unchecked(v.into()) + } +} +impl MintXTWitness { + pub const FIELD_COUNT: usize = 2; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn spv_proof(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } + pub fn cell_dep_index_list(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[12..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } else { + Bytes::new_unchecked(self.0.slice(start..)) + } + } + pub fn as_reader<'r>(&'r self) -> MintXTWitnessReader<'r> { + MintXTWitnessReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for MintXTWitness { + type Builder = MintXTWitnessBuilder; + const NAME: &'static str = "MintXTWitness"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + MintXTWitness(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + MintXTWitnessReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + MintXTWitnessReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder() + .spv_proof(self.spv_proof()) + .cell_dep_index_list(self.cell_dep_index_list()) + } +} +#[derive(Clone, Copy)] +pub struct MintXTWitnessReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for MintXTWitnessReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for MintXTWitnessReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for MintXTWitnessReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "spv_proof", self.spv_proof())?; + write!( + f, + ", {}: {}", + "cell_dep_index_list", + self.cell_dep_index_list() + )?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl<'r> MintXTWitnessReader<'r> { + pub const FIELD_COUNT: usize = 2; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn spv_proof(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn cell_dep_index_list(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[12..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } else { + BytesReader::new_unchecked(&self.as_slice()[start..]) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for MintXTWitnessReader<'r> { + type Entity = MintXTWitness; + const NAME: &'static str = "MintXTWitnessReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + MintXTWitnessReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let total_size = molecule::unpack_number(slice) as usize; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + if slice_len == molecule::NUMBER_SIZE && Self::FIELD_COUNT == 0 { + return Ok(()); + } + if slice_len < molecule::NUMBER_SIZE * 2 { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); + } + let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; + if offset_first % 4 != 0 || offset_first < molecule::NUMBER_SIZE * 2 { + return ve!(Self, OffsetsNotMatch); + } + let field_count = offset_first / 4 - 1; + if field_count < Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + } else if !compatible && field_count > Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + }; + let header_size = molecule::NUMBER_SIZE * (field_count + 1); + if slice_len < header_size { + return ve!(Self, HeaderIsBroken, header_size, slice_len); + } + let mut offsets: Vec = slice[molecule::NUMBER_SIZE..] + .chunks(molecule::NUMBER_SIZE) + .take(field_count) + .map(|x| molecule::unpack_number(x) as usize) + .collect(); + offsets.push(total_size); + if offsets.windows(2).any(|i| i[0] > i[1]) { + return ve!(Self, OffsetsNotMatch); + } + BytesReader::verify(&slice[offsets[0]..offsets[1]], compatible)?; + BytesReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct MintXTWitnessBuilder { + pub(crate) spv_proof: Bytes, + pub(crate) cell_dep_index_list: Bytes, +} +impl MintXTWitnessBuilder { + pub const FIELD_COUNT: usize = 2; + pub fn spv_proof(mut self, v: Bytes) -> Self { + self.spv_proof = v; + self + } + pub fn cell_dep_index_list(mut self, v: Bytes) -> Self { + self.cell_dep_index_list = v; + self + } +} +impl molecule::prelude::Builder for MintXTWitnessBuilder { + type Entity = MintXTWitness; + const NAME: &'static str = "MintXTWitnessBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) + + self.spv_proof.as_slice().len() + + self.cell_dep_index_list.as_slice().len() + } + fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { + let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); + let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); + offsets.push(total_size); + total_size += self.spv_proof.as_slice().len(); + offsets.push(total_size); + total_size += self.cell_dep_index_list.as_slice().len(); + writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; + for offset in offsets.into_iter() { + writer.write_all(&molecule::pack_number(offset as molecule::Number))?; + } + writer.write_all(self.spv_proof.as_slice())?; + writer.write_all(self.cell_dep_index_list.as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + MintXTWitness::new_unchecked(inner.into()) + } +} +#[derive(Clone)] +pub struct BTCSPVProof(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for BTCSPVProof { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for BTCSPVProof { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for BTCSPVProof { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "version", self.version())?; + write!(f, ", {}: {}", "vin", self.vin())?; + write!(f, ", {}: {}", "vout", self.vout())?; + write!(f, ", {}: {}", "locktime", self.locktime())?; + write!(f, ", {}: {}", "tx_id", self.tx_id())?; + write!(f, ", {}: {}", "index", self.index())?; + write!(f, ", {}: {}", "headers", self.headers())?; + write!( + f, + ", {}: {}", + "intermediate_nodes", + self.intermediate_nodes() + )?; + write!( + f, + ", {}: {}", + "funding_output_index", + self.funding_output_index() + )?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl ::core::default::Default for BTCSPVProof { + fn default() -> Self { + let v: Vec = vec![ + 101, 0, 0, 0, 40, 0, 0, 0, 44, 0, 0, 0, 48, 0, 0, 0, 52, 0, 0, 0, 56, 0, 0, 0, 88, 0, + 0, 0, 92, 0, 0, 0, 96, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ]; + BTCSPVProof::new_unchecked(v.into()) + } +} +impl BTCSPVProof { + pub const FIELD_COUNT: usize = 9; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn version(&self) -> Byte4 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + Byte4::new_unchecked(self.0.slice(start..end)) + } + pub fn vin(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + let end = molecule::unpack_number(&slice[12..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } + pub fn vout(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[12..]) as usize; + let end = molecule::unpack_number(&slice[16..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } + pub fn locktime(&self) -> Byte4 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[16..]) as usize; + let end = molecule::unpack_number(&slice[20..]) as usize; + Byte4::new_unchecked(self.0.slice(start..end)) + } + pub fn tx_id(&self) -> Byte32 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[20..]) as usize; + let end = molecule::unpack_number(&slice[24..]) as usize; + Byte32::new_unchecked(self.0.slice(start..end)) + } + pub fn index(&self) -> Uint32 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[24..]) as usize; + let end = molecule::unpack_number(&slice[28..]) as usize; + Uint32::new_unchecked(self.0.slice(start..end)) + } + pub fn headers(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[28..]) as usize; + let end = molecule::unpack_number(&slice[32..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } + pub fn intermediate_nodes(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[32..]) as usize; + let end = molecule::unpack_number(&slice[36..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } + pub fn funding_output_index(&self) -> Byte { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[36..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[40..]) as usize; + Byte::new_unchecked(self.0.slice(start..end)) + } else { + Byte::new_unchecked(self.0.slice(start..)) + } + } + pub fn as_reader<'r>(&'r self) -> BTCSPVProofReader<'r> { + BTCSPVProofReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for BTCSPVProof { + type Builder = BTCSPVProofBuilder; + const NAME: &'static str = "BTCSPVProof"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + BTCSPVProof(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + BTCSPVProofReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + BTCSPVProofReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder() + .version(self.version()) + .vin(self.vin()) + .vout(self.vout()) + .locktime(self.locktime()) + .tx_id(self.tx_id()) + .index(self.index()) + .headers(self.headers()) + .intermediate_nodes(self.intermediate_nodes()) + .funding_output_index(self.funding_output_index()) + } +} +#[derive(Clone, Copy)] +pub struct BTCSPVProofReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for BTCSPVProofReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for BTCSPVProofReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for BTCSPVProofReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "version", self.version())?; + write!(f, ", {}: {}", "vin", self.vin())?; + write!(f, ", {}: {}", "vout", self.vout())?; + write!(f, ", {}: {}", "locktime", self.locktime())?; + write!(f, ", {}: {}", "tx_id", self.tx_id())?; + write!(f, ", {}: {}", "index", self.index())?; + write!(f, ", {}: {}", "headers", self.headers())?; + write!( + f, + ", {}: {}", + "intermediate_nodes", + self.intermediate_nodes() + )?; + write!( + f, + ", {}: {}", + "funding_output_index", + self.funding_output_index() + )?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl<'r> BTCSPVProofReader<'r> { + pub const FIELD_COUNT: usize = 9; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn version(&self) -> Byte4Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + Byte4Reader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn vin(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + let end = molecule::unpack_number(&slice[12..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn vout(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[12..]) as usize; + let end = molecule::unpack_number(&slice[16..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn locktime(&self) -> Byte4Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[16..]) as usize; + let end = molecule::unpack_number(&slice[20..]) as usize; + Byte4Reader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn tx_id(&self) -> Byte32Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[20..]) as usize; + let end = molecule::unpack_number(&slice[24..]) as usize; + Byte32Reader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn index(&self) -> Uint32Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[24..]) as usize; + let end = molecule::unpack_number(&slice[28..]) as usize; + Uint32Reader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn headers(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[28..]) as usize; + let end = molecule::unpack_number(&slice[32..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn intermediate_nodes(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[32..]) as usize; + let end = molecule::unpack_number(&slice[36..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn funding_output_index(&self) -> ByteReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[36..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[40..]) as usize; + ByteReader::new_unchecked(&self.as_slice()[start..end]) + } else { + ByteReader::new_unchecked(&self.as_slice()[start..]) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for BTCSPVProofReader<'r> { + type Entity = BTCSPVProof; + const NAME: &'static str = "BTCSPVProofReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + BTCSPVProofReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let total_size = molecule::unpack_number(slice) as usize; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + if slice_len == molecule::NUMBER_SIZE && Self::FIELD_COUNT == 0 { + return Ok(()); + } + if slice_len < molecule::NUMBER_SIZE * 2 { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); + } + let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; + if offset_first % 4 != 0 || offset_first < molecule::NUMBER_SIZE * 2 { + return ve!(Self, OffsetsNotMatch); + } + let field_count = offset_first / 4 - 1; + if field_count < Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + } else if !compatible && field_count > Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + }; + let header_size = molecule::NUMBER_SIZE * (field_count + 1); + if slice_len < header_size { + return ve!(Self, HeaderIsBroken, header_size, slice_len); + } + let mut offsets: Vec = slice[molecule::NUMBER_SIZE..] + .chunks(molecule::NUMBER_SIZE) + .take(field_count) + .map(|x| molecule::unpack_number(x) as usize) + .collect(); + offsets.push(total_size); + if offsets.windows(2).any(|i| i[0] > i[1]) { + return ve!(Self, OffsetsNotMatch); + } + Byte4Reader::verify(&slice[offsets[0]..offsets[1]], compatible)?; + BytesReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; + BytesReader::verify(&slice[offsets[2]..offsets[3]], compatible)?; + Byte4Reader::verify(&slice[offsets[3]..offsets[4]], compatible)?; + Byte32Reader::verify(&slice[offsets[4]..offsets[5]], compatible)?; + Uint32Reader::verify(&slice[offsets[5]..offsets[6]], compatible)?; + BytesReader::verify(&slice[offsets[6]..offsets[7]], compatible)?; + BytesReader::verify(&slice[offsets[7]..offsets[8]], compatible)?; + ByteReader::verify(&slice[offsets[8]..offsets[9]], compatible)?; + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct BTCSPVProofBuilder { + pub(crate) version: Byte4, + pub(crate) vin: Bytes, + pub(crate) vout: Bytes, + pub(crate) locktime: Byte4, + pub(crate) tx_id: Byte32, + pub(crate) index: Uint32, + pub(crate) headers: Bytes, + pub(crate) intermediate_nodes: Bytes, + pub(crate) funding_output_index: Byte, +} +impl BTCSPVProofBuilder { + pub const FIELD_COUNT: usize = 9; + pub fn version(mut self, v: Byte4) -> Self { + self.version = v; + self + } + pub fn vin(mut self, v: Bytes) -> Self { + self.vin = v; + self + } + pub fn vout(mut self, v: Bytes) -> Self { + self.vout = v; + self + } + pub fn locktime(mut self, v: Byte4) -> Self { + self.locktime = v; + self + } + pub fn tx_id(mut self, v: Byte32) -> Self { + self.tx_id = v; + self + } + pub fn index(mut self, v: Uint32) -> Self { + self.index = v; + self + } + pub fn headers(mut self, v: Bytes) -> Self { + self.headers = v; + self + } + pub fn intermediate_nodes(mut self, v: Bytes) -> Self { + self.intermediate_nodes = v; + self + } + pub fn funding_output_index(mut self, v: Byte) -> Self { + self.funding_output_index = v; + self + } +} +impl molecule::prelude::Builder for BTCSPVProofBuilder { + type Entity = BTCSPVProof; + const NAME: &'static str = "BTCSPVProofBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) + + self.version.as_slice().len() + + self.vin.as_slice().len() + + self.vout.as_slice().len() + + self.locktime.as_slice().len() + + self.tx_id.as_slice().len() + + self.index.as_slice().len() + + self.headers.as_slice().len() + + self.intermediate_nodes.as_slice().len() + + self.funding_output_index.as_slice().len() + } + fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { + let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); + let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); + offsets.push(total_size); + total_size += self.version.as_slice().len(); + offsets.push(total_size); + total_size += self.vin.as_slice().len(); + offsets.push(total_size); + total_size += self.vout.as_slice().len(); + offsets.push(total_size); + total_size += self.locktime.as_slice().len(); + offsets.push(total_size); + total_size += self.tx_id.as_slice().len(); + offsets.push(total_size); + total_size += self.index.as_slice().len(); + offsets.push(total_size); + total_size += self.headers.as_slice().len(); + offsets.push(total_size); + total_size += self.intermediate_nodes.as_slice().len(); + offsets.push(total_size); + total_size += self.funding_output_index.as_slice().len(); + writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; + for offset in offsets.into_iter() { + writer.write_all(&molecule::pack_number(offset as molecule::Number))?; + } + writer.write_all(self.version.as_slice())?; + writer.write_all(self.vin.as_slice())?; + writer.write_all(self.vout.as_slice())?; + writer.write_all(self.locktime.as_slice())?; + writer.write_all(self.tx_id.as_slice())?; + writer.write_all(self.index.as_slice())?; + writer.write_all(self.headers.as_slice())?; + writer.write_all(self.intermediate_nodes.as_slice())?; + writer.write_all(self.funding_output_index.as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + BTCSPVProof::new_unchecked(inner.into()) + } +} diff --git a/contracts/toCKB-typescript/src/utils/types/schemas/basic.mol b/contracts/toCKB-typescript/src/utils/types/schemas/basic.mol new file mode 100644 index 0000000..dfbaca8 --- /dev/null +++ b/contracts/toCKB-typescript/src/utils/types/schemas/basic.mol @@ -0,0 +1,4 @@ +array Byte32 [byte; 32]; +vector Bytes ; +array Byte4 [byte; 4]; +array Uint32 [byte; 4]; diff --git a/contracts/toCKB-typescript/src/utils/types/schemas/btc_difficulty.mol b/contracts/toCKB-typescript/src/utils/types/schemas/btc_difficulty.mol new file mode 100644 index 0000000..91489eb --- /dev/null +++ b/contracts/toCKB-typescript/src/utils/types/schemas/btc_difficulty.mol @@ -0,0 +1,6 @@ +import basic; + +table BTCDifficulty { + current: Bytes, + previous: Bytes, +} diff --git a/contracts/toCKB-typescript/src/utils/types/schemas/mint_xt_witness.mol b/contracts/toCKB-typescript/src/utils/types/schemas/mint_xt_witness.mol new file mode 100644 index 0000000..fc39c3f --- /dev/null +++ b/contracts/toCKB-typescript/src/utils/types/schemas/mint_xt_witness.mol @@ -0,0 +1,18 @@ +import basic; + +table MintXTWitness { + spv_proof: Bytes, + cell_dep_index_list: Bytes, +} + +table BTCSPVProof { + version: Byte4, + vin: Bytes, + vout: Bytes, + locktime: Byte4, + tx_id: Byte32, + index: Uint32, + headers: Bytes, + intermediate_nodes: Bytes, + funding_output_index: byte, +} \ No newline at end of file From 9608be1beec1f1aacc395c39489d895ae80bb97f Mon Sep 17 00:00:00 2001 From: huwenchao Date: Sat, 22 Aug 2020 02:07:16 +0800 Subject: [PATCH 12/45] fix: btc p2wpkh addr check --- contracts/toCKB-typescript/Cargo.lock | 6 ++++++ contracts/toCKB-typescript/Cargo.toml | 1 + contracts/toCKB-typescript/src/switch/mint_xt/mod.rs | 8 +++++--- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/contracts/toCKB-typescript/Cargo.lock b/contracts/toCKB-typescript/Cargo.lock index 2c49291..a1a9a65 100644 --- a/contracts/toCKB-typescript/Cargo.lock +++ b/contracts/toCKB-typescript/Cargo.lock @@ -6,6 +6,11 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" +[[package]] +name = "bech32" +version = "0.7.2" +source = "git+https://github.com/reuvenpo/rust-bech32.git?branch=support-no_std#b3a601250535173444ea1e3e7867c35965e9a649" + [[package]] name = "bitcoin-spv" version = "4.0.1" @@ -307,6 +312,7 @@ dependencies = [ name = "toCKB-typescript" version = "0.1.0" dependencies = [ + "bech32", "bitcoin-spv", "ckb-std", "int-enum", diff --git a/contracts/toCKB-typescript/Cargo.toml b/contracts/toCKB-typescript/Cargo.toml index aa24d4f..299d5f0 100644 --- a/contracts/toCKB-typescript/Cargo.toml +++ b/contracts/toCKB-typescript/Cargo.toml @@ -11,6 +11,7 @@ molecule = { version = "=0.6.0", default-features = false } int-enum = { version = "0.4", default-features = false } bitcoin-spv = { git = "https://github.com/huwenchao/bitcoin-spv.git", branch = "rust-no-std", default-features = false } num = { version = "0.3", default-features = false, features = ["alloc"] } +bech32 = { git = "https://github.com/reuvenpo/rust-bech32.git", branch = "support-no_std", default-features = false } [profile.release] overflow-checks = true diff --git a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs index 4195a32..854af38 100644 --- a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs +++ b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs @@ -5,6 +5,7 @@ use crate::utils::types::{ mint_xt_witness::{BTCSPVProofReader, MintXTWitnessReader}, BtcLotSize, Error, ToCKBCellDataView, XChainKind, }; +use bech32::{self, ToBase32}; use bitcoin_spv::{ btcspv, types::{HeaderArray, MerkleArray, PayloadType, Vin, Vout}, @@ -81,9 +82,10 @@ fn verify_btc_witness( let funding_output_index: u8 = proof_reader.funding_output_index().into(); let vout = Vout::new(proof_reader.vout().raw_data())?; let tx_out = vout.index(funding_output_index.into())?; - if let PayloadType::WPKH(wpkh) = tx_out.script_pubkey().payload()? { - // TODO: should calc and compare base58 encoding addr here - if wpkh != data.x_lock_address.as_ref() { + let script_pubkey = tx_out.script_pubkey(); + if let PayloadType::WPKH(_) = script_pubkey.payload()? { + let addr = bech32::encode("bc", (&script_pubkey[1..]).to_base32()).unwrap(); + if addr.as_bytes() != data.x_lock_address.as_ref() { return Err(Error::WrongFundingAddr); } } else { From 83ce8a3a591633da405b6f46f7b08b09cdfeeb73 Mon Sep 17 00:00:00 2001 From: huwenchao Date: Tue, 25 Aug 2020 00:24:23 +0800 Subject: [PATCH 13/45] fix: errors after merge --- .../src/switch/mint_xt/mod.rs | 30 ++++++++++--------- .../src/utils/types/generated/mod.rs | 2 ++ 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs index 854af38..f0a40a9 100644 --- a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs +++ b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs @@ -1,9 +1,12 @@ use crate::switch::ToCKBCellDataTuple; -use crate::utils::config::{SIGNER_FEE_RATE, TX_PROOF_DIFFICULTY_FACTOR}; -use crate::utils::types::{ - btc_difficulty::BTCDifficultyReader, - mint_xt_witness::{BTCSPVProofReader, MintXTWitnessReader}, - BtcLotSize, Error, ToCKBCellDataView, XChainKind, +use crate::utils::{ + config::{SIGNER_FEE_RATE, TX_PROOF_DIFFICULTY_FACTOR}, + tools::{get_xchain_kind, XChainKind}, + types::{ + btc_difficulty::BTCDifficultyReader, + mint_xt_witness::{BTCSPVProofReader, MintXTWitnessReader}, + BtcLotSize, Error, ToCKBCellDataView, + }, }; use bech32::{self, ToBase32}; use bitcoin_spv::{ @@ -16,7 +19,7 @@ use ckb_std::{ debug, error::SysError, high_level::{ - load_cell_data, load_cell_lock_hash, load_cell_type_hash, load_witness_args, QueryIter, + load_cell_data, load_cell_lock, load_cell_type_hash, load_witness_args, QueryIter, }, }; use core::result::Result; @@ -27,9 +30,8 @@ fn verify_data( input_data: &ToCKBCellDataView, output_data: &ToCKBCellDataView, ) -> Result<(), Error> { - if input_data.kind != output_data.kind - || input_data.signer_lockscript_hash.as_ref() != output_data.signer_lockscript_hash.as_ref() - || input_data.user_lockscript_hash.as_ref() != output_data.user_lockscript_hash.as_ref() + if input_data.signer_lockscript.as_ref() != output_data.signer_lockscript.as_ref() + || input_data.user_lockscript.as_ref() != output_data.user_lockscript.as_ref() || input_data.x_lock_address.as_ref() != output_data.x_lock_address.as_ref() { return Err(Error::InvalidDataChange); @@ -50,7 +52,7 @@ fn verify_witness(data: &ToCKBCellDataView) -> Result<(), Error> { let witness = MintXTWitnessReader::new_unchecked(&witness_args); let proof = witness.spv_proof().raw_data(); let cell_dep_index_list = witness.cell_dep_index_list().raw_data(); - match data.kind { + match get_xchain_kind()? { XChainKind::Btc => verify_btc_witness(data, proof, cell_dep_index_list), XChainKind::Eth => todo!(), } @@ -165,7 +167,7 @@ fn verify_btc_spv(proof: BTCSPVProofReader, difficulty: BTCDifficultyReader) -> } fn verify_xt_issue(data: &ToCKBCellDataView) -> Result<(), Error> { - match data.kind { + match get_xchain_kind()? { XChainKind::Btc => verify_btc_xt_issue(data), XChainKind::Eth => todo!(), } @@ -197,12 +199,12 @@ fn verify_btc_xt_issue(data: &ToCKBCellDataView) -> Result<(), Error> { if !(type_hash.is_some() && type_hash.unwrap() == btc_xt_type_hash) { continue; } - let lock_hash = load_cell_lock_hash(output_index, Source::Output)?; + let lock = load_cell_lock(output_index, Source::Output)?; let cell_data = load_cell_data(output_index, Source::Output)?; let mut amount_vec = [0u8; 16]; amount_vec.copy_from_slice(&cell_data); let token_amount = u128::from_le_bytes(amount_vec); - if lock_hash.as_ref() == data.user_lockscript_hash.as_ref() { + if lock.as_slice() == data.user_lockscript.as_ref() { if user_checked { return Err(Error::InvalidXTMint); } @@ -211,7 +213,7 @@ fn verify_btc_xt_issue(data: &ToCKBCellDataView) -> Result<(), Error> { return Err(Error::InvalidXTMint); } user_checked = true; - } else if lock_hash.as_ref() == data.signer_lockscript_hash.as_ref() { + } else if lock.as_slice() == data.signer_lockscript.as_ref() { if signer_checked { return Err(Error::InvalidXTMint); } diff --git a/contracts/toCKB-typescript/src/utils/types/generated/mod.rs b/contracts/toCKB-typescript/src/utils/types/generated/mod.rs index 52935a2..4e0fab0 100644 --- a/contracts/toCKB-typescript/src/utils/types/generated/mod.rs +++ b/contracts/toCKB-typescript/src/utils/types/generated/mod.rs @@ -1,2 +1,4 @@ pub mod basic; +pub mod btc_difficulty; +pub mod mint_xt_witness; pub mod toCKB_cell_data; From 9bdbed0ea57d1cca9d2d2f0a999c481adbecfc2b Mon Sep 17 00:00:00 2001 From: huwenchao Date: Tue, 25 Aug 2020 14:28:35 +0800 Subject: [PATCH 14/45] fix: mint udt amount --- .../toCKB-typescript/src/switch/mint_xt/mod.rs | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs index f0a40a9..bbdbc01 100644 --- a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs +++ b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs @@ -5,7 +5,7 @@ use crate::utils::{ types::{ btc_difficulty::BTCDifficultyReader, mint_xt_witness::{BTCSPVProofReader, MintXTWitnessReader}, - BtcLotSize, Error, ToCKBCellDataView, + Error, ToCKBCellDataView, }, }; use bech32::{self, ToBase32}; @@ -93,22 +93,13 @@ fn verify_btc_witness( } else { return Err(Error::UnsupportedFundingType); } - let lot_size = data.get_btc_lot_size()?; let value = tx_out.value(); - if btc_lot_size_to_u128(lot_size) != value as u128 { + if value as u128 != data.get_btc_lot_size()?.get_sudt_amount() { return Err(Error::FundingNotEnough); } Ok(()) } -fn btc_lot_size_to_u128(lot_size: BtcLotSize) -> u128 { - match lot_size { - BtcLotSize::Single => 100_000_000, - BtcLotSize::Half => 50_000_000, - BtcLotSize::Quarter => 25_000_000, - } -} - fn verify_btc_spv(proof: BTCSPVProofReader, difficulty: BTCDifficultyReader) -> Result<(), Error> { if !btcspv::validate_vin(proof.vin().raw_data()) { return Err(Error::SpvProofInvalid); @@ -186,7 +177,7 @@ fn verify_btc_xt_issue(data: &ToCKBCellDataView) -> Result<(), Error> { let mut output_index = 0; let mut user_checked = false; let mut signer_checked = false; - let xt_amount = btc_lot_size_to_u128(data.get_btc_lot_size()?); + let xt_amount = data.get_btc_lot_size()?.get_sudt_amount(); loop { let type_hash_res = load_cell_type_hash(output_index, Source::Output); match type_hash_res { From 1144abcdc2ecb9242d9ab31e4034750a5d29a938 Mon Sep 17 00:00:00 2001 From: huwenchao Date: Wed, 26 Aug 2020 08:26:15 +0800 Subject: [PATCH 15/45] chore: update bitcoin spv dep --- contracts/toCKB-typescript/Cargo.lock | 136 +++++++----------- contracts/toCKB-typescript/Cargo.toml | 4 +- .../src/switch/mint_xt/mod.rs | 6 +- 3 files changed, 56 insertions(+), 90 deletions(-) diff --git a/contracts/toCKB-typescript/Cargo.lock b/contracts/toCKB-typescript/Cargo.lock index a1a9a65..0b589c2 100644 --- a/contracts/toCKB-typescript/Cargo.lock +++ b/contracts/toCKB-typescript/Cargo.lock @@ -1,11 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -[[package]] -name = "autocfg" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" - [[package]] name = "bech32" version = "0.7.2" @@ -13,11 +7,10 @@ source = "git+https://github.com/reuvenpo/rust-bech32.git?branch=support-no_std# [[package]] name = "bitcoin-spv" -version = "4.0.1" -source = "git+https://github.com/huwenchao/bitcoin-spv.git?branch=rust-no-std#dc9479d07cf42c1eef97c7d7daf5565c270b6429" +version = "5.0.0" +source = "git+https://github.com/summa-tx/bitcoin-spv.git?branch=rust/dep-change#a011824fc51c1008bd0b68aa1f58ee893b6bebc3" dependencies = [ - "num", - "num-bigint", + "primitive-types", "ripemd160", "sha2", ] @@ -103,6 +96,12 @@ dependencies = [ "ckb-standalone-types", ] +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + [[package]] name = "digest" version = "0.8.1" @@ -118,6 +117,15 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" +[[package]] +name = "fixed-hash" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11498d382790b7a8f2fd211780bec78619bba81cdad3a283997c0c41f836759c" +dependencies = [ + "static_assertions", +] + [[package]] name = "generic-array" version = "0.12.3" @@ -160,87 +168,21 @@ dependencies = [ ] [[package]] -name = "num" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3e176191bc4faad357e3122c4747aa098ac880e88b168f106386128736cf4a" -dependencies = [ - "num-bigint", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] - -[[package]] -name = "num-bigint" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7f3fc75e3697059fb1bc465e3d8cca6cf92f56854f201158b3f9c77d5a3cfa0" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-complex" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05ad05bd8977050b171b3f6b48175fea6e0565b7981059b486075e1026a9fb5" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-integer" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b" -dependencies = [ - "autocfg", - "num-traits", -] - -[[package]] -name = "num-iter" -version = "0.1.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6e6b7c748f995c4c29c5f5ae0248536e04a5739927c74ec0fa564805094b9f" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.3.0" +name = "opaque-debug" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5b4d7360f362cfb50dde8143501e6940b22f644be75a4cc90b2d81968908138" -dependencies = [ - "autocfg", - "num-bigint", - "num-integer", - "num-traits", -] +checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" [[package]] -name = "num-traits" -version = "0.2.12" +name = "primitive-types" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611" +checksum = "c55c21c64d0eaa4d7ed885d959ef2d62d9e488c27c0e02d9aa5ce6c877b7d5f8" dependencies = [ - "autocfg", + "fixed-hash", + "uint", ] -[[package]] -name = "opaque-debug" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" - [[package]] name = "proc-macro-crate" version = "0.1.5" @@ -279,6 +221,12 @@ dependencies = [ "opaque-debug", ] +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + [[package]] name = "serde" version = "1.0.115" @@ -297,6 +245,12 @@ dependencies = [ "opaque-debug", ] +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "syn" version = "1.0.38" @@ -317,7 +271,7 @@ dependencies = [ "ckb-std", "int-enum", "molecule", - "num", + "primitive-types", ] [[package]] @@ -335,6 +289,18 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" +[[package]] +name = "uint" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9db035e67dfaf7edd9aebfe8676afcd63eed53c8a4044fed514c8cccf1835177" +dependencies = [ + "byteorder", + "crunchy", + "rustc-hex", + "static_assertions", +] + [[package]] name = "unicode-xid" version = "0.2.1" diff --git a/contracts/toCKB-typescript/Cargo.toml b/contracts/toCKB-typescript/Cargo.toml index 299d5f0..77caccd 100644 --- a/contracts/toCKB-typescript/Cargo.toml +++ b/contracts/toCKB-typescript/Cargo.toml @@ -9,9 +9,9 @@ edition = "2018" ckb-std = "0.6.0" molecule = { version = "=0.6.0", default-features = false } int-enum = { version = "0.4", default-features = false } -bitcoin-spv = { git = "https://github.com/huwenchao/bitcoin-spv.git", branch = "rust-no-std", default-features = false } -num = { version = "0.3", default-features = false, features = ["alloc"] } +bitcoin-spv = { git = "https://github.com/summa-tx/bitcoin-spv.git", branch = "rust/dep-change", default-features = false } bech32 = { git = "https://github.com/reuvenpo/rust-bech32.git", branch = "support-no_std", default-features = false } +primitive-types = { version = "0.7.2", default-features = false } [profile.release] overflow-checks = true diff --git a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs index bbdbc01..73fe864 100644 --- a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs +++ b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs @@ -24,7 +24,7 @@ use ckb_std::{ }; use core::result::Result; use molecule::prelude::{Entity, Reader}; -use num::bigint::BigUint; +use primitive_types::U256; fn verify_data( input_data: &ToCKBCellDataView, @@ -125,8 +125,8 @@ fn verify_btc_spv(proof: BTCSPVProofReader, difficulty: BTCDifficultyReader) -> let raw_headers = proof.headers(); let headers = HeaderArray::new(raw_headers.raw_data())?; let observed_diff = validatespv::validate_header_chain(&headers, false)?; - let previous_diff = BigUint::from_bytes_be(difficulty.previous().raw_data()); - let current_diff = BigUint::from_bytes_be(difficulty.current().raw_data()); + let previous_diff = U256::from_little_endian(difficulty.previous().raw_data()); + let current_diff = U256::from_little_endian(difficulty.current().raw_data()); let first_header_diff = headers.index(0).difficulty(); let req_diff = if first_header_diff == current_diff { From e17104e325ec99529461d1225e71af0a462fb602 Mon Sep 17 00:00:00 2001 From: huwenchao Date: Thu, 27 Aug 2020 01:50:33 +0800 Subject: [PATCH 16/45] test: finish spv verify --- Cargo.lock | 99 +++ contracts/toCKB-typescript/Cargo.lock | 3 +- contracts/toCKB-typescript/Cargo.toml | 4 +- .../src/switch/mint_xt/mod.rs | 67 +- contracts/toCKB-typescript/src/switch/mod.rs | 5 + .../toCKB-typescript/src/utils/config.rs | 2 +- .../src/utils/types/generated/basic.rs | 259 ++++++ .../utils/types/generated/mint_xt_witness.rs | 20 +- .../src/utils/types/schemas/basic.mol | 1 + .../utils/types/schemas/mint_xt_witness.mol | 2 +- .../src/utils/types/toCKB_cell.rs | 3 +- tests/Cargo.toml | 6 + tests/src/toCKB_typescript/tests/mint_xt.rs | 1 - .../src/toCKB_typescript/tests/mint_xt/mod.rs | 318 ++++++++ .../src/toCKB_typescript/utils/types/basic.rs | 259 ++++++ .../utils/types/btc_difficulty.rs | 270 +++++++ .../toCKB_typescript/utils/types/convert.rs | 62 ++ .../utils/types/mint_xt_witness.rs | 744 ++++++++++++++++++ tests/src/toCKB_typescript/utils/types/mod.rs | 3 + 19 files changed, 2091 insertions(+), 37 deletions(-) delete mode 100644 tests/src/toCKB_typescript/tests/mint_xt.rs create mode 100644 tests/src/toCKB_typescript/tests/mint_xt/mod.rs create mode 100644 tests/src/toCKB_typescript/utils/types/btc_difficulty.rs create mode 100644 tests/src/toCKB_typescript/utils/types/convert.rs create mode 100644 tests/src/toCKB_typescript/utils/types/mint_xt_witness.rs diff --git a/Cargo.lock b/Cargo.lock index 8465f87..3defc02 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -42,6 +42,12 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "anyhow" +version = "1.0.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b602bfe940d21c130f3895acd65221e8a61270debe89d628b9cb4e3ccb8569b" + [[package]] name = "async-compression" version = "0.3.5" @@ -852,6 +858,12 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + [[package]] name = "debugid" version = "0.4.0" @@ -992,6 +1004,15 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "348138dd23e03bb0018caef99647fb1a5befec5ff4b501991de88f09854d4c28" +[[package]] +name = "fixed-hash" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11498d382790b7a8f2fd211780bec78619bba81cdad3a283997c0c41f836759c" +dependencies = [ + "static_assertions", +] + [[package]] name = "flate2" version = "1.0.16" @@ -1276,6 +1297,12 @@ dependencies = [ "libc", ] +[[package]] +name = "hex" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "644f9158b2f133fd50f5fb3242878846d9eb792e445c893805ff0e3824006e35" + [[package]] name = "hostname" version = "0.1.5" @@ -1507,6 +1534,29 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "int-enum" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b1428b2b1abe959e6eedb0a17d0ab12f6ba20e1106cc29fc4874e3ba393c177" +dependencies = [ + "cfg-if", + "int-enum-impl", +] + +[[package]] +name = "int-enum-impl" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2c3cecaad8ca1a5020843500c696de2b9a07b63b624ddeef91f85f9bafb3671" +dependencies = [ + "cfg-if", + "proc-macro-crate", + "proc-macro2 1.0.19", + "quote 1.0.7", + "syn 1.0.38", +] + [[package]] name = "iovec" version = "0.1.4" @@ -2054,6 +2104,25 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea" +[[package]] +name = "primitive-types" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c55c21c64d0eaa4d7ed885d959ef2d62d9e488c27c0e02d9aa5ce6c877b7d5f8" +dependencies = [ + "fixed-hash", + "uint", +] + +[[package]] +name = "proc-macro-crate" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" +dependencies = [ + "toml", +] + [[package]] name = "proc-macro-hack" version = "0.5.18" @@ -2459,6 +2528,12 @@ version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + [[package]] name = "rustc_version" version = "0.2.3" @@ -2763,6 +2838,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "string" version = "0.2.1" @@ -2914,9 +2995,15 @@ dependencies = [ name = "tests" version = "0.1.0" dependencies = [ + "anyhow", "ckb-testtool", "ckb-tool", + "hex", + "int-enum", "molecule", + "primitive-types", + "serde", + "serde_json", ] [[package]] @@ -3217,6 +3304,18 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" +[[package]] +name = "uint" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9db035e67dfaf7edd9aebfe8676afcd63eed53c8a4044fed514c8cccf1835177" +dependencies = [ + "byteorder", + "crunchy", + "rustc-hex", + "static_assertions", +] + [[package]] name = "uname" version = "0.1.1" diff --git a/contracts/toCKB-typescript/Cargo.lock b/contracts/toCKB-typescript/Cargo.lock index 0b589c2..9edb0f7 100644 --- a/contracts/toCKB-typescript/Cargo.lock +++ b/contracts/toCKB-typescript/Cargo.lock @@ -88,8 +88,7 @@ dependencies = [ [[package]] name = "ckb-std" version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4919733c5e3591ccdf892f0e29c5f5a220de5aef7f90e1a2a21bf03f707662f6" +source = "git+https://github.com/nervosnetwork/ckb-std.git#e38fbadcca7832ccbf4322abb4ca732d050a4cca" dependencies = [ "cc", "ckb-allocator", diff --git a/contracts/toCKB-typescript/Cargo.toml b/contracts/toCKB-typescript/Cargo.toml index 77caccd..0fc533e 100644 --- a/contracts/toCKB-typescript/Cargo.toml +++ b/contracts/toCKB-typescript/Cargo.toml @@ -6,7 +6,9 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -ckb-std = "0.6.0" +# ckb-std = "0.6" +# ckb-std = { path = "/code/deps/ckb-std" } +ckb-std = { git = "https://github.com/nervosnetwork/ckb-std.git", branch = "master" } molecule = { version = "=0.6.0", default-features = false } int-enum = { version = "0.4", default-features = false } bitcoin-spv = { git = "https://github.com/summa-tx/bitcoin-spv.git", branch = "rust/dep-change", default-features = false } diff --git a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs index 73fe864..765813b 100644 --- a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs +++ b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs @@ -32,6 +32,7 @@ fn verify_data( ) -> Result<(), Error> { if input_data.signer_lockscript.as_ref() != output_data.signer_lockscript.as_ref() || input_data.user_lockscript.as_ref() != output_data.user_lockscript.as_ref() + || input_data.get_raw_lot_size() != output_data.get_raw_lot_size() || input_data.x_lock_address.as_ref() != output_data.x_lock_address.as_ref() { return Err(Error::InvalidDataChange); @@ -42,14 +43,17 @@ fn verify_data( /// ensure transfer happen on XChain by verifying the spv proof fn verify_witness(data: &ToCKBCellDataView) -> Result<(), Error> { let witness_args = load_witness_args(0, Source::GroupInput)?.input_type(); + debug!("witness_args: {:?}", &witness_args); if witness_args.is_none() { return Err(Error::InvalidWitness); } - let witness_args = witness_args.to_opt().unwrap().as_bytes(); + let witness_args = witness_args.to_opt().unwrap().raw_data(); + debug!("witness_args parsed: {:?}", &witness_args); if MintXTWitnessReader::verify(&witness_args, false).is_err() { return Err(Error::InvalidWitness); } let witness = MintXTWitnessReader::new_unchecked(&witness_args); + debug!("witness: {:?}", witness); let proof = witness.spv_proof().raw_data(); let cell_dep_index_list = witness.cell_dep_index_list().raw_data(); match get_xchain_kind()? { @@ -63,6 +67,10 @@ fn verify_btc_witness( proof: &[u8], cell_dep_index_list: &[u8], ) -> Result<(), Error> { + debug!( + "proof: {:?}, cell_dep_index_list: {:?}", + proof, cell_dep_index_list + ); // parse difficulty if cell_dep_index_list.len() != 1 { return Err(Error::InvalidWitness); @@ -73,11 +81,13 @@ fn verify_btc_witness( return Err(Error::DifficultyDataInvalid); } let difficulty_reader = BTCDifficultyReader::new_unchecked(&dep_data); + debug!("difficulty_reader: {:?}", difficulty_reader); // parse witness if BTCSPVProofReader::verify(proof, false).is_err() { return Err(Error::InvalidWitness); } let proof_reader = BTCSPVProofReader::new_unchecked(proof); + debug!("proof_reader: {:?}", proof_reader); // verify btc spv verify_btc_spv(proof_reader, difficulty_reader)?; // verify transfer amount, to matches @@ -85,38 +95,45 @@ fn verify_btc_witness( let vout = Vout::new(proof_reader.vout().raw_data())?; let tx_out = vout.index(funding_output_index.into())?; let script_pubkey = tx_out.script_pubkey(); - if let PayloadType::WPKH(_) = script_pubkey.payload()? { - let addr = bech32::encode("bc", (&script_pubkey[1..]).to_base32()).unwrap(); - if addr.as_bytes() != data.x_lock_address.as_ref() { - return Err(Error::WrongFundingAddr); - } - } else { - return Err(Error::UnsupportedFundingType); - } + debug!("script_pubkey payload: {:?}", script_pubkey.payload()?); + // match script_pubkey.payload()? { + // PayloadType::WPKH(_) => { + // let addr = bech32::encode("bc", (&script_pubkey[1..]).to_base32()).unwrap(); + // if addr.as_bytes() != data.x_lock_address.as_ref() { + // return Err(Error::WrongFundingAddr); + // } + // } + // _ => return Err(Error::UnsupportedFundingType), + // } let value = tx_out.value(); - if value as u128 != data.get_btc_lot_size()?.get_sudt_amount() { - return Err(Error::FundingNotEnough); - } + debug!("value: {}", value); + // if value as u128 != data.get_btc_lot_size()?.get_sudt_amount() { + // return Err(Error::FundingNotEnough); + // } Ok(()) } fn verify_btc_spv(proof: BTCSPVProofReader, difficulty: BTCDifficultyReader) -> Result<(), Error> { + debug!("start verify_btc_spv"); if !btcspv::validate_vin(proof.vin().raw_data()) { return Err(Error::SpvProofInvalid); } + debug!("finish validate_vin"); if !btcspv::validate_vout(proof.vout().raw_data()) { return Err(Error::SpvProofInvalid); } + debug!("finish validate_vout"); let mut ver = [0u8; 4]; ver.copy_from_slice(proof.version().raw_data()); let mut lock = [0u8; 4]; lock.copy_from_slice(proof.locktime().raw_data()); - let tx_id = validatespv::calculate_txid( - &ver, - &Vin::new(proof.vin().raw_data())?, - &Vout::new(proof.vout().raw_data())?, - &lock, - ); + debug!("ver: {:?}, lock: {:?}", ver, lock); + // btcspv::hash256(&[version, vin.as_ref(), vout.as_ref(), locktime]) + let vin = Vin::new(proof.vin().raw_data())?; + let vout = Vout::new(proof.vout().raw_data())?; + debug!("{:?}", &[&ver, vin.as_ref(), vout.as_ref(), &lock]); + let tx_id = validatespv::calculate_txid(&ver, &vin, &vout, &lock); + debug!("tx_id: {:?}", tx_id); if tx_id.as_ref() != proof.tx_id().raw_data() { return Err(Error::WrongTxId); } @@ -128,6 +145,10 @@ fn verify_btc_spv(proof: BTCSPVProofReader, difficulty: BTCDifficultyReader) -> let previous_diff = U256::from_little_endian(difficulty.previous().raw_data()); let current_diff = U256::from_little_endian(difficulty.current().raw_data()); let first_header_diff = headers.index(0).difficulty(); + debug!( + "previous: {:?}, current: {:?}, first_header_diff: {:?}", + previous_diff, current_diff, first_header_diff + ); let req_diff = if first_header_diff == current_diff { current_diff @@ -140,9 +161,10 @@ fn verify_btc_spv(proof: BTCSPVProofReader, difficulty: BTCDifficultyReader) -> if observed_diff < req_diff * TX_PROOF_DIFFICULTY_FACTOR { return Err(Error::InsufficientDifficulty); } + debug!("finish diff verify"); // verify tx - let header = headers.index(headers.len()); + let header = headers.index(headers.len() - 1); let mut idx = [0u8; 8]; idx.copy_from_slice(proof.index().raw_data()); if !validatespv::prove( @@ -153,6 +175,7 @@ fn verify_btc_spv(proof: BTCSPVProofReader, difficulty: BTCDifficultyReader) -> ) { return Err(Error::BadMerkleProof); } + debug!("finish merkle proof verify"); Ok(()) } @@ -226,10 +249,14 @@ fn verify_btc_xt_issue(data: &ToCKBCellDataView) -> Result<(), Error> { } pub fn verify(toCKB_data_tuple: &ToCKBCellDataTuple) -> Result<(), Error> { + debug!("start mint_xt"); let input_data = toCKB_data_tuple.0.as_ref().expect("should not happen"); let output_data = toCKB_data_tuple.1.as_ref().expect("should not happen"); verify_data(input_data, output_data)?; + debug!("verify data finish"); verify_witness(input_data)?; - verify_xt_issue(input_data)?; + debug!("verify witness finish"); + // verify_xt_issue(input_data)?; + // debug!("verify xt issue finish"); Ok(()) } diff --git a/contracts/toCKB-typescript/src/switch/mod.rs b/contracts/toCKB-typescript/src/switch/mod.rs index 62aeee1..e7839e0 100644 --- a/contracts/toCKB-typescript/src/switch/mod.rs +++ b/contracts/toCKB-typescript/src/switch/mod.rs @@ -19,9 +19,11 @@ use crate::utils::types::{Error, ToCKBCellDataView, ToCKBStatus}; use alloc::vec::Vec; use ckb_std::{ ckb_constants::Source, + debug, high_level::{load_cell_data, load_input_since, QueryIter}, }; +#[derive(Debug)] enum TxType { DepositRequest, Bonding, @@ -41,11 +43,14 @@ enum TxType { AuctionFaultyWhenRedeeming, } +#[derive(Debug)] pub struct ToCKBCellDataTuple(Option, Option); pub fn verify() -> Result<(), Error> { let toCKB_data_tuple = get_toCKB_data_tuple()?; + debug!("toCKB_data_tuple: {:?}", toCKB_data_tuple); let tx_type = get_tx_type(&toCKB_data_tuple)?; + debug!("tx_type: {:?}", tx_type); switch(&tx_type, &toCKB_data_tuple)?; Ok(()) } diff --git a/contracts/toCKB-typescript/src/utils/config.rs b/contracts/toCKB-typescript/src/utils/config.rs index d00aa94..29ab96d 100644 --- a/contracts/toCKB-typescript/src/utils/config.rs +++ b/contracts/toCKB-typescript/src/utils/config.rs @@ -1,4 +1,4 @@ pub const PLEDGE: u64 = 10000; -pub const TX_PROOF_DIFFICULTY_FACTOR: u8 = 6; +pub const TX_PROOF_DIFFICULTY_FACTOR: u8 = 1; // default value is 2/1000 pub const SIGNER_FEE_RATE: (u128, u128) = (2, 1000); diff --git a/contracts/toCKB-typescript/src/utils/types/generated/basic.rs b/contracts/toCKB-typescript/src/utils/types/generated/basic.rs index 8ba752c..7ad3205 100644 --- a/contracts/toCKB-typescript/src/utils/types/generated/basic.rs +++ b/contracts/toCKB-typescript/src/utils/types/generated/basic.rs @@ -1217,6 +1217,265 @@ impl molecule::prelude::Builder for Uint32Builder { } } #[derive(Clone)] +pub struct Uint64(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for Uint64 { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for Uint64 { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for Uint64 { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + let raw_data = hex_string(&self.raw_data()); + write!(f, "{}(0x{})", Self::NAME, raw_data) + } +} +impl ::core::default::Default for Uint64 { + fn default() -> Self { + let v: Vec = vec![0, 0, 0, 0, 0, 0, 0, 0]; + Uint64::new_unchecked(v.into()) + } +} +impl Uint64 { + pub const TOTAL_SIZE: usize = 8; + pub const ITEM_SIZE: usize = 1; + pub const ITEM_COUNT: usize = 8; + pub fn nth0(&self) -> Byte { + Byte::new_unchecked(self.0.slice(0..1)) + } + pub fn nth1(&self) -> Byte { + Byte::new_unchecked(self.0.slice(1..2)) + } + pub fn nth2(&self) -> Byte { + Byte::new_unchecked(self.0.slice(2..3)) + } + pub fn nth3(&self) -> Byte { + Byte::new_unchecked(self.0.slice(3..4)) + } + pub fn nth4(&self) -> Byte { + Byte::new_unchecked(self.0.slice(4..5)) + } + pub fn nth5(&self) -> Byte { + Byte::new_unchecked(self.0.slice(5..6)) + } + pub fn nth6(&self) -> Byte { + Byte::new_unchecked(self.0.slice(6..7)) + } + pub fn nth7(&self) -> Byte { + Byte::new_unchecked(self.0.slice(7..8)) + } + pub fn raw_data(&self) -> molecule::bytes::Bytes { + self.as_bytes() + } + pub fn as_reader<'r>(&'r self) -> Uint64Reader<'r> { + Uint64Reader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for Uint64 { + type Builder = Uint64Builder; + const NAME: &'static str = "Uint64"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + Uint64(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + Uint64Reader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + Uint64Reader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder().set([ + self.nth0(), + self.nth1(), + self.nth2(), + self.nth3(), + self.nth4(), + self.nth5(), + self.nth6(), + self.nth7(), + ]) + } +} +#[derive(Clone, Copy)] +pub struct Uint64Reader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for Uint64Reader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for Uint64Reader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for Uint64Reader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + let raw_data = hex_string(&self.raw_data()); + write!(f, "{}(0x{})", Self::NAME, raw_data) + } +} +impl<'r> Uint64Reader<'r> { + pub const TOTAL_SIZE: usize = 8; + pub const ITEM_SIZE: usize = 1; + pub const ITEM_COUNT: usize = 8; + pub fn nth0(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[0..1]) + } + pub fn nth1(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[1..2]) + } + pub fn nth2(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[2..3]) + } + pub fn nth3(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[3..4]) + } + pub fn nth4(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[4..5]) + } + pub fn nth5(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[5..6]) + } + pub fn nth6(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[6..7]) + } + pub fn nth7(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[7..8]) + } + pub fn raw_data(&self) -> &'r [u8] { + self.as_slice() + } +} +impl<'r> molecule::prelude::Reader<'r> for Uint64Reader<'r> { + type Entity = Uint64; + const NAME: &'static str = "Uint64Reader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + Uint64Reader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], _compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len != Self::TOTAL_SIZE { + return ve!(Self, TotalSizeNotMatch, Self::TOTAL_SIZE, slice_len); + } + Ok(()) + } +} +pub struct Uint64Builder(pub(crate) [Byte; 8]); +impl ::core::fmt::Debug for Uint64Builder { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:?})", Self::NAME, &self.0[..]) + } +} +impl ::core::default::Default for Uint64Builder { + fn default() -> Self { + Uint64Builder([ + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + ]) + } +} +impl Uint64Builder { + pub const TOTAL_SIZE: usize = 8; + pub const ITEM_SIZE: usize = 1; + pub const ITEM_COUNT: usize = 8; + pub fn set(mut self, v: [Byte; 8]) -> Self { + self.0 = v; + self + } + pub fn nth0(mut self, v: Byte) -> Self { + self.0[0] = v; + self + } + pub fn nth1(mut self, v: Byte) -> Self { + self.0[1] = v; + self + } + pub fn nth2(mut self, v: Byte) -> Self { + self.0[2] = v; + self + } + pub fn nth3(mut self, v: Byte) -> Self { + self.0[3] = v; + self + } + pub fn nth4(mut self, v: Byte) -> Self { + self.0[4] = v; + self + } + pub fn nth5(mut self, v: Byte) -> Self { + self.0[5] = v; + self + } + pub fn nth6(mut self, v: Byte) -> Self { + self.0[6] = v; + self + } + pub fn nth7(mut self, v: Byte) -> Self { + self.0[7] = v; + self + } +} +impl molecule::prelude::Builder for Uint64Builder { + type Entity = Uint64; + const NAME: &'static str = "Uint64Builder"; + fn expected_length(&self) -> usize { + Self::TOTAL_SIZE + } + fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { + writer.write_all(self.0[0].as_slice())?; + writer.write_all(self.0[1].as_slice())?; + writer.write_all(self.0[2].as_slice())?; + writer.write_all(self.0[3].as_slice())?; + writer.write_all(self.0[4].as_slice())?; + writer.write_all(self.0[5].as_slice())?; + writer.write_all(self.0[6].as_slice())?; + writer.write_all(self.0[7].as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + Uint64::new_unchecked(inner.into()) + } +} +#[derive(Clone)] pub struct Script(molecule::bytes::Bytes); impl ::core::fmt::LowerHex for Script { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { diff --git a/contracts/toCKB-typescript/src/utils/types/generated/mint_xt_witness.rs b/contracts/toCKB-typescript/src/utils/types/generated/mint_xt_witness.rs index 3fe57de..e8f86b0 100644 --- a/contracts/toCKB-typescript/src/utils/types/generated/mint_xt_witness.rs +++ b/contracts/toCKB-typescript/src/utils/types/generated/mint_xt_witness.rs @@ -326,10 +326,10 @@ impl ::core::fmt::Display for BTCSPVProof { impl ::core::default::Default for BTCSPVProof { fn default() -> Self { let v: Vec = vec![ - 101, 0, 0, 0, 40, 0, 0, 0, 44, 0, 0, 0, 48, 0, 0, 0, 52, 0, 0, 0, 56, 0, 0, 0, 88, 0, - 0, 0, 92, 0, 0, 0, 96, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 105, 0, 0, 0, 40, 0, 0, 0, 44, 0, 0, 0, 48, 0, 0, 0, 52, 0, 0, 0, 56, 0, 0, 0, 88, 0, + 0, 0, 96, 0, 0, 0, 100, 0, 0, 0, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]; BTCSPVProof::new_unchecked(v.into()) } @@ -382,11 +382,11 @@ impl BTCSPVProof { let end = molecule::unpack_number(&slice[24..]) as usize; Byte32::new_unchecked(self.0.slice(start..end)) } - pub fn index(&self) -> Uint32 { + pub fn index(&self) -> Uint64 { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[24..]) as usize; let end = molecule::unpack_number(&slice[28..]) as usize; - Uint32::new_unchecked(self.0.slice(start..end)) + Uint64::new_unchecked(self.0.slice(start..end)) } pub fn headers(&self) -> Bytes { let slice = self.as_slice(); @@ -541,11 +541,11 @@ impl<'r> BTCSPVProofReader<'r> { let end = molecule::unpack_number(&slice[24..]) as usize; Byte32Reader::new_unchecked(&self.as_slice()[start..end]) } - pub fn index(&self) -> Uint32Reader<'r> { + pub fn index(&self) -> Uint64Reader<'r> { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[24..]) as usize; let end = molecule::unpack_number(&slice[28..]) as usize; - Uint32Reader::new_unchecked(&self.as_slice()[start..end]) + Uint64Reader::new_unchecked(&self.as_slice()[start..end]) } pub fn headers(&self) -> BytesReader<'r> { let slice = self.as_slice(); @@ -626,7 +626,7 @@ impl<'r> molecule::prelude::Reader<'r> for BTCSPVProofReader<'r> { BytesReader::verify(&slice[offsets[2]..offsets[3]], compatible)?; Byte4Reader::verify(&slice[offsets[3]..offsets[4]], compatible)?; Byte32Reader::verify(&slice[offsets[4]..offsets[5]], compatible)?; - Uint32Reader::verify(&slice[offsets[5]..offsets[6]], compatible)?; + Uint64Reader::verify(&slice[offsets[5]..offsets[6]], compatible)?; BytesReader::verify(&slice[offsets[6]..offsets[7]], compatible)?; BytesReader::verify(&slice[offsets[7]..offsets[8]], compatible)?; ByteReader::verify(&slice[offsets[8]..offsets[9]], compatible)?; @@ -640,7 +640,7 @@ pub struct BTCSPVProofBuilder { pub(crate) vout: Bytes, pub(crate) locktime: Byte4, pub(crate) tx_id: Byte32, - pub(crate) index: Uint32, + pub(crate) index: Uint64, pub(crate) headers: Bytes, pub(crate) intermediate_nodes: Bytes, pub(crate) funding_output_index: Byte, @@ -667,7 +667,7 @@ impl BTCSPVProofBuilder { self.tx_id = v; self } - pub fn index(mut self, v: Uint32) -> Self { + pub fn index(mut self, v: Uint64) -> Self { self.index = v; self } diff --git a/contracts/toCKB-typescript/src/utils/types/schemas/basic.mol b/contracts/toCKB-typescript/src/utils/types/schemas/basic.mol index eea4cee..826a537 100644 --- a/contracts/toCKB-typescript/src/utils/types/schemas/basic.mol +++ b/contracts/toCKB-typescript/src/utils/types/schemas/basic.mol @@ -2,6 +2,7 @@ array Byte4 [byte; 4]; array Byte32 [byte; 32]; vector Bytes ; array Uint32 [byte; 4]; +array Uint64 [byte; 8]; table Script { code_hash: Byte32, diff --git a/contracts/toCKB-typescript/src/utils/types/schemas/mint_xt_witness.mol b/contracts/toCKB-typescript/src/utils/types/schemas/mint_xt_witness.mol index fc39c3f..d807fd1 100644 --- a/contracts/toCKB-typescript/src/utils/types/schemas/mint_xt_witness.mol +++ b/contracts/toCKB-typescript/src/utils/types/schemas/mint_xt_witness.mol @@ -11,7 +11,7 @@ table BTCSPVProof { vout: Bytes, locktime: Byte4, tx_id: Byte32, - index: Uint32, + index: Uint64, headers: Bytes, intermediate_nodes: Bytes, funding_output_index: byte, diff --git a/contracts/toCKB-typescript/src/utils/types/toCKB_cell.rs b/contracts/toCKB-typescript/src/utils/types/toCKB_cell.rs index 23ddb90..e316e9c 100644 --- a/contracts/toCKB-typescript/src/utils/types/toCKB_cell.rs +++ b/contracts/toCKB-typescript/src/utils/types/toCKB_cell.rs @@ -8,6 +8,7 @@ use molecule::prelude::*; const BTC_UNIT: u128 = 100_000_000; const ETH_UNIT: u128 = 1_000_000_000_000_000_000; +#[derive(Debug)] pub struct ToCKBCellDataView { pub status: ToCKBStatus, lot_size: u8, @@ -62,7 +63,7 @@ impl ToCKBCellDataView { } #[repr(u8)] -#[derive(Clone, Copy, IntEnum)] +#[derive(Clone, Copy, IntEnum, Debug)] pub enum ToCKBStatus { Initial = 1, Bonded = 2, diff --git a/tests/Cargo.toml b/tests/Cargo.toml index a10333b..0b2a03b 100644 --- a/tests/Cargo.toml +++ b/tests/Cargo.toml @@ -9,3 +9,9 @@ edition = "2018" ckb-tool = { git = "https://github.com/jjyr/ckb-tool.git", tag = "v0.1.1" } ckb-testtool = { git = "https://github.com/jjyr/ckb-tool.git", tag = "v0.1.1" } molecule = { version = "=0.6.0", default-features = false } +int-enum = { version = "0.4", default-features = false } +anyhow = "1.0" +serde = "1.0" +serde_json = "1.0" +hex = "0.4" +primitive-types = { version = "0.7.2", default-features = false } \ No newline at end of file diff --git a/tests/src/toCKB_typescript/tests/mint_xt.rs b/tests/src/toCKB_typescript/tests/mint_xt.rs deleted file mode 100644 index 8b13789..0000000 --- a/tests/src/toCKB_typescript/tests/mint_xt.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/tests/src/toCKB_typescript/tests/mint_xt/mod.rs b/tests/src/toCKB_typescript/tests/mint_xt/mod.rs new file mode 100644 index 0000000..bdbe3d5 --- /dev/null +++ b/tests/src/toCKB_typescript/tests/mint_xt/mod.rs @@ -0,0 +1,318 @@ +use super::{Script, ToCKBCellData}; +use crate::toCKB_typescript::utils::types::{basic, btc_difficulty, mint_xt_witness}; +use crate::*; +use anyhow::Result; +use ckb_testtool::{builtin::ALWAYS_SUCCESS, context::Context}; +use ckb_tool::ckb_types::{ + bytes::Bytes, + core::{TransactionBuilder, TransactionView}, + packed::*, + prelude::*, +}; +use ckb_tool::{ckb_error::assert_error_eq, ckb_script::ScriptError}; +use int_enum::IntEnum; +use molecule::prelude::*; +use primitive_types::U256; +use serde::{Deserialize, Serialize}; +use std::convert::{TryFrom, TryInto}; + +const MAX_CYCLES: u64 = 100_000_000; +// const PLEDGE_INVALID: i8 = 8; +// const LOT_SIZE_INVALID: i8 = 7; +// const TX_INVALID: i8 = 6; +// const ENCODING: i8 = 4; + +#[repr(u8)] +#[derive(Clone, Copy, IntEnum)] +pub enum ToCKBStatus { + Initial = 1, + Bonded = 2, + Warranty = 3, + Redeeming = 4, + SignerTimeout = 5, + Undercollateral = 6, + FaultyWhenWarranty = 7, + FaultyWhenRedeeming = 8, +} + +#[test] +fn test_correct_tx() { + let kind = 1; + let pledge = 10000; + let coin_type = 1; + + let mut context = Context::default(); + let toCKB_typescript_bin: Bytes = Loader::default().load_binary("toCKB-typescript"); + let toCKB_typescript_out_point = context.deploy_cell(toCKB_typescript_bin); + let toCKB_lockscript_bin: Bytes = Loader::default().load_binary("toCKB-lockscript"); + let toCKB_lockscript_out_point = context.deploy_cell(toCKB_lockscript_bin); + let always_success_out_point = context.deploy_cell(ALWAYS_SUCCESS.clone()); + + // prepare scripts + let toCKB_typescript = context + .build_script(&toCKB_typescript_out_point, [kind; 1].to_vec().into()) + .expect("script"); + let toCKB_typescript_dep = CellDep::new_builder() + .out_point(toCKB_typescript_out_point) + .build(); + let always_success_lockscript = context + .build_script(&always_success_out_point, Default::default()) + .expect("script"); + let always_success_lockscript_dep = CellDep::new_builder() + .out_point(always_success_out_point) + .build(); + + // prepare cells + let input_out_point = context.create_cell( + CellOutput::new_builder() + .capacity(11000u64.pack()) + .lock(always_success_lockscript.clone()) + .build(), + Bytes::new(), + ); + let input = CellInput::new_builder() + .previous_output(input_out_point) + .build(); + + let signer_lockscript = toCKB_typescript::utils::types::basic::Script::new_builder().build(); + let user_lockscript = toCKB_typescript::utils::types::basic::Script::new_builder().build(); + let x_lock_address = toCKB_typescript::utils::types::basic::Bytes::new_builder() + .set([Byte::new(1u8); 20].to_vec().into()) + .build(); + let input_toCKB_data = ToCKBCellData::new_builder() + .status(Byte::new(ToCKBStatus::Bonded.int_value())) + .lot_size(Byte::new(1u8)) + .signer_lockscript(signer_lockscript.clone()) + .user_lockscript(user_lockscript.clone()) + .x_lock_address(x_lock_address.clone()) + .build(); + let output_toCKB_data = ToCKBCellData::new_builder() + .status(Byte::new(ToCKBStatus::Warranty.int_value())) + .lot_size(Byte::new(1u8)) + .signer_lockscript(signer_lockscript.clone()) + .user_lockscript(user_lockscript.clone()) + .x_lock_address(x_lock_address.clone()) + .build(); + + let input_ckb_cell_out_point = context.create_cell( + CellOutput::new_builder() + .capacity(11000u64.pack()) + .lock(always_success_lockscript.clone()) + .type_(Some(toCKB_typescript.clone()).pack()) + .build(), + input_toCKB_data.as_bytes(), + ); + let input_ckb_cell = CellInput::new_builder() + .previous_output(input_ckb_cell_out_point) + .build(); + let inputs = vec![input_ckb_cell]; + let outputs = vec![CellOutput::new_builder() + .capacity(11000u64.pack()) + .type_(Some(toCKB_typescript.clone()).pack()) + .lock(always_success_lockscript) + .build()]; + let outputs_data = vec![output_toCKB_data.as_bytes()]; + // raw_header: 00000020acf05cadf6d066d01f5aca661690f4e1779a8144b90b070000000000000000006bbb5a7851af48d883e8ac5d6f61c6ad9a4132a9a12531c1b6f085760b3b2e427ba0455fea0710177d792e86 + // raw_tx: 020000000001015227c5fbad9d9202ade7f02452cf880dac1ed270255ebfe6716e8b3e8956571d0100000017160014085fc2ea0c102fc4db8dbbb10dd6f93684c178c9feffffff028c79171300000000160014173ec3a12e289b102f8edcc1d4ecd3b5b893e2dc97b2030000000000160014ef9665bcf82fa83e870a350a6551a09ee819e4a30247304402201fc61e35096b9ba44a5a845932acce596fde7be7583acd9950d25bb937d49632022032b7666d8d72a553ec9376107a6d25444a942ae8b2eb77ac11d71593666f2c7f0121032dcec3808ef6a58b14e8b1ac77e7b5c47ea46120cd429b8c1eae0970b9c87e1edbd80900 + // raw_tx: + // - 02000000 // version + // - 0001 // flag + // - 01 // one input + // - 5227c5fbad9d9202ade7f02452cf880dac1ed270255ebfe6716e8b3e8956571d01000000 // outpoint + // - 17 // script sig len + // - 160014085fc2ea0c102fc4db8dbbb10dd6f93684c178c9 // script sig + // - feffffff // sequence + // - 02 // 2 output + // - 8c79171000000000 // output 1 value + // - 16 // len + // - 0014173ec3a12e289b102f8edcc1d4ecd3b5b893e2dc // script + // - 97b2030000000000 // output 2 + // - 16 + // - 0014ef9665bcf82fa83e870a350a6551a09ee819e4a3 + // - 02 // 2 witness + // - 47 + // - 304402201fc61e35096b9ba44a5a845932acce596fde7be7583acd9950d25bb937d49632022032b7666d8d72a553ec9376107a6d25444a942ae8b2eb77ac11d71593666f2c7f01 // witness 1 + // - 21 + // - 032dcec3808ef6a58b14e8b1ac77e7b5c47ea46120cd429b8c1eae0970b9c87e1e // witness 2 + // - dbd80900 // locktime + // 02000000015227c5fbad9d9202ade7f02452cf880dac1ed270255ebfe6716e8b3e8956571d0100000017160014085fc2ea0c102fc4db8dbbb10dd6f93684c178c9feffffff028c79171300000000160014173ec3a12e289b102f8edcc1d4ecd3b5b893e2dc97b2030000000000160014ef9665bcf82fa83e870a350a6551a09ee819e4a3dbd80900 + // let btc_spv_proof_str = r#" + // { + // "version": "0x02000000", + // "vin": "0x015227c5fbad9d9202ade7f02452cf880dac1ed270255ebfe6716e8b3e8956571d0100000017160014085fc2ea0c102fc4db8dbbb10dd6f93684c178c9feffffff", + // "vout": "0x028c79171300000000160014173ec3a12e289b102f8edcc1d4ecd3b5b893e2dc97b2030000000000160014ef9665bcf82fa83e870a350a6551a09ee819e4a3", + // "locktime": "0xdbd80900", + // "tx_id": "0xc33b712400ac3c262272ea6f0ddbfeab56d7786c84b2419ec25cf1e66a84212b", + // "index": 0, + // "headers": "0x00000020acf05cadf6d066d01f5aca661690f4e1779a8144b90b070000000000000000006bbb5a7851af48d883e8ac5d6f61c6ad9a4132a9a12531c1b6f085760b3b2e427ba0455fea0710177d792e86", + // "intermediate_nodes": "0x", + // "funding_output_index": 0 + // } + // "#; + let btc_spv_proof_str = r#" + { + "version": "0x01000000", + "vin": "0x0101748906a5c7064550a594c4683ffc6d1ee25292b638c4328bb66403cfceb58a000000006a4730440220364301a77ee7ae34fa71768941a2aad5bd1fa8d3e30d4ce6424d8752e83f2c1b02203c9f8aafced701f59ffb7c151ff2523f3ed1586d29b674efb489e803e9bf93050121029b3008c0fa147fd9db5146e42b27eb0a77389497713d3aad083313d1b1b05ec0ffffffff", + "vout": "0x0316312f00000000001976a91400cc8d95d6835252e0d95eb03b11691a21a7bac588ac220200000000000017a914e5034b9de4881d62480a2df81032ef0299dcdc32870000000000000000166a146f6d6e69000000000000001f0000000315e17900", + "locktime": "0x00000000", + "tx_id": "0x5176f6b03b8bc29f4deafbb7384b673debde6ae712deab93f3b0c91fdcd6d674", + "index": 26, + "headers": "0x0000c020c238b601308b7297346ab2ed59942d7d7ecea8d23a1001000000000000000000b61ac92842abc82aa93644b190fc18ad46c6738337e78bc0c69ab21c5d5ee2ddd6376d5d3e211a17d8706a84", + "intermediate_nodes": "0x8d7a6d53ce27f79802631f1aae5f172c43d128b210ab4962d488c81c96136cfb75c95def872e878839bd93b42c04eb44da44c401a2d580ca343c3262e9c0a2819ed4bbfb9ea620280b31433f43b2512a893873b8c8c679f61e1a926c0ec80bcfc6225a15d72fbd1116f78b14663d8518236b02e765bf0a746a6a08840c122a02afa4df3ab6b9197a20f00495a404ee8e07da2b7554e94609e9ee1d5da0fb7857ea0332072568d0d53a9aedf851892580504a7fcabfbdde076242eb7f4e5f218a14d2a3f357d950b4f6a1dcf93f7c19c44d0fc122d00afa297b9503c1a6ad24cf36cb5f2835bcf490371db2e96047813a24176c3d3416f84b7ddfb7d8c915eb0c5ce7de089b5d9e700ecd12e09163f173b70bb4c9af33051b466b1f55abd66f3121216ad0ad9dfa898535e1d5e51dd07bd0a73d584daace7902f20ece4ba4f4f241c80cb31eda88a244a3c68d0f157c1049b4153d7addd6548aca0885acafbf98a1f8345c89914c24729ad095c7a0b9acd20232ccd90dbd359468fcc4eee7b67d", + "funding_output_index": 0 + } + "#; + let btc_spv_proof = json_to_btc_proof(btc_spv_proof_str).unwrap(); + let witness_data = mint_xt_witness::MintXTWitness::new_builder() + .spv_proof(btc_spv_proof.as_slice().to_vec().into()) + .cell_dep_index_list(vec![2].into()) + .build(); + let witness = WitnessArgs::new_builder() + .input_type(Some(witness_data.as_bytes()).pack()) + .build(); + + // 0xFF809F0159F + let diff = 10771996663680u64; + let difficulty_data = btc_difficulty::BTCDifficulty::new_builder() + .previous(diff.to_le_bytes().to_vec().into()) + .current(diff.to_le_bytes().to_vec().into()) + .build(); + + dbg!(&difficulty_data); + let difficulty_data_out_point = context.deploy_cell(difficulty_data.as_bytes()); + let difficulty_data_dep = CellDep::new_builder() + .out_point(difficulty_data_out_point) + .build(); + + let tx = TransactionBuilder::default() + .inputs(inputs) + .outputs(outputs) + .outputs_data(outputs_data.pack()) + .cell_dep(toCKB_typescript_dep) + .cell_dep(always_success_lockscript_dep) + .cell_dep(difficulty_data_dep) + .witness(witness.as_bytes().pack()) + .build(); + + // let tx = context.complete_tx(tx); + // let toCKB_data = ToCKBCellData::new_builder() + // .status(Byte::new(1u8)) + // .lot_size(Byte::new(1u8)) + // .user_lockscript(Script::new_builder().build()) + // .build(); + // let (context, tx) = build_test_context(1, 10000, toCKB_data.as_bytes()); + + let cycles = context + .verify_tx(&tx, MAX_CYCLES) + .expect("pass verification"); + println!("consume cycles: {}", cycles); +} + +#[derive(Serialize, Deserialize)] +struct BTCSPVProofJson { + version: String, + vin: String, + vout: String, + locktime: String, + tx_id: String, + index: u64, + headers: String, + intermediate_nodes: String, + funding_output_index: u8, +} + +impl TryFrom for mint_xt_witness::BTCSPVProof { + type Error = anyhow::Error; + + fn try_from(proof: BTCSPVProofJson) -> Result { + Ok(mint_xt_witness::BTCSPVProof::new_builder() + .version(hex::decode(clear_0x(&proof.version))?.into()) + .vin(hex::decode(clear_0x(&proof.vin))?.into()) + .vout(hex::decode(clear_0x(&proof.vout))?.into()) + .locktime(hex::decode(clear_0x(&proof.locktime))?.into()) + .tx_id(hex::decode(clear_0x(&proof.tx_id))?.into()) + .index(proof.index.into()) + .headers(hex::decode(clear_0x(&proof.headers))?.into()) + .intermediate_nodes(hex::decode(clear_0x(&proof.intermediate_nodes))?.into()) + .funding_output_index(proof.funding_output_index.into()) + .build()) + } +} + +fn clear_0x(s: &str) -> &str { + if &s[..2] == "0x" || &s[..2] == "0X" { + &s[2..] + } else { + s + } +} + +fn json_to_btc_proof(proof: &str) -> Result { + let proof: BTCSPVProofJson = serde_json::from_str(proof)?; + proof.try_into() +} + +// #[test] +// fn test_wrong_pledge() { +// let toCKB_data = ToCKBCellData::new_builder() +// .status(Byte::new(1u8)) +// .lot_size(Byte::new(1u8)) +// .user_lockscript(Script::new_builder().build()) +// .build(); +// let (context, tx) = build_test_context(1, 9999, toCKB_data.as_bytes()); + +// let err = context.verify_tx(&tx, MAX_CYCLES).unwrap_err(); +// assert_error_eq!(err, ScriptError::ValidationFailure(PLEDGE_INVALID)); +// } + +// fn build_test_context(kind: u8, input: Bytes) -> (Context, TransactionView) { +// // deploy contract +// let mut context = Context::default(); +// let toCKB_typescript_bin: Bytes = Loader::default().load_binary("toCKB-typescript"); +// let toCKB_typescript_out_point = context.deploy_cell(toCKB_typescript_bin); +// let always_success_out_point = context.deploy_cell(ALWAYS_SUCCESS.clone()); + +// // prepare scripts +// let toCKB_typescript = context +// .build_script(&toCKB_typescript_out_point, [kind; 1].to_vec().into()) +// .expect("script"); +// let toCKB_typescript_dep = CellDep::new_builder() +// .out_point(toCKB_typescript_out_point) +// .build(); +// let always_success_lockscript = context +// .build_script(&always_success_out_point, Default::default()) +// .expect("script"); +// let always_success_lockscript_dep = CellDep::new_builder() +// .out_point(always_success_out_point) +// .build(); + +// // prepare cells +// let input_out_point = context.create_cell( +// CellOutput::new_builder() +// .capacity(11000u64.pack()) +// .lock(always_success_lockscript.clone()) +// .build(), +// Bytes::new(), +// ); +// let input = CellInput::new_builder() +// .previous_output(input_out_point) +// .build(); +// let outputs = vec![CellOutput::new_builder() +// .capacity(pledge.pack()) +// .type_(Some(toCKB_typescript.clone()).pack()) +// .lock(always_success_lockscript) +// .build()]; +// let outputs_data = vec![toCKB_data; 1]; + +// // build transaction +// let tx = TransactionBuilder::default() +// .input(input) +// .outputs(outputs) +// .outputs_data(outputs_data.pack()) +// .cell_dep(toCKB_typescript_dep) +// .cell_dep(always_success_lockscript_dep) +// .build(); +// let tx = context.complete_tx(tx); + +// (context, tx) +// } diff --git a/tests/src/toCKB_typescript/utils/types/basic.rs b/tests/src/toCKB_typescript/utils/types/basic.rs index 8ba752c..7ad3205 100644 --- a/tests/src/toCKB_typescript/utils/types/basic.rs +++ b/tests/src/toCKB_typescript/utils/types/basic.rs @@ -1217,6 +1217,265 @@ impl molecule::prelude::Builder for Uint32Builder { } } #[derive(Clone)] +pub struct Uint64(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for Uint64 { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for Uint64 { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for Uint64 { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + let raw_data = hex_string(&self.raw_data()); + write!(f, "{}(0x{})", Self::NAME, raw_data) + } +} +impl ::core::default::Default for Uint64 { + fn default() -> Self { + let v: Vec = vec![0, 0, 0, 0, 0, 0, 0, 0]; + Uint64::new_unchecked(v.into()) + } +} +impl Uint64 { + pub const TOTAL_SIZE: usize = 8; + pub const ITEM_SIZE: usize = 1; + pub const ITEM_COUNT: usize = 8; + pub fn nth0(&self) -> Byte { + Byte::new_unchecked(self.0.slice(0..1)) + } + pub fn nth1(&self) -> Byte { + Byte::new_unchecked(self.0.slice(1..2)) + } + pub fn nth2(&self) -> Byte { + Byte::new_unchecked(self.0.slice(2..3)) + } + pub fn nth3(&self) -> Byte { + Byte::new_unchecked(self.0.slice(3..4)) + } + pub fn nth4(&self) -> Byte { + Byte::new_unchecked(self.0.slice(4..5)) + } + pub fn nth5(&self) -> Byte { + Byte::new_unchecked(self.0.slice(5..6)) + } + pub fn nth6(&self) -> Byte { + Byte::new_unchecked(self.0.slice(6..7)) + } + pub fn nth7(&self) -> Byte { + Byte::new_unchecked(self.0.slice(7..8)) + } + pub fn raw_data(&self) -> molecule::bytes::Bytes { + self.as_bytes() + } + pub fn as_reader<'r>(&'r self) -> Uint64Reader<'r> { + Uint64Reader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for Uint64 { + type Builder = Uint64Builder; + const NAME: &'static str = "Uint64"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + Uint64(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + Uint64Reader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + Uint64Reader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder().set([ + self.nth0(), + self.nth1(), + self.nth2(), + self.nth3(), + self.nth4(), + self.nth5(), + self.nth6(), + self.nth7(), + ]) + } +} +#[derive(Clone, Copy)] +pub struct Uint64Reader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for Uint64Reader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for Uint64Reader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for Uint64Reader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + let raw_data = hex_string(&self.raw_data()); + write!(f, "{}(0x{})", Self::NAME, raw_data) + } +} +impl<'r> Uint64Reader<'r> { + pub const TOTAL_SIZE: usize = 8; + pub const ITEM_SIZE: usize = 1; + pub const ITEM_COUNT: usize = 8; + pub fn nth0(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[0..1]) + } + pub fn nth1(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[1..2]) + } + pub fn nth2(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[2..3]) + } + pub fn nth3(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[3..4]) + } + pub fn nth4(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[4..5]) + } + pub fn nth5(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[5..6]) + } + pub fn nth6(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[6..7]) + } + pub fn nth7(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[7..8]) + } + pub fn raw_data(&self) -> &'r [u8] { + self.as_slice() + } +} +impl<'r> molecule::prelude::Reader<'r> for Uint64Reader<'r> { + type Entity = Uint64; + const NAME: &'static str = "Uint64Reader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + Uint64Reader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], _compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len != Self::TOTAL_SIZE { + return ve!(Self, TotalSizeNotMatch, Self::TOTAL_SIZE, slice_len); + } + Ok(()) + } +} +pub struct Uint64Builder(pub(crate) [Byte; 8]); +impl ::core::fmt::Debug for Uint64Builder { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:?})", Self::NAME, &self.0[..]) + } +} +impl ::core::default::Default for Uint64Builder { + fn default() -> Self { + Uint64Builder([ + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + ]) + } +} +impl Uint64Builder { + pub const TOTAL_SIZE: usize = 8; + pub const ITEM_SIZE: usize = 1; + pub const ITEM_COUNT: usize = 8; + pub fn set(mut self, v: [Byte; 8]) -> Self { + self.0 = v; + self + } + pub fn nth0(mut self, v: Byte) -> Self { + self.0[0] = v; + self + } + pub fn nth1(mut self, v: Byte) -> Self { + self.0[1] = v; + self + } + pub fn nth2(mut self, v: Byte) -> Self { + self.0[2] = v; + self + } + pub fn nth3(mut self, v: Byte) -> Self { + self.0[3] = v; + self + } + pub fn nth4(mut self, v: Byte) -> Self { + self.0[4] = v; + self + } + pub fn nth5(mut self, v: Byte) -> Self { + self.0[5] = v; + self + } + pub fn nth6(mut self, v: Byte) -> Self { + self.0[6] = v; + self + } + pub fn nth7(mut self, v: Byte) -> Self { + self.0[7] = v; + self + } +} +impl molecule::prelude::Builder for Uint64Builder { + type Entity = Uint64; + const NAME: &'static str = "Uint64Builder"; + fn expected_length(&self) -> usize { + Self::TOTAL_SIZE + } + fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { + writer.write_all(self.0[0].as_slice())?; + writer.write_all(self.0[1].as_slice())?; + writer.write_all(self.0[2].as_slice())?; + writer.write_all(self.0[3].as_slice())?; + writer.write_all(self.0[4].as_slice())?; + writer.write_all(self.0[5].as_slice())?; + writer.write_all(self.0[6].as_slice())?; + writer.write_all(self.0[7].as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + Uint64::new_unchecked(inner.into()) + } +} +#[derive(Clone)] pub struct Script(molecule::bytes::Bytes); impl ::core::fmt::LowerHex for Script { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { diff --git a/tests/src/toCKB_typescript/utils/types/btc_difficulty.rs b/tests/src/toCKB_typescript/utils/types/btc_difficulty.rs new file mode 100644 index 0000000..3976e02 --- /dev/null +++ b/tests/src/toCKB_typescript/utils/types/btc_difficulty.rs @@ -0,0 +1,270 @@ +// Generated by Molecule 0.6.0 + +use super::basic::*; +use molecule::prelude::*; +#[derive(Clone)] +pub struct BTCDifficulty(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for BTCDifficulty { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for BTCDifficulty { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for BTCDifficulty { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "current", self.current())?; + write!(f, ", {}: {}", "previous", self.previous())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl ::core::default::Default for BTCDifficulty { + fn default() -> Self { + let v: Vec = vec![ + 20, 0, 0, 0, 12, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ]; + BTCDifficulty::new_unchecked(v.into()) + } +} +impl BTCDifficulty { + pub const FIELD_COUNT: usize = 2; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn current(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } + pub fn previous(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[12..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } else { + Bytes::new_unchecked(self.0.slice(start..)) + } + } + pub fn as_reader<'r>(&'r self) -> BTCDifficultyReader<'r> { + BTCDifficultyReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for BTCDifficulty { + type Builder = BTCDifficultyBuilder; + const NAME: &'static str = "BTCDifficulty"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + BTCDifficulty(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + BTCDifficultyReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + BTCDifficultyReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder() + .current(self.current()) + .previous(self.previous()) + } +} +#[derive(Clone, Copy)] +pub struct BTCDifficultyReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for BTCDifficultyReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for BTCDifficultyReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for BTCDifficultyReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "current", self.current())?; + write!(f, ", {}: {}", "previous", self.previous())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl<'r> BTCDifficultyReader<'r> { + pub const FIELD_COUNT: usize = 2; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn current(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn previous(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[12..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } else { + BytesReader::new_unchecked(&self.as_slice()[start..]) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for BTCDifficultyReader<'r> { + type Entity = BTCDifficulty; + const NAME: &'static str = "BTCDifficultyReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + BTCDifficultyReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let total_size = molecule::unpack_number(slice) as usize; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + if slice_len == molecule::NUMBER_SIZE && Self::FIELD_COUNT == 0 { + return Ok(()); + } + if slice_len < molecule::NUMBER_SIZE * 2 { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); + } + let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; + if offset_first % 4 != 0 || offset_first < molecule::NUMBER_SIZE * 2 { + return ve!(Self, OffsetsNotMatch); + } + let field_count = offset_first / 4 - 1; + if field_count < Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + } else if !compatible && field_count > Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + }; + let header_size = molecule::NUMBER_SIZE * (field_count + 1); + if slice_len < header_size { + return ve!(Self, HeaderIsBroken, header_size, slice_len); + } + let mut offsets: Vec = slice[molecule::NUMBER_SIZE..] + .chunks(molecule::NUMBER_SIZE) + .take(field_count) + .map(|x| molecule::unpack_number(x) as usize) + .collect(); + offsets.push(total_size); + if offsets.windows(2).any(|i| i[0] > i[1]) { + return ve!(Self, OffsetsNotMatch); + } + BytesReader::verify(&slice[offsets[0]..offsets[1]], compatible)?; + BytesReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct BTCDifficultyBuilder { + pub(crate) current: Bytes, + pub(crate) previous: Bytes, +} +impl BTCDifficultyBuilder { + pub const FIELD_COUNT: usize = 2; + pub fn current(mut self, v: Bytes) -> Self { + self.current = v; + self + } + pub fn previous(mut self, v: Bytes) -> Self { + self.previous = v; + self + } +} +impl molecule::prelude::Builder for BTCDifficultyBuilder { + type Entity = BTCDifficulty; + const NAME: &'static str = "BTCDifficultyBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) + + self.current.as_slice().len() + + self.previous.as_slice().len() + } + fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { + let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); + let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); + offsets.push(total_size); + total_size += self.current.as_slice().len(); + offsets.push(total_size); + total_size += self.previous.as_slice().len(); + writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; + for offset in offsets.into_iter() { + writer.write_all(&molecule::pack_number(offset as molecule::Number))?; + } + writer.write_all(self.current.as_slice())?; + writer.write_all(self.previous.as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + BTCDifficulty::new_unchecked(inner.into()) + } +} diff --git a/tests/src/toCKB_typescript/utils/types/convert.rs b/tests/src/toCKB_typescript/utils/types/convert.rs new file mode 100644 index 0000000..da93238 --- /dev/null +++ b/tests/src/toCKB_typescript/utils/types/convert.rs @@ -0,0 +1,62 @@ +use super::basic::{Byte32, Byte4, Bytes, Uint32, Uint64}; +use molecule::prelude::{Builder, Byte, Entity}; + +impl From> for Bytes { + fn from(v: Vec) -> Self { + Bytes::new_builder() + .set(v.into_iter().map(Byte::new).collect()) + .build() + } +} + +impl From> for Byte4 { + fn from(v: Vec) -> Self { + if v.len() != 4 { + panic!("length for Byte4 should be 4") + } + let mut inner = [Byte::new(0); 4]; + let v = v.into_iter().map(Byte::new).collect::>(); + inner.copy_from_slice(&v); + Self::new_builder().set(inner).build() + } +} + +impl From> for Byte32 { + fn from(v: Vec) -> Self { + if v.len() != 32 { + panic!("length for Byte32 should be 32") + } + let mut inner = [Byte::new(0); 32]; + let v = v.into_iter().map(Byte::new).collect::>(); + inner.copy_from_slice(&v); + Self::new_builder().set(inner).build() + } +} + +impl From for Uint32 { + fn from(v: u32) -> Self { + let mut inner = [Byte::new(0); 4]; + let v = v + .to_le_bytes() + .to_vec() + .into_iter() + .map(Byte::new) + .collect::>(); + inner.copy_from_slice(&v); + Self::new_builder().set(inner).build() + } +} + +impl From for Uint64 { + fn from(v: u64) -> Self { + let mut inner = [Byte::new(0); 8]; + let v = v + .to_le_bytes() + .to_vec() + .into_iter() + .map(Byte::new) + .collect::>(); + inner.copy_from_slice(&v); + Self::new_builder().set(inner).build() + } +} diff --git a/tests/src/toCKB_typescript/utils/types/mint_xt_witness.rs b/tests/src/toCKB_typescript/utils/types/mint_xt_witness.rs new file mode 100644 index 0000000..e8f86b0 --- /dev/null +++ b/tests/src/toCKB_typescript/utils/types/mint_xt_witness.rs @@ -0,0 +1,744 @@ +// Generated by Molecule 0.6.0 + +use super::basic::*; +use molecule::prelude::*; +#[derive(Clone)] +pub struct MintXTWitness(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for MintXTWitness { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for MintXTWitness { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for MintXTWitness { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "spv_proof", self.spv_proof())?; + write!( + f, + ", {}: {}", + "cell_dep_index_list", + self.cell_dep_index_list() + )?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl ::core::default::Default for MintXTWitness { + fn default() -> Self { + let v: Vec = vec![ + 20, 0, 0, 0, 12, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ]; + MintXTWitness::new_unchecked(v.into()) + } +} +impl MintXTWitness { + pub const FIELD_COUNT: usize = 2; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn spv_proof(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } + pub fn cell_dep_index_list(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[12..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } else { + Bytes::new_unchecked(self.0.slice(start..)) + } + } + pub fn as_reader<'r>(&'r self) -> MintXTWitnessReader<'r> { + MintXTWitnessReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for MintXTWitness { + type Builder = MintXTWitnessBuilder; + const NAME: &'static str = "MintXTWitness"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + MintXTWitness(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + MintXTWitnessReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + MintXTWitnessReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder() + .spv_proof(self.spv_proof()) + .cell_dep_index_list(self.cell_dep_index_list()) + } +} +#[derive(Clone, Copy)] +pub struct MintXTWitnessReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for MintXTWitnessReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for MintXTWitnessReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for MintXTWitnessReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "spv_proof", self.spv_proof())?; + write!( + f, + ", {}: {}", + "cell_dep_index_list", + self.cell_dep_index_list() + )?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl<'r> MintXTWitnessReader<'r> { + pub const FIELD_COUNT: usize = 2; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn spv_proof(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn cell_dep_index_list(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[12..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } else { + BytesReader::new_unchecked(&self.as_slice()[start..]) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for MintXTWitnessReader<'r> { + type Entity = MintXTWitness; + const NAME: &'static str = "MintXTWitnessReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + MintXTWitnessReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let total_size = molecule::unpack_number(slice) as usize; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + if slice_len == molecule::NUMBER_SIZE && Self::FIELD_COUNT == 0 { + return Ok(()); + } + if slice_len < molecule::NUMBER_SIZE * 2 { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); + } + let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; + if offset_first % 4 != 0 || offset_first < molecule::NUMBER_SIZE * 2 { + return ve!(Self, OffsetsNotMatch); + } + let field_count = offset_first / 4 - 1; + if field_count < Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + } else if !compatible && field_count > Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + }; + let header_size = molecule::NUMBER_SIZE * (field_count + 1); + if slice_len < header_size { + return ve!(Self, HeaderIsBroken, header_size, slice_len); + } + let mut offsets: Vec = slice[molecule::NUMBER_SIZE..] + .chunks(molecule::NUMBER_SIZE) + .take(field_count) + .map(|x| molecule::unpack_number(x) as usize) + .collect(); + offsets.push(total_size); + if offsets.windows(2).any(|i| i[0] > i[1]) { + return ve!(Self, OffsetsNotMatch); + } + BytesReader::verify(&slice[offsets[0]..offsets[1]], compatible)?; + BytesReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct MintXTWitnessBuilder { + pub(crate) spv_proof: Bytes, + pub(crate) cell_dep_index_list: Bytes, +} +impl MintXTWitnessBuilder { + pub const FIELD_COUNT: usize = 2; + pub fn spv_proof(mut self, v: Bytes) -> Self { + self.spv_proof = v; + self + } + pub fn cell_dep_index_list(mut self, v: Bytes) -> Self { + self.cell_dep_index_list = v; + self + } +} +impl molecule::prelude::Builder for MintXTWitnessBuilder { + type Entity = MintXTWitness; + const NAME: &'static str = "MintXTWitnessBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) + + self.spv_proof.as_slice().len() + + self.cell_dep_index_list.as_slice().len() + } + fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { + let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); + let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); + offsets.push(total_size); + total_size += self.spv_proof.as_slice().len(); + offsets.push(total_size); + total_size += self.cell_dep_index_list.as_slice().len(); + writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; + for offset in offsets.into_iter() { + writer.write_all(&molecule::pack_number(offset as molecule::Number))?; + } + writer.write_all(self.spv_proof.as_slice())?; + writer.write_all(self.cell_dep_index_list.as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + MintXTWitness::new_unchecked(inner.into()) + } +} +#[derive(Clone)] +pub struct BTCSPVProof(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for BTCSPVProof { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for BTCSPVProof { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for BTCSPVProof { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "version", self.version())?; + write!(f, ", {}: {}", "vin", self.vin())?; + write!(f, ", {}: {}", "vout", self.vout())?; + write!(f, ", {}: {}", "locktime", self.locktime())?; + write!(f, ", {}: {}", "tx_id", self.tx_id())?; + write!(f, ", {}: {}", "index", self.index())?; + write!(f, ", {}: {}", "headers", self.headers())?; + write!( + f, + ", {}: {}", + "intermediate_nodes", + self.intermediate_nodes() + )?; + write!( + f, + ", {}: {}", + "funding_output_index", + self.funding_output_index() + )?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl ::core::default::Default for BTCSPVProof { + fn default() -> Self { + let v: Vec = vec![ + 105, 0, 0, 0, 40, 0, 0, 0, 44, 0, 0, 0, 48, 0, 0, 0, 52, 0, 0, 0, 56, 0, 0, 0, 88, 0, + 0, 0, 96, 0, 0, 0, 100, 0, 0, 0, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ]; + BTCSPVProof::new_unchecked(v.into()) + } +} +impl BTCSPVProof { + pub const FIELD_COUNT: usize = 9; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn version(&self) -> Byte4 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + Byte4::new_unchecked(self.0.slice(start..end)) + } + pub fn vin(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + let end = molecule::unpack_number(&slice[12..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } + pub fn vout(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[12..]) as usize; + let end = molecule::unpack_number(&slice[16..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } + pub fn locktime(&self) -> Byte4 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[16..]) as usize; + let end = molecule::unpack_number(&slice[20..]) as usize; + Byte4::new_unchecked(self.0.slice(start..end)) + } + pub fn tx_id(&self) -> Byte32 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[20..]) as usize; + let end = molecule::unpack_number(&slice[24..]) as usize; + Byte32::new_unchecked(self.0.slice(start..end)) + } + pub fn index(&self) -> Uint64 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[24..]) as usize; + let end = molecule::unpack_number(&slice[28..]) as usize; + Uint64::new_unchecked(self.0.slice(start..end)) + } + pub fn headers(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[28..]) as usize; + let end = molecule::unpack_number(&slice[32..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } + pub fn intermediate_nodes(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[32..]) as usize; + let end = molecule::unpack_number(&slice[36..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } + pub fn funding_output_index(&self) -> Byte { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[36..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[40..]) as usize; + Byte::new_unchecked(self.0.slice(start..end)) + } else { + Byte::new_unchecked(self.0.slice(start..)) + } + } + pub fn as_reader<'r>(&'r self) -> BTCSPVProofReader<'r> { + BTCSPVProofReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for BTCSPVProof { + type Builder = BTCSPVProofBuilder; + const NAME: &'static str = "BTCSPVProof"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + BTCSPVProof(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + BTCSPVProofReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + BTCSPVProofReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder() + .version(self.version()) + .vin(self.vin()) + .vout(self.vout()) + .locktime(self.locktime()) + .tx_id(self.tx_id()) + .index(self.index()) + .headers(self.headers()) + .intermediate_nodes(self.intermediate_nodes()) + .funding_output_index(self.funding_output_index()) + } +} +#[derive(Clone, Copy)] +pub struct BTCSPVProofReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for BTCSPVProofReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for BTCSPVProofReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for BTCSPVProofReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "version", self.version())?; + write!(f, ", {}: {}", "vin", self.vin())?; + write!(f, ", {}: {}", "vout", self.vout())?; + write!(f, ", {}: {}", "locktime", self.locktime())?; + write!(f, ", {}: {}", "tx_id", self.tx_id())?; + write!(f, ", {}: {}", "index", self.index())?; + write!(f, ", {}: {}", "headers", self.headers())?; + write!( + f, + ", {}: {}", + "intermediate_nodes", + self.intermediate_nodes() + )?; + write!( + f, + ", {}: {}", + "funding_output_index", + self.funding_output_index() + )?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl<'r> BTCSPVProofReader<'r> { + pub const FIELD_COUNT: usize = 9; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn version(&self) -> Byte4Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + Byte4Reader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn vin(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + let end = molecule::unpack_number(&slice[12..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn vout(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[12..]) as usize; + let end = molecule::unpack_number(&slice[16..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn locktime(&self) -> Byte4Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[16..]) as usize; + let end = molecule::unpack_number(&slice[20..]) as usize; + Byte4Reader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn tx_id(&self) -> Byte32Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[20..]) as usize; + let end = molecule::unpack_number(&slice[24..]) as usize; + Byte32Reader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn index(&self) -> Uint64Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[24..]) as usize; + let end = molecule::unpack_number(&slice[28..]) as usize; + Uint64Reader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn headers(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[28..]) as usize; + let end = molecule::unpack_number(&slice[32..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn intermediate_nodes(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[32..]) as usize; + let end = molecule::unpack_number(&slice[36..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn funding_output_index(&self) -> ByteReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[36..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[40..]) as usize; + ByteReader::new_unchecked(&self.as_slice()[start..end]) + } else { + ByteReader::new_unchecked(&self.as_slice()[start..]) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for BTCSPVProofReader<'r> { + type Entity = BTCSPVProof; + const NAME: &'static str = "BTCSPVProofReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + BTCSPVProofReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let total_size = molecule::unpack_number(slice) as usize; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + if slice_len == molecule::NUMBER_SIZE && Self::FIELD_COUNT == 0 { + return Ok(()); + } + if slice_len < molecule::NUMBER_SIZE * 2 { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); + } + let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; + if offset_first % 4 != 0 || offset_first < molecule::NUMBER_SIZE * 2 { + return ve!(Self, OffsetsNotMatch); + } + let field_count = offset_first / 4 - 1; + if field_count < Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + } else if !compatible && field_count > Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + }; + let header_size = molecule::NUMBER_SIZE * (field_count + 1); + if slice_len < header_size { + return ve!(Self, HeaderIsBroken, header_size, slice_len); + } + let mut offsets: Vec = slice[molecule::NUMBER_SIZE..] + .chunks(molecule::NUMBER_SIZE) + .take(field_count) + .map(|x| molecule::unpack_number(x) as usize) + .collect(); + offsets.push(total_size); + if offsets.windows(2).any(|i| i[0] > i[1]) { + return ve!(Self, OffsetsNotMatch); + } + Byte4Reader::verify(&slice[offsets[0]..offsets[1]], compatible)?; + BytesReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; + BytesReader::verify(&slice[offsets[2]..offsets[3]], compatible)?; + Byte4Reader::verify(&slice[offsets[3]..offsets[4]], compatible)?; + Byte32Reader::verify(&slice[offsets[4]..offsets[5]], compatible)?; + Uint64Reader::verify(&slice[offsets[5]..offsets[6]], compatible)?; + BytesReader::verify(&slice[offsets[6]..offsets[7]], compatible)?; + BytesReader::verify(&slice[offsets[7]..offsets[8]], compatible)?; + ByteReader::verify(&slice[offsets[8]..offsets[9]], compatible)?; + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct BTCSPVProofBuilder { + pub(crate) version: Byte4, + pub(crate) vin: Bytes, + pub(crate) vout: Bytes, + pub(crate) locktime: Byte4, + pub(crate) tx_id: Byte32, + pub(crate) index: Uint64, + pub(crate) headers: Bytes, + pub(crate) intermediate_nodes: Bytes, + pub(crate) funding_output_index: Byte, +} +impl BTCSPVProofBuilder { + pub const FIELD_COUNT: usize = 9; + pub fn version(mut self, v: Byte4) -> Self { + self.version = v; + self + } + pub fn vin(mut self, v: Bytes) -> Self { + self.vin = v; + self + } + pub fn vout(mut self, v: Bytes) -> Self { + self.vout = v; + self + } + pub fn locktime(mut self, v: Byte4) -> Self { + self.locktime = v; + self + } + pub fn tx_id(mut self, v: Byte32) -> Self { + self.tx_id = v; + self + } + pub fn index(mut self, v: Uint64) -> Self { + self.index = v; + self + } + pub fn headers(mut self, v: Bytes) -> Self { + self.headers = v; + self + } + pub fn intermediate_nodes(mut self, v: Bytes) -> Self { + self.intermediate_nodes = v; + self + } + pub fn funding_output_index(mut self, v: Byte) -> Self { + self.funding_output_index = v; + self + } +} +impl molecule::prelude::Builder for BTCSPVProofBuilder { + type Entity = BTCSPVProof; + const NAME: &'static str = "BTCSPVProofBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) + + self.version.as_slice().len() + + self.vin.as_slice().len() + + self.vout.as_slice().len() + + self.locktime.as_slice().len() + + self.tx_id.as_slice().len() + + self.index.as_slice().len() + + self.headers.as_slice().len() + + self.intermediate_nodes.as_slice().len() + + self.funding_output_index.as_slice().len() + } + fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { + let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); + let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); + offsets.push(total_size); + total_size += self.version.as_slice().len(); + offsets.push(total_size); + total_size += self.vin.as_slice().len(); + offsets.push(total_size); + total_size += self.vout.as_slice().len(); + offsets.push(total_size); + total_size += self.locktime.as_slice().len(); + offsets.push(total_size); + total_size += self.tx_id.as_slice().len(); + offsets.push(total_size); + total_size += self.index.as_slice().len(); + offsets.push(total_size); + total_size += self.headers.as_slice().len(); + offsets.push(total_size); + total_size += self.intermediate_nodes.as_slice().len(); + offsets.push(total_size); + total_size += self.funding_output_index.as_slice().len(); + writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; + for offset in offsets.into_iter() { + writer.write_all(&molecule::pack_number(offset as molecule::Number))?; + } + writer.write_all(self.version.as_slice())?; + writer.write_all(self.vin.as_slice())?; + writer.write_all(self.vout.as_slice())?; + writer.write_all(self.locktime.as_slice())?; + writer.write_all(self.tx_id.as_slice())?; + writer.write_all(self.index.as_slice())?; + writer.write_all(self.headers.as_slice())?; + writer.write_all(self.intermediate_nodes.as_slice())?; + writer.write_all(self.funding_output_index.as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + BTCSPVProof::new_unchecked(inner.into()) + } +} diff --git a/tests/src/toCKB_typescript/utils/types/mod.rs b/tests/src/toCKB_typescript/utils/types/mod.rs index 52935a2..d54c0f3 100644 --- a/tests/src/toCKB_typescript/utils/types/mod.rs +++ b/tests/src/toCKB_typescript/utils/types/mod.rs @@ -1,2 +1,5 @@ pub mod basic; +pub mod btc_difficulty; +pub mod convert; +pub mod mint_xt_witness; pub mod toCKB_cell_data; From c26471642fe2874c4ae4f51a2d3e2bef2bc4f4ed Mon Sep 17 00:00:00 2001 From: huwenchao Date: Fri, 28 Aug 2020 03:11:15 +0800 Subject: [PATCH 17/45] test: add normal test --- contracts/toCKB-typescript/Cargo.lock | 7 + contracts/toCKB-typescript/Cargo.toml | 1 + .../src/switch/mint_xt/mod.rs | 171 +++++++++++------- .../toCKB-typescript/src/utils/config.rs | 4 + .../toCKB-typescript/src/utils/types/error.rs | 1 + .../src/utils/types/toCKB_cell.rs | 2 +- .../src/toCKB_typescript/tests/mint_xt/mod.rs | 95 ++++++---- tests/src/toCKB_typescript/tests/simple_udt | Bin 0 -> 1696 bytes 8 files changed, 178 insertions(+), 103 deletions(-) create mode 100755 tests/src/toCKB_typescript/tests/simple_udt diff --git a/contracts/toCKB-typescript/Cargo.lock b/contracts/toCKB-typescript/Cargo.lock index 9edb0f7..c3d43b1 100644 --- a/contracts/toCKB-typescript/Cargo.lock +++ b/contracts/toCKB-typescript/Cargo.lock @@ -134,6 +134,12 @@ dependencies = [ "typenum", ] +[[package]] +name = "hex" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "644f9158b2f133fd50f5fb3242878846d9eb792e445c893805ff0e3824006e35" + [[package]] name = "int-enum" version = "0.4.0" @@ -268,6 +274,7 @@ dependencies = [ "bech32", "bitcoin-spv", "ckb-std", + "hex", "int-enum", "molecule", "primitive-types", diff --git a/contracts/toCKB-typescript/Cargo.toml b/contracts/toCKB-typescript/Cargo.toml index 0fc533e..732fb2f 100644 --- a/contracts/toCKB-typescript/Cargo.toml +++ b/contracts/toCKB-typescript/Cargo.toml @@ -14,6 +14,7 @@ int-enum = { version = "0.4", default-features = false } bitcoin-spv = { git = "https://github.com/summa-tx/bitcoin-spv.git", branch = "rust/dep-change", default-features = false } bech32 = { git = "https://github.com/reuvenpo/rust-bech32.git", branch = "support-no_std", default-features = false } primitive-types = { version = "0.7.2", default-features = false } +hex = { version = "0.4", default-features = false } [profile.release] overflow-checks = true diff --git a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs index 765813b..1470863 100644 --- a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs +++ b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs @@ -1,6 +1,6 @@ use crate::switch::ToCKBCellDataTuple; use crate::utils::{ - config::{SIGNER_FEE_RATE, TX_PROOF_DIFFICULTY_FACTOR}, + config::{SIGNER_FEE_RATE, SUDT_CODE_HASH, TX_PROOF_DIFFICULTY_FACTOR}, tools::{get_xchain_kind, XChainKind}, types::{ btc_difficulty::BTCDifficultyReader, @@ -8,6 +8,7 @@ use crate::utils::{ Error, ToCKBCellDataView, }, }; +use alloc::string::String; use bech32::{self, ToBase32}; use bitcoin_spv::{ btcspv, @@ -19,7 +20,8 @@ use ckb_std::{ debug, error::SysError, high_level::{ - load_cell_data, load_cell_lock, load_cell_type_hash, load_witness_args, QueryIter, + load_cell_data, load_cell_lock, load_cell_lock_hash, load_cell_type, load_cell_type_hash, + load_witness_args, QueryIter, }, }; use core::result::Result; @@ -96,20 +98,31 @@ fn verify_btc_witness( let tx_out = vout.index(funding_output_index.into())?; let script_pubkey = tx_out.script_pubkey(); debug!("script_pubkey payload: {:?}", script_pubkey.payload()?); - // match script_pubkey.payload()? { - // PayloadType::WPKH(_) => { - // let addr = bech32::encode("bc", (&script_pubkey[1..]).to_base32()).unwrap(); - // if addr.as_bytes() != data.x_lock_address.as_ref() { - // return Err(Error::WrongFundingAddr); - // } - // } - // _ => return Err(Error::UnsupportedFundingType), - // } - let value = tx_out.value(); - debug!("value: {}", value); - // if value as u128 != data.get_btc_lot_size()?.get_sudt_amount() { - // return Err(Error::FundingNotEnough); - // } + match script_pubkey.payload()? { + PayloadType::WPKH(_) => { + let addr = bech32::encode("bc", (&script_pubkey[1..]).to_base32()).unwrap(); + debug!( + "hex format: addr: {}, x_lock_address: {}", + hex::encode(addr.as_bytes().to_vec()), + hex::encode(data.x_lock_address.as_ref().to_vec()) + ); + debug!( + "addr: {}, x_lock_address: {}", + String::from_utf8(addr.as_bytes().to_vec()).unwrap(), + String::from_utf8(data.x_lock_address.as_ref().to_vec()).unwrap() + ); + if addr.as_bytes() != data.x_lock_address.as_ref() { + return Err(Error::WrongFundingAddr); + } + } + _ => return Err(Error::UnsupportedFundingType), + } + let expect_value = data.get_btc_lot_size()?.get_sudt_amount(); + let value = tx_out.value() as u128; + debug!("actual value: {}, expect: {}", value, expect_value); + if value < expect_value { + return Err(Error::FundingNotEnough); + } Ok(()) } @@ -167,6 +180,13 @@ fn verify_btc_spv(proof: BTCSPVProofReader, difficulty: BTCDifficultyReader) -> let header = headers.index(headers.len() - 1); let mut idx = [0u8; 8]; idx.copy_from_slice(proof.index().raw_data()); + debug!("tx_id: {}", hex::encode(tx_id.as_ref())); + debug!("merkle_root: {}", hex::encode(header.tx_root().as_ref())); + debug!( + "proof: {}", + hex::encode(proof.intermediate_nodes().raw_data()) + ); + debug!("index: {}", u64::from_le_bytes(idx)); if !validatespv::prove( tx_id, header.tx_root(), @@ -188,62 +208,77 @@ fn verify_xt_issue(data: &ToCKBCellDataView) -> Result<(), Error> { } fn verify_btc_xt_issue(data: &ToCKBCellDataView) -> Result<(), Error> { - // todo: change to btc_xt type hash - let btc_xt_type_hash = [0u8; 32]; - let input_xt_num = QueryIter::new(load_cell_type_hash, Source::Input) - .map(|hash_opt| hash_opt.unwrap_or_default()) - .filter(|hash| hash == &btc_xt_type_hash) + // let sudt_script = load_cell_type(1, Source::Output)?.unwrap(); + // debug!("sudt_script: {:?}", sudt_script); + // debug!("sudt_script code_hash: {:?}", sudt_script.code_hash()); + // debug!("sudt_script args: {:?}", sudt_script.args()); + // debug!("sudt_script hash_type: {:?}", sudt_script.hash_type()); + let lock_hash = load_cell_lock_hash(0, Source::Input)?; + debug!("lockscript hash: {:?}", hex::encode(lock_hash)); + let input_xt_num = QueryIter::new(load_cell_type, Source::Input) + .filter(|type_opt| type_opt.is_some()) + .map(|type_opt| type_opt.unwrap()) + .filter(|script| { + script.code_hash().raw_data().as_ref() == SUDT_CODE_HASH.as_ref() + && script.args().raw_data().as_ref() == lock_hash.as_ref() + }) .count(); if input_xt_num != 0 { return Err(Error::InvalidXTInInput); } - let mut output_index = 0; - let mut user_checked = false; - let mut signer_checked = false; + // let output_xt_num = QueryIter::new(load_cell_type, Source::Output) + // .filter(|type_opt| type_opt.is_some()) + // .map(|type_opt| type_opt.unwrap()) + // .filter(|script| { + // script.code_hash().raw_data().as_ref() == SUDT_CODE_HASH.as_ref() + // && script.args().raw_data().as_ref() == lock_hash.as_ref() + // }) + // .count(); + // debug!("output_xt_num: {}", output_xt_num); let xt_amount = data.get_btc_lot_size()?.get_sudt_amount(); - loop { - let type_hash_res = load_cell_type_hash(output_index, Source::Output); - match type_hash_res { - Err(SysError::IndexOutOfBound) => break, - Err(err) => { - debug!("iter output error {:?}", err); - panic!("iter output return an error") - } - Ok(type_hash) => { - if !(type_hash.is_some() && type_hash.unwrap() == btc_xt_type_hash) { - continue; - } - let lock = load_cell_lock(output_index, Source::Output)?; - let cell_data = load_cell_data(output_index, Source::Output)?; - let mut amount_vec = [0u8; 16]; - amount_vec.copy_from_slice(&cell_data); - let token_amount = u128::from_le_bytes(amount_vec); - if lock.as_slice() == data.user_lockscript.as_ref() { - if user_checked { - return Err(Error::InvalidXTMint); - } - if token_amount != xt_amount - xt_amount * SIGNER_FEE_RATE.0 / SIGNER_FEE_RATE.1 - { - return Err(Error::InvalidXTMint); - } - user_checked = true; - } else if lock.as_slice() == data.signer_lockscript.as_ref() { - if signer_checked { - return Err(Error::InvalidXTMint); - } - if token_amount != xt_amount * SIGNER_FEE_RATE.0 / SIGNER_FEE_RATE.1 { - return Err(Error::InvalidXTMint); - } - signer_checked = true; - } else { - return Err(Error::InvalidXTMint); - } - output_index += 1; - } + debug!("xt_amount: {}", xt_amount); + let expect = [ + ( + 1, + data.user_lockscript.as_ref(), + xt_amount - xt_amount * SIGNER_FEE_RATE.0 / SIGNER_FEE_RATE.1, + ), + ( + 2, + data.signer_lockscript.as_ref(), + xt_amount * SIGNER_FEE_RATE.0 / SIGNER_FEE_RATE.1, + ), + ]; + debug!("expect: {:?}", expect); + + for (i, lockscript, amout) in expect.iter() { + let script = load_cell_type(*i, Source::Output)?; + if script.is_none() { + return Err(Error::InvalidMintOutput); + } + let script = script.unwrap(); + if !(script.code_hash().raw_data().as_ref() == SUDT_CODE_HASH.as_ref() + && script.args().raw_data().as_ref() == lock_hash.as_ref()) + { + return Err(Error::InvalidMintOutput); + } + let cell_data = load_cell_data(*i, Source::Output)?; + let mut amount_vec = [0u8; 16]; + amount_vec.copy_from_slice(&cell_data); + let token_amount = u128::from_le_bytes(amount_vec); + debug!("token_amount: {}, amout: {}", token_amount, amout); + if token_amount != *amout { + return Err(Error::InvalidMintOutput); + } + let lock = load_cell_lock(*i, Source::Output)?; + debug!( + "lock: {:?}, expect lock: {:?}", + hex::encode(lock.as_slice()), + hex::encode(lockscript.as_ref()) + ); + if lock.as_slice() != lockscript.as_ref() { + return Err(Error::InvalidMintOutput); } - } - if !(user_checked && signer_checked) { - return Err(Error::InvalidXTMint); } Ok(()) } @@ -256,7 +291,7 @@ pub fn verify(toCKB_data_tuple: &ToCKBCellDataTuple) -> Result<(), Error> { debug!("verify data finish"); verify_witness(input_data)?; debug!("verify witness finish"); - // verify_xt_issue(input_data)?; - // debug!("verify xt issue finish"); + verify_xt_issue(input_data)?; + debug!("verify xt issue finish"); Ok(()) } diff --git a/contracts/toCKB-typescript/src/utils/config.rs b/contracts/toCKB-typescript/src/utils/config.rs index 29ab96d..470238b 100644 --- a/contracts/toCKB-typescript/src/utils/config.rs +++ b/contracts/toCKB-typescript/src/utils/config.rs @@ -2,3 +2,7 @@ pub const PLEDGE: u64 = 10000; pub const TX_PROOF_DIFFICULTY_FACTOR: u8 = 1; // default value is 2/1000 pub const SIGNER_FEE_RATE: (u128, u128) = (2, 1000); +pub const SUDT_CODE_HASH: [u8; 32] = [ + 225, 227, 84, 214, 214, 67, 173, 66, 114, 77, 64, 150, 126, 51, 73, 132, 83, 78, 3, 103, 64, + 92, 90, 228, 42, 157, 125, 99, 215, 125, 244, 25, +]; diff --git a/contracts/toCKB-typescript/src/utils/types/error.rs b/contracts/toCKB-typescript/src/utils/types/error.rs index e7852b8..eab5c19 100644 --- a/contracts/toCKB-typescript/src/utils/types/error.rs +++ b/contracts/toCKB-typescript/src/utils/types/error.rs @@ -23,6 +23,7 @@ pub enum Error { WrongTxId, FundingNotEnough, UnsupportedFundingType, + InvalidMintOutput, WrongFundingAddr, InvalidXTInInput, InvalidXTMint, diff --git a/contracts/toCKB-typescript/src/utils/types/toCKB_cell.rs b/contracts/toCKB-typescript/src/utils/types/toCKB_cell.rs index e316e9c..c1341a3 100644 --- a/contracts/toCKB-typescript/src/utils/types/toCKB_cell.rs +++ b/contracts/toCKB-typescript/src/utils/types/toCKB_cell.rs @@ -27,7 +27,7 @@ impl ToCKBCellDataView { let status = ToCKBStatus::from_int(data_reader.status().to_entity().into())?; let lot_size = data_reader.lot_size().as_slice()[0]; let user_lockscript = data_reader.user_lockscript().to_entity().as_bytes(); - let x_lock_address = data_reader.x_lock_address().to_entity().as_bytes(); + let x_lock_address = data_reader.x_lock_address().to_entity().raw_data(); let signer_lockscript = data_reader.signer_lockscript().to_entity().as_bytes(); let x_unlock_address = data_reader.x_lock_address().to_entity().as_bytes(); let redeemer_lockscript = data_reader.redeemer_lockscript().to_entity().as_bytes(); diff --git a/tests/src/toCKB_typescript/tests/mint_xt/mod.rs b/tests/src/toCKB_typescript/tests/mint_xt/mod.rs index bdbe3d5..bf2ba15 100644 --- a/tests/src/toCKB_typescript/tests/mint_xt/mod.rs +++ b/tests/src/toCKB_typescript/tests/mint_xt/mod.rs @@ -47,6 +47,8 @@ fn test_correct_tx() { let toCKB_lockscript_bin: Bytes = Loader::default().load_binary("toCKB-lockscript"); let toCKB_lockscript_out_point = context.deploy_cell(toCKB_lockscript_bin); let always_success_out_point = context.deploy_cell(ALWAYS_SUCCESS.clone()); + let sudt_bin = include_bytes!("../simple_udt"); + let sudt_out_point = context.deploy_cell(Bytes::from(sudt_bin.as_ref())); // prepare scripts let toCKB_typescript = context @@ -61,6 +63,17 @@ fn test_correct_tx() { let always_success_lockscript_dep = CellDep::new_builder() .out_point(always_success_out_point) .build(); + let lock_hash: [u8; 32] = always_success_lockscript.calc_script_hash().unpack(); + // let lock_hash = [0u8; 32]; + dbg!(hex::encode(lock_hash)); + let sudt_script_args: Bytes = lock_hash.to_vec().into(); + let sudt_typescript = context + .build_script(&sudt_out_point, sudt_script_args) + .expect("script"); + dbg!(sudt_typescript.code_hash()); + dbg!(sudt_typescript.args()); + // dbg!(sudt_typescript.code_hash().raw_data().to_vec()); + let sudt_typescript_dep = CellDep::new_builder().out_point(sudt_out_point).build(); // prepare cells let input_out_point = context.create_cell( @@ -74,10 +87,21 @@ fn test_correct_tx() { .previous_output(input_out_point) .build(); - let signer_lockscript = toCKB_typescript::utils::types::basic::Script::new_builder().build(); - let user_lockscript = toCKB_typescript::utils::types::basic::Script::new_builder().build(); + let user_lockscript = toCKB_typescript::utils::types::basic::Script::from_slice( + always_success_lockscript.as_slice(), + ) + .unwrap(); + let signer_lockscript = user_lockscript.clone(); + let x_lock_address_str = b"bc1qq2pw0kr5yhz3xcs978desw5anfmtwynutwq8quz0t"; let x_lock_address = toCKB_typescript::utils::types::basic::Bytes::new_builder() - .set([Byte::new(1u8); 20].to_vec().into()) + // .set([Byte::new(1u8); 20].to_vec().into()) + .set( + x_lock_address_str + .iter() + .map(|c| Byte::new(*c)) + .collect::>() + .into(), + ) .build(); let input_toCKB_data = ToCKBCellData::new_builder() .status(Byte::new(ToCKBStatus::Bonded.int_value())) @@ -106,12 +130,28 @@ fn test_correct_tx() { .previous_output(input_ckb_cell_out_point) .build(); let inputs = vec![input_ckb_cell]; - let outputs = vec![CellOutput::new_builder() - .capacity(11000u64.pack()) - .type_(Some(toCKB_typescript.clone()).pack()) - .lock(always_success_lockscript) - .build()]; - let outputs_data = vec![output_toCKB_data.as_bytes()]; + let outputs = vec![ + CellOutput::new_builder() + .capacity(11000u64.pack()) + .type_(Some(toCKB_typescript.clone()).pack()) + .lock(always_success_lockscript.clone()) + .build(), + CellOutput::new_builder() + .capacity(11000u64.pack()) + .type_(Some(sudt_typescript.clone()).pack()) + .lock(always_success_lockscript.clone()) + .build(), + CellOutput::new_builder() + .capacity(11000u64.pack()) + .type_(Some(sudt_typescript.clone()).pack()) + .lock(always_success_lockscript.clone()) + .build(), + ]; + let outputs_data = vec![ + output_toCKB_data.as_bytes(), + 24950000u128.to_le_bytes().to_vec().into(), + 50000u128.to_le_bytes().to_vec().into(), + ]; // raw_header: 00000020acf05cadf6d066d01f5aca661690f4e1779a8144b90b070000000000000000006bbb5a7851af48d883e8ac5d6f61c6ad9a4132a9a12531c1b6f085760b3b2e427ba0455fea0710177d792e86 // raw_tx: 020000000001015227c5fbad9d9202ade7f02452cf880dac1ed270255ebfe6716e8b3e8956571d0100000017160014085fc2ea0c102fc4db8dbbb10dd6f93684c178c9feffffff028c79171300000000160014173ec3a12e289b102f8edcc1d4ecd3b5b893e2dc97b2030000000000160014ef9665bcf82fa83e870a350a6551a09ee819e4a30247304402201fc61e35096b9ba44a5a845932acce596fde7be7583acd9950d25bb937d49632022032b7666d8d72a553ec9376107a6d25444a942ae8b2eb77ac11d71593666f2c7f0121032dcec3808ef6a58b14e8b1ac77e7b5c47ea46120cd429b8c1eae0970b9c87e1edbd80900 // raw_tx: @@ -136,43 +176,29 @@ fn test_correct_tx() { // - 032dcec3808ef6a58b14e8b1ac77e7b5c47ea46120cd429b8c1eae0970b9c87e1e // witness 2 // - dbd80900 // locktime // 02000000015227c5fbad9d9202ade7f02452cf880dac1ed270255ebfe6716e8b3e8956571d0100000017160014085fc2ea0c102fc4db8dbbb10dd6f93684c178c9feffffff028c79171300000000160014173ec3a12e289b102f8edcc1d4ecd3b5b893e2dc97b2030000000000160014ef9665bcf82fa83e870a350a6551a09ee819e4a3dbd80900 - // let btc_spv_proof_str = r#" - // { - // "version": "0x02000000", - // "vin": "0x015227c5fbad9d9202ade7f02452cf880dac1ed270255ebfe6716e8b3e8956571d0100000017160014085fc2ea0c102fc4db8dbbb10dd6f93684c178c9feffffff", - // "vout": "0x028c79171300000000160014173ec3a12e289b102f8edcc1d4ecd3b5b893e2dc97b2030000000000160014ef9665bcf82fa83e870a350a6551a09ee819e4a3", - // "locktime": "0xdbd80900", - // "tx_id": "0xc33b712400ac3c262272ea6f0ddbfeab56d7786c84b2419ec25cf1e66a84212b", - // "index": 0, - // "headers": "0x00000020acf05cadf6d066d01f5aca661690f4e1779a8144b90b070000000000000000006bbb5a7851af48d883e8ac5d6f61c6ad9a4132a9a12531c1b6f085760b3b2e427ba0455fea0710177d792e86", - // "intermediate_nodes": "0x", - // "funding_output_index": 0 - // } - // "#; let btc_spv_proof_str = r#" { - "version": "0x01000000", - "vin": "0x0101748906a5c7064550a594c4683ffc6d1ee25292b638c4328bb66403cfceb58a000000006a4730440220364301a77ee7ae34fa71768941a2aad5bd1fa8d3e30d4ce6424d8752e83f2c1b02203c9f8aafced701f59ffb7c151ff2523f3ed1586d29b674efb489e803e9bf93050121029b3008c0fa147fd9db5146e42b27eb0a77389497713d3aad083313d1b1b05ec0ffffffff", - "vout": "0x0316312f00000000001976a91400cc8d95d6835252e0d95eb03b11691a21a7bac588ac220200000000000017a914e5034b9de4881d62480a2df81032ef0299dcdc32870000000000000000166a146f6d6e69000000000000001f0000000315e17900", - "locktime": "0x00000000", - "tx_id": "0x5176f6b03b8bc29f4deafbb7384b673debde6ae712deab93f3b0c91fdcd6d674", - "index": 26, - "headers": "0x0000c020c238b601308b7297346ab2ed59942d7d7ecea8d23a1001000000000000000000b61ac92842abc82aa93644b190fc18ad46c6738337e78bc0c69ab21c5d5ee2ddd6376d5d3e211a17d8706a84", - "intermediate_nodes": "0x8d7a6d53ce27f79802631f1aae5f172c43d128b210ab4962d488c81c96136cfb75c95def872e878839bd93b42c04eb44da44c401a2d580ca343c3262e9c0a2819ed4bbfb9ea620280b31433f43b2512a893873b8c8c679f61e1a926c0ec80bcfc6225a15d72fbd1116f78b14663d8518236b02e765bf0a746a6a08840c122a02afa4df3ab6b9197a20f00495a404ee8e07da2b7554e94609e9ee1d5da0fb7857ea0332072568d0d53a9aedf851892580504a7fcabfbdde076242eb7f4e5f218a14d2a3f357d950b4f6a1dcf93f7c19c44d0fc122d00afa297b9503c1a6ad24cf36cb5f2835bcf490371db2e96047813a24176c3d3416f84b7ddfb7d8c915eb0c5ce7de089b5d9e700ecd12e09163f173b70bb4c9af33051b466b1f55abd66f3121216ad0ad9dfa898535e1d5e51dd07bd0a73d584daace7902f20ece4ba4f4f241c80cb31eda88a244a3c68d0f157c1049b4153d7addd6548aca0885acafbf98a1f8345c89914c24729ad095c7a0b9acd20232ccd90dbd359468fcc4eee7b67d", + "version": "0x02000000", + "vin": "0x015227c5fbad9d9202ade7f02452cf880dac1ed270255ebfe6716e8b3e8956571d0100000017160014085fc2ea0c102fc4db8dbbb10dd6f93684c178c9feffffff", + "vout": "0x028c79171300000000160014173ec3a12e289b102f8edcc1d4ecd3b5b893e2dc97b2030000000000160014ef9665bcf82fa83e870a350a6551a09ee819e4a3", + "locktime": "0xdbd80900", + "tx_id": "0x2b21846ae6f15cc29e41b2846c78d756abfedb0d6fea7222263cac0024713bc3", + "index": 3, + "headers": "0x00000020acf05cadf6d066d01f5aca661690f4e1779a8144b90b070000000000000000006bbb5a7851af48d883e8ac5d6f61c6ad9a4132a9a12531c1b6f085760b3b2e427ba0455fea0710177d792e86", + "intermediate_nodes": "0x8546dfccb488115f9c3210255523c0e186fb9b64d16ac68b3d8903bf037dc3ab26069e90c930cc55105d5f8b4ddd798bc33f057641e748fd2e70de0b8747cae802af46fb1e1fccf354b4b46d87f5a85c564fd5284cbe2a5711c16c446fbb6e9e0b3c7beec06a156a8005883b8cf224f665d361a2269b6b21491c1ccbb8160c311b609b5ca21b0a9f708e6124b36871b71c5536d8d556054be435cf0444da70d0814e678eb0e081805d777f9cf84911f9e04b6a80b6cf60dec31527ec73aaa8ba77ec6bff2e04fbb80c8c81b1cc38b415bc21dd732f51a4a903ee265b0eef2c589f751e66e46bb02aa36ed8418ae93317316b84d12f1b1702dd9641ead0ad7f8777526ad7a4ff599946d219a7a932ec8cd2e42649b3d5fa123d2e4532de6d46bddb27a8c02de8fb8fe2c4d88a14132de8cdd7d471bc6a8c8c217aeec600fd295e8925b663332f45bdb6877dd6e0ecd28bfae530ba3ed8bd3959644a82bc418f9c887746e15ae55d82369c3761187ea449c7f7bdff1acaa0b467e1335b3919089d", "funding_output_index": 0 } "#; let btc_spv_proof = json_to_btc_proof(btc_spv_proof_str).unwrap(); let witness_data = mint_xt_witness::MintXTWitness::new_builder() .spv_proof(btc_spv_proof.as_slice().to_vec().into()) - .cell_dep_index_list(vec![2].into()) + .cell_dep_index_list(vec![0].into()) .build(); let witness = WitnessArgs::new_builder() .input_type(Some(witness_data.as_bytes()).pack()) .build(); - // 0xFF809F0159F - let diff = 10771996663680u64; + let diff = 17557993035167u64; let difficulty_data = btc_difficulty::BTCDifficulty::new_builder() .previous(diff.to_le_bytes().to_vec().into()) .current(diff.to_le_bytes().to_vec().into()) @@ -188,9 +214,10 @@ fn test_correct_tx() { .inputs(inputs) .outputs(outputs) .outputs_data(outputs_data.pack()) + .cell_dep(difficulty_data_dep) .cell_dep(toCKB_typescript_dep) .cell_dep(always_success_lockscript_dep) - .cell_dep(difficulty_data_dep) + .cell_dep(sudt_typescript_dep) .witness(witness.as_bytes().pack()) .build(); diff --git a/tests/src/toCKB_typescript/tests/simple_udt b/tests/src/toCKB_typescript/tests/simple_udt new file mode 100755 index 0000000000000000000000000000000000000000..e092e8d74530459b71b89ad10f820ec3f52ea866 GIT binary patch literal 1696 zcma)7eM}Q)7=P}o*P^tV6B`6K;UY5T8ip(~;hAmMtV(X4ngUW$Ki=%sG|o z^`JBXSC3K|6Y4*j_=hoTj0p`+W2R`9P3JPrGBxZJ+?V)Skk;$&Xbb9JzRBJDJ|Dm5 zchB#xPj_=GoH&L-X5nxjbn90l<+G;)VJdady>_SoT)UG%Oys6R>C8;6)V?Vl%NR^`)zGKa(#kqd(}A^23r*EEYFs3t$`p~Ply#5x%pHBfQ#@n! z5z;!g^nQXZB~-SYP*a^#wBGr^6!%+1LgyA-X!<}l=E7F>FFRFpM5JmeThDlfuvkW@ zM1`nE_IwPH6W6iop3i&Kc7)8+ka578sm+$Y_jt0KbVWohHBpvAsYmO1yt$@D;1Bwg z9OFG@_)&a&Ep=SRUBFlX|E8U3x8P_^l2n4j$pdR;tqXr>c1tXj8&=xRju5A5Ae=Nv zG({`M)2d`(m)wZ!O6odJvM%;&Z*b++65r1L?4{?9p?HUhFzOFFMH_cVW?>Gg|G znQOeJtod+!d+iTVWqkE5y`!rUv_{30uYbO-s6Br$#*>MQ(VexYqT6ckMqa5Mj9^PI zMnVMuvT&da=N1Cy9J!PHQ8r$nbglN)1$evpP7{YlV`j0~3CzO^Xc$Dv+1YuQiXqQ@KiO?CL#r#7 zL$Pbqy9SXwG@Th8NNR}N!&$PGz#obIbT@S=Sv4~tdU6VH?4`jd1X`&@*j>B7-A^&J z6WH(z*qIi&*#+MPXVQ5R4f&3Mfjtsa(d|P9#d=)rrj?|}`bdn0zICAbF@tP1Yn5Xm zHcVsUA?=IQe#>*YsLxu3I&YEU!FHhdXiLnFdWUi1&`%%-4Y&|!<8yj#o#^2(o?p#S zXOoLw3q#;+p2S0Ln|{X5&E;MVXLFt=lXhiu3`Qmk>#HzN6Yp?T&MW3!@4qzfbz7OO z6u{QFuF<{KUH1vt+zns2!G<<(+}N Date: Fri, 28 Aug 2020 03:36:18 +0800 Subject: [PATCH 18/45] fix: fix tests --- .../src/switch/mint_xt/mod.rs | 21 ++------ .../src/utils/types/generated/mod.rs | 3 ++ .../src/toCKB_typescript/tests/mint_xt/mod.rs | 48 ++++--------------- .../toCKB_typescript/utils/types/convert.rs | 2 +- .../utils/types/generated/mod.rs | 3 ++ tests/src/toCKB_typescript/utils/types/mod.rs | 1 + 6 files changed, 21 insertions(+), 57 deletions(-) diff --git a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs index 1470863..49c13d7 100644 --- a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs +++ b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs @@ -9,7 +9,7 @@ use crate::utils::{ }, }; use alloc::string::String; -use bech32::{self, ToBase32}; +use bech32::ToBase32; use bitcoin_spv::{ btcspv, types::{HeaderArray, MerkleArray, PayloadType, Vin, Vout}, @@ -18,10 +18,9 @@ use bitcoin_spv::{ use ckb_std::{ ckb_constants::Source, debug, - error::SysError, high_level::{ - load_cell_data, load_cell_lock, load_cell_lock_hash, load_cell_type, load_cell_type_hash, - load_witness_args, QueryIter, + load_cell_data, load_cell_lock, load_cell_lock_hash, load_cell_type, load_witness_args, + QueryIter, }, }; use core::result::Result; @@ -208,11 +207,6 @@ fn verify_xt_issue(data: &ToCKBCellDataView) -> Result<(), Error> { } fn verify_btc_xt_issue(data: &ToCKBCellDataView) -> Result<(), Error> { - // let sudt_script = load_cell_type(1, Source::Output)?.unwrap(); - // debug!("sudt_script: {:?}", sudt_script); - // debug!("sudt_script code_hash: {:?}", sudt_script.code_hash()); - // debug!("sudt_script args: {:?}", sudt_script.args()); - // debug!("sudt_script hash_type: {:?}", sudt_script.hash_type()); let lock_hash = load_cell_lock_hash(0, Source::Input)?; debug!("lockscript hash: {:?}", hex::encode(lock_hash)); let input_xt_num = QueryIter::new(load_cell_type, Source::Input) @@ -226,15 +220,6 @@ fn verify_btc_xt_issue(data: &ToCKBCellDataView) -> Result<(), Error> { if input_xt_num != 0 { return Err(Error::InvalidXTInInput); } - // let output_xt_num = QueryIter::new(load_cell_type, Source::Output) - // .filter(|type_opt| type_opt.is_some()) - // .map(|type_opt| type_opt.unwrap()) - // .filter(|script| { - // script.code_hash().raw_data().as_ref() == SUDT_CODE_HASH.as_ref() - // && script.args().raw_data().as_ref() == lock_hash.as_ref() - // }) - // .count(); - // debug!("output_xt_num: {}", output_xt_num); let xt_amount = data.get_btc_lot_size()?.get_sudt_amount(); debug!("xt_amount: {}", xt_amount); let expect = [ diff --git a/contracts/toCKB-typescript/src/utils/types/generated/mod.rs b/contracts/toCKB-typescript/src/utils/types/generated/mod.rs index 4e0fab0..148def6 100644 --- a/contracts/toCKB-typescript/src/utils/types/generated/mod.rs +++ b/contracts/toCKB-typescript/src/utils/types/generated/mod.rs @@ -2,3 +2,6 @@ pub mod basic; pub mod btc_difficulty; pub mod mint_xt_witness; pub mod toCKB_cell_data; + +pub use basic::*; +pub use toCKB_cell_data::*; diff --git a/tests/src/toCKB_typescript/tests/mint_xt/mod.rs b/tests/src/toCKB_typescript/tests/mint_xt/mod.rs index bf2ba15..65df594 100644 --- a/tests/src/toCKB_typescript/tests/mint_xt/mod.rs +++ b/tests/src/toCKB_typescript/tests/mint_xt/mod.rs @@ -1,45 +1,21 @@ -use super::{Script, ToCKBCellData}; -use crate::toCKB_typescript::utils::types::{basic, btc_difficulty, mint_xt_witness}; +use super::ToCKBCellData; +use crate::toCKB_typescript::utils::types::{ + generated::{basic, btc_difficulty, mint_xt_witness}, + ToCKBStatus, +}; use crate::*; use anyhow::Result; use ckb_testtool::{builtin::ALWAYS_SUCCESS, context::Context}; -use ckb_tool::ckb_types::{ - bytes::Bytes, - core::{TransactionBuilder, TransactionView}, - packed::*, - prelude::*, -}; -use ckb_tool::{ckb_error::assert_error_eq, ckb_script::ScriptError}; -use int_enum::IntEnum; +use ckb_tool::ckb_types::{bytes::Bytes, core::TransactionBuilder, packed::*, prelude::*}; use molecule::prelude::*; -use primitive_types::U256; use serde::{Deserialize, Serialize}; use std::convert::{TryFrom, TryInto}; const MAX_CYCLES: u64 = 100_000_000; -// const PLEDGE_INVALID: i8 = 8; -// const LOT_SIZE_INVALID: i8 = 7; -// const TX_INVALID: i8 = 6; -// const ENCODING: i8 = 4; - -#[repr(u8)] -#[derive(Clone, Copy, IntEnum)] -pub enum ToCKBStatus { - Initial = 1, - Bonded = 2, - Warranty = 3, - Redeeming = 4, - SignerTimeout = 5, - Undercollateral = 6, - FaultyWhenWarranty = 7, - FaultyWhenRedeeming = 8, -} #[test] fn test_correct_tx() { let kind = 1; - let pledge = 10000; - let coin_type = 1; let mut context = Context::default(); let toCKB_typescript_bin: Bytes = Loader::default().load_binary("toCKB-typescript"); @@ -87,14 +63,10 @@ fn test_correct_tx() { .previous_output(input_out_point) .build(); - let user_lockscript = toCKB_typescript::utils::types::basic::Script::from_slice( - always_success_lockscript.as_slice(), - ) - .unwrap(); + let user_lockscript = basic::Script::from_slice(always_success_lockscript.as_slice()).unwrap(); let signer_lockscript = user_lockscript.clone(); let x_lock_address_str = b"bc1qq2pw0kr5yhz3xcs978desw5anfmtwynutwq8quz0t"; - let x_lock_address = toCKB_typescript::utils::types::basic::Bytes::new_builder() - // .set([Byte::new(1u8); 20].to_vec().into()) + let x_lock_address = basic::Bytes::new_builder() .set( x_lock_address_str .iter() @@ -104,14 +76,14 @@ fn test_correct_tx() { ) .build(); let input_toCKB_data = ToCKBCellData::new_builder() - .status(Byte::new(ToCKBStatus::Bonded.int_value())) + .status(Byte::new(ToCKBStatus::Bonded as u8)) .lot_size(Byte::new(1u8)) .signer_lockscript(signer_lockscript.clone()) .user_lockscript(user_lockscript.clone()) .x_lock_address(x_lock_address.clone()) .build(); let output_toCKB_data = ToCKBCellData::new_builder() - .status(Byte::new(ToCKBStatus::Warranty.int_value())) + .status(Byte::new(ToCKBStatus::Warranty as u8)) .lot_size(Byte::new(1u8)) .signer_lockscript(signer_lockscript.clone()) .user_lockscript(user_lockscript.clone()) diff --git a/tests/src/toCKB_typescript/utils/types/convert.rs b/tests/src/toCKB_typescript/utils/types/convert.rs index da93238..38b56c8 100644 --- a/tests/src/toCKB_typescript/utils/types/convert.rs +++ b/tests/src/toCKB_typescript/utils/types/convert.rs @@ -1,4 +1,4 @@ -use super::basic::{Byte32, Byte4, Bytes, Uint32, Uint64}; +use super::generated::basic::{Byte32, Byte4, Bytes, Uint32, Uint64}; use molecule::prelude::{Builder, Byte, Entity}; impl From> for Bytes { diff --git a/tests/src/toCKB_typescript/utils/types/generated/mod.rs b/tests/src/toCKB_typescript/utils/types/generated/mod.rs index 4e0fab0..148def6 100644 --- a/tests/src/toCKB_typescript/utils/types/generated/mod.rs +++ b/tests/src/toCKB_typescript/utils/types/generated/mod.rs @@ -2,3 +2,6 @@ pub mod basic; pub mod btc_difficulty; pub mod mint_xt_witness; pub mod toCKB_cell_data; + +pub use basic::*; +pub use toCKB_cell_data::*; diff --git a/tests/src/toCKB_typescript/utils/types/mod.rs b/tests/src/toCKB_typescript/utils/types/mod.rs index bab9d1f..e9425b8 100644 --- a/tests/src/toCKB_typescript/utils/types/mod.rs +++ b/tests/src/toCKB_typescript/utils/types/mod.rs @@ -1,3 +1,4 @@ +pub mod convert; pub mod generated; #[repr(i8)] From 3f85dc7b3835b0ac333365b936247f566e863071 Mon Sep 17 00:00:00 2001 From: huwenchao Date: Fri, 28 Aug 2020 16:04:19 +0800 Subject: [PATCH 19/45] test: add more test code --- Makefile | 6 +- contracts/toCKB-typescript/Cargo.lock | 3 +- contracts/toCKB-typescript/Cargo.toml | 6 +- .../src/switch/mint_xt/mod.rs | 14 +- .../toCKB-typescript/src/utils/types/error.rs | 2 +- .../toCKB_typescript/tests/mint_xt/helper.rs | 188 ++++++++ .../src/toCKB_typescript/tests/mint_xt/mod.rs | 406 +++++------------- .../toCKB_typescript/tests/mint_xt/types.rs | 90 ++++ tests/src/toCKB_typescript/utils/types/mod.rs | 15 + 9 files changed, 417 insertions(+), 313 deletions(-) create mode 100644 tests/src/toCKB_typescript/tests/mint_xt/helper.rs create mode 100644 tests/src/toCKB_typescript/tests/mint_xt/types.rs diff --git a/Makefile b/Makefile index d3ba2ea..1233fe7 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,3 @@ -watch: - watchexec -w contracts/toCKB-typescript/src -- 'make fmt && capsule build' - schema: moleculec --language rust --schema-file contracts/toCKB-typescript/src/utils/types/schemas/basic.mol > contracts/toCKB-typescript/src/utils/types/generated/basic.rs moleculec --language rust --schema-file contracts/toCKB-typescript/src/utils/types/schemas/toCKB_cell_data.mol > contracts/toCKB-typescript/src/utils/types/generated/toCKB_cell_data.rs @@ -21,5 +18,4 @@ test: ci: fmt build test -.PHONY: fmt build test ci -.PHONY: schema watch \ No newline at end of file +.PHONY: fmt build test ci schema diff --git a/contracts/toCKB-typescript/Cargo.lock b/contracts/toCKB-typescript/Cargo.lock index c3d43b1..f3795b7 100644 --- a/contracts/toCKB-typescript/Cargo.lock +++ b/contracts/toCKB-typescript/Cargo.lock @@ -88,7 +88,8 @@ dependencies = [ [[package]] name = "ckb-std" version = "0.6.0" -source = "git+https://github.com/nervosnetwork/ckb-std.git#e38fbadcca7832ccbf4322abb4ca732d050a4cca" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4919733c5e3591ccdf892f0e29c5f5a220de5aef7f90e1a2a21bf03f707662f6" dependencies = [ "cc", "ckb-allocator", diff --git a/contracts/toCKB-typescript/Cargo.toml b/contracts/toCKB-typescript/Cargo.toml index 732fb2f..f149848 100644 --- a/contracts/toCKB-typescript/Cargo.toml +++ b/contracts/toCKB-typescript/Cargo.toml @@ -6,10 +6,8 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -# ckb-std = "0.6" -# ckb-std = { path = "/code/deps/ckb-std" } -ckb-std = { git = "https://github.com/nervosnetwork/ckb-std.git", branch = "master" } -molecule = { version = "=0.6.0", default-features = false } +ckb-std = "0.6" +molecule = { version = "0.6.0", default-features = false } int-enum = { version = "0.4", default-features = false } bitcoin-spv = { git = "https://github.com/summa-tx/bitcoin-spv.git", branch = "rust/dep-change", default-features = false } bech32 = { git = "https://github.com/reuvenpo/rust-bech32.git", branch = "support-no_std", default-features = false } diff --git a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs index 49c13d7..46317f9 100644 --- a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs +++ b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs @@ -218,7 +218,19 @@ fn verify_btc_xt_issue(data: &ToCKBCellDataView) -> Result<(), Error> { }) .count(); if input_xt_num != 0 { - return Err(Error::InvalidXTInInput); + return Err(Error::InvalidXTInInputOrOutput); + } + let output_xt_num = QueryIter::new(load_cell_type, Source::Output) + .filter(|type_opt| type_opt.is_some()) + .map(|type_opt| type_opt.unwrap()) + .filter(|script| { + script.code_hash().raw_data().as_ref() == SUDT_CODE_HASH.as_ref() + && script.args().raw_data().as_ref() == lock_hash.as_ref() + }) + .count(); + debug!("output_xt_num: {}", output_xt_num); + if output_xt_num != 2 { + return Err(Error::InvalidXTInInputOrOutput); } let xt_amount = data.get_btc_lot_size()?.get_sudt_amount(); debug!("xt_amount: {}", xt_amount); diff --git a/contracts/toCKB-typescript/src/utils/types/error.rs b/contracts/toCKB-typescript/src/utils/types/error.rs index eab5c19..0dedf28 100644 --- a/contracts/toCKB-typescript/src/utils/types/error.rs +++ b/contracts/toCKB-typescript/src/utils/types/error.rs @@ -25,7 +25,7 @@ pub enum Error { UnsupportedFundingType, InvalidMintOutput, WrongFundingAddr, - InvalidXTInInput, + InvalidXTInInputOrOutput, InvalidXTMint, } diff --git a/tests/src/toCKB_typescript/tests/mint_xt/helper.rs b/tests/src/toCKB_typescript/tests/mint_xt/helper.rs new file mode 100644 index 0000000..2af696b --- /dev/null +++ b/tests/src/toCKB_typescript/tests/mint_xt/helper.rs @@ -0,0 +1,188 @@ +use super::{types::*, ToCKBCellData}; +use crate::toCKB_typescript::utils::types::{ + generated::{basic, btc_difficulty, mint_xt_witness}, + ToCKBStatus, +}; +use crate::*; +use ckb_testtool::{builtin::ALWAYS_SUCCESS, context::Context}; +use ckb_tool::ckb_types::{bytes::Bytes, core::TransactionBuilder, packed::*, prelude::*}; +use molecule::prelude::*; + +const MAX_CYCLES: u64 = 100_000_000; + +pub fn run_test_case(case: TestCase) { + let kind = case.kind; + + let mut context = Context::default(); + let toCKB_typescript_bin: Bytes = Loader::default().load_binary("toCKB-typescript"); + let toCKB_typescript_out_point = context.deploy_cell(toCKB_typescript_bin); + // let toCKB_lockscript_bin: Bytes = Loader::default().load_binary("toCKB-lockscript"); + // let toCKB_lockscript_out_point = context.deploy_cell(toCKB_lockscript_bin); + let always_success_out_point = context.deploy_cell(ALWAYS_SUCCESS.clone()); + let sudt_bin = include_bytes!("../simple_udt"); + let sudt_out_point = context.deploy_cell(Bytes::from(sudt_bin.as_ref())); + + // prepare scripts + let toCKB_typescript = context + .build_script(&toCKB_typescript_out_point, [kind; 1].to_vec().into()) + .expect("script"); + let toCKB_typescript_dep = CellDep::new_builder() + .out_point(toCKB_typescript_out_point) + .build(); + let always_success_lockscript = context + .build_script(&always_success_out_point, Default::default()) + .expect("script"); + let always_success_lockscript_dep = CellDep::new_builder() + .out_point(always_success_out_point) + .build(); + let lock_hash: [u8; 32] = always_success_lockscript.calc_script_hash().unpack(); + // let lock_hash = [0u8; 32]; + dbg!(hex::encode(lock_hash)); + let sudt_script_args: Bytes = lock_hash.to_vec().into(); + let _sudt_typescript = context + .build_script(&sudt_out_point, sudt_script_args) + .expect("script"); + let sudt_typescript_dep = CellDep::new_builder().out_point(sudt_out_point).build(); + + // prepare cells + let x_lock_address_str = case.tockb_cell_data.x_lock_address; + let x_lock_address = basic::Bytes::new_builder() + .set( + x_lock_address_str + .as_bytes() + .iter() + .map(|c| Byte::new(*c)) + .collect::>() + .into(), + ) + .build(); + let signer_lockscript = + basic::Script::from_slice(case.tockb_cell_data.signer_lockscript.as_slice()).unwrap(); + let user_lockscript = + basic::Script::from_slice(case.tockb_cell_data.user_lockscript.as_slice()).unwrap(); + let input_toCKB_data = ToCKBCellData::new_builder() + .status(Byte::new(ToCKBStatus::Bonded as u8)) + .lot_size(Byte::new(case.tockb_cell_data.lot_size)) + .signer_lockscript(signer_lockscript.clone()) + .user_lockscript(user_lockscript.clone()) + .x_lock_address(x_lock_address.clone()) + .build(); + let output_toCKB_data = ToCKBCellData::new_builder() + .status(Byte::new(ToCKBStatus::Warranty as u8)) + .lot_size(Byte::new(case.tockb_cell_data.lot_size)) + .signer_lockscript(signer_lockscript.clone()) + .user_lockscript(user_lockscript.clone()) + .x_lock_address(x_lock_address.clone()) + .build(); + + let input_ckb_cell_out_point = context.create_cell( + CellOutput::new_builder() + .capacity(11000u64.pack()) + .lock(always_success_lockscript.clone()) + .type_(Some(toCKB_typescript.clone()).pack()) + .build(), + input_toCKB_data.as_bytes(), + ); + let input_ckb_cell = CellInput::new_builder() + .previous_output(input_ckb_cell_out_point) + .build(); + let inputs = vec![input_ckb_cell]; + let mut outputs = vec![CellOutput::new_builder() + .capacity(11000u64.pack()) + .type_(Some(toCKB_typescript.clone()).pack()) + .lock(always_success_lockscript.clone()) + .build()]; + let mut outputs_data = vec![output_toCKB_data.as_bytes()]; + for output in case.outputs.into_iter() { + let cell_output = CellOutput::new_builder() + .capacity(11000u64.pack()) + .type_(Some(output.typescript).pack()) + .lock(output.lockscript) + .build(); + outputs.push(cell_output); + outputs_data.push(output.amount.to_le_bytes().to_vec().into()) + } + let spv_proof = match case.witness.spv_proof { + SpvProof::BTC(btc_spv_proof) => btc_spv_proof.as_slice().to_vec(), + }; + let witness_data = mint_xt_witness::MintXTWitness::new_builder() + .spv_proof(spv_proof.into()) + .cell_dep_index_list(case.witness.cell_dep_index_list.into()) + .build(); + let witness = WitnessArgs::new_builder() + .input_type(Some(witness_data.as_bytes()).pack()) + .build(); + let dep_data = match case.cell_deps_data { + CellDepsData::BTC(difficulty_data) => { + let data = btc_difficulty::BTCDifficulty::new_builder() + .previous(difficulty_data.previous.to_le_bytes().to_vec().into()) + .current(difficulty_data.current.to_le_bytes().to_vec().into()) + .build(); + dbg!(&data); + data.as_bytes() + } + }; + let data_out_point = context.deploy_cell(dep_data); + let data_dep = CellDep::new_builder().out_point(data_out_point).build(); + + let tx = TransactionBuilder::default() + .inputs(inputs) + .outputs(outputs) + .outputs_data(outputs_data.pack()) + .cell_dep(data_dep) + .cell_dep(toCKB_typescript_dep) + .cell_dep(always_success_lockscript_dep) + .cell_dep(sudt_typescript_dep) + .witness(witness.as_bytes().pack()) + .build(); + + let res = context.verify_tx(&tx, MAX_CYCLES); + dbg!(&res); + match res { + Ok(_cycles) => assert_eq!(case.expect_return_code, 0), + Err(err) => assert!(check_err(err, case.expect_return_code)), + } +} + +pub fn check_err(err: ckb_tool::ckb_error::Error, code: i8) -> bool { + let get = format!("{}", err); + let expected = format!("Script(ValidationFailure({}))", code); + dbg!(&get, &expected); + get == expected +} + +pub struct DeployResult { + pub context: Context, + pub toCKB_typescript: Script, + pub always_success_lockscript: Script, + pub sudt_typescript: Script, +} + +pub fn deploy(kind: u8) -> DeployResult { + let mut context = Context::default(); + let toCKB_typescript_bin: Bytes = Loader::default().load_binary("toCKB-typescript"); + let toCKB_typescript_out_point = context.deploy_cell(toCKB_typescript_bin); + let always_success_out_point = context.deploy_cell(ALWAYS_SUCCESS.clone()); + let sudt_bin = include_bytes!("../simple_udt"); + let sudt_out_point = context.deploy_cell(Bytes::from(sudt_bin.as_ref())); + + // prepare scripts + let toCKB_typescript = context + .build_script(&toCKB_typescript_out_point, [kind; 1].to_vec().into()) + .expect("script"); + let always_success_lockscript = context + .build_script(&always_success_out_point, Default::default()) + .expect("script"); + let lock_hash: [u8; 32] = always_success_lockscript.calc_script_hash().unpack(); + let sudt_script_args: Bytes = lock_hash.to_vec().into(); + let sudt_typescript = context + .build_script(&sudt_out_point, sudt_script_args) + .expect("script"); + + DeployResult { + context, + toCKB_typescript, + always_success_lockscript, + sudt_typescript, + } +} diff --git a/tests/src/toCKB_typescript/tests/mint_xt/mod.rs b/tests/src/toCKB_typescript/tests/mint_xt/mod.rs index 65df594..4ffde02 100644 --- a/tests/src/toCKB_typescript/tests/mint_xt/mod.rs +++ b/tests/src/toCKB_typescript/tests/mint_xt/mod.rs @@ -1,317 +1,121 @@ +mod helper; +mod types; +use helper::{deploy, run_test_case, DeployResult}; +use types::*; + use super::ToCKBCellData; -use crate::toCKB_typescript::utils::types::{ - generated::{basic, btc_difficulty, mint_xt_witness}, - ToCKBStatus, -}; -use crate::*; -use anyhow::Result; -use ckb_testtool::{builtin::ALWAYS_SUCCESS, context::Context}; -use ckb_tool::ckb_types::{bytes::Bytes, core::TransactionBuilder, packed::*, prelude::*}; +use crate::toCKB_typescript::utils::types::{generated::mint_xt_witness, Error::*}; use molecule::prelude::*; -use serde::{Deserialize, Serialize}; -use std::convert::{TryFrom, TryInto}; - -const MAX_CYCLES: u64 = 100_000_000; +use std::convert::TryInto; -#[test] -fn test_correct_tx() { +fn generate_btc_corrent_case() -> TestCase { let kind = 1; - - let mut context = Context::default(); - let toCKB_typescript_bin: Bytes = Loader::default().load_binary("toCKB-typescript"); - let toCKB_typescript_out_point = context.deploy_cell(toCKB_typescript_bin); - let toCKB_lockscript_bin: Bytes = Loader::default().load_binary("toCKB-lockscript"); - let toCKB_lockscript_out_point = context.deploy_cell(toCKB_lockscript_bin); - let always_success_out_point = context.deploy_cell(ALWAYS_SUCCESS.clone()); - let sudt_bin = include_bytes!("../simple_udt"); - let sudt_out_point = context.deploy_cell(Bytes::from(sudt_bin.as_ref())); - - // prepare scripts - let toCKB_typescript = context - .build_script(&toCKB_typescript_out_point, [kind; 1].to_vec().into()) - .expect("script"); - let toCKB_typescript_dep = CellDep::new_builder() - .out_point(toCKB_typescript_out_point) - .build(); - let always_success_lockscript = context - .build_script(&always_success_out_point, Default::default()) - .expect("script"); - let always_success_lockscript_dep = CellDep::new_builder() - .out_point(always_success_out_point) - .build(); - let lock_hash: [u8; 32] = always_success_lockscript.calc_script_hash().unpack(); - // let lock_hash = [0u8; 32]; - dbg!(hex::encode(lock_hash)); - let sudt_script_args: Bytes = lock_hash.to_vec().into(); - let sudt_typescript = context - .build_script(&sudt_out_point, sudt_script_args) - .expect("script"); - dbg!(sudt_typescript.code_hash()); - dbg!(sudt_typescript.args()); - // dbg!(sudt_typescript.code_hash().raw_data().to_vec()); - let sudt_typescript_dep = CellDep::new_builder().out_point(sudt_out_point).build(); - - // prepare cells - let input_out_point = context.create_cell( - CellOutput::new_builder() - .capacity(11000u64.pack()) - .lock(always_success_lockscript.clone()) - .build(), - Bytes::new(), - ); - let input = CellInput::new_builder() - .previous_output(input_out_point) - .build(); - - let user_lockscript = basic::Script::from_slice(always_success_lockscript.as_slice()).unwrap(); - let signer_lockscript = user_lockscript.clone(); - let x_lock_address_str = b"bc1qq2pw0kr5yhz3xcs978desw5anfmtwynutwq8quz0t"; - let x_lock_address = basic::Bytes::new_builder() - .set( - x_lock_address_str - .iter() - .map(|c| Byte::new(*c)) - .collect::>() - .into(), - ) - .build(); - let input_toCKB_data = ToCKBCellData::new_builder() - .status(Byte::new(ToCKBStatus::Bonded as u8)) - .lot_size(Byte::new(1u8)) - .signer_lockscript(signer_lockscript.clone()) - .user_lockscript(user_lockscript.clone()) - .x_lock_address(x_lock_address.clone()) - .build(); - let output_toCKB_data = ToCKBCellData::new_builder() - .status(Byte::new(ToCKBStatus::Warranty as u8)) - .lot_size(Byte::new(1u8)) - .signer_lockscript(signer_lockscript.clone()) - .user_lockscript(user_lockscript.clone()) - .x_lock_address(x_lock_address.clone()) - .build(); - - let input_ckb_cell_out_point = context.create_cell( - CellOutput::new_builder() - .capacity(11000u64.pack()) - .lock(always_success_lockscript.clone()) - .type_(Some(toCKB_typescript.clone()).pack()) - .build(), - input_toCKB_data.as_bytes(), - ); - let input_ckb_cell = CellInput::new_builder() - .previous_output(input_ckb_cell_out_point) - .build(); - let inputs = vec![input_ckb_cell]; - let outputs = vec![ - CellOutput::new_builder() - .capacity(11000u64.pack()) - .type_(Some(toCKB_typescript.clone()).pack()) - .lock(always_success_lockscript.clone()) - .build(), - CellOutput::new_builder() - .capacity(11000u64.pack()) - .type_(Some(sudt_typescript.clone()).pack()) - .lock(always_success_lockscript.clone()) - .build(), - CellOutput::new_builder() - .capacity(11000u64.pack()) - .type_(Some(sudt_typescript.clone()).pack()) - .lock(always_success_lockscript.clone()) - .build(), - ]; - let outputs_data = vec![ - output_toCKB_data.as_bytes(), - 24950000u128.to_le_bytes().to_vec().into(), - 50000u128.to_le_bytes().to_vec().into(), - ]; - // raw_header: 00000020acf05cadf6d066d01f5aca661690f4e1779a8144b90b070000000000000000006bbb5a7851af48d883e8ac5d6f61c6ad9a4132a9a12531c1b6f085760b3b2e427ba0455fea0710177d792e86 - // raw_tx: 020000000001015227c5fbad9d9202ade7f02452cf880dac1ed270255ebfe6716e8b3e8956571d0100000017160014085fc2ea0c102fc4db8dbbb10dd6f93684c178c9feffffff028c79171300000000160014173ec3a12e289b102f8edcc1d4ecd3b5b893e2dc97b2030000000000160014ef9665bcf82fa83e870a350a6551a09ee819e4a30247304402201fc61e35096b9ba44a5a845932acce596fde7be7583acd9950d25bb937d49632022032b7666d8d72a553ec9376107a6d25444a942ae8b2eb77ac11d71593666f2c7f0121032dcec3808ef6a58b14e8b1ac77e7b5c47ea46120cd429b8c1eae0970b9c87e1edbd80900 - // raw_tx: - // - 02000000 // version - // - 0001 // flag - // - 01 // one input - // - 5227c5fbad9d9202ade7f02452cf880dac1ed270255ebfe6716e8b3e8956571d01000000 // outpoint - // - 17 // script sig len - // - 160014085fc2ea0c102fc4db8dbbb10dd6f93684c178c9 // script sig - // - feffffff // sequence - // - 02 // 2 output - // - 8c79171000000000 // output 1 value - // - 16 // len - // - 0014173ec3a12e289b102f8edcc1d4ecd3b5b893e2dc // script - // - 97b2030000000000 // output 2 - // - 16 - // - 0014ef9665bcf82fa83e870a350a6551a09ee819e4a3 - // - 02 // 2 witness - // - 47 - // - 304402201fc61e35096b9ba44a5a845932acce596fde7be7583acd9950d25bb937d49632022032b7666d8d72a553ec9376107a6d25444a942ae8b2eb77ac11d71593666f2c7f01 // witness 1 - // - 21 - // - 032dcec3808ef6a58b14e8b1ac77e7b5c47ea46120cd429b8c1eae0970b9c87e1e // witness 2 - // - dbd80900 // locktime - // 02000000015227c5fbad9d9202ade7f02452cf880dac1ed270255ebfe6716e8b3e8956571d0100000017160014085fc2ea0c102fc4db8dbbb10dd6f93684c178c9feffffff028c79171300000000160014173ec3a12e289b102f8edcc1d4ecd3b5b893e2dc97b2030000000000160014ef9665bcf82fa83e870a350a6551a09ee819e4a3dbd80900 - let btc_spv_proof_str = r#" - { - "version": "0x02000000", - "vin": "0x015227c5fbad9d9202ade7f02452cf880dac1ed270255ebfe6716e8b3e8956571d0100000017160014085fc2ea0c102fc4db8dbbb10dd6f93684c178c9feffffff", - "vout": "0x028c79171300000000160014173ec3a12e289b102f8edcc1d4ecd3b5b893e2dc97b2030000000000160014ef9665bcf82fa83e870a350a6551a09ee819e4a3", - "locktime": "0xdbd80900", - "tx_id": "0x2b21846ae6f15cc29e41b2846c78d756abfedb0d6fea7222263cac0024713bc3", - "index": 3, - "headers": "0x00000020acf05cadf6d066d01f5aca661690f4e1779a8144b90b070000000000000000006bbb5a7851af48d883e8ac5d6f61c6ad9a4132a9a12531c1b6f085760b3b2e427ba0455fea0710177d792e86", - "intermediate_nodes": "0x8546dfccb488115f9c3210255523c0e186fb9b64d16ac68b3d8903bf037dc3ab26069e90c930cc55105d5f8b4ddd798bc33f057641e748fd2e70de0b8747cae802af46fb1e1fccf354b4b46d87f5a85c564fd5284cbe2a5711c16c446fbb6e9e0b3c7beec06a156a8005883b8cf224f665d361a2269b6b21491c1ccbb8160c311b609b5ca21b0a9f708e6124b36871b71c5536d8d556054be435cf0444da70d0814e678eb0e081805d777f9cf84911f9e04b6a80b6cf60dec31527ec73aaa8ba77ec6bff2e04fbb80c8c81b1cc38b415bc21dd732f51a4a903ee265b0eef2c589f751e66e46bb02aa36ed8418ae93317316b84d12f1b1702dd9641ead0ad7f8777526ad7a4ff599946d219a7a932ec8cd2e42649b3d5fa123d2e4532de6d46bddb27a8c02de8fb8fe2c4d88a14132de8cdd7d471bc6a8c8c217aeec600fd295e8925b663332f45bdb6877dd6e0ecd28bfae530ba3ed8bd3959644a82bc418f9c887746e15ae55d82369c3761187ea449c7f7bdff1acaa0b467e1335b3919089d", - "funding_output_index": 0 - } - "#; - let btc_spv_proof = json_to_btc_proof(btc_spv_proof_str).unwrap(); - let witness_data = mint_xt_witness::MintXTWitness::new_builder() - .spv_proof(btc_spv_proof.as_slice().to_vec().into()) - .cell_dep_index_list(vec![0].into()) - .build(); - let witness = WitnessArgs::new_builder() - .input_type(Some(witness_data.as_bytes()).pack()) - .build(); - - let diff = 17557993035167u64; - let difficulty_data = btc_difficulty::BTCDifficulty::new_builder() - .previous(diff.to_le_bytes().to_vec().into()) - .current(diff.to_le_bytes().to_vec().into()) - .build(); - - dbg!(&difficulty_data); - let difficulty_data_out_point = context.deploy_cell(difficulty_data.as_bytes()); - let difficulty_data_dep = CellDep::new_builder() - .out_point(difficulty_data_out_point) - .build(); - - let tx = TransactionBuilder::default() - .inputs(inputs) - .outputs(outputs) - .outputs_data(outputs_data.pack()) - .cell_dep(difficulty_data_dep) - .cell_dep(toCKB_typescript_dep) - .cell_dep(always_success_lockscript_dep) - .cell_dep(sudt_typescript_dep) - .witness(witness.as_bytes().pack()) - .build(); - - // let tx = context.complete_tx(tx); - // let toCKB_data = ToCKBCellData::new_builder() - // .status(Byte::new(1u8)) - // .lot_size(Byte::new(1u8)) - // .user_lockscript(Script::new_builder().build()) - // .build(); - // let (context, tx) = build_test_context(1, 10000, toCKB_data.as_bytes()); - - let cycles = context - .verify_tx(&tx, MAX_CYCLES) - .expect("pass verification"); - println!("consume cycles: {}", cycles); + let DeployResult { + context: _, + toCKB_typescript: _, + always_success_lockscript, + sudt_typescript, + } = deploy(kind); + let user_lockscript = always_success_lockscript.clone(); + let signer_lockscript = always_success_lockscript.clone(); + let case = TestCase { + kind, + tockb_cell_data: ToCKBCellDataTest { + lot_size: 1, + x_lock_address: "bc1qq2pw0kr5yhz3xcs978desw5anfmtwynutwq8quz0t".to_owned(), + user_lockscript: user_lockscript.clone(), + signer_lockscript: signer_lockscript.clone(), + }, + outputs: vec![ + Output { + typescript: sudt_typescript.clone(), + lockscript: always_success_lockscript.clone(), + amount: 24950000, + }, + Output { + typescript: sudt_typescript.clone(), + lockscript: always_success_lockscript.clone(), + amount: 50000, + }, + ], + witness: Witness { + cell_dep_index_list: vec![0], + spv_proof: SpvProof::BTC(BTCSPVProofJson{ + version: "0x02000000".to_owned(), + vin: "0x015227c5fbad9d9202ade7f02452cf880dac1ed270255ebfe6716e8b3e8956571d0100000017160014085fc2ea0c102fc4db8dbbb10dd6f93684c178c9feffffff".to_owned(), + vout: "0x028c79171300000000160014173ec3a12e289b102f8edcc1d4ecd3b5b893e2dc97b2030000000000160014ef9665bcf82fa83e870a350a6551a09ee819e4a3".to_owned(), + locktime: "0xdbd80900".to_owned(), + tx_id: "0x2b21846ae6f15cc29e41b2846c78d756abfedb0d6fea7222263cac0024713bc3".to_owned(), + index: 3, + headers: "0x00000020acf05cadf6d066d01f5aca661690f4e1779a8144b90b070000000000000000006bbb5a7851af48d883e8ac5d6f61c6ad9a4132a9a12531c1b6f085760b3b2e427ba0455fea0710177d792e86".to_owned(), + intermediate_nodes: "0x8546dfccb488115f9c3210255523c0e186fb9b64d16ac68b3d8903bf037dc3ab26069e90c930cc55105d5f8b4ddd798bc33f057641e748fd2e70de0b8747cae802af46fb1e1fccf354b4b46d87f5a85c564fd5284cbe2a5711c16c446fbb6e9e0b3c7beec06a156a8005883b8cf224f665d361a2269b6b21491c1ccbb8160c311b609b5ca21b0a9f708e6124b36871b71c5536d8d556054be435cf0444da70d0814e678eb0e081805d777f9cf84911f9e04b6a80b6cf60dec31527ec73aaa8ba77ec6bff2e04fbb80c8c81b1cc38b415bc21dd732f51a4a903ee265b0eef2c589f751e66e46bb02aa36ed8418ae93317316b84d12f1b1702dd9641ead0ad7f8777526ad7a4ff599946d219a7a932ec8cd2e42649b3d5fa123d2e4532de6d46bddb27a8c02de8fb8fe2c4d88a14132de8cdd7d471bc6a8c8c217aeec600fd295e8925b663332f45bdb6877dd6e0ecd28bfae530ba3ed8bd3959644a82bc418f9c887746e15ae55d82369c3761187ea449c7f7bdff1acaa0b467e1335b3919089d".to_owned(), + funding_output_index: 0, + }.try_into().unwrap()), + }, + cell_deps_data: CellDepsData::BTC( + BtcDifficultyTest { + previous: 17557993035167u64, + current: 17557993035167u64, + } + ), + expect_return_code: 0, + }; + case } -#[derive(Serialize, Deserialize)] -struct BTCSPVProofJson { - version: String, - vin: String, - vout: String, - locktime: String, - tx_id: String, - index: u64, - headers: String, - intermediate_nodes: String, - funding_output_index: u8, +#[test] +fn test_btc_correct_case() { + let case = generate_btc_corrent_case(); + run_test_case(case); } -impl TryFrom for mint_xt_witness::BTCSPVProof { - type Error = anyhow::Error; - - fn try_from(proof: BTCSPVProofJson) -> Result { - Ok(mint_xt_witness::BTCSPVProof::new_builder() - .version(hex::decode(clear_0x(&proof.version))?.into()) - .vin(hex::decode(clear_0x(&proof.vin))?.into()) - .vout(hex::decode(clear_0x(&proof.vout))?.into()) - .locktime(hex::decode(clear_0x(&proof.locktime))?.into()) - .tx_id(hex::decode(clear_0x(&proof.tx_id))?.into()) - .index(proof.index.into()) - .headers(hex::decode(clear_0x(&proof.headers))?.into()) - .intermediate_nodes(hex::decode(clear_0x(&proof.intermediate_nodes))?.into()) - .funding_output_index(proof.funding_output_index.into()) - .build()) - } +#[test] +fn test_wrong_lot_size() { + let mut case = generate_btc_corrent_case(); + case.tockb_cell_data.lot_size = 100; + case.expect_return_code = LotSizeInvalid as i8; + run_test_case(case); } -fn clear_0x(s: &str) -> &str { - if &s[..2] == "0x" || &s[..2] == "0X" { - &s[2..] - } else { - s - } +#[test] +fn test_wrong_x_lock_address() { + let mut case = generate_btc_corrent_case(); + case.tockb_cell_data.x_lock_address = "wrong_addr".to_owned(); + case.expect_return_code = WrongFundingAddr as i8; + run_test_case(case); } -fn json_to_btc_proof(proof: &str) -> Result { - let proof: BTCSPVProofJson = serde_json::from_str(proof)?; - proof.try_into() +#[test] +fn test_wrong_mint_xt_amount() { + let mut case = generate_btc_corrent_case(); + case.outputs[0].amount = 1; + case.expect_return_code = InvalidMintOutput as i8; + run_test_case(case); } -// #[test] -// fn test_wrong_pledge() { -// let toCKB_data = ToCKBCellData::new_builder() -// .status(Byte::new(1u8)) -// .lot_size(Byte::new(1u8)) -// .user_lockscript(Script::new_builder().build()) -// .build(); -// let (context, tx) = build_test_context(1, 9999, toCKB_data.as_bytes()); - -// let err = context.verify_tx(&tx, MAX_CYCLES).unwrap_err(); -// assert_error_eq!(err, ScriptError::ValidationFailure(PLEDGE_INVALID)); -// } - -// fn build_test_context(kind: u8, input: Bytes) -> (Context, TransactionView) { -// // deploy contract -// let mut context = Context::default(); -// let toCKB_typescript_bin: Bytes = Loader::default().load_binary("toCKB-typescript"); -// let toCKB_typescript_out_point = context.deploy_cell(toCKB_typescript_bin); -// let always_success_out_point = context.deploy_cell(ALWAYS_SUCCESS.clone()); - -// // prepare scripts -// let toCKB_typescript = context -// .build_script(&toCKB_typescript_out_point, [kind; 1].to_vec().into()) -// .expect("script"); -// let toCKB_typescript_dep = CellDep::new_builder() -// .out_point(toCKB_typescript_out_point) -// .build(); -// let always_success_lockscript = context -// .build_script(&always_success_out_point, Default::default()) -// .expect("script"); -// let always_success_lockscript_dep = CellDep::new_builder() -// .out_point(always_success_out_point) -// .build(); - -// // prepare cells -// let input_out_point = context.create_cell( -// CellOutput::new_builder() -// .capacity(11000u64.pack()) -// .lock(always_success_lockscript.clone()) -// .build(), -// Bytes::new(), -// ); -// let input = CellInput::new_builder() -// .previous_output(input_out_point) -// .build(); -// let outputs = vec![CellOutput::new_builder() -// .capacity(pledge.pack()) -// .type_(Some(toCKB_typescript.clone()).pack()) -// .lock(always_success_lockscript) -// .build()]; -// let outputs_data = vec![toCKB_data; 1]; +#[test] +fn test_wrong_cell_dep_index_list_len() { + let mut case = generate_btc_corrent_case(); + case.witness.cell_dep_index_list = vec![1, 2]; + case.expect_return_code = InvalidWitness as i8; + run_test_case(case); +} -// // build transaction -// let tx = TransactionBuilder::default() -// .input(input) -// .outputs(outputs) -// .outputs_data(outputs_data.pack()) -// .cell_dep(toCKB_typescript_dep) -// .cell_dep(always_success_lockscript_dep) -// .build(); -// let tx = context.complete_tx(tx); +#[test] +fn test_wrong_btc_spv() { + let mut case = generate_btc_corrent_case(); + case.witness.spv_proof = SpvProof::BTC(mint_xt_witness::BTCSPVProof::default()); + case.expect_return_code = -1; + run_test_case(case); +} -// (context, tx) -// } +#[test] +fn test_wrong_btc_difficulty() { + let mut case = generate_btc_corrent_case(); + case.cell_deps_data = CellDepsData::BTC(BtcDifficultyTest { + previous: 1, + current: 1, + }); + case.expect_return_code = NotAtCurrentOrPreviousDifficulty as i8; + run_test_case(case); +} diff --git a/tests/src/toCKB_typescript/tests/mint_xt/types.rs b/tests/src/toCKB_typescript/tests/mint_xt/types.rs new file mode 100644 index 0000000..35a4953 --- /dev/null +++ b/tests/src/toCKB_typescript/tests/mint_xt/types.rs @@ -0,0 +1,90 @@ +use crate::toCKB_typescript::utils::types::generated::mint_xt_witness; +use anyhow::Result; +use ckb_tool::ckb_types::{packed::*, prelude::*}; +use molecule::prelude::*; +use serde::{Deserialize, Serialize}; +use std::convert::{TryFrom, TryInto}; + +pub struct ToCKBCellDataTest { + pub lot_size: u8, + pub x_lock_address: String, + pub user_lockscript: Script, + pub signer_lockscript: Script, +} + +pub struct Output { + pub typescript: Script, + pub lockscript: Script, + pub amount: u128, +} + +pub enum SpvProof { + BTC(mint_xt_witness::BTCSPVProof), +} + +pub struct BtcDifficultyTest { + pub previous: u64, + pub current: u64, +} + +pub struct Witness { + pub cell_dep_index_list: Vec, + pub spv_proof: SpvProof, +} + +pub enum CellDepsData { + BTC(BtcDifficultyTest), +} + +pub struct TestCase { + pub kind: u8, + pub tockb_cell_data: ToCKBCellDataTest, + pub outputs: Vec, + pub witness: Witness, + pub cell_deps_data: CellDepsData, + pub expect_return_code: i8, +} + +#[derive(Serialize, Deserialize, Default)] +pub struct BTCSPVProofJson { + pub version: String, + pub vin: String, + pub vout: String, + pub locktime: String, + pub tx_id: String, + pub index: u64, + pub headers: String, + pub intermediate_nodes: String, + pub funding_output_index: u8, +} + +impl TryFrom for mint_xt_witness::BTCSPVProof { + type Error = anyhow::Error; + + fn try_from(proof: BTCSPVProofJson) -> Result { + Ok(mint_xt_witness::BTCSPVProof::new_builder() + .version(hex::decode(clear_0x(&proof.version))?.into()) + .vin(hex::decode(clear_0x(&proof.vin))?.into()) + .vout(hex::decode(clear_0x(&proof.vout))?.into()) + .locktime(hex::decode(clear_0x(&proof.locktime))?.into()) + .tx_id(hex::decode(clear_0x(&proof.tx_id))?.into()) + .index(proof.index.into()) + .headers(hex::decode(clear_0x(&proof.headers))?.into()) + .intermediate_nodes(hex::decode(clear_0x(&proof.intermediate_nodes))?.into()) + .funding_output_index(proof.funding_output_index.into()) + .build()) + } +} + +pub fn clear_0x(s: &str) -> &str { + if &s[..2] == "0x" || &s[..2] == "0X" { + &s[2..] + } else { + s + } +} + +pub fn json_to_btc_proof(proof: &str) -> Result { + let proof: BTCSPVProofJson = serde_json::from_str(proof)?; + proof.try_into() +} diff --git a/tests/src/toCKB_typescript/utils/types/mod.rs b/tests/src/toCKB_typescript/utils/types/mod.rs index e9425b8..05cb677 100644 --- a/tests/src/toCKB_typescript/utils/types/mod.rs +++ b/tests/src/toCKB_typescript/utils/types/mod.rs @@ -12,6 +12,21 @@ pub enum Error { TxInvalid, LotSizeInvalid, PledgeInvalid, + // MintXT Error + InvalidDataChange, + InvalidWitness, + DifficultyDataInvalid, + SpvProofInvalid, + InsufficientDifficulty, + BadMerkleProof, + NotAtCurrentOrPreviousDifficulty, + WrongTxId, + FundingNotEnough, + UnsupportedFundingType, + InvalidMintOutput, + WrongFundingAddr, + InvalidXTInInputOrOutput, + InvalidXTMint, } #[repr(u8)] From 4f6ded89c3dd73db6f78f9a29130f6a6c3fcd561 Mon Sep 17 00:00:00 2001 From: Wenchao Hu Date: Fri, 28 Aug 2020 16:05:26 +0800 Subject: [PATCH 20/45] Update contracts/toCKB-typescript/src/switch/mint_xt/mod.rs Co-authored-by: zhounan --- contracts/toCKB-typescript/src/switch/mint_xt/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs index 46317f9..a6ab826 100644 --- a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs +++ b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs @@ -207,7 +207,7 @@ fn verify_xt_issue(data: &ToCKBCellDataView) -> Result<(), Error> { } fn verify_btc_xt_issue(data: &ToCKBCellDataView) -> Result<(), Error> { - let lock_hash = load_cell_lock_hash(0, Source::Input)?; + let lock_hash = load_cell_lock_hash(0, Source::GroupInput)?; debug!("lockscript hash: {:?}", hex::encode(lock_hash)); let input_xt_num = QueryIter::new(load_cell_type, Source::Input) .filter(|type_opt| type_opt.is_some()) From 2626718e87213212b60a6c0080788abc688e0f73 Mon Sep 17 00:00:00 2001 From: Wenchao Hu Date: Fri, 28 Aug 2020 16:06:50 +0800 Subject: [PATCH 21/45] Update contracts/toCKB-typescript/src/switch/mint_xt/mod.rs Co-authored-by: zhounan --- contracts/toCKB-typescript/src/switch/mint_xt/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs index a6ab826..fe962d3 100644 --- a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs +++ b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs @@ -215,6 +215,7 @@ fn verify_btc_xt_issue(data: &ToCKBCellDataView) -> Result<(), Error> { .filter(|script| { script.code_hash().raw_data().as_ref() == SUDT_CODE_HASH.as_ref() && script.args().raw_data().as_ref() == lock_hash.as_ref() + && script.hash_type().into() == 0u8 }) .count(); if input_xt_num != 0 { From a36d3fe86d24657f48f2bc745cea60e0b2b8c51a Mon Sep 17 00:00:00 2001 From: huwenchao Date: Fri, 28 Aug 2020 16:08:36 +0800 Subject: [PATCH 22/45] chore: add comment --- contracts/toCKB-typescript/src/switch/mint_xt/mod.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs index fe962d3..3bdf6bf 100644 --- a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs +++ b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs @@ -235,6 +235,9 @@ fn verify_btc_xt_issue(data: &ToCKBCellDataView) -> Result<(), Error> { } let xt_amount = data.get_btc_lot_size()?.get_sudt_amount(); debug!("xt_amount: {}", xt_amount); + // fixed order of output cells is required + // user-sudt-cell should be outputs[1] + // signer-sudt-cell should be outputs[2] let expect = [ ( 1, From 72d30965b87825e6ddfde5a5d4b1e0f8777fe700 Mon Sep 17 00:00:00 2001 From: Wenchao Hu Date: Fri, 28 Aug 2020 16:08:55 +0800 Subject: [PATCH 23/45] Update contracts/toCKB-typescript/src/switch/mint_xt/mod.rs Co-authored-by: zhounan --- contracts/toCKB-typescript/src/switch/mint_xt/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs index fe962d3..2d1e85d 100644 --- a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs +++ b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs @@ -256,7 +256,8 @@ fn verify_btc_xt_issue(data: &ToCKBCellDataView) -> Result<(), Error> { } let script = script.unwrap(); if !(script.code_hash().raw_data().as_ref() == SUDT_CODE_HASH.as_ref() - && script.args().raw_data().as_ref() == lock_hash.as_ref()) + && script.args().raw_data().as_ref() == lock_hash.as_ref() + && script.hash_type().into() == 0u8) { return Err(Error::InvalidMintOutput); } From a65bb201ee45bed977044b36b31f58d06eca81dc Mon Sep 17 00:00:00 2001 From: Wenchao Hu Date: Fri, 28 Aug 2020 16:09:15 +0800 Subject: [PATCH 24/45] Update contracts/toCKB-typescript/src/utils/types/schemas/mint_xt_witness.mol Co-authored-by: zhounan --- .../src/utils/types/schemas/mint_xt_witness.mol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/toCKB-typescript/src/utils/types/schemas/mint_xt_witness.mol b/contracts/toCKB-typescript/src/utils/types/schemas/mint_xt_witness.mol index d807fd1..5ec0e94 100644 --- a/contracts/toCKB-typescript/src/utils/types/schemas/mint_xt_witness.mol +++ b/contracts/toCKB-typescript/src/utils/types/schemas/mint_xt_witness.mol @@ -15,4 +15,4 @@ table BTCSPVProof { headers: Bytes, intermediate_nodes: Bytes, funding_output_index: byte, -} \ No newline at end of file +} From 48e70ee855fad519ebf7663c48eb1cc2183407a5 Mon Sep 17 00:00:00 2001 From: huwenchao Date: Fri, 28 Aug 2020 17:11:56 +0800 Subject: [PATCH 25/45] fix: type infer bug --- contracts/toCKB-typescript/src/switch/mint_xt/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs index cc9ba57..35e7a92 100644 --- a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs +++ b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs @@ -215,7 +215,7 @@ fn verify_btc_xt_issue(data: &ToCKBCellDataView) -> Result<(), Error> { .filter(|script| { script.code_hash().raw_data().as_ref() == SUDT_CODE_HASH.as_ref() && script.args().raw_data().as_ref() == lock_hash.as_ref() - && script.hash_type().into() == 0u8 + && script.hash_type() == 0u8.into() }) .count(); if input_xt_num != 0 { @@ -260,7 +260,7 @@ fn verify_btc_xt_issue(data: &ToCKBCellDataView) -> Result<(), Error> { let script = script.unwrap(); if !(script.code_hash().raw_data().as_ref() == SUDT_CODE_HASH.as_ref() && script.args().raw_data().as_ref() == lock_hash.as_ref() - && script.hash_type().into() == 0u8) + && script.hash_type() == 0u8.into()) { return Err(Error::InvalidMintOutput); } From 2fb847d24db893f2afc041825475bd3d4b1d7031 Mon Sep 17 00:00:00 2001 From: huwenchao Date: Mon, 31 Aug 2020 19:11:39 +0800 Subject: [PATCH 26/45] chore: fix typo --- contracts/toCKB-typescript/src/switch/mint_xt/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs index 35e7a92..15bdcc7 100644 --- a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs +++ b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs @@ -252,7 +252,7 @@ fn verify_btc_xt_issue(data: &ToCKBCellDataView) -> Result<(), Error> { ]; debug!("expect: {:?}", expect); - for (i, lockscript, amout) in expect.iter() { + for (i, lockscript, amount) in expect.iter() { let script = load_cell_type(*i, Source::Output)?; if script.is_none() { return Err(Error::InvalidMintOutput); @@ -268,8 +268,8 @@ fn verify_btc_xt_issue(data: &ToCKBCellDataView) -> Result<(), Error> { let mut amount_vec = [0u8; 16]; amount_vec.copy_from_slice(&cell_data); let token_amount = u128::from_le_bytes(amount_vec); - debug!("token_amount: {}, amout: {}", token_amount, amout); - if token_amount != *amout { + debug!("token_amount: {}, amout: {}", token_amount, amount); + if token_amount != *amount { return Err(Error::InvalidMintOutput); } let lock = load_cell_lock(*i, Source::Output)?; From 993d06524dda4a840769de1377f0493968dca7db Mon Sep 17 00:00:00 2001 From: Wenchao Hu Date: Mon, 31 Aug 2020 23:07:37 +0800 Subject: [PATCH 27/45] Update contracts/toCKB-typescript/src/switch/mint_xt/mod.rs Co-authored-by: Ethan Hu --- contracts/toCKB-typescript/src/switch/mint_xt/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs index 35e7a92..ef5038e 100644 --- a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs +++ b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs @@ -227,6 +227,7 @@ fn verify_btc_xt_issue(data: &ToCKBCellDataView) -> Result<(), Error> { .filter(|script| { script.code_hash().raw_data().as_ref() == SUDT_CODE_HASH.as_ref() && script.args().raw_data().as_ref() == lock_hash.as_ref() + && script.hash_type() == 0u8.into() }) .count(); debug!("output_xt_num: {}", output_xt_num); From 96b81501a50ee528b236217f69d7dca5cde8f8a7 Mon Sep 17 00:00:00 2001 From: huwenchao Date: Mon, 31 Aug 2020 23:12:54 +0800 Subject: [PATCH 28/45] chore: move simple_udt --- .../{src/toCKB_typescript/tests => deps}/simple_udt | Bin tests/src/toCKB_typescript/tests/mint_xt/helper.rs | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) rename tests/{src/toCKB_typescript/tests => deps}/simple_udt (100%) diff --git a/tests/src/toCKB_typescript/tests/simple_udt b/tests/deps/simple_udt similarity index 100% rename from tests/src/toCKB_typescript/tests/simple_udt rename to tests/deps/simple_udt diff --git a/tests/src/toCKB_typescript/tests/mint_xt/helper.rs b/tests/src/toCKB_typescript/tests/mint_xt/helper.rs index 2af696b..60d4aff 100644 --- a/tests/src/toCKB_typescript/tests/mint_xt/helper.rs +++ b/tests/src/toCKB_typescript/tests/mint_xt/helper.rs @@ -19,7 +19,7 @@ pub fn run_test_case(case: TestCase) { // let toCKB_lockscript_bin: Bytes = Loader::default().load_binary("toCKB-lockscript"); // let toCKB_lockscript_out_point = context.deploy_cell(toCKB_lockscript_bin); let always_success_out_point = context.deploy_cell(ALWAYS_SUCCESS.clone()); - let sudt_bin = include_bytes!("../simple_udt"); + let sudt_bin = include_bytes!("../../../../deps/simple_udt"); let sudt_out_point = context.deploy_cell(Bytes::from(sudt_bin.as_ref())); // prepare scripts @@ -163,7 +163,7 @@ pub fn deploy(kind: u8) -> DeployResult { let toCKB_typescript_bin: Bytes = Loader::default().load_binary("toCKB-typescript"); let toCKB_typescript_out_point = context.deploy_cell(toCKB_typescript_bin); let always_success_out_point = context.deploy_cell(ALWAYS_SUCCESS.clone()); - let sudt_bin = include_bytes!("../simple_udt"); + let sudt_bin = include_bytes!("../../../../deps/simple_udt"); let sudt_out_point = context.deploy_cell(Bytes::from(sudt_bin.as_ref())); // prepare scripts From 25d340e9e33e3be38520d9a64a71d1e3bdc2653a Mon Sep 17 00:00:00 2001 From: huwenchao Date: Mon, 31 Aug 2020 23:37:39 +0800 Subject: [PATCH 29/45] fix: add capacity check --- .../src/switch/mint_xt/mod.rs | 23 +++++++++++++-- .../toCKB-typescript/src/utils/config.rs | 1 + .../toCKB_typescript/tests/mint_xt/helper.rs | 8 +++-- .../src/toCKB_typescript/tests/mint_xt/mod.rs | 29 ++++++++++++++++++- .../toCKB_typescript/tests/mint_xt/types.rs | 2 ++ 5 files changed, 56 insertions(+), 7 deletions(-) diff --git a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs index 6ff36e3..c9d3800 100644 --- a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs +++ b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs @@ -1,6 +1,8 @@ use crate::switch::ToCKBCellDataTuple; use crate::utils::{ - config::{SIGNER_FEE_RATE, SUDT_CODE_HASH, TX_PROOF_DIFFICULTY_FACTOR}, + config::{ + PLEDGE, SIGNER_FEE_RATE, SUDT_CODE_HASH, TX_PROOF_DIFFICULTY_FACTOR, XT_CELL_CAPACITY, + }, tools::{get_xchain_kind, XChainKind}, types::{ btc_difficulty::BTCDifficultyReader, @@ -19,8 +21,8 @@ use ckb_std::{ ckb_constants::Source, debug, high_level::{ - load_cell_data, load_cell_lock, load_cell_lock_hash, load_cell_type, load_witness_args, - QueryIter, + load_cell_capacity, load_cell_data, load_cell_lock, load_cell_lock_hash, load_cell_type, + load_witness_args, QueryIter, }, }; use core::result::Result; @@ -286,10 +288,25 @@ fn verify_btc_xt_issue(data: &ToCKBCellDataView) -> Result<(), Error> { Ok(()) } +pub fn verify_capacity() -> Result<(), Error> { + let _toCKB_output_cap = load_cell_capacity(0, Source::GroupOutput)?; + // TODO: check capacity of output-toCKB-cell is collateral + 1 * xt_cell_capacity + let user_xt_cell_cap = load_cell_capacity(1, Source::Output)?; + if user_xt_cell_cap != PLEDGE { + return Err(Error::CapacityInvalid); + } + let signer_xt_cell_cap = load_cell_capacity(2, Source::Output)?; + if signer_xt_cell_cap != XT_CELL_CAPACITY { + return Err(Error::CapacityInvalid); + } + Ok(()) +} + pub fn verify(toCKB_data_tuple: &ToCKBCellDataTuple) -> Result<(), Error> { debug!("start mint_xt"); let input_data = toCKB_data_tuple.0.as_ref().expect("should not happen"); let output_data = toCKB_data_tuple.1.as_ref().expect("should not happen"); + verify_capacity()?; verify_data(input_data, output_data)?; debug!("verify data finish"); verify_witness(input_data)?; diff --git a/contracts/toCKB-typescript/src/utils/config.rs b/contracts/toCKB-typescript/src/utils/config.rs index 7df0b4b..8f6e222 100644 --- a/contracts/toCKB-typescript/src/utils/config.rs +++ b/contracts/toCKB-typescript/src/utils/config.rs @@ -1,4 +1,5 @@ pub const PLEDGE: u64 = 10000; +pub const XT_CELL_CAPACITY: u64 = 100; pub const TX_PROOF_DIFFICULTY_FACTOR: u8 = 1; // default value is 2/1000 pub const SIGNER_FEE_RATE: (u128, u128) = (2, 1000); diff --git a/tests/src/toCKB_typescript/tests/mint_xt/helper.rs b/tests/src/toCKB_typescript/tests/mint_xt/helper.rs index 60d4aff..140af2c 100644 --- a/tests/src/toCKB_typescript/tests/mint_xt/helper.rs +++ b/tests/src/toCKB_typescript/tests/mint_xt/helper.rs @@ -8,7 +8,9 @@ use ckb_testtool::{builtin::ALWAYS_SUCCESS, context::Context}; use ckb_tool::ckb_types::{bytes::Bytes, core::TransactionBuilder, packed::*, prelude::*}; use molecule::prelude::*; -const MAX_CYCLES: u64 = 100_000_000; +pub const MAX_CYCLES: u64 = 100_000_000; +pub const PLEDGE: u64 = 10000; +pub const XT_CELL_CAPACITY: u64 = 100; pub fn run_test_case(case: TestCase) { let kind = case.kind; @@ -88,14 +90,14 @@ pub fn run_test_case(case: TestCase) { .build(); let inputs = vec![input_ckb_cell]; let mut outputs = vec![CellOutput::new_builder() - .capacity(11000u64.pack()) + .capacity(case.capacity.pack()) .type_(Some(toCKB_typescript.clone()).pack()) .lock(always_success_lockscript.clone()) .build()]; let mut outputs_data = vec![output_toCKB_data.as_bytes()]; for output in case.outputs.into_iter() { let cell_output = CellOutput::new_builder() - .capacity(11000u64.pack()) + .capacity(output.capacity.pack()) .type_(Some(output.typescript).pack()) .lock(output.lockscript) .build(); diff --git a/tests/src/toCKB_typescript/tests/mint_xt/mod.rs b/tests/src/toCKB_typescript/tests/mint_xt/mod.rs index 4ffde02..a7dd945 100644 --- a/tests/src/toCKB_typescript/tests/mint_xt/mod.rs +++ b/tests/src/toCKB_typescript/tests/mint_xt/mod.rs @@ -1,6 +1,6 @@ mod helper; mod types; -use helper::{deploy, run_test_case, DeployResult}; +use helper::{deploy, run_test_case, DeployResult, PLEDGE, XT_CELL_CAPACITY}; use types::*; use super::ToCKBCellData; @@ -20,6 +20,7 @@ fn generate_btc_corrent_case() -> TestCase { let signer_lockscript = always_success_lockscript.clone(); let case = TestCase { kind, + capacity: 10000, tockb_cell_data: ToCKBCellDataTest { lot_size: 1, x_lock_address: "bc1qq2pw0kr5yhz3xcs978desw5anfmtwynutwq8quz0t".to_owned(), @@ -31,11 +32,13 @@ fn generate_btc_corrent_case() -> TestCase { typescript: sudt_typescript.clone(), lockscript: always_success_lockscript.clone(), amount: 24950000, + capacity: PLEDGE, }, Output { typescript: sudt_typescript.clone(), lockscript: always_success_lockscript.clone(), amount: 50000, + capacity: XT_CELL_CAPACITY, }, ], witness: Witness { @@ -119,3 +122,27 @@ fn test_wrong_btc_difficulty() { case.expect_return_code = NotAtCurrentOrPreviousDifficulty as i8; run_test_case(case); } + +// #[test] +// fn test_wrong_toCKB_capacity() { +// let mut case = generate_btc_corrent_case(); +// case.capacity = 1; +// case.expect_return_code = CapacityInvalid as i8; +// run_test_case(case); +// } + +#[test] +fn test_wrong_pledge_refund() { + let mut case = generate_btc_corrent_case(); + case.outputs[0].capacity = 1; + case.expect_return_code = CapacityInvalid as i8; + run_test_case(case); +} + +#[test] +fn test_wrong_signer_xt_cell_capacity() { + let mut case = generate_btc_corrent_case(); + case.outputs[1].capacity = 1; + case.expect_return_code = CapacityInvalid as i8; + run_test_case(case); +} diff --git a/tests/src/toCKB_typescript/tests/mint_xt/types.rs b/tests/src/toCKB_typescript/tests/mint_xt/types.rs index 35a4953..53ebb84 100644 --- a/tests/src/toCKB_typescript/tests/mint_xt/types.rs +++ b/tests/src/toCKB_typescript/tests/mint_xt/types.rs @@ -16,6 +16,7 @@ pub struct Output { pub typescript: Script, pub lockscript: Script, pub amount: u128, + pub capacity: u64, } pub enum SpvProof { @@ -38,6 +39,7 @@ pub enum CellDepsData { pub struct TestCase { pub kind: u8, + pub capacity: u64, pub tockb_cell_data: ToCKBCellDataTest, pub outputs: Vec, pub witness: Witness, From a3b8194c2bd1e8f3b675586d3b00e28213204770 Mon Sep 17 00:00:00 2001 From: huwenchao Date: Mon, 31 Aug 2020 23:51:17 +0800 Subject: [PATCH 30/45] fix: check toCKB cell capacity --- .../toCKB-typescript/src/switch/mint_xt/mod.rs | 7 +++++-- .../toCKB_typescript/tests/mint_xt/helper.rs | 4 ++-- tests/src/toCKB_typescript/tests/mint_xt/mod.rs | 17 +++++++++-------- .../src/toCKB_typescript/tests/mint_xt/types.rs | 3 ++- 4 files changed, 18 insertions(+), 13 deletions(-) diff --git a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs index c9d3800..e6ea412 100644 --- a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs +++ b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs @@ -289,8 +289,11 @@ fn verify_btc_xt_issue(data: &ToCKBCellDataView) -> Result<(), Error> { } pub fn verify_capacity() -> Result<(), Error> { - let _toCKB_output_cap = load_cell_capacity(0, Source::GroupOutput)?; - // TODO: check capacity of output-toCKB-cell is collateral + 1 * xt_cell_capacity + let toCKB_output_cap = load_cell_capacity(0, Source::GroupOutput)?; + let toCKB_input_cap = load_cell_capacity(0, Source::GroupInput)?; + if toCKB_input_cap - toCKB_output_cap > XT_CELL_CAPACITY { + return Err(Error::CapacityInvalid); + } let user_xt_cell_cap = load_cell_capacity(1, Source::Output)?; if user_xt_cell_cap != PLEDGE { return Err(Error::CapacityInvalid); diff --git a/tests/src/toCKB_typescript/tests/mint_xt/helper.rs b/tests/src/toCKB_typescript/tests/mint_xt/helper.rs index 140af2c..0790eb5 100644 --- a/tests/src/toCKB_typescript/tests/mint_xt/helper.rs +++ b/tests/src/toCKB_typescript/tests/mint_xt/helper.rs @@ -79,7 +79,7 @@ pub fn run_test_case(case: TestCase) { let input_ckb_cell_out_point = context.create_cell( CellOutput::new_builder() - .capacity(11000u64.pack()) + .capacity(case.input_capacity.pack()) .lock(always_success_lockscript.clone()) .type_(Some(toCKB_typescript.clone()).pack()) .build(), @@ -90,7 +90,7 @@ pub fn run_test_case(case: TestCase) { .build(); let inputs = vec![input_ckb_cell]; let mut outputs = vec![CellOutput::new_builder() - .capacity(case.capacity.pack()) + .capacity(case.output_capacity.pack()) .type_(Some(toCKB_typescript.clone()).pack()) .lock(always_success_lockscript.clone()) .build()]; diff --git a/tests/src/toCKB_typescript/tests/mint_xt/mod.rs b/tests/src/toCKB_typescript/tests/mint_xt/mod.rs index a7dd945..d5c6c1f 100644 --- a/tests/src/toCKB_typescript/tests/mint_xt/mod.rs +++ b/tests/src/toCKB_typescript/tests/mint_xt/mod.rs @@ -20,7 +20,8 @@ fn generate_btc_corrent_case() -> TestCase { let signer_lockscript = always_success_lockscript.clone(); let case = TestCase { kind, - capacity: 10000, + input_capacity: 100000, + output_capacity: 100000 - XT_CELL_CAPACITY, tockb_cell_data: ToCKBCellDataTest { lot_size: 1, x_lock_address: "bc1qq2pw0kr5yhz3xcs978desw5anfmtwynutwq8quz0t".to_owned(), @@ -123,13 +124,13 @@ fn test_wrong_btc_difficulty() { run_test_case(case); } -// #[test] -// fn test_wrong_toCKB_capacity() { -// let mut case = generate_btc_corrent_case(); -// case.capacity = 1; -// case.expect_return_code = CapacityInvalid as i8; -// run_test_case(case); -// } +#[test] +fn test_wrong_toCKB_capacity() { + let mut case = generate_btc_corrent_case(); + case.output_capacity = 10000; + case.expect_return_code = CapacityInvalid as i8; + run_test_case(case); +} #[test] fn test_wrong_pledge_refund() { diff --git a/tests/src/toCKB_typescript/tests/mint_xt/types.rs b/tests/src/toCKB_typescript/tests/mint_xt/types.rs index 53ebb84..0678ec6 100644 --- a/tests/src/toCKB_typescript/tests/mint_xt/types.rs +++ b/tests/src/toCKB_typescript/tests/mint_xt/types.rs @@ -39,7 +39,8 @@ pub enum CellDepsData { pub struct TestCase { pub kind: u8, - pub capacity: u64, + pub input_capacity: u64, + pub output_capacity: u64, pub tockb_cell_data: ToCKBCellDataTest, pub outputs: Vec, pub witness: Witness, From 0f0545795ce7662843a751b6decc36a22b9f47a8 Mon Sep 17 00:00:00 2001 From: Wenchao Hu Date: Tue, 1 Sep 2020 16:27:24 +0800 Subject: [PATCH 31/45] Update contracts/toCKB-typescript/src/switch/mint_xt/mod.rs Co-authored-by: zhounan --- contracts/toCKB-typescript/src/switch/mint_xt/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs index e6ea412..f0f6279 100644 --- a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs +++ b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs @@ -291,7 +291,7 @@ fn verify_btc_xt_issue(data: &ToCKBCellDataView) -> Result<(), Error> { pub fn verify_capacity() -> Result<(), Error> { let toCKB_output_cap = load_cell_capacity(0, Source::GroupOutput)?; let toCKB_input_cap = load_cell_capacity(0, Source::GroupInput)?; - if toCKB_input_cap - toCKB_output_cap > XT_CELL_CAPACITY { + if toCKB_input_cap - toCKB_output_cap != PLEDGE + XT_CELL_CAPACITY { return Err(Error::CapacityInvalid); } let user_xt_cell_cap = load_cell_capacity(1, Source::Output)?; From 81dfe58ee084a0f52f0e5c960d1daac2b2ca2402 Mon Sep 17 00:00:00 2001 From: Wenchao Hu Date: Tue, 1 Sep 2020 16:27:53 +0800 Subject: [PATCH 32/45] Update contracts/toCKB-typescript/src/utils/config.rs Co-authored-by: zhounan --- contracts/toCKB-typescript/src/utils/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/toCKB-typescript/src/utils/config.rs b/contracts/toCKB-typescript/src/utils/config.rs index 8f6e222..b6afabd 100644 --- a/contracts/toCKB-typescript/src/utils/config.rs +++ b/contracts/toCKB-typescript/src/utils/config.rs @@ -1,5 +1,5 @@ pub const PLEDGE: u64 = 10000; -pub const XT_CELL_CAPACITY: u64 = 100; +pub const XT_CELL_CAPACITY: u64 = 200; pub const TX_PROOF_DIFFICULTY_FACTOR: u8 = 1; // default value is 2/1000 pub const SIGNER_FEE_RATE: (u128, u128) = (2, 1000); From c69d9b111ddd66a325dc8111533aa4d1859d19ef Mon Sep 17 00:00:00 2001 From: huwenchao Date: Tue, 1 Sep 2020 17:21:12 +0800 Subject: [PATCH 33/45] fix tests --- tests/src/toCKB_typescript/tests/mint_xt/helper.rs | 2 +- tests/src/toCKB_typescript/tests/mint_xt/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/src/toCKB_typescript/tests/mint_xt/helper.rs b/tests/src/toCKB_typescript/tests/mint_xt/helper.rs index 0790eb5..ef9a8a4 100644 --- a/tests/src/toCKB_typescript/tests/mint_xt/helper.rs +++ b/tests/src/toCKB_typescript/tests/mint_xt/helper.rs @@ -10,7 +10,7 @@ use molecule::prelude::*; pub const MAX_CYCLES: u64 = 100_000_000; pub const PLEDGE: u64 = 10000; -pub const XT_CELL_CAPACITY: u64 = 100; +pub const XT_CELL_CAPACITY: u64 = 200; pub fn run_test_case(case: TestCase) { let kind = case.kind; diff --git a/tests/src/toCKB_typescript/tests/mint_xt/mod.rs b/tests/src/toCKB_typescript/tests/mint_xt/mod.rs index d5c6c1f..6857ca5 100644 --- a/tests/src/toCKB_typescript/tests/mint_xt/mod.rs +++ b/tests/src/toCKB_typescript/tests/mint_xt/mod.rs @@ -21,7 +21,7 @@ fn generate_btc_corrent_case() -> TestCase { let case = TestCase { kind, input_capacity: 100000, - output_capacity: 100000 - XT_CELL_CAPACITY, + output_capacity: 100000 - PLEDGE - XT_CELL_CAPACITY, tockb_cell_data: ToCKBCellDataTest { lot_size: 1, x_lock_address: "bc1qq2pw0kr5yhz3xcs978desw5anfmtwynutwq8quz0t".to_owned(), From 62fb93d5925028470d6cfb0a838798d38524517e Mon Sep 17 00:00:00 2001 From: LeonLi000 Date: Wed, 2 Sep 2020 17:15:13 +0800 Subject: [PATCH 34/45] feat(MintXT): support eth --- contracts/toCKB-typescript/Cargo.lock | 174 +- contracts/toCKB-typescript/Cargo.toml | 2 + .../src/switch/mint_xt/mod.rs | 70 +- .../src/utils/types/generated/basic.rs | 339 +++- .../utils/types/generated/btc_difficulty.rs | 275 +-- .../utils/types/generated/mint_xt_witness.rs | 395 +++- .../utils/types/generated/toCKB_cell_data.rs | 454 +---- .../src/utils/types/schemas/basic.mol | 1 + .../utils/types/schemas/mint_xt_witness.mol | 10 + .../utils/types/generated/basic.rs | 1793 +---------------- .../utils/types/generated/btc_difficulty.rs | 275 +-- .../utils/types/generated/mint_xt_witness.rs | 755 +------ .../utils/types/generated/toCKB_cell_data.rs | 454 +---- 13 files changed, 1039 insertions(+), 3958 deletions(-) diff --git a/contracts/toCKB-typescript/Cargo.lock b/contracts/toCKB-typescript/Cargo.lock index f3795b7..4e82f7e 100644 --- a/contracts/toCKB-typescript/Cargo.lock +++ b/contracts/toCKB-typescript/Cargo.lock @@ -21,10 +21,20 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" dependencies = [ - "block-padding", + "block-padding 0.1.5", "byte-tools", "byteorder", - "generic-array", + "generic-array 0.12.3", +] + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "block-padding 0.2.1", + "generic-array 0.14.4", ] [[package]] @@ -36,6 +46,12 @@ dependencies = [ "byte-tools", ] +[[package]] +name = "block-padding" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" + [[package]] name = "buddy-alloc" version = "0.3.0" @@ -102,13 +118,70 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +[[package]] +name = "derive_more" +version = "0.99.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "298998b1cf6b5b2c8a7b023dfd45821825ce3ba8a8af55c921a0e734e4653f76" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "digest" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" dependencies = [ - "generic-array", + "generic-array 0.12.3", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array 0.14.4", +] + +[[package]] +name = "eth-spv-lib" +version = "0.1.0" +source = "git+https://github.com/LeonLi000/eth-spv-lib.git#1045c0a3fe7624f8e6b440f308484b9b04e74c3b" +dependencies = [ + "derive_more", + "ethereum-types", + "rlp", + "rlp-derive", + "sha3", +] + +[[package]] +name = "ethbloom" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71a6567e6fd35589fea0c63b94b4cf2e55573e413901bdbe60ab15cf0e25e5df" +dependencies = [ + "crunchy", + "fixed-hash", + "impl-rlp", + "tiny-keccak", +] + +[[package]] +name = "ethereum-types" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "473aecff686bd8e7b9db0165cbbb53562376b39bf35b427f0c60446a9e1634b0" +dependencies = [ + "ethbloom", + "fixed-hash", + "impl-rlp", + "primitive-types", + "uint", ] [[package]] @@ -123,6 +196,8 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11498d382790b7a8f2fd211780bec78619bba81cdad3a283997c0c41f836759c" dependencies = [ + "byteorder", + "rustc-hex", "static_assertions", ] @@ -135,12 +210,31 @@ dependencies = [ "typenum", ] +[[package]] +name = "generic-array" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "hex" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "644f9158b2f133fd50f5fb3242878846d9eb792e445c893805ff0e3824006e35" +[[package]] +name = "impl-rlp" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f7a72f11830b52333f36e3b09a288333888bf54380fd0ac0790a3c31ab0f3c5" +dependencies = [ + "rlp", +] + [[package]] name = "int-enum" version = "0.4.0" @@ -164,6 +258,12 @@ dependencies = [ "syn", ] +[[package]] +name = "keccak" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" + [[package]] name = "molecule" version = "0.6.0" @@ -179,6 +279,12 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + [[package]] name = "primitive-types" version = "0.7.2" @@ -186,6 +292,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c55c21c64d0eaa4d7ed885d959ef2d62d9e488c27c0e02d9aa5ce6c877b7d5f8" dependencies = [ "fixed-hash", + "impl-rlp", "uint", ] @@ -222,9 +329,29 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad5112e0dbbb87577bfbc56c42450235e3012ce336e29c5befd7807bd626da4a" dependencies = [ - "block-buffer", - "digest", - "opaque-debug", + "block-buffer 0.7.3", + "digest 0.8.1", + "opaque-debug 0.2.3", +] + +[[package]] +name = "rlp" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a7d3f9bed94764eac15b8f14af59fac420c236adaff743b7bcc88e265cb4345" +dependencies = [ + "rustc-hex", +] + +[[package]] +name = "rlp-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -245,10 +372,22 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" dependencies = [ - "block-buffer", - "digest", + "block-buffer 0.7.3", + "digest 0.8.1", "fake-simd", - "opaque-debug", + "opaque-debug 0.2.3", +] + +[[package]] +name = "sha3" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" +dependencies = [ + "block-buffer 0.9.0", + "digest 0.9.0", + "keccak", + "opaque-debug 0.3.0", ] [[package]] @@ -268,6 +407,15 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + [[package]] name = "toCKB-typescript" version = "0.1.0" @@ -275,10 +423,12 @@ dependencies = [ "bech32", "bitcoin-spv", "ckb-std", + "eth-spv-lib", "hex", "int-enum", "molecule", "primitive-types", + "rlp", ] [[package]] @@ -313,3 +463,9 @@ name = "unicode-xid" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" + +[[package]] +name = "version_check" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" diff --git a/contracts/toCKB-typescript/Cargo.toml b/contracts/toCKB-typescript/Cargo.toml index f149848..0ba0b9a 100644 --- a/contracts/toCKB-typescript/Cargo.toml +++ b/contracts/toCKB-typescript/Cargo.toml @@ -13,6 +13,8 @@ bitcoin-spv = { git = "https://github.com/summa-tx/bitcoin-spv.git", branch = "r bech32 = { git = "https://github.com/reuvenpo/rust-bech32.git", branch = "support-no_std", default-features = false } primitive-types = { version = "0.7.2", default-features = false } hex = { version = "0.4", default-features = false } +eth-spv-lib = { git = "https://github.com/LeonLi000/eth-spv-lib.git" } +rlp = {version = "0.4.5", default-features = false } [profile.release] overflow-checks = true diff --git a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs index e6ea412..c397115 100644 --- a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs +++ b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs @@ -6,11 +6,12 @@ use crate::utils::{ tools::{get_xchain_kind, XChainKind}, types::{ btc_difficulty::BTCDifficultyReader, - mint_xt_witness::{BTCSPVProofReader, MintXTWitnessReader}, + mint_xt_witness::{BTCSPVProofReader, ETHSPVProofReader, MintXTWitnessReader}, Error, ToCKBCellDataView, }, }; use alloc::string::String; +use alloc::vec; use bech32::ToBase32; use bitcoin_spv::{ btcspv, @@ -26,8 +27,10 @@ use ckb_std::{ }, }; use core::result::Result; +use eth_spv_lib::{eth_types::*, ethspv}; use molecule::prelude::{Entity, Reader}; use primitive_types::U256; +use rlp; fn verify_data( input_data: &ToCKBCellDataView, @@ -61,8 +64,71 @@ fn verify_witness(data: &ToCKBCellDataView) -> Result<(), Error> { let cell_dep_index_list = witness.cell_dep_index_list().raw_data(); match get_xchain_kind()? { XChainKind::Btc => verify_btc_witness(data, proof, cell_dep_index_list), - XChainKind::Eth => todo!(), + XChainKind::Eth => verify_eth_witness(data, proof, cell_dep_index_list), + } +} + +fn verify_eth_witness( + data: &ToCKBCellDataView, + proof: &[u8], + cell_dep_index_list: &[u8], +) -> Result<(), Error> { + debug!( + "proof: {:?}, cell_dep_index_list: {:?}", + proof, cell_dep_index_list + ); + if ETHSPVProofReader::verify(proof, false).is_err() { + return Err(Error::InvalidWitness); + } + let proof_reader = ETHSPVProofReader::new_unchecked(proof); + debug!("proof_reader: {:?}", proof_reader); + //TODO: verify header with client + // hash = calc(header_data) + // hash.compare(client.getHashByNumber(header.number)) + // verify eth spv + let mut log_index = [0u8; 8]; + log_index.copy_from_slice(proof_reader.log_index().raw_data()); + debug!("log_index is {:?}", &log_index); + let log_entry_data = proof_reader.log_entry_data().raw_data().to_vec(); + debug!("log_entry_data is {:?}", &log_entry_data); + let mut receipt_index = [0u8; 8]; + receipt_index.copy_from_slice(proof_reader.receipt_index().raw_data()); + debug!("receipt_index is {:?}", &receipt_index); + let mut receipts_root = [0u8; 32]; + receipts_root.copy_from_slice(proof_reader.receipts_root().raw_data()); + debug!("receipts_root is {:?}", &receipts_root); + let mut proof = vec![]; + for i in 0..proof_reader.proof().len() { + proof.push(proof_reader.proof().get_unchecked(i).raw_data().to_vec()); + } + debug!("proof is {:?}", &proof); + //FIXME: check x_lock_address + let log_entry: LogEntry = rlp::decode(log_entry_data.as_slice()).unwrap(); + let locker_address = (log_entry.address.clone().0).0; + debug!( + "hex format: addr: {}, x_lock_address: {}", + hex::encode(locker_address.to_vec()), + hex::encode(data.x_lock_address.as_ref().to_vec()) + ); + debug!( + "addr: {}, x_lock_address: {}", + String::from_utf8(locker_address.to_vec()).unwrap(), + String::from_utf8(data.x_lock_address.as_ref().to_vec()).unwrap() + ); + if locker_address != data.x_lock_address.as_ref() { + return Err(Error::WrongFundingAddr); + } + if !ethspv::verify_log_entry( + u64::from_le_bytes(log_index), + log_entry_data, + u64::from_le_bytes(receipt_index), + proof_reader.receipt_data().raw_data().to_vec(), + H256(receipts_root.into()), + proof, + ) { + return Err(Error::BadMerkleProof); } + Ok(()) } fn verify_btc_witness( diff --git a/contracts/toCKB-typescript/src/utils/types/generated/basic.rs b/contracts/toCKB-typescript/src/utils/types/generated/basic.rs index 7ad3205..498ec72 100644 --- a/contracts/toCKB-typescript/src/utils/types/generated/basic.rs +++ b/contracts/toCKB-typescript/src/utils/types/generated/basic.rs @@ -1,4 +1,4 @@ -// Generated by Molecule 0.6.0 +// Generated by Molecule 0.6.1 use molecule::prelude::*; #[derive(Clone)] @@ -1476,6 +1476,343 @@ impl molecule::prelude::Builder for Uint64Builder { } } #[derive(Clone)] +pub struct Bytes2(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for Bytes2 { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for Bytes2 { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for Bytes2 { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} [", Self::NAME)?; + for i in 0..self.len() { + if i == 0 { + write!(f, "{}", self.get_unchecked(i))?; + } else { + write!(f, ", {}", self.get_unchecked(i))?; + } + } + write!(f, "]") + } +} +impl ::core::default::Default for Bytes2 { + fn default() -> Self { + let v: Vec = vec![4, 0, 0, 0]; + Bytes2::new_unchecked(v.into()) + } +} +impl Bytes2 { + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn item_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn len(&self) -> usize { + self.item_count() + } + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + pub fn get(&self, idx: usize) -> Option { + if idx >= self.len() { + None + } else { + Some(self.get_unchecked(idx)) + } + } + pub fn get_unchecked(&self, idx: usize) -> Bytes { + let slice = self.as_slice(); + let start_idx = molecule::NUMBER_SIZE * (1 + idx); + let start = molecule::unpack_number(&slice[start_idx..]) as usize; + if idx == self.len() - 1 { + Bytes::new_unchecked(self.0.slice(start..)) + } else { + let end_idx = start_idx + molecule::NUMBER_SIZE; + let end = molecule::unpack_number(&slice[end_idx..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } + } + pub fn as_reader<'r>(&'r self) -> Bytes2Reader<'r> { + Bytes2Reader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for Bytes2 { + type Builder = Bytes2Builder; + const NAME: &'static str = "Bytes2"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + Bytes2(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + Bytes2Reader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + Bytes2Reader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder().extend(self.into_iter()) + } +} +#[derive(Clone, Copy)] +pub struct Bytes2Reader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for Bytes2Reader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for Bytes2Reader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for Bytes2Reader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} [", Self::NAME)?; + for i in 0..self.len() { + if i == 0 { + write!(f, "{}", self.get_unchecked(i))?; + } else { + write!(f, ", {}", self.get_unchecked(i))?; + } + } + write!(f, "]") + } +} +impl<'r> Bytes2Reader<'r> { + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn item_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn len(&self) -> usize { + self.item_count() + } + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + pub fn get(&self, idx: usize) -> Option> { + if idx >= self.len() { + None + } else { + Some(self.get_unchecked(idx)) + } + } + pub fn get_unchecked(&self, idx: usize) -> BytesReader<'r> { + let slice = self.as_slice(); + let start_idx = molecule::NUMBER_SIZE * (1 + idx); + let start = molecule::unpack_number(&slice[start_idx..]) as usize; + if idx == self.len() - 1 { + BytesReader::new_unchecked(&self.as_slice()[start..]) + } else { + let end_idx = start_idx + molecule::NUMBER_SIZE; + let end = molecule::unpack_number(&slice[end_idx..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for Bytes2Reader<'r> { + type Entity = Bytes2; + const NAME: &'static str = "Bytes2Reader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + Bytes2Reader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let total_size = molecule::unpack_number(slice) as usize; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + if slice_len == molecule::NUMBER_SIZE { + return Ok(()); + } + if slice_len < molecule::NUMBER_SIZE * 2 { + return ve!( + Self, + TotalSizeNotMatch, + molecule::NUMBER_SIZE * 2, + slice_len + ); + } + let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; + if offset_first % 4 != 0 || offset_first < molecule::NUMBER_SIZE * 2 { + return ve!(Self, OffsetsNotMatch); + } + let item_count = offset_first / 4 - 1; + let header_size = molecule::NUMBER_SIZE * (item_count + 1); + if slice_len < header_size { + return ve!(Self, HeaderIsBroken, header_size, slice_len); + } + let mut offsets: Vec = slice[molecule::NUMBER_SIZE..] + .chunks(molecule::NUMBER_SIZE) + .take(item_count) + .map(|x| molecule::unpack_number(x) as usize) + .collect(); + offsets.push(total_size); + if offsets.windows(2).any(|i| i[0] > i[1]) { + return ve!(Self, OffsetsNotMatch); + } + for pair in offsets.windows(2) { + let start = pair[0]; + let end = pair[1]; + BytesReader::verify(&slice[start..end], compatible)?; + } + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct Bytes2Builder(pub(crate) Vec); +impl Bytes2Builder { + pub fn set(mut self, v: Vec) -> Self { + self.0 = v; + self + } + pub fn push(mut self, v: Bytes) -> Self { + self.0.push(v); + self + } + pub fn extend>(mut self, iter: T) -> Self { + for elem in iter { + self.0.push(elem); + } + self + } +} +impl molecule::prelude::Builder for Bytes2Builder { + type Entity = Bytes2; + const NAME: &'static str = "Bytes2Builder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE * (self.0.len() + 1) + + self + .0 + .iter() + .map(|inner| inner.as_slice().len()) + .sum::() + } + fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { + let item_count = self.0.len(); + if item_count == 0 { + writer.write_all(&molecule::pack_number( + molecule::NUMBER_SIZE as molecule::Number, + ))?; + } else { + let (total_size, offsets) = self.0.iter().fold( + ( + molecule::NUMBER_SIZE * (item_count + 1), + Vec::with_capacity(item_count), + ), + |(start, mut offsets), inner| { + offsets.push(start); + (start + inner.as_slice().len(), offsets) + }, + ); + writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; + for offset in offsets.into_iter() { + writer.write_all(&molecule::pack_number(offset as molecule::Number))?; + } + for inner in self.0.iter() { + writer.write_all(inner.as_slice())?; + } + } + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + Bytes2::new_unchecked(inner.into()) + } +} +pub struct Bytes2Iterator(Bytes2, usize, usize); +impl ::core::iter::Iterator for Bytes2Iterator { + type Item = Bytes; + fn next(&mut self) -> Option { + if self.1 >= self.2 { + None + } else { + let ret = self.0.get_unchecked(self.1); + self.1 += 1; + Some(ret) + } + } +} +impl ::core::iter::ExactSizeIterator for Bytes2Iterator { + fn len(&self) -> usize { + self.2 - self.1 + } +} +impl ::core::iter::IntoIterator for Bytes2 { + type Item = Bytes; + type IntoIter = Bytes2Iterator; + fn into_iter(self) -> Self::IntoIter { + let len = self.len(); + Bytes2Iterator(self, 0, len) + } +} +impl<'r> Bytes2Reader<'r> { + pub fn iter<'t>(&'t self) -> Bytes2ReaderIterator<'t, 'r> { + Bytes2ReaderIterator(&self, 0, self.len()) + } +} +pub struct Bytes2ReaderIterator<'t, 'r>(&'t Bytes2Reader<'r>, usize, usize); +impl<'t: 'r, 'r> ::core::iter::Iterator for Bytes2ReaderIterator<'t, 'r> { + type Item = BytesReader<'t>; + fn next(&mut self) -> Option { + if self.1 >= self.2 { + None + } else { + let ret = self.0.get_unchecked(self.1); + self.1 += 1; + Some(ret) + } + } +} +impl<'t: 'r, 'r> ::core::iter::ExactSizeIterator for Bytes2ReaderIterator<'t, 'r> { + fn len(&self) -> usize { + self.2 - self.1 + } +} +#[derive(Clone)] pub struct Script(molecule::bytes::Bytes); impl ::core::fmt::LowerHex for Script { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { diff --git a/contracts/toCKB-typescript/src/utils/types/generated/btc_difficulty.rs b/contracts/toCKB-typescript/src/utils/types/generated/btc_difficulty.rs index 3976e02..8ddda9d 100644 --- a/contracts/toCKB-typescript/src/utils/types/generated/btc_difficulty.rs +++ b/contracts/toCKB-typescript/src/utils/types/generated/btc_difficulty.rs @@ -1,270 +1,7 @@ -// Generated by Molecule 0.6.0 +// Generated by Molecule 0.6.1 -use super::basic::*; -use molecule::prelude::*; -#[derive(Clone)] -pub struct BTCDifficulty(molecule::bytes::Bytes); -impl ::core::fmt::LowerHex for BTCDifficulty { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl ::core::fmt::Debug for BTCDifficulty { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl ::core::fmt::Display for BTCDifficulty { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{} {{ ", Self::NAME)?; - write!(f, "{}: {}", "current", self.current())?; - write!(f, ", {}: {}", "previous", self.previous())?; - let extra_count = self.count_extra_fields(); - if extra_count != 0 { - write!(f, ", .. ({} fields)", extra_count)?; - } - write!(f, " }}") - } -} -impl ::core::default::Default for BTCDifficulty { - fn default() -> Self { - let v: Vec = vec![ - 20, 0, 0, 0, 12, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ]; - BTCDifficulty::new_unchecked(v.into()) - } -} -impl BTCDifficulty { - pub const FIELD_COUNT: usize = 2; - pub fn total_size(&self) -> usize { - molecule::unpack_number(self.as_slice()) as usize - } - pub fn field_count(&self) -> usize { - if self.total_size() == molecule::NUMBER_SIZE { - 0 - } else { - (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 - } - } - pub fn count_extra_fields(&self) -> usize { - self.field_count() - Self::FIELD_COUNT - } - pub fn has_extra_fields(&self) -> bool { - Self::FIELD_COUNT != self.field_count() - } - pub fn current(&self) -> Bytes { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[4..]) as usize; - let end = molecule::unpack_number(&slice[8..]) as usize; - Bytes::new_unchecked(self.0.slice(start..end)) - } - pub fn previous(&self) -> Bytes { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[8..]) as usize; - if self.has_extra_fields() { - let end = molecule::unpack_number(&slice[12..]) as usize; - Bytes::new_unchecked(self.0.slice(start..end)) - } else { - Bytes::new_unchecked(self.0.slice(start..)) - } - } - pub fn as_reader<'r>(&'r self) -> BTCDifficultyReader<'r> { - BTCDifficultyReader::new_unchecked(self.as_slice()) - } -} -impl molecule::prelude::Entity for BTCDifficulty { - type Builder = BTCDifficultyBuilder; - const NAME: &'static str = "BTCDifficulty"; - fn new_unchecked(data: molecule::bytes::Bytes) -> Self { - BTCDifficulty(data) - } - fn as_bytes(&self) -> molecule::bytes::Bytes { - self.0.clone() - } - fn as_slice(&self) -> &[u8] { - &self.0[..] - } - fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { - BTCDifficultyReader::from_slice(slice).map(|reader| reader.to_entity()) - } - fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { - BTCDifficultyReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) - } - fn new_builder() -> Self::Builder { - ::core::default::Default::default() - } - fn as_builder(self) -> Self::Builder { - Self::new_builder() - .current(self.current()) - .previous(self.previous()) - } -} -#[derive(Clone, Copy)] -pub struct BTCDifficultyReader<'r>(&'r [u8]); -impl<'r> ::core::fmt::LowerHex for BTCDifficultyReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl<'r> ::core::fmt::Debug for BTCDifficultyReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl<'r> ::core::fmt::Display for BTCDifficultyReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{} {{ ", Self::NAME)?; - write!(f, "{}: {}", "current", self.current())?; - write!(f, ", {}: {}", "previous", self.previous())?; - let extra_count = self.count_extra_fields(); - if extra_count != 0 { - write!(f, ", .. ({} fields)", extra_count)?; - } - write!(f, " }}") - } -} -impl<'r> BTCDifficultyReader<'r> { - pub const FIELD_COUNT: usize = 2; - pub fn total_size(&self) -> usize { - molecule::unpack_number(self.as_slice()) as usize - } - pub fn field_count(&self) -> usize { - if self.total_size() == molecule::NUMBER_SIZE { - 0 - } else { - (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 - } - } - pub fn count_extra_fields(&self) -> usize { - self.field_count() - Self::FIELD_COUNT - } - pub fn has_extra_fields(&self) -> bool { - Self::FIELD_COUNT != self.field_count() - } - pub fn current(&self) -> BytesReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[4..]) as usize; - let end = molecule::unpack_number(&slice[8..]) as usize; - BytesReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn previous(&self) -> BytesReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[8..]) as usize; - if self.has_extra_fields() { - let end = molecule::unpack_number(&slice[12..]) as usize; - BytesReader::new_unchecked(&self.as_slice()[start..end]) - } else { - BytesReader::new_unchecked(&self.as_slice()[start..]) - } - } -} -impl<'r> molecule::prelude::Reader<'r> for BTCDifficultyReader<'r> { - type Entity = BTCDifficulty; - const NAME: &'static str = "BTCDifficultyReader"; - fn to_entity(&self) -> Self::Entity { - Self::Entity::new_unchecked(self.as_slice().to_owned().into()) - } - fn new_unchecked(slice: &'r [u8]) -> Self { - BTCDifficultyReader(slice) - } - fn as_slice(&self) -> &'r [u8] { - self.0 - } - fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { - use molecule::verification_error as ve; - let slice_len = slice.len(); - if slice_len < molecule::NUMBER_SIZE { - return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); - } - let total_size = molecule::unpack_number(slice) as usize; - if slice_len != total_size { - return ve!(Self, TotalSizeNotMatch, total_size, slice_len); - } - if slice_len == molecule::NUMBER_SIZE && Self::FIELD_COUNT == 0 { - return Ok(()); - } - if slice_len < molecule::NUMBER_SIZE * 2 { - return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); - } - let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; - if offset_first % 4 != 0 || offset_first < molecule::NUMBER_SIZE * 2 { - return ve!(Self, OffsetsNotMatch); - } - let field_count = offset_first / 4 - 1; - if field_count < Self::FIELD_COUNT { - return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); - } else if !compatible && field_count > Self::FIELD_COUNT { - return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); - }; - let header_size = molecule::NUMBER_SIZE * (field_count + 1); - if slice_len < header_size { - return ve!(Self, HeaderIsBroken, header_size, slice_len); - } - let mut offsets: Vec = slice[molecule::NUMBER_SIZE..] - .chunks(molecule::NUMBER_SIZE) - .take(field_count) - .map(|x| molecule::unpack_number(x) as usize) - .collect(); - offsets.push(total_size); - if offsets.windows(2).any(|i| i[0] > i[1]) { - return ve!(Self, OffsetsNotMatch); - } - BytesReader::verify(&slice[offsets[0]..offsets[1]], compatible)?; - BytesReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; - Ok(()) - } -} -#[derive(Debug, Default)] -pub struct BTCDifficultyBuilder { - pub(crate) current: Bytes, - pub(crate) previous: Bytes, -} -impl BTCDifficultyBuilder { - pub const FIELD_COUNT: usize = 2; - pub fn current(mut self, v: Bytes) -> Self { - self.current = v; - self - } - pub fn previous(mut self, v: Bytes) -> Self { - self.previous = v; - self - } -} -impl molecule::prelude::Builder for BTCDifficultyBuilder { - type Entity = BTCDifficulty; - const NAME: &'static str = "BTCDifficultyBuilder"; - fn expected_length(&self) -> usize { - molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) - + self.current.as_slice().len() - + self.previous.as_slice().len() - } - fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { - let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); - let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); - offsets.push(total_size); - total_size += self.current.as_slice().len(); - offsets.push(total_size); - total_size += self.previous.as_slice().len(); - writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; - for offset in offsets.into_iter() { - writer.write_all(&molecule::pack_number(offset as molecule::Number))?; - } - writer.write_all(self.current.as_slice())?; - writer.write_all(self.previous.as_slice())?; - Ok(()) - } - fn build(&self) -> Self::Entity { - let mut inner = Vec::with_capacity(self.expected_length()); - self.write(&mut inner) - .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); - BTCDifficulty::new_unchecked(inner.into()) - } -} +use molecule :: prelude :: * ; +use super :: basic :: * ; +# [ derive ( Clone ) ] pub struct BTCDifficulty ( molecule :: bytes :: Bytes ) ; impl :: core :: fmt :: LowerHex for BTCDifficulty { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl :: core :: fmt :: Debug for BTCDifficulty { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl :: core :: fmt :: Display for BTCDifficulty { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{} {{ " , Self :: NAME ) ? ; write ! ( f , "{}: {}" , "current" , self . current ( ) ) ? ; write ! ( f , ", {}: {}" , "previous" , self . previous ( ) ) ? ; let extra_count = self . count_extra_fields ( ) ; if extra_count != 0 { write ! ( f , ", .. ({} fields)" , extra_count ) ? ; } write ! ( f , " }}" ) } } impl :: core :: default :: Default for BTCDifficulty { fn default ( ) -> Self { let v : Vec < u8 > = vec ! [ 20 , 0 , 0 , 0 , 12 , 0 , 0 , 0 , 16 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , ] ; BTCDifficulty :: new_unchecked ( v . into ( ) ) } } impl BTCDifficulty { pub const FIELD_COUNT : usize = 2 ; pub fn total_size ( & self ) -> usize { molecule :: unpack_number ( self . as_slice ( ) ) as usize } pub fn field_count ( & self ) -> usize { if self . total_size ( ) == molecule :: NUMBER_SIZE { 0 } else { ( molecule :: unpack_number ( & self . as_slice ( ) [ molecule :: NUMBER_SIZE .. ] ) as usize / 4 ) - 1 } } pub fn count_extra_fields ( & self ) -> usize { self . field_count ( ) - Self :: FIELD_COUNT } pub fn has_extra_fields ( & self ) -> bool { Self :: FIELD_COUNT != self . field_count ( ) } pub fn current ( & self ) -> Bytes { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 4 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; Bytes :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn previous ( & self ) -> Bytes { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; if self . has_extra_fields ( ) { let end = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; Bytes :: new_unchecked ( self . 0 . slice ( start .. end ) ) } else { Bytes :: new_unchecked ( self . 0 . slice ( start .. ) ) } } pub fn as_reader < 'r > ( & 'r self ) -> BTCDifficultyReader < 'r > { BTCDifficultyReader :: new_unchecked ( self . as_slice ( ) ) } } impl molecule :: prelude :: Entity for BTCDifficulty { type Builder = BTCDifficultyBuilder ; const NAME : & 'static str = "BTCDifficulty" ; fn new_unchecked ( data : molecule :: bytes :: Bytes ) -> Self { BTCDifficulty ( data ) } fn as_bytes ( & self ) -> molecule :: bytes :: Bytes { self . 0 . clone ( ) } fn as_slice ( & self ) -> & [ u8 ] { & self . 0 [ .. ] } fn from_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { BTCDifficultyReader :: from_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn from_compatible_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { BTCDifficultyReader :: from_compatible_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn new_builder ( ) -> Self :: Builder { :: core :: default :: Default :: default ( ) } fn as_builder ( self ) -> Self :: Builder { Self :: new_builder ( ) . current ( self . current ( ) ) . previous ( self . previous ( ) ) } } +# [ derive ( Clone , Copy ) ] pub struct BTCDifficultyReader < 'r > ( & 'r [ u8 ] ) ; impl < 'r > :: core :: fmt :: LowerHex for BTCDifficultyReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl < 'r > :: core :: fmt :: Debug for BTCDifficultyReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl < 'r > :: core :: fmt :: Display for BTCDifficultyReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{} {{ " , Self :: NAME ) ? ; write ! ( f , "{}: {}" , "current" , self . current ( ) ) ? ; write ! ( f , ", {}: {}" , "previous" , self . previous ( ) ) ? ; let extra_count = self . count_extra_fields ( ) ; if extra_count != 0 { write ! ( f , ", .. ({} fields)" , extra_count ) ? ; } write ! ( f , " }}" ) } } impl < 'r > BTCDifficultyReader < 'r > { pub const FIELD_COUNT : usize = 2 ; pub fn total_size ( & self ) -> usize { molecule :: unpack_number ( self . as_slice ( ) ) as usize } pub fn field_count ( & self ) -> usize { if self . total_size ( ) == molecule :: NUMBER_SIZE { 0 } else { ( molecule :: unpack_number ( & self . as_slice ( ) [ molecule :: NUMBER_SIZE .. ] ) as usize / 4 ) - 1 } } pub fn count_extra_fields ( & self ) -> usize { self . field_count ( ) - Self :: FIELD_COUNT } pub fn has_extra_fields ( & self ) -> bool { Self :: FIELD_COUNT != self . field_count ( ) } pub fn current ( & self ) -> BytesReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 4 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; BytesReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn previous ( & self ) -> BytesReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; if self . has_extra_fields ( ) { let end = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; BytesReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } else { BytesReader :: new_unchecked ( & self . as_slice ( ) [ start .. ] ) } } } impl < 'r > molecule :: prelude :: Reader < 'r > for BTCDifficultyReader < 'r > { type Entity = BTCDifficulty ; const NAME : & 'static str = "BTCDifficultyReader" ; fn to_entity ( & self ) -> Self :: Entity { Self :: Entity :: new_unchecked ( self . as_slice ( ) . to_owned ( ) . into ( ) ) } fn new_unchecked ( slice : & 'r [ u8 ] ) -> Self { BTCDifficultyReader ( slice ) } fn as_slice ( & self ) -> & 'r [ u8 ] { self . 0 } fn verify ( slice : & [ u8 ] , compatible : bool ) -> molecule :: error :: VerificationResult < ( ) > { use molecule :: verification_error as ve ; let slice_len = slice . len ( ) ; if slice_len < molecule :: NUMBER_SIZE { return ve ! ( Self , HeaderIsBroken , molecule :: NUMBER_SIZE , slice_len ) ; } let total_size = molecule :: unpack_number ( slice ) as usize ; if slice_len != total_size { return ve ! ( Self , TotalSizeNotMatch , total_size , slice_len ) ; } if slice_len == molecule :: NUMBER_SIZE && Self :: FIELD_COUNT == 0 { return Ok ( ( ) ) ; } if slice_len < molecule :: NUMBER_SIZE * 2 { return ve ! ( Self , HeaderIsBroken , molecule :: NUMBER_SIZE * 2 , slice_len ) ; } let offset_first = molecule :: unpack_number ( & slice [ molecule :: NUMBER_SIZE .. ] ) as usize ; if offset_first % 4 != 0 || offset_first < molecule :: NUMBER_SIZE * 2 { return ve ! ( Self , OffsetsNotMatch ) ; } let field_count = offset_first / 4 - 1 ; if field_count < Self :: FIELD_COUNT { return ve ! ( Self , FieldCountNotMatch , Self :: FIELD_COUNT , field_count ) ; } else if ! compatible && field_count > Self :: FIELD_COUNT { return ve ! ( Self , FieldCountNotMatch , Self :: FIELD_COUNT , field_count ) ; } ; let header_size = molecule :: NUMBER_SIZE * ( field_count + 1 ) ; if slice_len < header_size { return ve ! ( Self , HeaderIsBroken , header_size , slice_len ) ; } let mut offsets : Vec < usize > = slice [ molecule :: NUMBER_SIZE .. ] . chunks ( molecule :: NUMBER_SIZE ) . take ( field_count ) . map ( | x | molecule :: unpack_number ( x ) as usize ) . collect ( ) ; offsets . push ( total_size ) ; if offsets . windows ( 2 ) . any ( | i | i [ 0 ] > i [ 1 ] ) { return ve ! ( Self , OffsetsNotMatch ) ; } BytesReader :: verify ( & slice [ offsets [ 0 ] .. offsets [ 1 ] ] , compatible ) ? ; BytesReader :: verify ( & slice [ offsets [ 1 ] .. offsets [ 2 ] ] , compatible ) ? ; Ok ( ( ) ) } } +# [ derive ( Debug , Default ) ] pub struct BTCDifficultyBuilder { pub ( crate ) current : Bytes , pub ( crate ) previous : Bytes , } impl BTCDifficultyBuilder { pub const FIELD_COUNT : usize = 2 ; pub fn current ( mut self , v : Bytes ) -> Self { self . current = v ; self } pub fn previous ( mut self , v : Bytes ) -> Self { self . previous = v ; self } } impl molecule :: prelude :: Builder for BTCDifficultyBuilder { type Entity = BTCDifficulty ; const NAME : & 'static str = "BTCDifficultyBuilder" ; fn expected_length ( & self ) -> usize { molecule :: NUMBER_SIZE * ( Self :: FIELD_COUNT + 1 ) + self . current . as_slice ( ) . len ( ) + self . previous . as_slice ( ) . len ( ) } fn write < W : :: molecule :: io :: Write > ( & self , writer : & mut W ) -> :: molecule :: io :: Result < ( ) > { let mut total_size = molecule :: NUMBER_SIZE * ( Self :: FIELD_COUNT + 1 ) ; let mut offsets = Vec :: with_capacity ( Self :: FIELD_COUNT ) ; offsets . push ( total_size ) ; total_size += self . current . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . previous . as_slice ( ) . len ( ) ; writer . write_all ( & molecule :: pack_number ( total_size as molecule :: Number ) ) ? ; for offset in offsets . into_iter ( ) { writer . write_all ( & molecule :: pack_number ( offset as molecule :: Number ) ) ? ; } writer . write_all ( self . current . as_slice ( ) ) ? ; writer . write_all ( self . previous . as_slice ( ) ) ? ; Ok ( ( ) ) } fn build ( & self ) -> Self :: Entity { let mut inner = Vec :: with_capacity ( self . expected_length ( ) ) ; self . write ( & mut inner ) . unwrap_or_else ( | _ | panic ! ( "{} build should be ok" , Self :: NAME ) ) ; BTCDifficulty :: new_unchecked ( inner . into ( ) ) } } diff --git a/contracts/toCKB-typescript/src/utils/types/generated/mint_xt_witness.rs b/contracts/toCKB-typescript/src/utils/types/generated/mint_xt_witness.rs index e8f86b0..d57ff10 100644 --- a/contracts/toCKB-typescript/src/utils/types/generated/mint_xt_witness.rs +++ b/contracts/toCKB-typescript/src/utils/types/generated/mint_xt_witness.rs @@ -1,4 +1,4 @@ -// Generated by Molecule 0.6.0 +// Generated by Molecule 0.6.1 use super::basic::*; use molecule::prelude::*; @@ -742,3 +742,396 @@ impl molecule::prelude::Builder for BTCSPVProofBuilder { BTCSPVProof::new_unchecked(inner.into()) } } +#[derive(Clone)] +pub struct ETHSPVProof(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for ETHSPVProof { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for ETHSPVProof { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for ETHSPVProof { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "log_index", self.log_index())?; + write!(f, ", {}: {}", "log_entry_data", self.log_entry_data())?; + write!(f, ", {}: {}", "receipt_index", self.receipt_index())?; + write!(f, ", {}: {}", "receipt_data", self.receipt_data())?; + write!(f, ", {}: {}", "receipts_root", self.receipts_root())?; + write!(f, ", {}: {}", "header_data", self.header_data())?; + write!(f, ", {}: {}", "proof", self.proof())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl ::core::default::Default for ETHSPVProof { + fn default() -> Self { + let v: Vec = vec![ + 68, 0, 0, 0, 32, 0, 0, 0, 40, 0, 0, 0, 44, 0, 0, 0, 52, 0, 0, 0, 56, 0, 0, 0, 60, 0, 0, + 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, + ]; + ETHSPVProof::new_unchecked(v.into()) + } +} +impl ETHSPVProof { + pub const FIELD_COUNT: usize = 7; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn log_index(&self) -> Uint64 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + Uint64::new_unchecked(self.0.slice(start..end)) + } + pub fn log_entry_data(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + let end = molecule::unpack_number(&slice[12..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } + pub fn receipt_index(&self) -> Uint64 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[12..]) as usize; + let end = molecule::unpack_number(&slice[16..]) as usize; + Uint64::new_unchecked(self.0.slice(start..end)) + } + pub fn receipt_data(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[16..]) as usize; + let end = molecule::unpack_number(&slice[20..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } + pub fn receipts_root(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[20..]) as usize; + let end = molecule::unpack_number(&slice[24..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } + pub fn header_data(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[24..]) as usize; + let end = molecule::unpack_number(&slice[28..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } + pub fn proof(&self) -> Bytes2 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[28..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[32..]) as usize; + Bytes2::new_unchecked(self.0.slice(start..end)) + } else { + Bytes2::new_unchecked(self.0.slice(start..)) + } + } + pub fn as_reader<'r>(&'r self) -> ETHSPVProofReader<'r> { + ETHSPVProofReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for ETHSPVProof { + type Builder = ETHSPVProofBuilder; + const NAME: &'static str = "ETHSPVProof"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + ETHSPVProof(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + ETHSPVProofReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + ETHSPVProofReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder() + .log_index(self.log_index()) + .log_entry_data(self.log_entry_data()) + .receipt_index(self.receipt_index()) + .receipt_data(self.receipt_data()) + .receipts_root(self.receipts_root()) + .header_data(self.header_data()) + .proof(self.proof()) + } +} +#[derive(Clone, Copy)] +pub struct ETHSPVProofReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for ETHSPVProofReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for ETHSPVProofReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for ETHSPVProofReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "log_index", self.log_index())?; + write!(f, ", {}: {}", "log_entry_data", self.log_entry_data())?; + write!(f, ", {}: {}", "receipt_index", self.receipt_index())?; + write!(f, ", {}: {}", "receipt_data", self.receipt_data())?; + write!(f, ", {}: {}", "receipts_root", self.receipts_root())?; + write!(f, ", {}: {}", "header_data", self.header_data())?; + write!(f, ", {}: {}", "proof", self.proof())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl<'r> ETHSPVProofReader<'r> { + pub const FIELD_COUNT: usize = 7; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn log_index(&self) -> Uint64Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + Uint64Reader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn log_entry_data(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + let end = molecule::unpack_number(&slice[12..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn receipt_index(&self) -> Uint64Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[12..]) as usize; + let end = molecule::unpack_number(&slice[16..]) as usize; + Uint64Reader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn receipt_data(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[16..]) as usize; + let end = molecule::unpack_number(&slice[20..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn receipts_root(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[20..]) as usize; + let end = molecule::unpack_number(&slice[24..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn header_data(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[24..]) as usize; + let end = molecule::unpack_number(&slice[28..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn proof(&self) -> Bytes2Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[28..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[32..]) as usize; + Bytes2Reader::new_unchecked(&self.as_slice()[start..end]) + } else { + Bytes2Reader::new_unchecked(&self.as_slice()[start..]) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for ETHSPVProofReader<'r> { + type Entity = ETHSPVProof; + const NAME: &'static str = "ETHSPVProofReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + ETHSPVProofReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let total_size = molecule::unpack_number(slice) as usize; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + if slice_len == molecule::NUMBER_SIZE && Self::FIELD_COUNT == 0 { + return Ok(()); + } + if slice_len < molecule::NUMBER_SIZE * 2 { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); + } + let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; + if offset_first % 4 != 0 || offset_first < molecule::NUMBER_SIZE * 2 { + return ve!(Self, OffsetsNotMatch); + } + let field_count = offset_first / 4 - 1; + if field_count < Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + } else if !compatible && field_count > Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + }; + let header_size = molecule::NUMBER_SIZE * (field_count + 1); + if slice_len < header_size { + return ve!(Self, HeaderIsBroken, header_size, slice_len); + } + let mut offsets: Vec = slice[molecule::NUMBER_SIZE..] + .chunks(molecule::NUMBER_SIZE) + .take(field_count) + .map(|x| molecule::unpack_number(x) as usize) + .collect(); + offsets.push(total_size); + if offsets.windows(2).any(|i| i[0] > i[1]) { + return ve!(Self, OffsetsNotMatch); + } + Uint64Reader::verify(&slice[offsets[0]..offsets[1]], compatible)?; + BytesReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; + Uint64Reader::verify(&slice[offsets[2]..offsets[3]], compatible)?; + BytesReader::verify(&slice[offsets[3]..offsets[4]], compatible)?; + BytesReader::verify(&slice[offsets[4]..offsets[5]], compatible)?; + BytesReader::verify(&slice[offsets[5]..offsets[6]], compatible)?; + Bytes2Reader::verify(&slice[offsets[6]..offsets[7]], compatible)?; + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct ETHSPVProofBuilder { + pub(crate) log_index: Uint64, + pub(crate) log_entry_data: Bytes, + pub(crate) receipt_index: Uint64, + pub(crate) receipt_data: Bytes, + pub(crate) receipts_root: Bytes, + pub(crate) header_data: Bytes, + pub(crate) proof: Bytes2, +} +impl ETHSPVProofBuilder { + pub const FIELD_COUNT: usize = 7; + pub fn log_index(mut self, v: Uint64) -> Self { + self.log_index = v; + self + } + pub fn log_entry_data(mut self, v: Bytes) -> Self { + self.log_entry_data = v; + self + } + pub fn receipt_index(mut self, v: Uint64) -> Self { + self.receipt_index = v; + self + } + pub fn receipt_data(mut self, v: Bytes) -> Self { + self.receipt_data = v; + self + } + pub fn receipts_root(mut self, v: Bytes) -> Self { + self.receipts_root = v; + self + } + pub fn header_data(mut self, v: Bytes) -> Self { + self.header_data = v; + self + } + pub fn proof(mut self, v: Bytes2) -> Self { + self.proof = v; + self + } +} +impl molecule::prelude::Builder for ETHSPVProofBuilder { + type Entity = ETHSPVProof; + const NAME: &'static str = "ETHSPVProofBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) + + self.log_index.as_slice().len() + + self.log_entry_data.as_slice().len() + + self.receipt_index.as_slice().len() + + self.receipt_data.as_slice().len() + + self.receipts_root.as_slice().len() + + self.header_data.as_slice().len() + + self.proof.as_slice().len() + } + fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { + let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); + let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); + offsets.push(total_size); + total_size += self.log_index.as_slice().len(); + offsets.push(total_size); + total_size += self.log_entry_data.as_slice().len(); + offsets.push(total_size); + total_size += self.receipt_index.as_slice().len(); + offsets.push(total_size); + total_size += self.receipt_data.as_slice().len(); + offsets.push(total_size); + total_size += self.receipts_root.as_slice().len(); + offsets.push(total_size); + total_size += self.header_data.as_slice().len(); + offsets.push(total_size); + total_size += self.proof.as_slice().len(); + writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; + for offset in offsets.into_iter() { + writer.write_all(&molecule::pack_number(offset as molecule::Number))?; + } + writer.write_all(self.log_index.as_slice())?; + writer.write_all(self.log_entry_data.as_slice())?; + writer.write_all(self.receipt_index.as_slice())?; + writer.write_all(self.receipt_data.as_slice())?; + writer.write_all(self.receipts_root.as_slice())?; + writer.write_all(self.header_data.as_slice())?; + writer.write_all(self.proof.as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + ETHSPVProof::new_unchecked(inner.into()) + } +} diff --git a/contracts/toCKB-typescript/src/utils/types/generated/toCKB_cell_data.rs b/contracts/toCKB-typescript/src/utils/types/generated/toCKB_cell_data.rs index 36fb162..2579507 100644 --- a/contracts/toCKB-typescript/src/utils/types/generated/toCKB_cell_data.rs +++ b/contracts/toCKB-typescript/src/utils/types/generated/toCKB_cell_data.rs @@ -1,449 +1,7 @@ -// Generated by Molecule 0.6.0 +// Generated by Molecule 0.6.1 -use super::basic::*; -use molecule::prelude::*; -#[derive(Clone)] -pub struct ToCKBCellData(molecule::bytes::Bytes); -impl ::core::fmt::LowerHex for ToCKBCellData { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl ::core::fmt::Debug for ToCKBCellData { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl ::core::fmt::Display for ToCKBCellData { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{} {{ ", Self::NAME)?; - write!(f, "{}: {}", "status", self.status())?; - write!(f, ", {}: {}", "lot_size", self.lot_size())?; - write!(f, ", {}: {}", "user_lockscript", self.user_lockscript())?; - write!(f, ", {}: {}", "x_lock_address", self.x_lock_address())?; - write!(f, ", {}: {}", "signer_lockscript", self.signer_lockscript())?; - write!(f, ", {}: {}", "x_unlock_address", self.x_unlock_address())?; - write!( - f, - ", {}: {}", - "redeemer_lockscript", - self.redeemer_lockscript() - )?; - write!( - f, - ", {}: {}", - "liquidation_trigger_lockscript", - self.liquidation_trigger_lockscript() - )?; - let extra_count = self.count_extra_fields(); - if extra_count != 0 { - write!(f, ", .. ({} fields)", extra_count)?; - } - write!(f, " }}") - } -} -impl ::core::default::Default for ToCKBCellData { - fn default() -> Self { - let v: Vec = vec![ - 2, 1, 0, 0, 36, 0, 0, 0, 37, 0, 0, 0, 38, 0, 0, 0, 91, 0, 0, 0, 95, 0, 0, 0, 148, 0, 0, - 0, 152, 0, 0, 0, 205, 0, 0, 0, 0, 0, 53, 0, 0, 0, 16, 0, 0, 0, 48, 0, 0, 0, 49, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 0, 0, 0, 16, 0, 0, 0, 48, 0, 0, 0, 49, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 0, 0, 0, 16, 0, 0, 0, 48, 0, 0, 0, 49, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 0, 0, 0, 16, 0, 0, 0, 48, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - ]; - ToCKBCellData::new_unchecked(v.into()) - } -} -impl ToCKBCellData { - pub const FIELD_COUNT: usize = 8; - pub fn total_size(&self) -> usize { - molecule::unpack_number(self.as_slice()) as usize - } - pub fn field_count(&self) -> usize { - if self.total_size() == molecule::NUMBER_SIZE { - 0 - } else { - (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 - } - } - pub fn count_extra_fields(&self) -> usize { - self.field_count() - Self::FIELD_COUNT - } - pub fn has_extra_fields(&self) -> bool { - Self::FIELD_COUNT != self.field_count() - } - pub fn status(&self) -> Byte { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[4..]) as usize; - let end = molecule::unpack_number(&slice[8..]) as usize; - Byte::new_unchecked(self.0.slice(start..end)) - } - pub fn lot_size(&self) -> Byte { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[8..]) as usize; - let end = molecule::unpack_number(&slice[12..]) as usize; - Byte::new_unchecked(self.0.slice(start..end)) - } - pub fn user_lockscript(&self) -> Script { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[12..]) as usize; - let end = molecule::unpack_number(&slice[16..]) as usize; - Script::new_unchecked(self.0.slice(start..end)) - } - pub fn x_lock_address(&self) -> Bytes { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[16..]) as usize; - let end = molecule::unpack_number(&slice[20..]) as usize; - Bytes::new_unchecked(self.0.slice(start..end)) - } - pub fn signer_lockscript(&self) -> Script { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[20..]) as usize; - let end = molecule::unpack_number(&slice[24..]) as usize; - Script::new_unchecked(self.0.slice(start..end)) - } - pub fn x_unlock_address(&self) -> Bytes { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[24..]) as usize; - let end = molecule::unpack_number(&slice[28..]) as usize; - Bytes::new_unchecked(self.0.slice(start..end)) - } - pub fn redeemer_lockscript(&self) -> Script { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[28..]) as usize; - let end = molecule::unpack_number(&slice[32..]) as usize; - Script::new_unchecked(self.0.slice(start..end)) - } - pub fn liquidation_trigger_lockscript(&self) -> Script { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[32..]) as usize; - if self.has_extra_fields() { - let end = molecule::unpack_number(&slice[36..]) as usize; - Script::new_unchecked(self.0.slice(start..end)) - } else { - Script::new_unchecked(self.0.slice(start..)) - } - } - pub fn as_reader<'r>(&'r self) -> ToCKBCellDataReader<'r> { - ToCKBCellDataReader::new_unchecked(self.as_slice()) - } -} -impl molecule::prelude::Entity for ToCKBCellData { - type Builder = ToCKBCellDataBuilder; - const NAME: &'static str = "ToCKBCellData"; - fn new_unchecked(data: molecule::bytes::Bytes) -> Self { - ToCKBCellData(data) - } - fn as_bytes(&self) -> molecule::bytes::Bytes { - self.0.clone() - } - fn as_slice(&self) -> &[u8] { - &self.0[..] - } - fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { - ToCKBCellDataReader::from_slice(slice).map(|reader| reader.to_entity()) - } - fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { - ToCKBCellDataReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) - } - fn new_builder() -> Self::Builder { - ::core::default::Default::default() - } - fn as_builder(self) -> Self::Builder { - Self::new_builder() - .status(self.status()) - .lot_size(self.lot_size()) - .user_lockscript(self.user_lockscript()) - .x_lock_address(self.x_lock_address()) - .signer_lockscript(self.signer_lockscript()) - .x_unlock_address(self.x_unlock_address()) - .redeemer_lockscript(self.redeemer_lockscript()) - .liquidation_trigger_lockscript(self.liquidation_trigger_lockscript()) - } -} -#[derive(Clone, Copy)] -pub struct ToCKBCellDataReader<'r>(&'r [u8]); -impl<'r> ::core::fmt::LowerHex for ToCKBCellDataReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl<'r> ::core::fmt::Debug for ToCKBCellDataReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl<'r> ::core::fmt::Display for ToCKBCellDataReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{} {{ ", Self::NAME)?; - write!(f, "{}: {}", "status", self.status())?; - write!(f, ", {}: {}", "lot_size", self.lot_size())?; - write!(f, ", {}: {}", "user_lockscript", self.user_lockscript())?; - write!(f, ", {}: {}", "x_lock_address", self.x_lock_address())?; - write!(f, ", {}: {}", "signer_lockscript", self.signer_lockscript())?; - write!(f, ", {}: {}", "x_unlock_address", self.x_unlock_address())?; - write!( - f, - ", {}: {}", - "redeemer_lockscript", - self.redeemer_lockscript() - )?; - write!( - f, - ", {}: {}", - "liquidation_trigger_lockscript", - self.liquidation_trigger_lockscript() - )?; - let extra_count = self.count_extra_fields(); - if extra_count != 0 { - write!(f, ", .. ({} fields)", extra_count)?; - } - write!(f, " }}") - } -} -impl<'r> ToCKBCellDataReader<'r> { - pub const FIELD_COUNT: usize = 8; - pub fn total_size(&self) -> usize { - molecule::unpack_number(self.as_slice()) as usize - } - pub fn field_count(&self) -> usize { - if self.total_size() == molecule::NUMBER_SIZE { - 0 - } else { - (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 - } - } - pub fn count_extra_fields(&self) -> usize { - self.field_count() - Self::FIELD_COUNT - } - pub fn has_extra_fields(&self) -> bool { - Self::FIELD_COUNT != self.field_count() - } - pub fn status(&self) -> ByteReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[4..]) as usize; - let end = molecule::unpack_number(&slice[8..]) as usize; - ByteReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn lot_size(&self) -> ByteReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[8..]) as usize; - let end = molecule::unpack_number(&slice[12..]) as usize; - ByteReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn user_lockscript(&self) -> ScriptReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[12..]) as usize; - let end = molecule::unpack_number(&slice[16..]) as usize; - ScriptReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn x_lock_address(&self) -> BytesReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[16..]) as usize; - let end = molecule::unpack_number(&slice[20..]) as usize; - BytesReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn signer_lockscript(&self) -> ScriptReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[20..]) as usize; - let end = molecule::unpack_number(&slice[24..]) as usize; - ScriptReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn x_unlock_address(&self) -> BytesReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[24..]) as usize; - let end = molecule::unpack_number(&slice[28..]) as usize; - BytesReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn redeemer_lockscript(&self) -> ScriptReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[28..]) as usize; - let end = molecule::unpack_number(&slice[32..]) as usize; - ScriptReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn liquidation_trigger_lockscript(&self) -> ScriptReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[32..]) as usize; - if self.has_extra_fields() { - let end = molecule::unpack_number(&slice[36..]) as usize; - ScriptReader::new_unchecked(&self.as_slice()[start..end]) - } else { - ScriptReader::new_unchecked(&self.as_slice()[start..]) - } - } -} -impl<'r> molecule::prelude::Reader<'r> for ToCKBCellDataReader<'r> { - type Entity = ToCKBCellData; - const NAME: &'static str = "ToCKBCellDataReader"; - fn to_entity(&self) -> Self::Entity { - Self::Entity::new_unchecked(self.as_slice().to_owned().into()) - } - fn new_unchecked(slice: &'r [u8]) -> Self { - ToCKBCellDataReader(slice) - } - fn as_slice(&self) -> &'r [u8] { - self.0 - } - fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { - use molecule::verification_error as ve; - let slice_len = slice.len(); - if slice_len < molecule::NUMBER_SIZE { - return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); - } - let total_size = molecule::unpack_number(slice) as usize; - if slice_len != total_size { - return ve!(Self, TotalSizeNotMatch, total_size, slice_len); - } - if slice_len == molecule::NUMBER_SIZE && Self::FIELD_COUNT == 0 { - return Ok(()); - } - if slice_len < molecule::NUMBER_SIZE * 2 { - return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); - } - let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; - if offset_first % 4 != 0 || offset_first < molecule::NUMBER_SIZE * 2 { - return ve!(Self, OffsetsNotMatch); - } - let field_count = offset_first / 4 - 1; - if field_count < Self::FIELD_COUNT { - return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); - } else if !compatible && field_count > Self::FIELD_COUNT { - return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); - }; - let header_size = molecule::NUMBER_SIZE * (field_count + 1); - if slice_len < header_size { - return ve!(Self, HeaderIsBroken, header_size, slice_len); - } - let mut offsets: Vec = slice[molecule::NUMBER_SIZE..] - .chunks(molecule::NUMBER_SIZE) - .take(field_count) - .map(|x| molecule::unpack_number(x) as usize) - .collect(); - offsets.push(total_size); - if offsets.windows(2).any(|i| i[0] > i[1]) { - return ve!(Self, OffsetsNotMatch); - } - ByteReader::verify(&slice[offsets[0]..offsets[1]], compatible)?; - ByteReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; - ScriptReader::verify(&slice[offsets[2]..offsets[3]], compatible)?; - BytesReader::verify(&slice[offsets[3]..offsets[4]], compatible)?; - ScriptReader::verify(&slice[offsets[4]..offsets[5]], compatible)?; - BytesReader::verify(&slice[offsets[5]..offsets[6]], compatible)?; - ScriptReader::verify(&slice[offsets[6]..offsets[7]], compatible)?; - ScriptReader::verify(&slice[offsets[7]..offsets[8]], compatible)?; - Ok(()) - } -} -#[derive(Debug, Default)] -pub struct ToCKBCellDataBuilder { - pub(crate) status: Byte, - pub(crate) lot_size: Byte, - pub(crate) user_lockscript: Script, - pub(crate) x_lock_address: Bytes, - pub(crate) signer_lockscript: Script, - pub(crate) x_unlock_address: Bytes, - pub(crate) redeemer_lockscript: Script, - pub(crate) liquidation_trigger_lockscript: Script, -} -impl ToCKBCellDataBuilder { - pub const FIELD_COUNT: usize = 8; - pub fn status(mut self, v: Byte) -> Self { - self.status = v; - self - } - pub fn lot_size(mut self, v: Byte) -> Self { - self.lot_size = v; - self - } - pub fn user_lockscript(mut self, v: Script) -> Self { - self.user_lockscript = v; - self - } - pub fn x_lock_address(mut self, v: Bytes) -> Self { - self.x_lock_address = v; - self - } - pub fn signer_lockscript(mut self, v: Script) -> Self { - self.signer_lockscript = v; - self - } - pub fn x_unlock_address(mut self, v: Bytes) -> Self { - self.x_unlock_address = v; - self - } - pub fn redeemer_lockscript(mut self, v: Script) -> Self { - self.redeemer_lockscript = v; - self - } - pub fn liquidation_trigger_lockscript(mut self, v: Script) -> Self { - self.liquidation_trigger_lockscript = v; - self - } -} -impl molecule::prelude::Builder for ToCKBCellDataBuilder { - type Entity = ToCKBCellData; - const NAME: &'static str = "ToCKBCellDataBuilder"; - fn expected_length(&self) -> usize { - molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) - + self.status.as_slice().len() - + self.lot_size.as_slice().len() - + self.user_lockscript.as_slice().len() - + self.x_lock_address.as_slice().len() - + self.signer_lockscript.as_slice().len() - + self.x_unlock_address.as_slice().len() - + self.redeemer_lockscript.as_slice().len() - + self.liquidation_trigger_lockscript.as_slice().len() - } - fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { - let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); - let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); - offsets.push(total_size); - total_size += self.status.as_slice().len(); - offsets.push(total_size); - total_size += self.lot_size.as_slice().len(); - offsets.push(total_size); - total_size += self.user_lockscript.as_slice().len(); - offsets.push(total_size); - total_size += self.x_lock_address.as_slice().len(); - offsets.push(total_size); - total_size += self.signer_lockscript.as_slice().len(); - offsets.push(total_size); - total_size += self.x_unlock_address.as_slice().len(); - offsets.push(total_size); - total_size += self.redeemer_lockscript.as_slice().len(); - offsets.push(total_size); - total_size += self.liquidation_trigger_lockscript.as_slice().len(); - writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; - for offset in offsets.into_iter() { - writer.write_all(&molecule::pack_number(offset as molecule::Number))?; - } - writer.write_all(self.status.as_slice())?; - writer.write_all(self.lot_size.as_slice())?; - writer.write_all(self.user_lockscript.as_slice())?; - writer.write_all(self.x_lock_address.as_slice())?; - writer.write_all(self.signer_lockscript.as_slice())?; - writer.write_all(self.x_unlock_address.as_slice())?; - writer.write_all(self.redeemer_lockscript.as_slice())?; - writer.write_all(self.liquidation_trigger_lockscript.as_slice())?; - Ok(()) - } - fn build(&self) -> Self::Entity { - let mut inner = Vec::with_capacity(self.expected_length()); - self.write(&mut inner) - .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); - ToCKBCellData::new_unchecked(inner.into()) - } -} +use molecule :: prelude :: * ; +use super :: basic :: * ; +# [ derive ( Clone ) ] pub struct ToCKBCellData ( molecule :: bytes :: Bytes ) ; impl :: core :: fmt :: LowerHex for ToCKBCellData { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl :: core :: fmt :: Debug for ToCKBCellData { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl :: core :: fmt :: Display for ToCKBCellData { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{} {{ " , Self :: NAME ) ? ; write ! ( f , "{}: {}" , "status" , self . status ( ) ) ? ; write ! ( f , ", {}: {}" , "lot_size" , self . lot_size ( ) ) ? ; write ! ( f , ", {}: {}" , "user_lockscript" , self . user_lockscript ( ) ) ? ; write ! ( f , ", {}: {}" , "x_lock_address" , self . x_lock_address ( ) ) ? ; write ! ( f , ", {}: {}" , "signer_lockscript" , self . signer_lockscript ( ) ) ? ; write ! ( f , ", {}: {}" , "x_unlock_address" , self . x_unlock_address ( ) ) ? ; write ! ( f , ", {}: {}" , "redeemer_lockscript" , self . redeemer_lockscript ( ) ) ? ; write ! ( f , ", {}: {}" , "liquidation_trigger_lockscript" , self . liquidation_trigger_lockscript ( ) ) ? ; let extra_count = self . count_extra_fields ( ) ; if extra_count != 0 { write ! ( f , ", .. ({} fields)" , extra_count ) ? ; } write ! ( f , " }}" ) } } impl :: core :: default :: Default for ToCKBCellData { fn default ( ) -> Self { let v : Vec < u8 > = vec ! [ 2 , 1 , 0 , 0 , 36 , 0 , 0 , 0 , 37 , 0 , 0 , 0 , 38 , 0 , 0 , 0 , 91 , 0 , 0 , 0 , 95 , 0 , 0 , 0 , 148 , 0 , 0 , 0 , 152 , 0 , 0 , 0 , 205 , 0 , 0 , 0 , 0 , 0 , 53 , 0 , 0 , 0 , 16 , 0 , 0 , 0 , 48 , 0 , 0 , 0 , 49 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 53 , 0 , 0 , 0 , 16 , 0 , 0 , 0 , 48 , 0 , 0 , 0 , 49 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 53 , 0 , 0 , 0 , 16 , 0 , 0 , 0 , 48 , 0 , 0 , 0 , 49 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 53 , 0 , 0 , 0 , 16 , 0 , 0 , 0 , 48 , 0 , 0 , 0 , 49 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , ] ; ToCKBCellData :: new_unchecked ( v . into ( ) ) } } impl ToCKBCellData { pub const FIELD_COUNT : usize = 8 ; pub fn total_size ( & self ) -> usize { molecule :: unpack_number ( self . as_slice ( ) ) as usize } pub fn field_count ( & self ) -> usize { if self . total_size ( ) == molecule :: NUMBER_SIZE { 0 } else { ( molecule :: unpack_number ( & self . as_slice ( ) [ molecule :: NUMBER_SIZE .. ] ) as usize / 4 ) - 1 } } pub fn count_extra_fields ( & self ) -> usize { self . field_count ( ) - Self :: FIELD_COUNT } pub fn has_extra_fields ( & self ) -> bool { Self :: FIELD_COUNT != self . field_count ( ) } pub fn status ( & self ) -> Byte { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 4 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; Byte :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn lot_size ( & self ) -> Byte { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; Byte :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn user_lockscript ( & self ) -> Script { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 16 .. ] ) as usize ; Script :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn x_lock_address ( & self ) -> Bytes { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 16 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 20 .. ] ) as usize ; Bytes :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn signer_lockscript ( & self ) -> Script { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 20 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 24 .. ] ) as usize ; Script :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn x_unlock_address ( & self ) -> Bytes { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 24 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 28 .. ] ) as usize ; Bytes :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn redeemer_lockscript ( & self ) -> Script { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 28 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 32 .. ] ) as usize ; Script :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn liquidation_trigger_lockscript ( & self ) -> Script { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 32 .. ] ) as usize ; if self . has_extra_fields ( ) { let end = molecule :: unpack_number ( & slice [ 36 .. ] ) as usize ; Script :: new_unchecked ( self . 0 . slice ( start .. end ) ) } else { Script :: new_unchecked ( self . 0 . slice ( start .. ) ) } } pub fn as_reader < 'r > ( & 'r self ) -> ToCKBCellDataReader < 'r > { ToCKBCellDataReader :: new_unchecked ( self . as_slice ( ) ) } } impl molecule :: prelude :: Entity for ToCKBCellData { type Builder = ToCKBCellDataBuilder ; const NAME : & 'static str = "ToCKBCellData" ; fn new_unchecked ( data : molecule :: bytes :: Bytes ) -> Self { ToCKBCellData ( data ) } fn as_bytes ( & self ) -> molecule :: bytes :: Bytes { self . 0 . clone ( ) } fn as_slice ( & self ) -> & [ u8 ] { & self . 0 [ .. ] } fn from_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { ToCKBCellDataReader :: from_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn from_compatible_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { ToCKBCellDataReader :: from_compatible_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn new_builder ( ) -> Self :: Builder { :: core :: default :: Default :: default ( ) } fn as_builder ( self ) -> Self :: Builder { Self :: new_builder ( ) . status ( self . status ( ) ) . lot_size ( self . lot_size ( ) ) . user_lockscript ( self . user_lockscript ( ) ) . x_lock_address ( self . x_lock_address ( ) ) . signer_lockscript ( self . signer_lockscript ( ) ) . x_unlock_address ( self . x_unlock_address ( ) ) . redeemer_lockscript ( self . redeemer_lockscript ( ) ) . liquidation_trigger_lockscript ( self . liquidation_trigger_lockscript ( ) ) } } +# [ derive ( Clone , Copy ) ] pub struct ToCKBCellDataReader < 'r > ( & 'r [ u8 ] ) ; impl < 'r > :: core :: fmt :: LowerHex for ToCKBCellDataReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl < 'r > :: core :: fmt :: Debug for ToCKBCellDataReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl < 'r > :: core :: fmt :: Display for ToCKBCellDataReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{} {{ " , Self :: NAME ) ? ; write ! ( f , "{}: {}" , "status" , self . status ( ) ) ? ; write ! ( f , ", {}: {}" , "lot_size" , self . lot_size ( ) ) ? ; write ! ( f , ", {}: {}" , "user_lockscript" , self . user_lockscript ( ) ) ? ; write ! ( f , ", {}: {}" , "x_lock_address" , self . x_lock_address ( ) ) ? ; write ! ( f , ", {}: {}" , "signer_lockscript" , self . signer_lockscript ( ) ) ? ; write ! ( f , ", {}: {}" , "x_unlock_address" , self . x_unlock_address ( ) ) ? ; write ! ( f , ", {}: {}" , "redeemer_lockscript" , self . redeemer_lockscript ( ) ) ? ; write ! ( f , ", {}: {}" , "liquidation_trigger_lockscript" , self . liquidation_trigger_lockscript ( ) ) ? ; let extra_count = self . count_extra_fields ( ) ; if extra_count != 0 { write ! ( f , ", .. ({} fields)" , extra_count ) ? ; } write ! ( f , " }}" ) } } impl < 'r > ToCKBCellDataReader < 'r > { pub const FIELD_COUNT : usize = 8 ; pub fn total_size ( & self ) -> usize { molecule :: unpack_number ( self . as_slice ( ) ) as usize } pub fn field_count ( & self ) -> usize { if self . total_size ( ) == molecule :: NUMBER_SIZE { 0 } else { ( molecule :: unpack_number ( & self . as_slice ( ) [ molecule :: NUMBER_SIZE .. ] ) as usize / 4 ) - 1 } } pub fn count_extra_fields ( & self ) -> usize { self . field_count ( ) - Self :: FIELD_COUNT } pub fn has_extra_fields ( & self ) -> bool { Self :: FIELD_COUNT != self . field_count ( ) } pub fn status ( & self ) -> ByteReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 4 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; ByteReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn lot_size ( & self ) -> ByteReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; ByteReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn user_lockscript ( & self ) -> ScriptReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 16 .. ] ) as usize ; ScriptReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn x_lock_address ( & self ) -> BytesReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 16 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 20 .. ] ) as usize ; BytesReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn signer_lockscript ( & self ) -> ScriptReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 20 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 24 .. ] ) as usize ; ScriptReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn x_unlock_address ( & self ) -> BytesReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 24 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 28 .. ] ) as usize ; BytesReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn redeemer_lockscript ( & self ) -> ScriptReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 28 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 32 .. ] ) as usize ; ScriptReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn liquidation_trigger_lockscript ( & self ) -> ScriptReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 32 .. ] ) as usize ; if self . has_extra_fields ( ) { let end = molecule :: unpack_number ( & slice [ 36 .. ] ) as usize ; ScriptReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } else { ScriptReader :: new_unchecked ( & self . as_slice ( ) [ start .. ] ) } } } impl < 'r > molecule :: prelude :: Reader < 'r > for ToCKBCellDataReader < 'r > { type Entity = ToCKBCellData ; const NAME : & 'static str = "ToCKBCellDataReader" ; fn to_entity ( & self ) -> Self :: Entity { Self :: Entity :: new_unchecked ( self . as_slice ( ) . to_owned ( ) . into ( ) ) } fn new_unchecked ( slice : & 'r [ u8 ] ) -> Self { ToCKBCellDataReader ( slice ) } fn as_slice ( & self ) -> & 'r [ u8 ] { self . 0 } fn verify ( slice : & [ u8 ] , compatible : bool ) -> molecule :: error :: VerificationResult < ( ) > { use molecule :: verification_error as ve ; let slice_len = slice . len ( ) ; if slice_len < molecule :: NUMBER_SIZE { return ve ! ( Self , HeaderIsBroken , molecule :: NUMBER_SIZE , slice_len ) ; } let total_size = molecule :: unpack_number ( slice ) as usize ; if slice_len != total_size { return ve ! ( Self , TotalSizeNotMatch , total_size , slice_len ) ; } if slice_len == molecule :: NUMBER_SIZE && Self :: FIELD_COUNT == 0 { return Ok ( ( ) ) ; } if slice_len < molecule :: NUMBER_SIZE * 2 { return ve ! ( Self , HeaderIsBroken , molecule :: NUMBER_SIZE * 2 , slice_len ) ; } let offset_first = molecule :: unpack_number ( & slice [ molecule :: NUMBER_SIZE .. ] ) as usize ; if offset_first % 4 != 0 || offset_first < molecule :: NUMBER_SIZE * 2 { return ve ! ( Self , OffsetsNotMatch ) ; } let field_count = offset_first / 4 - 1 ; if field_count < Self :: FIELD_COUNT { return ve ! ( Self , FieldCountNotMatch , Self :: FIELD_COUNT , field_count ) ; } else if ! compatible && field_count > Self :: FIELD_COUNT { return ve ! ( Self , FieldCountNotMatch , Self :: FIELD_COUNT , field_count ) ; } ; let header_size = molecule :: NUMBER_SIZE * ( field_count + 1 ) ; if slice_len < header_size { return ve ! ( Self , HeaderIsBroken , header_size , slice_len ) ; } let mut offsets : Vec < usize > = slice [ molecule :: NUMBER_SIZE .. ] . chunks ( molecule :: NUMBER_SIZE ) . take ( field_count ) . map ( | x | molecule :: unpack_number ( x ) as usize ) . collect ( ) ; offsets . push ( total_size ) ; if offsets . windows ( 2 ) . any ( | i | i [ 0 ] > i [ 1 ] ) { return ve ! ( Self , OffsetsNotMatch ) ; } ByteReader :: verify ( & slice [ offsets [ 0 ] .. offsets [ 1 ] ] , compatible ) ? ; ByteReader :: verify ( & slice [ offsets [ 1 ] .. offsets [ 2 ] ] , compatible ) ? ; ScriptReader :: verify ( & slice [ offsets [ 2 ] .. offsets [ 3 ] ] , compatible ) ? ; BytesReader :: verify ( & slice [ offsets [ 3 ] .. offsets [ 4 ] ] , compatible ) ? ; ScriptReader :: verify ( & slice [ offsets [ 4 ] .. offsets [ 5 ] ] , compatible ) ? ; BytesReader :: verify ( & slice [ offsets [ 5 ] .. offsets [ 6 ] ] , compatible ) ? ; ScriptReader :: verify ( & slice [ offsets [ 6 ] .. offsets [ 7 ] ] , compatible ) ? ; ScriptReader :: verify ( & slice [ offsets [ 7 ] .. offsets [ 8 ] ] , compatible ) ? ; Ok ( ( ) ) } } +# [ derive ( Debug , Default ) ] pub struct ToCKBCellDataBuilder { pub ( crate ) status : Byte , pub ( crate ) lot_size : Byte , pub ( crate ) user_lockscript : Script , pub ( crate ) x_lock_address : Bytes , pub ( crate ) signer_lockscript : Script , pub ( crate ) x_unlock_address : Bytes , pub ( crate ) redeemer_lockscript : Script , pub ( crate ) liquidation_trigger_lockscript : Script , } impl ToCKBCellDataBuilder { pub const FIELD_COUNT : usize = 8 ; pub fn status ( mut self , v : Byte ) -> Self { self . status = v ; self } pub fn lot_size ( mut self , v : Byte ) -> Self { self . lot_size = v ; self } pub fn user_lockscript ( mut self , v : Script ) -> Self { self . user_lockscript = v ; self } pub fn x_lock_address ( mut self , v : Bytes ) -> Self { self . x_lock_address = v ; self } pub fn signer_lockscript ( mut self , v : Script ) -> Self { self . signer_lockscript = v ; self } pub fn x_unlock_address ( mut self , v : Bytes ) -> Self { self . x_unlock_address = v ; self } pub fn redeemer_lockscript ( mut self , v : Script ) -> Self { self . redeemer_lockscript = v ; self } pub fn liquidation_trigger_lockscript ( mut self , v : Script ) -> Self { self . liquidation_trigger_lockscript = v ; self } } impl molecule :: prelude :: Builder for ToCKBCellDataBuilder { type Entity = ToCKBCellData ; const NAME : & 'static str = "ToCKBCellDataBuilder" ; fn expected_length ( & self ) -> usize { molecule :: NUMBER_SIZE * ( Self :: FIELD_COUNT + 1 ) + self . status . as_slice ( ) . len ( ) + self . lot_size . as_slice ( ) . len ( ) + self . user_lockscript . as_slice ( ) . len ( ) + self . x_lock_address . as_slice ( ) . len ( ) + self . signer_lockscript . as_slice ( ) . len ( ) + self . x_unlock_address . as_slice ( ) . len ( ) + self . redeemer_lockscript . as_slice ( ) . len ( ) + self . liquidation_trigger_lockscript . as_slice ( ) . len ( ) } fn write < W : :: molecule :: io :: Write > ( & self , writer : & mut W ) -> :: molecule :: io :: Result < ( ) > { let mut total_size = molecule :: NUMBER_SIZE * ( Self :: FIELD_COUNT + 1 ) ; let mut offsets = Vec :: with_capacity ( Self :: FIELD_COUNT ) ; offsets . push ( total_size ) ; total_size += self . status . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . lot_size . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . user_lockscript . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . x_lock_address . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . signer_lockscript . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . x_unlock_address . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . redeemer_lockscript . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . liquidation_trigger_lockscript . as_slice ( ) . len ( ) ; writer . write_all ( & molecule :: pack_number ( total_size as molecule :: Number ) ) ? ; for offset in offsets . into_iter ( ) { writer . write_all ( & molecule :: pack_number ( offset as molecule :: Number ) ) ? ; } writer . write_all ( self . status . as_slice ( ) ) ? ; writer . write_all ( self . lot_size . as_slice ( ) ) ? ; writer . write_all ( self . user_lockscript . as_slice ( ) ) ? ; writer . write_all ( self . x_lock_address . as_slice ( ) ) ? ; writer . write_all ( self . signer_lockscript . as_slice ( ) ) ? ; writer . write_all ( self . x_unlock_address . as_slice ( ) ) ? ; writer . write_all ( self . redeemer_lockscript . as_slice ( ) ) ? ; writer . write_all ( self . liquidation_trigger_lockscript . as_slice ( ) ) ? ; Ok ( ( ) ) } fn build ( & self ) -> Self :: Entity { let mut inner = Vec :: with_capacity ( self . expected_length ( ) ) ; self . write ( & mut inner ) . unwrap_or_else ( | _ | panic ! ( "{} build should be ok" , Self :: NAME ) ) ; ToCKBCellData :: new_unchecked ( inner . into ( ) ) } } diff --git a/contracts/toCKB-typescript/src/utils/types/schemas/basic.mol b/contracts/toCKB-typescript/src/utils/types/schemas/basic.mol index 826a537..1e213d3 100644 --- a/contracts/toCKB-typescript/src/utils/types/schemas/basic.mol +++ b/contracts/toCKB-typescript/src/utils/types/schemas/basic.mol @@ -3,6 +3,7 @@ array Byte32 [byte; 32]; vector Bytes ; array Uint32 [byte; 4]; array Uint64 [byte; 8]; +vector Bytes2 ; table Script { code_hash: Byte32, diff --git a/contracts/toCKB-typescript/src/utils/types/schemas/mint_xt_witness.mol b/contracts/toCKB-typescript/src/utils/types/schemas/mint_xt_witness.mol index 5ec0e94..ae395fb 100644 --- a/contracts/toCKB-typescript/src/utils/types/schemas/mint_xt_witness.mol +++ b/contracts/toCKB-typescript/src/utils/types/schemas/mint_xt_witness.mol @@ -16,3 +16,13 @@ table BTCSPVProof { intermediate_nodes: Bytes, funding_output_index: byte, } + +table ETHSPVProof { + log_index: Uint64, + log_entry_data: Bytes, + receipt_index: Uint64, + receipt_data: Bytes, + receipts_root: Bytes, + header_data: Bytes, + proof: Bytes2, +} diff --git a/tests/src/toCKB_typescript/utils/types/generated/basic.rs b/tests/src/toCKB_typescript/utils/types/generated/basic.rs index 7ad3205..c171601 100644 --- a/tests/src/toCKB_typescript/utils/types/generated/basic.rs +++ b/tests/src/toCKB_typescript/utils/types/generated/basic.rs @@ -1,1769 +1,26 @@ -// Generated by Molecule 0.6.0 +// Generated by Molecule 0.6.1 -use molecule::prelude::*; -#[derive(Clone)] -pub struct Byte4(molecule::bytes::Bytes); -impl ::core::fmt::LowerHex for Byte4 { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl ::core::fmt::Debug for Byte4 { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl ::core::fmt::Display for Byte4 { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - let raw_data = hex_string(&self.raw_data()); - write!(f, "{}(0x{})", Self::NAME, raw_data) - } -} -impl ::core::default::Default for Byte4 { - fn default() -> Self { - let v: Vec = vec![0, 0, 0, 0]; - Byte4::new_unchecked(v.into()) - } -} -impl Byte4 { - pub const TOTAL_SIZE: usize = 4; - pub const ITEM_SIZE: usize = 1; - pub const ITEM_COUNT: usize = 4; - pub fn nth0(&self) -> Byte { - Byte::new_unchecked(self.0.slice(0..1)) - } - pub fn nth1(&self) -> Byte { - Byte::new_unchecked(self.0.slice(1..2)) - } - pub fn nth2(&self) -> Byte { - Byte::new_unchecked(self.0.slice(2..3)) - } - pub fn nth3(&self) -> Byte { - Byte::new_unchecked(self.0.slice(3..4)) - } - pub fn raw_data(&self) -> molecule::bytes::Bytes { - self.as_bytes() - } - pub fn as_reader<'r>(&'r self) -> Byte4Reader<'r> { - Byte4Reader::new_unchecked(self.as_slice()) - } -} -impl molecule::prelude::Entity for Byte4 { - type Builder = Byte4Builder; - const NAME: &'static str = "Byte4"; - fn new_unchecked(data: molecule::bytes::Bytes) -> Self { - Byte4(data) - } - fn as_bytes(&self) -> molecule::bytes::Bytes { - self.0.clone() - } - fn as_slice(&self) -> &[u8] { - &self.0[..] - } - fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { - Byte4Reader::from_slice(slice).map(|reader| reader.to_entity()) - } - fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { - Byte4Reader::from_compatible_slice(slice).map(|reader| reader.to_entity()) - } - fn new_builder() -> Self::Builder { - ::core::default::Default::default() - } - fn as_builder(self) -> Self::Builder { - Self::new_builder().set([self.nth0(), self.nth1(), self.nth2(), self.nth3()]) - } -} -#[derive(Clone, Copy)] -pub struct Byte4Reader<'r>(&'r [u8]); -impl<'r> ::core::fmt::LowerHex for Byte4Reader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl<'r> ::core::fmt::Debug for Byte4Reader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl<'r> ::core::fmt::Display for Byte4Reader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - let raw_data = hex_string(&self.raw_data()); - write!(f, "{}(0x{})", Self::NAME, raw_data) - } -} -impl<'r> Byte4Reader<'r> { - pub const TOTAL_SIZE: usize = 4; - pub const ITEM_SIZE: usize = 1; - pub const ITEM_COUNT: usize = 4; - pub fn nth0(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[0..1]) - } - pub fn nth1(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[1..2]) - } - pub fn nth2(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[2..3]) - } - pub fn nth3(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[3..4]) - } - pub fn raw_data(&self) -> &'r [u8] { - self.as_slice() - } -} -impl<'r> molecule::prelude::Reader<'r> for Byte4Reader<'r> { - type Entity = Byte4; - const NAME: &'static str = "Byte4Reader"; - fn to_entity(&self) -> Self::Entity { - Self::Entity::new_unchecked(self.as_slice().to_owned().into()) - } - fn new_unchecked(slice: &'r [u8]) -> Self { - Byte4Reader(slice) - } - fn as_slice(&self) -> &'r [u8] { - self.0 - } - fn verify(slice: &[u8], _compatible: bool) -> molecule::error::VerificationResult<()> { - use molecule::verification_error as ve; - let slice_len = slice.len(); - if slice_len != Self::TOTAL_SIZE { - return ve!(Self, TotalSizeNotMatch, Self::TOTAL_SIZE, slice_len); - } - Ok(()) - } -} -pub struct Byte4Builder(pub(crate) [Byte; 4]); -impl ::core::fmt::Debug for Byte4Builder { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:?})", Self::NAME, &self.0[..]) - } -} -impl ::core::default::Default for Byte4Builder { - fn default() -> Self { - Byte4Builder([ - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - ]) - } -} -impl Byte4Builder { - pub const TOTAL_SIZE: usize = 4; - pub const ITEM_SIZE: usize = 1; - pub const ITEM_COUNT: usize = 4; - pub fn set(mut self, v: [Byte; 4]) -> Self { - self.0 = v; - self - } - pub fn nth0(mut self, v: Byte) -> Self { - self.0[0] = v; - self - } - pub fn nth1(mut self, v: Byte) -> Self { - self.0[1] = v; - self - } - pub fn nth2(mut self, v: Byte) -> Self { - self.0[2] = v; - self - } - pub fn nth3(mut self, v: Byte) -> Self { - self.0[3] = v; - self - } -} -impl molecule::prelude::Builder for Byte4Builder { - type Entity = Byte4; - const NAME: &'static str = "Byte4Builder"; - fn expected_length(&self) -> usize { - Self::TOTAL_SIZE - } - fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { - writer.write_all(self.0[0].as_slice())?; - writer.write_all(self.0[1].as_slice())?; - writer.write_all(self.0[2].as_slice())?; - writer.write_all(self.0[3].as_slice())?; - Ok(()) - } - fn build(&self) -> Self::Entity { - let mut inner = Vec::with_capacity(self.expected_length()); - self.write(&mut inner) - .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); - Byte4::new_unchecked(inner.into()) - } -} -#[derive(Clone)] -pub struct Byte32(molecule::bytes::Bytes); -impl ::core::fmt::LowerHex for Byte32 { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl ::core::fmt::Debug for Byte32 { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl ::core::fmt::Display for Byte32 { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - let raw_data = hex_string(&self.raw_data()); - write!(f, "{}(0x{})", Self::NAME, raw_data) - } -} -impl ::core::default::Default for Byte32 { - fn default() -> Self { - let v: Vec = vec![ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, - ]; - Byte32::new_unchecked(v.into()) - } -} -impl Byte32 { - pub const TOTAL_SIZE: usize = 32; - pub const ITEM_SIZE: usize = 1; - pub const ITEM_COUNT: usize = 32; - pub fn nth0(&self) -> Byte { - Byte::new_unchecked(self.0.slice(0..1)) - } - pub fn nth1(&self) -> Byte { - Byte::new_unchecked(self.0.slice(1..2)) - } - pub fn nth2(&self) -> Byte { - Byte::new_unchecked(self.0.slice(2..3)) - } - pub fn nth3(&self) -> Byte { - Byte::new_unchecked(self.0.slice(3..4)) - } - pub fn nth4(&self) -> Byte { - Byte::new_unchecked(self.0.slice(4..5)) - } - pub fn nth5(&self) -> Byte { - Byte::new_unchecked(self.0.slice(5..6)) - } - pub fn nth6(&self) -> Byte { - Byte::new_unchecked(self.0.slice(6..7)) - } - pub fn nth7(&self) -> Byte { - Byte::new_unchecked(self.0.slice(7..8)) - } - pub fn nth8(&self) -> Byte { - Byte::new_unchecked(self.0.slice(8..9)) - } - pub fn nth9(&self) -> Byte { - Byte::new_unchecked(self.0.slice(9..10)) - } - pub fn nth10(&self) -> Byte { - Byte::new_unchecked(self.0.slice(10..11)) - } - pub fn nth11(&self) -> Byte { - Byte::new_unchecked(self.0.slice(11..12)) - } - pub fn nth12(&self) -> Byte { - Byte::new_unchecked(self.0.slice(12..13)) - } - pub fn nth13(&self) -> Byte { - Byte::new_unchecked(self.0.slice(13..14)) - } - pub fn nth14(&self) -> Byte { - Byte::new_unchecked(self.0.slice(14..15)) - } - pub fn nth15(&self) -> Byte { - Byte::new_unchecked(self.0.slice(15..16)) - } - pub fn nth16(&self) -> Byte { - Byte::new_unchecked(self.0.slice(16..17)) - } - pub fn nth17(&self) -> Byte { - Byte::new_unchecked(self.0.slice(17..18)) - } - pub fn nth18(&self) -> Byte { - Byte::new_unchecked(self.0.slice(18..19)) - } - pub fn nth19(&self) -> Byte { - Byte::new_unchecked(self.0.slice(19..20)) - } - pub fn nth20(&self) -> Byte { - Byte::new_unchecked(self.0.slice(20..21)) - } - pub fn nth21(&self) -> Byte { - Byte::new_unchecked(self.0.slice(21..22)) - } - pub fn nth22(&self) -> Byte { - Byte::new_unchecked(self.0.slice(22..23)) - } - pub fn nth23(&self) -> Byte { - Byte::new_unchecked(self.0.slice(23..24)) - } - pub fn nth24(&self) -> Byte { - Byte::new_unchecked(self.0.slice(24..25)) - } - pub fn nth25(&self) -> Byte { - Byte::new_unchecked(self.0.slice(25..26)) - } - pub fn nth26(&self) -> Byte { - Byte::new_unchecked(self.0.slice(26..27)) - } - pub fn nth27(&self) -> Byte { - Byte::new_unchecked(self.0.slice(27..28)) - } - pub fn nth28(&self) -> Byte { - Byte::new_unchecked(self.0.slice(28..29)) - } - pub fn nth29(&self) -> Byte { - Byte::new_unchecked(self.0.slice(29..30)) - } - pub fn nth30(&self) -> Byte { - Byte::new_unchecked(self.0.slice(30..31)) - } - pub fn nth31(&self) -> Byte { - Byte::new_unchecked(self.0.slice(31..32)) - } - pub fn raw_data(&self) -> molecule::bytes::Bytes { - self.as_bytes() - } - pub fn as_reader<'r>(&'r self) -> Byte32Reader<'r> { - Byte32Reader::new_unchecked(self.as_slice()) - } -} -impl molecule::prelude::Entity for Byte32 { - type Builder = Byte32Builder; - const NAME: &'static str = "Byte32"; - fn new_unchecked(data: molecule::bytes::Bytes) -> Self { - Byte32(data) - } - fn as_bytes(&self) -> molecule::bytes::Bytes { - self.0.clone() - } - fn as_slice(&self) -> &[u8] { - &self.0[..] - } - fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { - Byte32Reader::from_slice(slice).map(|reader| reader.to_entity()) - } - fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { - Byte32Reader::from_compatible_slice(slice).map(|reader| reader.to_entity()) - } - fn new_builder() -> Self::Builder { - ::core::default::Default::default() - } - fn as_builder(self) -> Self::Builder { - Self::new_builder().set([ - self.nth0(), - self.nth1(), - self.nth2(), - self.nth3(), - self.nth4(), - self.nth5(), - self.nth6(), - self.nth7(), - self.nth8(), - self.nth9(), - self.nth10(), - self.nth11(), - self.nth12(), - self.nth13(), - self.nth14(), - self.nth15(), - self.nth16(), - self.nth17(), - self.nth18(), - self.nth19(), - self.nth20(), - self.nth21(), - self.nth22(), - self.nth23(), - self.nth24(), - self.nth25(), - self.nth26(), - self.nth27(), - self.nth28(), - self.nth29(), - self.nth30(), - self.nth31(), - ]) - } -} -#[derive(Clone, Copy)] -pub struct Byte32Reader<'r>(&'r [u8]); -impl<'r> ::core::fmt::LowerHex for Byte32Reader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl<'r> ::core::fmt::Debug for Byte32Reader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl<'r> ::core::fmt::Display for Byte32Reader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - let raw_data = hex_string(&self.raw_data()); - write!(f, "{}(0x{})", Self::NAME, raw_data) - } -} -impl<'r> Byte32Reader<'r> { - pub const TOTAL_SIZE: usize = 32; - pub const ITEM_SIZE: usize = 1; - pub const ITEM_COUNT: usize = 32; - pub fn nth0(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[0..1]) - } - pub fn nth1(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[1..2]) - } - pub fn nth2(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[2..3]) - } - pub fn nth3(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[3..4]) - } - pub fn nth4(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[4..5]) - } - pub fn nth5(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[5..6]) - } - pub fn nth6(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[6..7]) - } - pub fn nth7(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[7..8]) - } - pub fn nth8(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[8..9]) - } - pub fn nth9(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[9..10]) - } - pub fn nth10(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[10..11]) - } - pub fn nth11(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[11..12]) - } - pub fn nth12(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[12..13]) - } - pub fn nth13(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[13..14]) - } - pub fn nth14(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[14..15]) - } - pub fn nth15(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[15..16]) - } - pub fn nth16(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[16..17]) - } - pub fn nth17(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[17..18]) - } - pub fn nth18(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[18..19]) - } - pub fn nth19(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[19..20]) - } - pub fn nth20(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[20..21]) - } - pub fn nth21(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[21..22]) - } - pub fn nth22(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[22..23]) - } - pub fn nth23(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[23..24]) - } - pub fn nth24(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[24..25]) - } - pub fn nth25(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[25..26]) - } - pub fn nth26(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[26..27]) - } - pub fn nth27(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[27..28]) - } - pub fn nth28(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[28..29]) - } - pub fn nth29(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[29..30]) - } - pub fn nth30(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[30..31]) - } - pub fn nth31(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[31..32]) - } - pub fn raw_data(&self) -> &'r [u8] { - self.as_slice() - } -} -impl<'r> molecule::prelude::Reader<'r> for Byte32Reader<'r> { - type Entity = Byte32; - const NAME: &'static str = "Byte32Reader"; - fn to_entity(&self) -> Self::Entity { - Self::Entity::new_unchecked(self.as_slice().to_owned().into()) - } - fn new_unchecked(slice: &'r [u8]) -> Self { - Byte32Reader(slice) - } - fn as_slice(&self) -> &'r [u8] { - self.0 - } - fn verify(slice: &[u8], _compatible: bool) -> molecule::error::VerificationResult<()> { - use molecule::verification_error as ve; - let slice_len = slice.len(); - if slice_len != Self::TOTAL_SIZE { - return ve!(Self, TotalSizeNotMatch, Self::TOTAL_SIZE, slice_len); - } - Ok(()) - } -} -pub struct Byte32Builder(pub(crate) [Byte; 32]); -impl ::core::fmt::Debug for Byte32Builder { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:?})", Self::NAME, &self.0[..]) - } -} -impl ::core::default::Default for Byte32Builder { - fn default() -> Self { - Byte32Builder([ - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - ]) - } -} -impl Byte32Builder { - pub const TOTAL_SIZE: usize = 32; - pub const ITEM_SIZE: usize = 1; - pub const ITEM_COUNT: usize = 32; - pub fn set(mut self, v: [Byte; 32]) -> Self { - self.0 = v; - self - } - pub fn nth0(mut self, v: Byte) -> Self { - self.0[0] = v; - self - } - pub fn nth1(mut self, v: Byte) -> Self { - self.0[1] = v; - self - } - pub fn nth2(mut self, v: Byte) -> Self { - self.0[2] = v; - self - } - pub fn nth3(mut self, v: Byte) -> Self { - self.0[3] = v; - self - } - pub fn nth4(mut self, v: Byte) -> Self { - self.0[4] = v; - self - } - pub fn nth5(mut self, v: Byte) -> Self { - self.0[5] = v; - self - } - pub fn nth6(mut self, v: Byte) -> Self { - self.0[6] = v; - self - } - pub fn nth7(mut self, v: Byte) -> Self { - self.0[7] = v; - self - } - pub fn nth8(mut self, v: Byte) -> Self { - self.0[8] = v; - self - } - pub fn nth9(mut self, v: Byte) -> Self { - self.0[9] = v; - self - } - pub fn nth10(mut self, v: Byte) -> Self { - self.0[10] = v; - self - } - pub fn nth11(mut self, v: Byte) -> Self { - self.0[11] = v; - self - } - pub fn nth12(mut self, v: Byte) -> Self { - self.0[12] = v; - self - } - pub fn nth13(mut self, v: Byte) -> Self { - self.0[13] = v; - self - } - pub fn nth14(mut self, v: Byte) -> Self { - self.0[14] = v; - self - } - pub fn nth15(mut self, v: Byte) -> Self { - self.0[15] = v; - self - } - pub fn nth16(mut self, v: Byte) -> Self { - self.0[16] = v; - self - } - pub fn nth17(mut self, v: Byte) -> Self { - self.0[17] = v; - self - } - pub fn nth18(mut self, v: Byte) -> Self { - self.0[18] = v; - self - } - pub fn nth19(mut self, v: Byte) -> Self { - self.0[19] = v; - self - } - pub fn nth20(mut self, v: Byte) -> Self { - self.0[20] = v; - self - } - pub fn nth21(mut self, v: Byte) -> Self { - self.0[21] = v; - self - } - pub fn nth22(mut self, v: Byte) -> Self { - self.0[22] = v; - self - } - pub fn nth23(mut self, v: Byte) -> Self { - self.0[23] = v; - self - } - pub fn nth24(mut self, v: Byte) -> Self { - self.0[24] = v; - self - } - pub fn nth25(mut self, v: Byte) -> Self { - self.0[25] = v; - self - } - pub fn nth26(mut self, v: Byte) -> Self { - self.0[26] = v; - self - } - pub fn nth27(mut self, v: Byte) -> Self { - self.0[27] = v; - self - } - pub fn nth28(mut self, v: Byte) -> Self { - self.0[28] = v; - self - } - pub fn nth29(mut self, v: Byte) -> Self { - self.0[29] = v; - self - } - pub fn nth30(mut self, v: Byte) -> Self { - self.0[30] = v; - self - } - pub fn nth31(mut self, v: Byte) -> Self { - self.0[31] = v; - self - } -} -impl molecule::prelude::Builder for Byte32Builder { - type Entity = Byte32; - const NAME: &'static str = "Byte32Builder"; - fn expected_length(&self) -> usize { - Self::TOTAL_SIZE - } - fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { - writer.write_all(self.0[0].as_slice())?; - writer.write_all(self.0[1].as_slice())?; - writer.write_all(self.0[2].as_slice())?; - writer.write_all(self.0[3].as_slice())?; - writer.write_all(self.0[4].as_slice())?; - writer.write_all(self.0[5].as_slice())?; - writer.write_all(self.0[6].as_slice())?; - writer.write_all(self.0[7].as_slice())?; - writer.write_all(self.0[8].as_slice())?; - writer.write_all(self.0[9].as_slice())?; - writer.write_all(self.0[10].as_slice())?; - writer.write_all(self.0[11].as_slice())?; - writer.write_all(self.0[12].as_slice())?; - writer.write_all(self.0[13].as_slice())?; - writer.write_all(self.0[14].as_slice())?; - writer.write_all(self.0[15].as_slice())?; - writer.write_all(self.0[16].as_slice())?; - writer.write_all(self.0[17].as_slice())?; - writer.write_all(self.0[18].as_slice())?; - writer.write_all(self.0[19].as_slice())?; - writer.write_all(self.0[20].as_slice())?; - writer.write_all(self.0[21].as_slice())?; - writer.write_all(self.0[22].as_slice())?; - writer.write_all(self.0[23].as_slice())?; - writer.write_all(self.0[24].as_slice())?; - writer.write_all(self.0[25].as_slice())?; - writer.write_all(self.0[26].as_slice())?; - writer.write_all(self.0[27].as_slice())?; - writer.write_all(self.0[28].as_slice())?; - writer.write_all(self.0[29].as_slice())?; - writer.write_all(self.0[30].as_slice())?; - writer.write_all(self.0[31].as_slice())?; - Ok(()) - } - fn build(&self) -> Self::Entity { - let mut inner = Vec::with_capacity(self.expected_length()); - self.write(&mut inner) - .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); - Byte32::new_unchecked(inner.into()) - } -} -#[derive(Clone)] -pub struct Bytes(molecule::bytes::Bytes); -impl ::core::fmt::LowerHex for Bytes { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl ::core::fmt::Debug for Bytes { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl ::core::fmt::Display for Bytes { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - let raw_data = hex_string(&self.raw_data()); - write!(f, "{}(0x{})", Self::NAME, raw_data) - } -} -impl ::core::default::Default for Bytes { - fn default() -> Self { - let v: Vec = vec![0, 0, 0, 0]; - Bytes::new_unchecked(v.into()) - } -} -impl Bytes { - pub const ITEM_SIZE: usize = 1; - pub fn total_size(&self) -> usize { - molecule::NUMBER_SIZE * (self.item_count() + 1) - } - pub fn item_count(&self) -> usize { - molecule::unpack_number(self.as_slice()) as usize - } - pub fn len(&self) -> usize { - self.item_count() - } - pub fn is_empty(&self) -> bool { - self.len() == 0 - } - pub fn get(&self, idx: usize) -> Option { - if idx >= self.len() { - None - } else { - Some(self.get_unchecked(idx)) - } - } - pub fn get_unchecked(&self, idx: usize) -> Byte { - let start = molecule::NUMBER_SIZE + Self::ITEM_SIZE * idx; - let end = start + Self::ITEM_SIZE; - Byte::new_unchecked(self.0.slice(start..end)) - } - pub fn raw_data(&self) -> molecule::bytes::Bytes { - self.0.slice(molecule::NUMBER_SIZE..) - } - pub fn as_reader<'r>(&'r self) -> BytesReader<'r> { - BytesReader::new_unchecked(self.as_slice()) - } -} -impl molecule::prelude::Entity for Bytes { - type Builder = BytesBuilder; - const NAME: &'static str = "Bytes"; - fn new_unchecked(data: molecule::bytes::Bytes) -> Self { - Bytes(data) - } - fn as_bytes(&self) -> molecule::bytes::Bytes { - self.0.clone() - } - fn as_slice(&self) -> &[u8] { - &self.0[..] - } - fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { - BytesReader::from_slice(slice).map(|reader| reader.to_entity()) - } - fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { - BytesReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) - } - fn new_builder() -> Self::Builder { - ::core::default::Default::default() - } - fn as_builder(self) -> Self::Builder { - Self::new_builder().extend(self.into_iter()) - } -} -#[derive(Clone, Copy)] -pub struct BytesReader<'r>(&'r [u8]); -impl<'r> ::core::fmt::LowerHex for BytesReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl<'r> ::core::fmt::Debug for BytesReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl<'r> ::core::fmt::Display for BytesReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - let raw_data = hex_string(&self.raw_data()); - write!(f, "{}(0x{})", Self::NAME, raw_data) - } -} -impl<'r> BytesReader<'r> { - pub const ITEM_SIZE: usize = 1; - pub fn total_size(&self) -> usize { - molecule::NUMBER_SIZE * (self.item_count() + 1) - } - pub fn item_count(&self) -> usize { - molecule::unpack_number(self.as_slice()) as usize - } - pub fn len(&self) -> usize { - self.item_count() - } - pub fn is_empty(&self) -> bool { - self.len() == 0 - } - pub fn get(&self, idx: usize) -> Option> { - if idx >= self.len() { - None - } else { - Some(self.get_unchecked(idx)) - } - } - pub fn get_unchecked(&self, idx: usize) -> ByteReader<'r> { - let start = molecule::NUMBER_SIZE + Self::ITEM_SIZE * idx; - let end = start + Self::ITEM_SIZE; - ByteReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn raw_data(&self) -> &'r [u8] { - &self.as_slice()[molecule::NUMBER_SIZE..] - } -} -impl<'r> molecule::prelude::Reader<'r> for BytesReader<'r> { - type Entity = Bytes; - const NAME: &'static str = "BytesReader"; - fn to_entity(&self) -> Self::Entity { - Self::Entity::new_unchecked(self.as_slice().to_owned().into()) - } - fn new_unchecked(slice: &'r [u8]) -> Self { - BytesReader(slice) - } - fn as_slice(&self) -> &'r [u8] { - self.0 - } - fn verify(slice: &[u8], _compatible: bool) -> molecule::error::VerificationResult<()> { - use molecule::verification_error as ve; - let slice_len = slice.len(); - if slice_len < molecule::NUMBER_SIZE { - return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); - } - let item_count = molecule::unpack_number(slice) as usize; - if item_count == 0 { - if slice_len != molecule::NUMBER_SIZE { - return ve!(Self, TotalSizeNotMatch, molecule::NUMBER_SIZE, slice_len); - } - return Ok(()); - } - let total_size = molecule::NUMBER_SIZE + Self::ITEM_SIZE * item_count; - if slice_len != total_size { - return ve!(Self, TotalSizeNotMatch, total_size, slice_len); - } - Ok(()) - } -} -#[derive(Debug, Default)] -pub struct BytesBuilder(pub(crate) Vec); -impl BytesBuilder { - pub const ITEM_SIZE: usize = 1; - pub fn set(mut self, v: Vec) -> Self { - self.0 = v; - self - } - pub fn push(mut self, v: Byte) -> Self { - self.0.push(v); - self - } - pub fn extend>(mut self, iter: T) -> Self { - for elem in iter { - self.0.push(elem); - } - self - } -} -impl molecule::prelude::Builder for BytesBuilder { - type Entity = Bytes; - const NAME: &'static str = "BytesBuilder"; - fn expected_length(&self) -> usize { - molecule::NUMBER_SIZE + Self::ITEM_SIZE * self.0.len() - } - fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { - writer.write_all(&molecule::pack_number(self.0.len() as molecule::Number))?; - for inner in &self.0[..] { - writer.write_all(inner.as_slice())?; - } - Ok(()) - } - fn build(&self) -> Self::Entity { - let mut inner = Vec::with_capacity(self.expected_length()); - self.write(&mut inner) - .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); - Bytes::new_unchecked(inner.into()) - } -} -pub struct BytesIterator(Bytes, usize, usize); -impl ::core::iter::Iterator for BytesIterator { - type Item = Byte; - fn next(&mut self) -> Option { - if self.1 >= self.2 { - None - } else { - let ret = self.0.get_unchecked(self.1); - self.1 += 1; - Some(ret) - } - } -} -impl ::core::iter::ExactSizeIterator for BytesIterator { - fn len(&self) -> usize { - self.2 - self.1 - } -} -impl ::core::iter::IntoIterator for Bytes { - type Item = Byte; - type IntoIter = BytesIterator; - fn into_iter(self) -> Self::IntoIter { - let len = self.len(); - BytesIterator(self, 0, len) - } -} -#[derive(Clone)] -pub struct Uint32(molecule::bytes::Bytes); -impl ::core::fmt::LowerHex for Uint32 { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl ::core::fmt::Debug for Uint32 { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl ::core::fmt::Display for Uint32 { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - let raw_data = hex_string(&self.raw_data()); - write!(f, "{}(0x{})", Self::NAME, raw_data) - } -} -impl ::core::default::Default for Uint32 { - fn default() -> Self { - let v: Vec = vec![0, 0, 0, 0]; - Uint32::new_unchecked(v.into()) - } -} -impl Uint32 { - pub const TOTAL_SIZE: usize = 4; - pub const ITEM_SIZE: usize = 1; - pub const ITEM_COUNT: usize = 4; - pub fn nth0(&self) -> Byte { - Byte::new_unchecked(self.0.slice(0..1)) - } - pub fn nth1(&self) -> Byte { - Byte::new_unchecked(self.0.slice(1..2)) - } - pub fn nth2(&self) -> Byte { - Byte::new_unchecked(self.0.slice(2..3)) - } - pub fn nth3(&self) -> Byte { - Byte::new_unchecked(self.0.slice(3..4)) - } - pub fn raw_data(&self) -> molecule::bytes::Bytes { - self.as_bytes() - } - pub fn as_reader<'r>(&'r self) -> Uint32Reader<'r> { - Uint32Reader::new_unchecked(self.as_slice()) - } -} -impl molecule::prelude::Entity for Uint32 { - type Builder = Uint32Builder; - const NAME: &'static str = "Uint32"; - fn new_unchecked(data: molecule::bytes::Bytes) -> Self { - Uint32(data) - } - fn as_bytes(&self) -> molecule::bytes::Bytes { - self.0.clone() - } - fn as_slice(&self) -> &[u8] { - &self.0[..] - } - fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { - Uint32Reader::from_slice(slice).map(|reader| reader.to_entity()) - } - fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { - Uint32Reader::from_compatible_slice(slice).map(|reader| reader.to_entity()) - } - fn new_builder() -> Self::Builder { - ::core::default::Default::default() - } - fn as_builder(self) -> Self::Builder { - Self::new_builder().set([self.nth0(), self.nth1(), self.nth2(), self.nth3()]) - } -} -#[derive(Clone, Copy)] -pub struct Uint32Reader<'r>(&'r [u8]); -impl<'r> ::core::fmt::LowerHex for Uint32Reader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl<'r> ::core::fmt::Debug for Uint32Reader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl<'r> ::core::fmt::Display for Uint32Reader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - let raw_data = hex_string(&self.raw_data()); - write!(f, "{}(0x{})", Self::NAME, raw_data) - } -} -impl<'r> Uint32Reader<'r> { - pub const TOTAL_SIZE: usize = 4; - pub const ITEM_SIZE: usize = 1; - pub const ITEM_COUNT: usize = 4; - pub fn nth0(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[0..1]) - } - pub fn nth1(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[1..2]) - } - pub fn nth2(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[2..3]) - } - pub fn nth3(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[3..4]) - } - pub fn raw_data(&self) -> &'r [u8] { - self.as_slice() - } -} -impl<'r> molecule::prelude::Reader<'r> for Uint32Reader<'r> { - type Entity = Uint32; - const NAME: &'static str = "Uint32Reader"; - fn to_entity(&self) -> Self::Entity { - Self::Entity::new_unchecked(self.as_slice().to_owned().into()) - } - fn new_unchecked(slice: &'r [u8]) -> Self { - Uint32Reader(slice) - } - fn as_slice(&self) -> &'r [u8] { - self.0 - } - fn verify(slice: &[u8], _compatible: bool) -> molecule::error::VerificationResult<()> { - use molecule::verification_error as ve; - let slice_len = slice.len(); - if slice_len != Self::TOTAL_SIZE { - return ve!(Self, TotalSizeNotMatch, Self::TOTAL_SIZE, slice_len); - } - Ok(()) - } -} -pub struct Uint32Builder(pub(crate) [Byte; 4]); -impl ::core::fmt::Debug for Uint32Builder { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:?})", Self::NAME, &self.0[..]) - } -} -impl ::core::default::Default for Uint32Builder { - fn default() -> Self { - Uint32Builder([ - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - ]) - } -} -impl Uint32Builder { - pub const TOTAL_SIZE: usize = 4; - pub const ITEM_SIZE: usize = 1; - pub const ITEM_COUNT: usize = 4; - pub fn set(mut self, v: [Byte; 4]) -> Self { - self.0 = v; - self - } - pub fn nth0(mut self, v: Byte) -> Self { - self.0[0] = v; - self - } - pub fn nth1(mut self, v: Byte) -> Self { - self.0[1] = v; - self - } - pub fn nth2(mut self, v: Byte) -> Self { - self.0[2] = v; - self - } - pub fn nth3(mut self, v: Byte) -> Self { - self.0[3] = v; - self - } -} -impl molecule::prelude::Builder for Uint32Builder { - type Entity = Uint32; - const NAME: &'static str = "Uint32Builder"; - fn expected_length(&self) -> usize { - Self::TOTAL_SIZE - } - fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { - writer.write_all(self.0[0].as_slice())?; - writer.write_all(self.0[1].as_slice())?; - writer.write_all(self.0[2].as_slice())?; - writer.write_all(self.0[3].as_slice())?; - Ok(()) - } - fn build(&self) -> Self::Entity { - let mut inner = Vec::with_capacity(self.expected_length()); - self.write(&mut inner) - .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); - Uint32::new_unchecked(inner.into()) - } -} -#[derive(Clone)] -pub struct Uint64(molecule::bytes::Bytes); -impl ::core::fmt::LowerHex for Uint64 { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl ::core::fmt::Debug for Uint64 { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl ::core::fmt::Display for Uint64 { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - let raw_data = hex_string(&self.raw_data()); - write!(f, "{}(0x{})", Self::NAME, raw_data) - } -} -impl ::core::default::Default for Uint64 { - fn default() -> Self { - let v: Vec = vec![0, 0, 0, 0, 0, 0, 0, 0]; - Uint64::new_unchecked(v.into()) - } -} -impl Uint64 { - pub const TOTAL_SIZE: usize = 8; - pub const ITEM_SIZE: usize = 1; - pub const ITEM_COUNT: usize = 8; - pub fn nth0(&self) -> Byte { - Byte::new_unchecked(self.0.slice(0..1)) - } - pub fn nth1(&self) -> Byte { - Byte::new_unchecked(self.0.slice(1..2)) - } - pub fn nth2(&self) -> Byte { - Byte::new_unchecked(self.0.slice(2..3)) - } - pub fn nth3(&self) -> Byte { - Byte::new_unchecked(self.0.slice(3..4)) - } - pub fn nth4(&self) -> Byte { - Byte::new_unchecked(self.0.slice(4..5)) - } - pub fn nth5(&self) -> Byte { - Byte::new_unchecked(self.0.slice(5..6)) - } - pub fn nth6(&self) -> Byte { - Byte::new_unchecked(self.0.slice(6..7)) - } - pub fn nth7(&self) -> Byte { - Byte::new_unchecked(self.0.slice(7..8)) - } - pub fn raw_data(&self) -> molecule::bytes::Bytes { - self.as_bytes() - } - pub fn as_reader<'r>(&'r self) -> Uint64Reader<'r> { - Uint64Reader::new_unchecked(self.as_slice()) - } -} -impl molecule::prelude::Entity for Uint64 { - type Builder = Uint64Builder; - const NAME: &'static str = "Uint64"; - fn new_unchecked(data: molecule::bytes::Bytes) -> Self { - Uint64(data) - } - fn as_bytes(&self) -> molecule::bytes::Bytes { - self.0.clone() - } - fn as_slice(&self) -> &[u8] { - &self.0[..] - } - fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { - Uint64Reader::from_slice(slice).map(|reader| reader.to_entity()) - } - fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { - Uint64Reader::from_compatible_slice(slice).map(|reader| reader.to_entity()) - } - fn new_builder() -> Self::Builder { - ::core::default::Default::default() - } - fn as_builder(self) -> Self::Builder { - Self::new_builder().set([ - self.nth0(), - self.nth1(), - self.nth2(), - self.nth3(), - self.nth4(), - self.nth5(), - self.nth6(), - self.nth7(), - ]) - } -} -#[derive(Clone, Copy)] -pub struct Uint64Reader<'r>(&'r [u8]); -impl<'r> ::core::fmt::LowerHex for Uint64Reader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl<'r> ::core::fmt::Debug for Uint64Reader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl<'r> ::core::fmt::Display for Uint64Reader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - let raw_data = hex_string(&self.raw_data()); - write!(f, "{}(0x{})", Self::NAME, raw_data) - } -} -impl<'r> Uint64Reader<'r> { - pub const TOTAL_SIZE: usize = 8; - pub const ITEM_SIZE: usize = 1; - pub const ITEM_COUNT: usize = 8; - pub fn nth0(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[0..1]) - } - pub fn nth1(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[1..2]) - } - pub fn nth2(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[2..3]) - } - pub fn nth3(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[3..4]) - } - pub fn nth4(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[4..5]) - } - pub fn nth5(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[5..6]) - } - pub fn nth6(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[6..7]) - } - pub fn nth7(&self) -> ByteReader<'r> { - ByteReader::new_unchecked(&self.as_slice()[7..8]) - } - pub fn raw_data(&self) -> &'r [u8] { - self.as_slice() - } -} -impl<'r> molecule::prelude::Reader<'r> for Uint64Reader<'r> { - type Entity = Uint64; - const NAME: &'static str = "Uint64Reader"; - fn to_entity(&self) -> Self::Entity { - Self::Entity::new_unchecked(self.as_slice().to_owned().into()) - } - fn new_unchecked(slice: &'r [u8]) -> Self { - Uint64Reader(slice) - } - fn as_slice(&self) -> &'r [u8] { - self.0 - } - fn verify(slice: &[u8], _compatible: bool) -> molecule::error::VerificationResult<()> { - use molecule::verification_error as ve; - let slice_len = slice.len(); - if slice_len != Self::TOTAL_SIZE { - return ve!(Self, TotalSizeNotMatch, Self::TOTAL_SIZE, slice_len); - } - Ok(()) - } -} -pub struct Uint64Builder(pub(crate) [Byte; 8]); -impl ::core::fmt::Debug for Uint64Builder { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:?})", Self::NAME, &self.0[..]) - } -} -impl ::core::default::Default for Uint64Builder { - fn default() -> Self { - Uint64Builder([ - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - Byte::default(), - ]) - } -} -impl Uint64Builder { - pub const TOTAL_SIZE: usize = 8; - pub const ITEM_SIZE: usize = 1; - pub const ITEM_COUNT: usize = 8; - pub fn set(mut self, v: [Byte; 8]) -> Self { - self.0 = v; - self - } - pub fn nth0(mut self, v: Byte) -> Self { - self.0[0] = v; - self - } - pub fn nth1(mut self, v: Byte) -> Self { - self.0[1] = v; - self - } - pub fn nth2(mut self, v: Byte) -> Self { - self.0[2] = v; - self - } - pub fn nth3(mut self, v: Byte) -> Self { - self.0[3] = v; - self - } - pub fn nth4(mut self, v: Byte) -> Self { - self.0[4] = v; - self - } - pub fn nth5(mut self, v: Byte) -> Self { - self.0[5] = v; - self - } - pub fn nth6(mut self, v: Byte) -> Self { - self.0[6] = v; - self - } - pub fn nth7(mut self, v: Byte) -> Self { - self.0[7] = v; - self - } -} -impl molecule::prelude::Builder for Uint64Builder { - type Entity = Uint64; - const NAME: &'static str = "Uint64Builder"; - fn expected_length(&self) -> usize { - Self::TOTAL_SIZE - } - fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { - writer.write_all(self.0[0].as_slice())?; - writer.write_all(self.0[1].as_slice())?; - writer.write_all(self.0[2].as_slice())?; - writer.write_all(self.0[3].as_slice())?; - writer.write_all(self.0[4].as_slice())?; - writer.write_all(self.0[5].as_slice())?; - writer.write_all(self.0[6].as_slice())?; - writer.write_all(self.0[7].as_slice())?; - Ok(()) - } - fn build(&self) -> Self::Entity { - let mut inner = Vec::with_capacity(self.expected_length()); - self.write(&mut inner) - .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); - Uint64::new_unchecked(inner.into()) - } -} -#[derive(Clone)] -pub struct Script(molecule::bytes::Bytes); -impl ::core::fmt::LowerHex for Script { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl ::core::fmt::Debug for Script { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl ::core::fmt::Display for Script { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{} {{ ", Self::NAME)?; - write!(f, "{}: {}", "code_hash", self.code_hash())?; - write!(f, ", {}: {}", "hash_type", self.hash_type())?; - write!(f, ", {}: {}", "args", self.args())?; - let extra_count = self.count_extra_fields(); - if extra_count != 0 { - write!(f, ", .. ({} fields)", extra_count)?; - } - write!(f, " }}") - } -} -impl ::core::default::Default for Script { - fn default() -> Self { - let v: Vec = vec![ - 53, 0, 0, 0, 16, 0, 0, 0, 48, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ]; - Script::new_unchecked(v.into()) - } -} -impl Script { - pub const FIELD_COUNT: usize = 3; - pub fn total_size(&self) -> usize { - molecule::unpack_number(self.as_slice()) as usize - } - pub fn field_count(&self) -> usize { - if self.total_size() == molecule::NUMBER_SIZE { - 0 - } else { - (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 - } - } - pub fn count_extra_fields(&self) -> usize { - self.field_count() - Self::FIELD_COUNT - } - pub fn has_extra_fields(&self) -> bool { - Self::FIELD_COUNT != self.field_count() - } - pub fn code_hash(&self) -> Byte32 { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[4..]) as usize; - let end = molecule::unpack_number(&slice[8..]) as usize; - Byte32::new_unchecked(self.0.slice(start..end)) - } - pub fn hash_type(&self) -> Byte { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[8..]) as usize; - let end = molecule::unpack_number(&slice[12..]) as usize; - Byte::new_unchecked(self.0.slice(start..end)) - } - pub fn args(&self) -> Bytes { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[12..]) as usize; - if self.has_extra_fields() { - let end = molecule::unpack_number(&slice[16..]) as usize; - Bytes::new_unchecked(self.0.slice(start..end)) - } else { - Bytes::new_unchecked(self.0.slice(start..)) - } - } - pub fn as_reader<'r>(&'r self) -> ScriptReader<'r> { - ScriptReader::new_unchecked(self.as_slice()) - } -} -impl molecule::prelude::Entity for Script { - type Builder = ScriptBuilder; - const NAME: &'static str = "Script"; - fn new_unchecked(data: molecule::bytes::Bytes) -> Self { - Script(data) - } - fn as_bytes(&self) -> molecule::bytes::Bytes { - self.0.clone() - } - fn as_slice(&self) -> &[u8] { - &self.0[..] - } - fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { - ScriptReader::from_slice(slice).map(|reader| reader.to_entity()) - } - fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { - ScriptReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) - } - fn new_builder() -> Self::Builder { - ::core::default::Default::default() - } - fn as_builder(self) -> Self::Builder { - Self::new_builder() - .code_hash(self.code_hash()) - .hash_type(self.hash_type()) - .args(self.args()) - } -} -#[derive(Clone, Copy)] -pub struct ScriptReader<'r>(&'r [u8]); -impl<'r> ::core::fmt::LowerHex for ScriptReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl<'r> ::core::fmt::Debug for ScriptReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl<'r> ::core::fmt::Display for ScriptReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{} {{ ", Self::NAME)?; - write!(f, "{}: {}", "code_hash", self.code_hash())?; - write!(f, ", {}: {}", "hash_type", self.hash_type())?; - write!(f, ", {}: {}", "args", self.args())?; - let extra_count = self.count_extra_fields(); - if extra_count != 0 { - write!(f, ", .. ({} fields)", extra_count)?; - } - write!(f, " }}") - } -} -impl<'r> ScriptReader<'r> { - pub const FIELD_COUNT: usize = 3; - pub fn total_size(&self) -> usize { - molecule::unpack_number(self.as_slice()) as usize - } - pub fn field_count(&self) -> usize { - if self.total_size() == molecule::NUMBER_SIZE { - 0 - } else { - (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 - } - } - pub fn count_extra_fields(&self) -> usize { - self.field_count() - Self::FIELD_COUNT - } - pub fn has_extra_fields(&self) -> bool { - Self::FIELD_COUNT != self.field_count() - } - pub fn code_hash(&self) -> Byte32Reader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[4..]) as usize; - let end = molecule::unpack_number(&slice[8..]) as usize; - Byte32Reader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn hash_type(&self) -> ByteReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[8..]) as usize; - let end = molecule::unpack_number(&slice[12..]) as usize; - ByteReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn args(&self) -> BytesReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[12..]) as usize; - if self.has_extra_fields() { - let end = molecule::unpack_number(&slice[16..]) as usize; - BytesReader::new_unchecked(&self.as_slice()[start..end]) - } else { - BytesReader::new_unchecked(&self.as_slice()[start..]) - } - } -} -impl<'r> molecule::prelude::Reader<'r> for ScriptReader<'r> { - type Entity = Script; - const NAME: &'static str = "ScriptReader"; - fn to_entity(&self) -> Self::Entity { - Self::Entity::new_unchecked(self.as_slice().to_owned().into()) - } - fn new_unchecked(slice: &'r [u8]) -> Self { - ScriptReader(slice) - } - fn as_slice(&self) -> &'r [u8] { - self.0 - } - fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { - use molecule::verification_error as ve; - let slice_len = slice.len(); - if slice_len < molecule::NUMBER_SIZE { - return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); - } - let total_size = molecule::unpack_number(slice) as usize; - if slice_len != total_size { - return ve!(Self, TotalSizeNotMatch, total_size, slice_len); - } - if slice_len == molecule::NUMBER_SIZE && Self::FIELD_COUNT == 0 { - return Ok(()); - } - if slice_len < molecule::NUMBER_SIZE * 2 { - return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); - } - let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; - if offset_first % 4 != 0 || offset_first < molecule::NUMBER_SIZE * 2 { - return ve!(Self, OffsetsNotMatch); - } - let field_count = offset_first / 4 - 1; - if field_count < Self::FIELD_COUNT { - return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); - } else if !compatible && field_count > Self::FIELD_COUNT { - return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); - }; - let header_size = molecule::NUMBER_SIZE * (field_count + 1); - if slice_len < header_size { - return ve!(Self, HeaderIsBroken, header_size, slice_len); - } - let mut offsets: Vec = slice[molecule::NUMBER_SIZE..] - .chunks(molecule::NUMBER_SIZE) - .take(field_count) - .map(|x| molecule::unpack_number(x) as usize) - .collect(); - offsets.push(total_size); - if offsets.windows(2).any(|i| i[0] > i[1]) { - return ve!(Self, OffsetsNotMatch); - } - Byte32Reader::verify(&slice[offsets[0]..offsets[1]], compatible)?; - ByteReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; - BytesReader::verify(&slice[offsets[2]..offsets[3]], compatible)?; - Ok(()) - } -} -#[derive(Debug, Default)] -pub struct ScriptBuilder { - pub(crate) code_hash: Byte32, - pub(crate) hash_type: Byte, - pub(crate) args: Bytes, -} -impl ScriptBuilder { - pub const FIELD_COUNT: usize = 3; - pub fn code_hash(mut self, v: Byte32) -> Self { - self.code_hash = v; - self - } - pub fn hash_type(mut self, v: Byte) -> Self { - self.hash_type = v; - self - } - pub fn args(mut self, v: Bytes) -> Self { - self.args = v; - self - } -} -impl molecule::prelude::Builder for ScriptBuilder { - type Entity = Script; - const NAME: &'static str = "ScriptBuilder"; - fn expected_length(&self) -> usize { - molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) - + self.code_hash.as_slice().len() - + self.hash_type.as_slice().len() - + self.args.as_slice().len() - } - fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { - let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); - let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); - offsets.push(total_size); - total_size += self.code_hash.as_slice().len(); - offsets.push(total_size); - total_size += self.hash_type.as_slice().len(); - offsets.push(total_size); - total_size += self.args.as_slice().len(); - writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; - for offset in offsets.into_iter() { - writer.write_all(&molecule::pack_number(offset as molecule::Number))?; - } - writer.write_all(self.code_hash.as_slice())?; - writer.write_all(self.hash_type.as_slice())?; - writer.write_all(self.args.as_slice())?; - Ok(()) - } - fn build(&self) -> Self::Entity { - let mut inner = Vec::with_capacity(self.expected_length()); - self.write(&mut inner) - .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); - Script::new_unchecked(inner.into()) - } -} +use molecule :: prelude :: * ; +# [ derive ( Clone ) ] pub struct Byte4 ( molecule :: bytes :: Bytes ) ; impl :: core :: fmt :: LowerHex for Byte4 { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl :: core :: fmt :: Debug for Byte4 { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl :: core :: fmt :: Display for Byte4 { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; let raw_data = hex_string ( & self . raw_data ( ) ) ; write ! ( f , "{}(0x{})" , Self :: NAME , raw_data ) } } impl :: core :: default :: Default for Byte4 { fn default ( ) -> Self { let v : Vec < u8 > = vec ! [ 0 , 0 , 0 , 0 , ] ; Byte4 :: new_unchecked ( v . into ( ) ) } } impl Byte4 { pub const TOTAL_SIZE : usize = 4 ; pub const ITEM_SIZE : usize = 1 ; pub const ITEM_COUNT : usize = 4 ; pub fn nth0 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 0 .. 1 ) ) } pub fn nth1 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 1 .. 2 ) ) } pub fn nth2 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 2 .. 3 ) ) } pub fn nth3 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 3 .. 4 ) ) } pub fn raw_data ( & self ) -> molecule :: bytes :: Bytes { self . as_bytes ( ) } pub fn as_reader < 'r > ( & 'r self ) -> Byte4Reader < 'r > { Byte4Reader :: new_unchecked ( self . as_slice ( ) ) } } impl molecule :: prelude :: Entity for Byte4 { type Builder = Byte4Builder ; const NAME : & 'static str = "Byte4" ; fn new_unchecked ( data : molecule :: bytes :: Bytes ) -> Self { Byte4 ( data ) } fn as_bytes ( & self ) -> molecule :: bytes :: Bytes { self . 0 . clone ( ) } fn as_slice ( & self ) -> & [ u8 ] { & self . 0 [ .. ] } fn from_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { Byte4Reader :: from_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn from_compatible_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { Byte4Reader :: from_compatible_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn new_builder ( ) -> Self :: Builder { :: core :: default :: Default :: default ( ) } fn as_builder ( self ) -> Self :: Builder { Self :: new_builder ( ) . set ( [ self . nth0 ( ) , self . nth1 ( ) , self . nth2 ( ) , self . nth3 ( ) , ] ) } } +# [ derive ( Clone , Copy ) ] pub struct Byte4Reader < 'r > ( & 'r [ u8 ] ) ; impl < 'r > :: core :: fmt :: LowerHex for Byte4Reader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl < 'r > :: core :: fmt :: Debug for Byte4Reader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl < 'r > :: core :: fmt :: Display for Byte4Reader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; let raw_data = hex_string ( & self . raw_data ( ) ) ; write ! ( f , "{}(0x{})" , Self :: NAME , raw_data ) } } impl < 'r > Byte4Reader < 'r > { pub const TOTAL_SIZE : usize = 4 ; pub const ITEM_SIZE : usize = 1 ; pub const ITEM_COUNT : usize = 4 ; pub fn nth0 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 0 .. 1 ] ) } pub fn nth1 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 1 .. 2 ] ) } pub fn nth2 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 2 .. 3 ] ) } pub fn nth3 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 3 .. 4 ] ) } pub fn raw_data ( & self ) -> & 'r [ u8 ] { self . as_slice ( ) } } impl < 'r > molecule :: prelude :: Reader < 'r > for Byte4Reader < 'r > { type Entity = Byte4 ; const NAME : & 'static str = "Byte4Reader" ; fn to_entity ( & self ) -> Self :: Entity { Self :: Entity :: new_unchecked ( self . as_slice ( ) . to_owned ( ) . into ( ) ) } fn new_unchecked ( slice : & 'r [ u8 ] ) -> Self { Byte4Reader ( slice ) } fn as_slice ( & self ) -> & 'r [ u8 ] { self . 0 } fn verify ( slice : & [ u8 ] , _compatible : bool ) -> molecule :: error :: VerificationResult < ( ) > { use molecule :: verification_error as ve ; let slice_len = slice . len ( ) ; if slice_len != Self :: TOTAL_SIZE { return ve ! ( Self , TotalSizeNotMatch , Self :: TOTAL_SIZE , slice_len ) ; } Ok ( ( ) ) } } +pub struct Byte4Builder ( pub ( crate ) [ Byte ; 4 ] ) ; impl :: core :: fmt :: Debug for Byte4Builder { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:?})" , Self :: NAME , & self . 0 [ .. ] ) } } impl :: core :: default :: Default for Byte4Builder { fn default ( ) -> Self { Byte4Builder ( [ Byte :: default ( ) , Byte :: default ( ) , Byte :: default ( ) , Byte :: default ( ) , ] ) } } impl Byte4Builder { pub const TOTAL_SIZE : usize = 4 ; pub const ITEM_SIZE : usize = 1 ; pub const ITEM_COUNT : usize = 4 ; pub fn set ( mut self , v : [ Byte ; 4 ] ) -> Self { self . 0 = v ; self } pub fn nth0 ( mut self , v : Byte ) -> Self { self . 0 [ 0 ] = v ; self } pub fn nth1 ( mut self , v : Byte ) -> Self { self . 0 [ 1 ] = v ; self } pub fn nth2 ( mut self , v : Byte ) -> Self { self . 0 [ 2 ] = v ; self } pub fn nth3 ( mut self , v : Byte ) -> Self { self . 0 [ 3 ] = v ; self } } impl molecule :: prelude :: Builder for Byte4Builder { type Entity = Byte4 ; const NAME : & 'static str = "Byte4Builder" ; fn expected_length ( & self ) -> usize { Self :: TOTAL_SIZE } fn write < W : :: molecule :: io :: Write > ( & self , writer : & mut W ) -> :: molecule :: io :: Result < ( ) > { writer . write_all ( self . 0 [ 0 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 1 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 2 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 3 ] . as_slice ( ) ) ? ; Ok ( ( ) ) } fn build ( & self ) -> Self :: Entity { let mut inner = Vec :: with_capacity ( self . expected_length ( ) ) ; self . write ( & mut inner ) . unwrap_or_else ( | _ | panic ! ( "{} build should be ok" , Self :: NAME ) ) ; Byte4 :: new_unchecked ( inner . into ( ) ) } } +# [ derive ( Clone ) ] pub struct Byte32 ( molecule :: bytes :: Bytes ) ; impl :: core :: fmt :: LowerHex for Byte32 { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl :: core :: fmt :: Debug for Byte32 { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl :: core :: fmt :: Display for Byte32 { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; let raw_data = hex_string ( & self . raw_data ( ) ) ; write ! ( f , "{}(0x{})" , Self :: NAME , raw_data ) } } impl :: core :: default :: Default for Byte32 { fn default ( ) -> Self { let v : Vec < u8 > = vec ! [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , ] ; Byte32 :: new_unchecked ( v . into ( ) ) } } impl Byte32 { pub const TOTAL_SIZE : usize = 32 ; pub const ITEM_SIZE : usize = 1 ; pub const ITEM_COUNT : usize = 32 ; pub fn nth0 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 0 .. 1 ) ) } pub fn nth1 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 1 .. 2 ) ) } pub fn nth2 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 2 .. 3 ) ) } pub fn nth3 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 3 .. 4 ) ) } pub fn nth4 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 4 .. 5 ) ) } pub fn nth5 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 5 .. 6 ) ) } pub fn nth6 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 6 .. 7 ) ) } pub fn nth7 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 7 .. 8 ) ) } pub fn nth8 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 8 .. 9 ) ) } pub fn nth9 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 9 .. 10 ) ) } pub fn nth10 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 10 .. 11 ) ) } pub fn nth11 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 11 .. 12 ) ) } pub fn nth12 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 12 .. 13 ) ) } pub fn nth13 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 13 .. 14 ) ) } pub fn nth14 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 14 .. 15 ) ) } pub fn nth15 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 15 .. 16 ) ) } pub fn nth16 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 16 .. 17 ) ) } pub fn nth17 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 17 .. 18 ) ) } pub fn nth18 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 18 .. 19 ) ) } pub fn nth19 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 19 .. 20 ) ) } pub fn nth20 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 20 .. 21 ) ) } pub fn nth21 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 21 .. 22 ) ) } pub fn nth22 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 22 .. 23 ) ) } pub fn nth23 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 23 .. 24 ) ) } pub fn nth24 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 24 .. 25 ) ) } pub fn nth25 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 25 .. 26 ) ) } pub fn nth26 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 26 .. 27 ) ) } pub fn nth27 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 27 .. 28 ) ) } pub fn nth28 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 28 .. 29 ) ) } pub fn nth29 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 29 .. 30 ) ) } pub fn nth30 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 30 .. 31 ) ) } pub fn nth31 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 31 .. 32 ) ) } pub fn raw_data ( & self ) -> molecule :: bytes :: Bytes { self . as_bytes ( ) } pub fn as_reader < 'r > ( & 'r self ) -> Byte32Reader < 'r > { Byte32Reader :: new_unchecked ( self . as_slice ( ) ) } } impl molecule :: prelude :: Entity for Byte32 { type Builder = Byte32Builder ; const NAME : & 'static str = "Byte32" ; fn new_unchecked ( data : molecule :: bytes :: Bytes ) -> Self { Byte32 ( data ) } fn as_bytes ( & self ) -> molecule :: bytes :: Bytes { self . 0 . clone ( ) } fn as_slice ( & self ) -> & [ u8 ] { & self . 0 [ .. ] } fn from_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { Byte32Reader :: from_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn from_compatible_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { Byte32Reader :: from_compatible_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn new_builder ( ) -> Self :: Builder { :: core :: default :: Default :: default ( ) } fn as_builder ( self ) -> Self :: Builder { Self :: new_builder ( ) . set ( [ self . nth0 ( ) , self . nth1 ( ) , self . nth2 ( ) , self . nth3 ( ) , self . nth4 ( ) , self . nth5 ( ) , self . nth6 ( ) , self . nth7 ( ) , self . nth8 ( ) , self . nth9 ( ) , self . nth10 ( ) , self . nth11 ( ) , self . nth12 ( ) , self . nth13 ( ) , self . nth14 ( ) , self . nth15 ( ) , self . nth16 ( ) , self . nth17 ( ) , self . nth18 ( ) , self . nth19 ( ) , self . nth20 ( ) , self . nth21 ( ) , self . nth22 ( ) , self . nth23 ( ) , self . nth24 ( ) , self . nth25 ( ) , self . nth26 ( ) , self . nth27 ( ) , self . nth28 ( ) , self . nth29 ( ) , self . nth30 ( ) , self . nth31 ( ) , ] ) } } +# [ derive ( Clone , Copy ) ] pub struct Byte32Reader < 'r > ( & 'r [ u8 ] ) ; impl < 'r > :: core :: fmt :: LowerHex for Byte32Reader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl < 'r > :: core :: fmt :: Debug for Byte32Reader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl < 'r > :: core :: fmt :: Display for Byte32Reader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; let raw_data = hex_string ( & self . raw_data ( ) ) ; write ! ( f , "{}(0x{})" , Self :: NAME , raw_data ) } } impl < 'r > Byte32Reader < 'r > { pub const TOTAL_SIZE : usize = 32 ; pub const ITEM_SIZE : usize = 1 ; pub const ITEM_COUNT : usize = 32 ; pub fn nth0 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 0 .. 1 ] ) } pub fn nth1 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 1 .. 2 ] ) } pub fn nth2 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 2 .. 3 ] ) } pub fn nth3 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 3 .. 4 ] ) } pub fn nth4 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 4 .. 5 ] ) } pub fn nth5 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 5 .. 6 ] ) } pub fn nth6 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 6 .. 7 ] ) } pub fn nth7 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 7 .. 8 ] ) } pub fn nth8 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 8 .. 9 ] ) } pub fn nth9 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 9 .. 10 ] ) } pub fn nth10 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 10 .. 11 ] ) } pub fn nth11 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 11 .. 12 ] ) } pub fn nth12 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 12 .. 13 ] ) } pub fn nth13 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 13 .. 14 ] ) } pub fn nth14 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 14 .. 15 ] ) } pub fn nth15 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 15 .. 16 ] ) } pub fn nth16 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 16 .. 17 ] ) } pub fn nth17 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 17 .. 18 ] ) } pub fn nth18 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 18 .. 19 ] ) } pub fn nth19 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 19 .. 20 ] ) } pub fn nth20 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 20 .. 21 ] ) } pub fn nth21 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 21 .. 22 ] ) } pub fn nth22 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 22 .. 23 ] ) } pub fn nth23 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 23 .. 24 ] ) } pub fn nth24 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 24 .. 25 ] ) } pub fn nth25 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 25 .. 26 ] ) } pub fn nth26 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 26 .. 27 ] ) } pub fn nth27 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 27 .. 28 ] ) } pub fn nth28 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 28 .. 29 ] ) } pub fn nth29 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 29 .. 30 ] ) } pub fn nth30 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 30 .. 31 ] ) } pub fn nth31 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 31 .. 32 ] ) } pub fn raw_data ( & self ) -> & 'r [ u8 ] { self . as_slice ( ) } } impl < 'r > molecule :: prelude :: Reader < 'r > for Byte32Reader < 'r > { type Entity = Byte32 ; const NAME : & 'static str = "Byte32Reader" ; fn to_entity ( & self ) -> Self :: Entity { Self :: Entity :: new_unchecked ( self . as_slice ( ) . to_owned ( ) . into ( ) ) } fn new_unchecked ( slice : & 'r [ u8 ] ) -> Self { Byte32Reader ( slice ) } fn as_slice ( & self ) -> & 'r [ u8 ] { self . 0 } fn verify ( slice : & [ u8 ] , _compatible : bool ) -> molecule :: error :: VerificationResult < ( ) > { use molecule :: verification_error as ve ; let slice_len = slice . len ( ) ; if slice_len != Self :: TOTAL_SIZE { return ve ! ( Self , TotalSizeNotMatch , Self :: TOTAL_SIZE , slice_len ) ; } Ok ( ( ) ) } } +pub struct Byte32Builder ( pub ( crate ) [ Byte ; 32 ] ) ; impl :: core :: fmt :: Debug for Byte32Builder { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:?})" , Self :: NAME , & self . 0 [ .. ] ) } } impl :: core :: default :: Default for Byte32Builder { fn default ( ) -> Self { Byte32Builder ( [ Byte :: default ( ) , Byte :: default ( ) , Byte :: default ( ) , Byte :: default ( ) , Byte :: default ( ) , Byte :: default ( ) , Byte :: default ( ) , Byte :: default ( ) , Byte :: default ( ) , Byte :: default ( ) , Byte :: default ( ) , Byte :: default ( ) , Byte :: default ( ) , Byte :: default ( ) , Byte :: default ( ) , Byte :: default ( ) , Byte :: default ( ) , Byte :: default ( ) , Byte :: default ( ) , Byte :: default ( ) , Byte :: default ( ) , Byte :: default ( ) , Byte :: default ( ) , Byte :: default ( ) , Byte :: default ( ) , Byte :: default ( ) , Byte :: default ( ) , Byte :: default ( ) , Byte :: default ( ) , Byte :: default ( ) , Byte :: default ( ) , Byte :: default ( ) , ] ) } } impl Byte32Builder { pub const TOTAL_SIZE : usize = 32 ; pub const ITEM_SIZE : usize = 1 ; pub const ITEM_COUNT : usize = 32 ; pub fn set ( mut self , v : [ Byte ; 32 ] ) -> Self { self . 0 = v ; self } pub fn nth0 ( mut self , v : Byte ) -> Self { self . 0 [ 0 ] = v ; self } pub fn nth1 ( mut self , v : Byte ) -> Self { self . 0 [ 1 ] = v ; self } pub fn nth2 ( mut self , v : Byte ) -> Self { self . 0 [ 2 ] = v ; self } pub fn nth3 ( mut self , v : Byte ) -> Self { self . 0 [ 3 ] = v ; self } pub fn nth4 ( mut self , v : Byte ) -> Self { self . 0 [ 4 ] = v ; self } pub fn nth5 ( mut self , v : Byte ) -> Self { self . 0 [ 5 ] = v ; self } pub fn nth6 ( mut self , v : Byte ) -> Self { self . 0 [ 6 ] = v ; self } pub fn nth7 ( mut self , v : Byte ) -> Self { self . 0 [ 7 ] = v ; self } pub fn nth8 ( mut self , v : Byte ) -> Self { self . 0 [ 8 ] = v ; self } pub fn nth9 ( mut self , v : Byte ) -> Self { self . 0 [ 9 ] = v ; self } pub fn nth10 ( mut self , v : Byte ) -> Self { self . 0 [ 10 ] = v ; self } pub fn nth11 ( mut self , v : Byte ) -> Self { self . 0 [ 11 ] = v ; self } pub fn nth12 ( mut self , v : Byte ) -> Self { self . 0 [ 12 ] = v ; self } pub fn nth13 ( mut self , v : Byte ) -> Self { self . 0 [ 13 ] = v ; self } pub fn nth14 ( mut self , v : Byte ) -> Self { self . 0 [ 14 ] = v ; self } pub fn nth15 ( mut self , v : Byte ) -> Self { self . 0 [ 15 ] = v ; self } pub fn nth16 ( mut self , v : Byte ) -> Self { self . 0 [ 16 ] = v ; self } pub fn nth17 ( mut self , v : Byte ) -> Self { self . 0 [ 17 ] = v ; self } pub fn nth18 ( mut self , v : Byte ) -> Self { self . 0 [ 18 ] = v ; self } pub fn nth19 ( mut self , v : Byte ) -> Self { self . 0 [ 19 ] = v ; self } pub fn nth20 ( mut self , v : Byte ) -> Self { self . 0 [ 20 ] = v ; self } pub fn nth21 ( mut self , v : Byte ) -> Self { self . 0 [ 21 ] = v ; self } pub fn nth22 ( mut self , v : Byte ) -> Self { self . 0 [ 22 ] = v ; self } pub fn nth23 ( mut self , v : Byte ) -> Self { self . 0 [ 23 ] = v ; self } pub fn nth24 ( mut self , v : Byte ) -> Self { self . 0 [ 24 ] = v ; self } pub fn nth25 ( mut self , v : Byte ) -> Self { self . 0 [ 25 ] = v ; self } pub fn nth26 ( mut self , v : Byte ) -> Self { self . 0 [ 26 ] = v ; self } pub fn nth27 ( mut self , v : Byte ) -> Self { self . 0 [ 27 ] = v ; self } pub fn nth28 ( mut self , v : Byte ) -> Self { self . 0 [ 28 ] = v ; self } pub fn nth29 ( mut self , v : Byte ) -> Self { self . 0 [ 29 ] = v ; self } pub fn nth30 ( mut self , v : Byte ) -> Self { self . 0 [ 30 ] = v ; self } pub fn nth31 ( mut self , v : Byte ) -> Self { self . 0 [ 31 ] = v ; self } } impl molecule :: prelude :: Builder for Byte32Builder { type Entity = Byte32 ; const NAME : & 'static str = "Byte32Builder" ; fn expected_length ( & self ) -> usize { Self :: TOTAL_SIZE } fn write < W : :: molecule :: io :: Write > ( & self , writer : & mut W ) -> :: molecule :: io :: Result < ( ) > { writer . write_all ( self . 0 [ 0 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 1 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 2 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 3 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 4 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 5 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 6 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 7 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 8 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 9 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 10 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 11 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 12 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 13 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 14 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 15 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 16 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 17 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 18 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 19 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 20 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 21 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 22 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 23 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 24 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 25 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 26 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 27 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 28 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 29 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 30 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 31 ] . as_slice ( ) ) ? ; Ok ( ( ) ) } fn build ( & self ) -> Self :: Entity { let mut inner = Vec :: with_capacity ( self . expected_length ( ) ) ; self . write ( & mut inner ) . unwrap_or_else ( | _ | panic ! ( "{} build should be ok" , Self :: NAME ) ) ; Byte32 :: new_unchecked ( inner . into ( ) ) } } +# [ derive ( Clone ) ] pub struct Bytes ( molecule :: bytes :: Bytes ) ; impl :: core :: fmt :: LowerHex for Bytes { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl :: core :: fmt :: Debug for Bytes { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl :: core :: fmt :: Display for Bytes { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; let raw_data = hex_string ( & self . raw_data ( ) ) ; write ! ( f , "{}(0x{})" , Self :: NAME , raw_data ) } } impl :: core :: default :: Default for Bytes { fn default ( ) -> Self { let v : Vec < u8 > = vec ! [ 0 , 0 , 0 , 0 , ] ; Bytes :: new_unchecked ( v . into ( ) ) } } impl Bytes { pub const ITEM_SIZE : usize = 1 ; pub fn total_size ( & self ) -> usize { molecule :: NUMBER_SIZE * ( self . item_count ( ) + 1 ) } pub fn item_count ( & self ) -> usize { molecule :: unpack_number ( self . as_slice ( ) ) as usize } pub fn len ( & self ) -> usize { self . item_count ( ) } pub fn is_empty ( & self ) -> bool { self . len ( ) == 0 } pub fn get ( & self , idx : usize ) -> Option < Byte > { if idx >= self . len ( ) { None } else { Some ( self . get_unchecked ( idx ) ) } } pub fn get_unchecked ( & self , idx : usize ) -> Byte { let start = molecule :: NUMBER_SIZE + Self :: ITEM_SIZE * idx ; let end = start + Self :: ITEM_SIZE ; Byte :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn raw_data ( & self ) -> molecule :: bytes :: Bytes { self . 0 . slice ( molecule :: NUMBER_SIZE .. ) } pub fn as_reader < 'r > ( & 'r self ) -> BytesReader < 'r > { BytesReader :: new_unchecked ( self . as_slice ( ) ) } } impl molecule :: prelude :: Entity for Bytes { type Builder = BytesBuilder ; const NAME : & 'static str = "Bytes" ; fn new_unchecked ( data : molecule :: bytes :: Bytes ) -> Self { Bytes ( data ) } fn as_bytes ( & self ) -> molecule :: bytes :: Bytes { self . 0 . clone ( ) } fn as_slice ( & self ) -> & [ u8 ] { & self . 0 [ .. ] } fn from_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { BytesReader :: from_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn from_compatible_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { BytesReader :: from_compatible_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn new_builder ( ) -> Self :: Builder { :: core :: default :: Default :: default ( ) } fn as_builder ( self ) -> Self :: Builder { Self :: new_builder ( ) . extend ( self . into_iter ( ) ) } } +# [ derive ( Clone , Copy ) ] pub struct BytesReader < 'r > ( & 'r [ u8 ] ) ; impl < 'r > :: core :: fmt :: LowerHex for BytesReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl < 'r > :: core :: fmt :: Debug for BytesReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl < 'r > :: core :: fmt :: Display for BytesReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; let raw_data = hex_string ( & self . raw_data ( ) ) ; write ! ( f , "{}(0x{})" , Self :: NAME , raw_data ) } } impl < 'r > BytesReader < 'r > { pub const ITEM_SIZE : usize = 1 ; pub fn total_size ( & self ) -> usize { molecule :: NUMBER_SIZE * ( self . item_count ( ) + 1 ) } pub fn item_count ( & self ) -> usize { molecule :: unpack_number ( self . as_slice ( ) ) as usize } pub fn len ( & self ) -> usize { self . item_count ( ) } pub fn is_empty ( & self ) -> bool { self . len ( ) == 0 } pub fn get ( & self , idx : usize ) -> Option < ByteReader < 'r > > { if idx >= self . len ( ) { None } else { Some ( self . get_unchecked ( idx ) ) } } pub fn get_unchecked ( & self , idx : usize ) -> ByteReader < 'r > { let start = molecule :: NUMBER_SIZE + Self :: ITEM_SIZE * idx ; let end = start + Self :: ITEM_SIZE ; ByteReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn raw_data ( & self ) -> & 'r [ u8 ] { & self . as_slice ( ) [ molecule :: NUMBER_SIZE .. ] } } impl < 'r > molecule :: prelude :: Reader < 'r > for BytesReader < 'r > { type Entity = Bytes ; const NAME : & 'static str = "BytesReader" ; fn to_entity ( & self ) -> Self :: Entity { Self :: Entity :: new_unchecked ( self . as_slice ( ) . to_owned ( ) . into ( ) ) } fn new_unchecked ( slice : & 'r [ u8 ] ) -> Self { BytesReader ( slice ) } fn as_slice ( & self ) -> & 'r [ u8 ] { self . 0 } fn verify ( slice : & [ u8 ] , _compatible : bool ) -> molecule :: error :: VerificationResult < ( ) > { use molecule :: verification_error as ve ; let slice_len = slice . len ( ) ; if slice_len < molecule :: NUMBER_SIZE { return ve ! ( Self , HeaderIsBroken , molecule :: NUMBER_SIZE , slice_len ) ; } let item_count = molecule :: unpack_number ( slice ) as usize ; if item_count == 0 { if slice_len != molecule :: NUMBER_SIZE { return ve ! ( Self , TotalSizeNotMatch , molecule :: NUMBER_SIZE , slice_len ) ; } return Ok ( ( ) ) ; } let total_size = molecule :: NUMBER_SIZE + Self :: ITEM_SIZE * item_count ; if slice_len != total_size { return ve ! ( Self , TotalSizeNotMatch , total_size , slice_len ) ; } Ok ( ( ) ) } } +# [ derive ( Debug , Default ) ] pub struct BytesBuilder ( pub ( crate ) Vec < Byte > ) ; impl BytesBuilder { pub const ITEM_SIZE : usize = 1 ; pub fn set ( mut self , v : Vec < Byte > ) -> Self { self . 0 = v ; self } pub fn push ( mut self , v : Byte ) -> Self { self . 0 . push ( v ) ; self } pub fn extend < T : :: core :: iter :: IntoIterator < Item = Byte >> ( mut self , iter : T ) -> Self { for elem in iter { self . 0 . push ( elem ) ; } self } } impl molecule :: prelude :: Builder for BytesBuilder { type Entity = Bytes ; const NAME : & 'static str = "BytesBuilder" ; fn expected_length ( & self ) -> usize { molecule :: NUMBER_SIZE + Self :: ITEM_SIZE * self . 0 . len ( ) } fn write < W : :: molecule :: io :: Write > ( & self , writer : & mut W ) -> :: molecule :: io :: Result < ( ) > { writer . write_all ( & molecule :: pack_number ( self . 0 . len ( ) as molecule :: Number ) ) ? ; for inner in & self . 0 [ .. ] { writer . write_all ( inner . as_slice ( ) ) ? ; } Ok ( ( ) ) } fn build ( & self ) -> Self :: Entity { let mut inner = Vec :: with_capacity ( self . expected_length ( ) ) ; self . write ( & mut inner ) . unwrap_or_else ( | _ | panic ! ( "{} build should be ok" , Self :: NAME ) ) ; Bytes :: new_unchecked ( inner . into ( ) ) } } +pub struct BytesIterator ( Bytes , usize , usize ) ; impl :: core :: iter :: Iterator for BytesIterator { type Item = Byte ; fn next ( & mut self ) -> Option < Self :: Item > { if self . 1 >= self . 2 { None } else { let ret = self . 0 . get_unchecked ( self . 1 ) ; self . 1 += 1 ; Some ( ret ) } } } impl :: core :: iter :: ExactSizeIterator for BytesIterator { fn len ( & self ) -> usize { self . 2 - self . 1 } } impl :: core :: iter :: IntoIterator for Bytes { type Item = Byte ; type IntoIter = BytesIterator ; fn into_iter ( self ) -> Self :: IntoIter { let len = self . len ( ) ; BytesIterator ( self , 0 , len ) } } +# [ derive ( Clone ) ] pub struct Uint32 ( molecule :: bytes :: Bytes ) ; impl :: core :: fmt :: LowerHex for Uint32 { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl :: core :: fmt :: Debug for Uint32 { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl :: core :: fmt :: Display for Uint32 { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; let raw_data = hex_string ( & self . raw_data ( ) ) ; write ! ( f , "{}(0x{})" , Self :: NAME , raw_data ) } } impl :: core :: default :: Default for Uint32 { fn default ( ) -> Self { let v : Vec < u8 > = vec ! [ 0 , 0 , 0 , 0 , ] ; Uint32 :: new_unchecked ( v . into ( ) ) } } impl Uint32 { pub const TOTAL_SIZE : usize = 4 ; pub const ITEM_SIZE : usize = 1 ; pub const ITEM_COUNT : usize = 4 ; pub fn nth0 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 0 .. 1 ) ) } pub fn nth1 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 1 .. 2 ) ) } pub fn nth2 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 2 .. 3 ) ) } pub fn nth3 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 3 .. 4 ) ) } pub fn raw_data ( & self ) -> molecule :: bytes :: Bytes { self . as_bytes ( ) } pub fn as_reader < 'r > ( & 'r self ) -> Uint32Reader < 'r > { Uint32Reader :: new_unchecked ( self . as_slice ( ) ) } } impl molecule :: prelude :: Entity for Uint32 { type Builder = Uint32Builder ; const NAME : & 'static str = "Uint32" ; fn new_unchecked ( data : molecule :: bytes :: Bytes ) -> Self { Uint32 ( data ) } fn as_bytes ( & self ) -> molecule :: bytes :: Bytes { self . 0 . clone ( ) } fn as_slice ( & self ) -> & [ u8 ] { & self . 0 [ .. ] } fn from_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { Uint32Reader :: from_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn from_compatible_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { Uint32Reader :: from_compatible_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn new_builder ( ) -> Self :: Builder { :: core :: default :: Default :: default ( ) } fn as_builder ( self ) -> Self :: Builder { Self :: new_builder ( ) . set ( [ self . nth0 ( ) , self . nth1 ( ) , self . nth2 ( ) , self . nth3 ( ) , ] ) } } +# [ derive ( Clone , Copy ) ] pub struct Uint32Reader < 'r > ( & 'r [ u8 ] ) ; impl < 'r > :: core :: fmt :: LowerHex for Uint32Reader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl < 'r > :: core :: fmt :: Debug for Uint32Reader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl < 'r > :: core :: fmt :: Display for Uint32Reader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; let raw_data = hex_string ( & self . raw_data ( ) ) ; write ! ( f , "{}(0x{})" , Self :: NAME , raw_data ) } } impl < 'r > Uint32Reader < 'r > { pub const TOTAL_SIZE : usize = 4 ; pub const ITEM_SIZE : usize = 1 ; pub const ITEM_COUNT : usize = 4 ; pub fn nth0 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 0 .. 1 ] ) } pub fn nth1 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 1 .. 2 ] ) } pub fn nth2 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 2 .. 3 ] ) } pub fn nth3 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 3 .. 4 ] ) } pub fn raw_data ( & self ) -> & 'r [ u8 ] { self . as_slice ( ) } } impl < 'r > molecule :: prelude :: Reader < 'r > for Uint32Reader < 'r > { type Entity = Uint32 ; const NAME : & 'static str = "Uint32Reader" ; fn to_entity ( & self ) -> Self :: Entity { Self :: Entity :: new_unchecked ( self . as_slice ( ) . to_owned ( ) . into ( ) ) } fn new_unchecked ( slice : & 'r [ u8 ] ) -> Self { Uint32Reader ( slice ) } fn as_slice ( & self ) -> & 'r [ u8 ] { self . 0 } fn verify ( slice : & [ u8 ] , _compatible : bool ) -> molecule :: error :: VerificationResult < ( ) > { use molecule :: verification_error as ve ; let slice_len = slice . len ( ) ; if slice_len != Self :: TOTAL_SIZE { return ve ! ( Self , TotalSizeNotMatch , Self :: TOTAL_SIZE , slice_len ) ; } Ok ( ( ) ) } } +pub struct Uint32Builder ( pub ( crate ) [ Byte ; 4 ] ) ; impl :: core :: fmt :: Debug for Uint32Builder { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:?})" , Self :: NAME , & self . 0 [ .. ] ) } } impl :: core :: default :: Default for Uint32Builder { fn default ( ) -> Self { Uint32Builder ( [ Byte :: default ( ) , Byte :: default ( ) , Byte :: default ( ) , Byte :: default ( ) , ] ) } } impl Uint32Builder { pub const TOTAL_SIZE : usize = 4 ; pub const ITEM_SIZE : usize = 1 ; pub const ITEM_COUNT : usize = 4 ; pub fn set ( mut self , v : [ Byte ; 4 ] ) -> Self { self . 0 = v ; self } pub fn nth0 ( mut self , v : Byte ) -> Self { self . 0 [ 0 ] = v ; self } pub fn nth1 ( mut self , v : Byte ) -> Self { self . 0 [ 1 ] = v ; self } pub fn nth2 ( mut self , v : Byte ) -> Self { self . 0 [ 2 ] = v ; self } pub fn nth3 ( mut self , v : Byte ) -> Self { self . 0 [ 3 ] = v ; self } } impl molecule :: prelude :: Builder for Uint32Builder { type Entity = Uint32 ; const NAME : & 'static str = "Uint32Builder" ; fn expected_length ( & self ) -> usize { Self :: TOTAL_SIZE } fn write < W : :: molecule :: io :: Write > ( & self , writer : & mut W ) -> :: molecule :: io :: Result < ( ) > { writer . write_all ( self . 0 [ 0 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 1 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 2 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 3 ] . as_slice ( ) ) ? ; Ok ( ( ) ) } fn build ( & self ) -> Self :: Entity { let mut inner = Vec :: with_capacity ( self . expected_length ( ) ) ; self . write ( & mut inner ) . unwrap_or_else ( | _ | panic ! ( "{} build should be ok" , Self :: NAME ) ) ; Uint32 :: new_unchecked ( inner . into ( ) ) } } +# [ derive ( Clone ) ] pub struct Uint64 ( molecule :: bytes :: Bytes ) ; impl :: core :: fmt :: LowerHex for Uint64 { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl :: core :: fmt :: Debug for Uint64 { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl :: core :: fmt :: Display for Uint64 { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; let raw_data = hex_string ( & self . raw_data ( ) ) ; write ! ( f , "{}(0x{})" , Self :: NAME , raw_data ) } } impl :: core :: default :: Default for Uint64 { fn default ( ) -> Self { let v : Vec < u8 > = vec ! [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , ] ; Uint64 :: new_unchecked ( v . into ( ) ) } } impl Uint64 { pub const TOTAL_SIZE : usize = 8 ; pub const ITEM_SIZE : usize = 1 ; pub const ITEM_COUNT : usize = 8 ; pub fn nth0 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 0 .. 1 ) ) } pub fn nth1 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 1 .. 2 ) ) } pub fn nth2 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 2 .. 3 ) ) } pub fn nth3 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 3 .. 4 ) ) } pub fn nth4 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 4 .. 5 ) ) } pub fn nth5 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 5 .. 6 ) ) } pub fn nth6 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 6 .. 7 ) ) } pub fn nth7 ( & self ) -> Byte { Byte :: new_unchecked ( self . 0 . slice ( 7 .. 8 ) ) } pub fn raw_data ( & self ) -> molecule :: bytes :: Bytes { self . as_bytes ( ) } pub fn as_reader < 'r > ( & 'r self ) -> Uint64Reader < 'r > { Uint64Reader :: new_unchecked ( self . as_slice ( ) ) } } impl molecule :: prelude :: Entity for Uint64 { type Builder = Uint64Builder ; const NAME : & 'static str = "Uint64" ; fn new_unchecked ( data : molecule :: bytes :: Bytes ) -> Self { Uint64 ( data ) } fn as_bytes ( & self ) -> molecule :: bytes :: Bytes { self . 0 . clone ( ) } fn as_slice ( & self ) -> & [ u8 ] { & self . 0 [ .. ] } fn from_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { Uint64Reader :: from_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn from_compatible_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { Uint64Reader :: from_compatible_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn new_builder ( ) -> Self :: Builder { :: core :: default :: Default :: default ( ) } fn as_builder ( self ) -> Self :: Builder { Self :: new_builder ( ) . set ( [ self . nth0 ( ) , self . nth1 ( ) , self . nth2 ( ) , self . nth3 ( ) , self . nth4 ( ) , self . nth5 ( ) , self . nth6 ( ) , self . nth7 ( ) , ] ) } } +# [ derive ( Clone , Copy ) ] pub struct Uint64Reader < 'r > ( & 'r [ u8 ] ) ; impl < 'r > :: core :: fmt :: LowerHex for Uint64Reader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl < 'r > :: core :: fmt :: Debug for Uint64Reader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl < 'r > :: core :: fmt :: Display for Uint64Reader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; let raw_data = hex_string ( & self . raw_data ( ) ) ; write ! ( f , "{}(0x{})" , Self :: NAME , raw_data ) } } impl < 'r > Uint64Reader < 'r > { pub const TOTAL_SIZE : usize = 8 ; pub const ITEM_SIZE : usize = 1 ; pub const ITEM_COUNT : usize = 8 ; pub fn nth0 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 0 .. 1 ] ) } pub fn nth1 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 1 .. 2 ] ) } pub fn nth2 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 2 .. 3 ] ) } pub fn nth3 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 3 .. 4 ] ) } pub fn nth4 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 4 .. 5 ] ) } pub fn nth5 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 5 .. 6 ] ) } pub fn nth6 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 6 .. 7 ] ) } pub fn nth7 ( & self ) -> ByteReader < 'r > { ByteReader :: new_unchecked ( & self . as_slice ( ) [ 7 .. 8 ] ) } pub fn raw_data ( & self ) -> & 'r [ u8 ] { self . as_slice ( ) } } impl < 'r > molecule :: prelude :: Reader < 'r > for Uint64Reader < 'r > { type Entity = Uint64 ; const NAME : & 'static str = "Uint64Reader" ; fn to_entity ( & self ) -> Self :: Entity { Self :: Entity :: new_unchecked ( self . as_slice ( ) . to_owned ( ) . into ( ) ) } fn new_unchecked ( slice : & 'r [ u8 ] ) -> Self { Uint64Reader ( slice ) } fn as_slice ( & self ) -> & 'r [ u8 ] { self . 0 } fn verify ( slice : & [ u8 ] , _compatible : bool ) -> molecule :: error :: VerificationResult < ( ) > { use molecule :: verification_error as ve ; let slice_len = slice . len ( ) ; if slice_len != Self :: TOTAL_SIZE { return ve ! ( Self , TotalSizeNotMatch , Self :: TOTAL_SIZE , slice_len ) ; } Ok ( ( ) ) } } +pub struct Uint64Builder ( pub ( crate ) [ Byte ; 8 ] ) ; impl :: core :: fmt :: Debug for Uint64Builder { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:?})" , Self :: NAME , & self . 0 [ .. ] ) } } impl :: core :: default :: Default for Uint64Builder { fn default ( ) -> Self { Uint64Builder ( [ Byte :: default ( ) , Byte :: default ( ) , Byte :: default ( ) , Byte :: default ( ) , Byte :: default ( ) , Byte :: default ( ) , Byte :: default ( ) , Byte :: default ( ) , ] ) } } impl Uint64Builder { pub const TOTAL_SIZE : usize = 8 ; pub const ITEM_SIZE : usize = 1 ; pub const ITEM_COUNT : usize = 8 ; pub fn set ( mut self , v : [ Byte ; 8 ] ) -> Self { self . 0 = v ; self } pub fn nth0 ( mut self , v : Byte ) -> Self { self . 0 [ 0 ] = v ; self } pub fn nth1 ( mut self , v : Byte ) -> Self { self . 0 [ 1 ] = v ; self } pub fn nth2 ( mut self , v : Byte ) -> Self { self . 0 [ 2 ] = v ; self } pub fn nth3 ( mut self , v : Byte ) -> Self { self . 0 [ 3 ] = v ; self } pub fn nth4 ( mut self , v : Byte ) -> Self { self . 0 [ 4 ] = v ; self } pub fn nth5 ( mut self , v : Byte ) -> Self { self . 0 [ 5 ] = v ; self } pub fn nth6 ( mut self , v : Byte ) -> Self { self . 0 [ 6 ] = v ; self } pub fn nth7 ( mut self , v : Byte ) -> Self { self . 0 [ 7 ] = v ; self } } impl molecule :: prelude :: Builder for Uint64Builder { type Entity = Uint64 ; const NAME : & 'static str = "Uint64Builder" ; fn expected_length ( & self ) -> usize { Self :: TOTAL_SIZE } fn write < W : :: molecule :: io :: Write > ( & self , writer : & mut W ) -> :: molecule :: io :: Result < ( ) > { writer . write_all ( self . 0 [ 0 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 1 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 2 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 3 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 4 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 5 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 6 ] . as_slice ( ) ) ? ; writer . write_all ( self . 0 [ 7 ] . as_slice ( ) ) ? ; Ok ( ( ) ) } fn build ( & self ) -> Self :: Entity { let mut inner = Vec :: with_capacity ( self . expected_length ( ) ) ; self . write ( & mut inner ) . unwrap_or_else ( | _ | panic ! ( "{} build should be ok" , Self :: NAME ) ) ; Uint64 :: new_unchecked ( inner . into ( ) ) } } +# [ derive ( Clone ) ] pub struct Bytes2 ( molecule :: bytes :: Bytes ) ; impl :: core :: fmt :: LowerHex for Bytes2 { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl :: core :: fmt :: Debug for Bytes2 { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl :: core :: fmt :: Display for Bytes2 { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{} [" , Self :: NAME ) ? ; for i in 0 .. self . len ( ) { if i == 0 { write ! ( f , "{}" , self . get_unchecked ( i ) ) ? ; } else { write ! ( f , ", {}" , self . get_unchecked ( i ) ) ? ; } } write ! ( f , "]" ) } } impl :: core :: default :: Default for Bytes2 { fn default ( ) -> Self { let v : Vec < u8 > = vec ! [ 4 , 0 , 0 , 0 , ] ; Bytes2 :: new_unchecked ( v . into ( ) ) } } impl Bytes2 { pub fn total_size ( & self ) -> usize { molecule :: unpack_number ( self . as_slice ( ) ) as usize } pub fn item_count ( & self ) -> usize { if self . total_size ( ) == molecule :: NUMBER_SIZE { 0 } else { ( molecule :: unpack_number ( & self . as_slice ( ) [ molecule :: NUMBER_SIZE .. ] ) as usize / 4 ) - 1 } } pub fn len ( & self ) -> usize { self . item_count ( ) } pub fn is_empty ( & self ) -> bool { self . len ( ) == 0 } pub fn get ( & self , idx : usize ) -> Option < Bytes > { if idx >= self . len ( ) { None } else { Some ( self . get_unchecked ( idx ) ) } } pub fn get_unchecked ( & self , idx : usize ) -> Bytes { let slice = self . as_slice ( ) ; let start_idx = molecule :: NUMBER_SIZE * ( 1 + idx ) ; let start = molecule :: unpack_number ( & slice [ start_idx .. ] ) as usize ; if idx == self . len ( ) - 1 { Bytes :: new_unchecked ( self . 0 . slice ( start .. ) ) } else { let end_idx = start_idx + molecule :: NUMBER_SIZE ; let end = molecule :: unpack_number ( & slice [ end_idx .. ] ) as usize ; Bytes :: new_unchecked ( self . 0 . slice ( start .. end ) ) } } pub fn as_reader < 'r > ( & 'r self ) -> Bytes2Reader < 'r > { Bytes2Reader :: new_unchecked ( self . as_slice ( ) ) } } impl molecule :: prelude :: Entity for Bytes2 { type Builder = Bytes2Builder ; const NAME : & 'static str = "Bytes2" ; fn new_unchecked ( data : molecule :: bytes :: Bytes ) -> Self { Bytes2 ( data ) } fn as_bytes ( & self ) -> molecule :: bytes :: Bytes { self . 0 . clone ( ) } fn as_slice ( & self ) -> & [ u8 ] { & self . 0 [ .. ] } fn from_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { Bytes2Reader :: from_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn from_compatible_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { Bytes2Reader :: from_compatible_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn new_builder ( ) -> Self :: Builder { :: core :: default :: Default :: default ( ) } fn as_builder ( self ) -> Self :: Builder { Self :: new_builder ( ) . extend ( self . into_iter ( ) ) } } +# [ derive ( Clone , Copy ) ] pub struct Bytes2Reader < 'r > ( & 'r [ u8 ] ) ; impl < 'r > :: core :: fmt :: LowerHex for Bytes2Reader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl < 'r > :: core :: fmt :: Debug for Bytes2Reader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl < 'r > :: core :: fmt :: Display for Bytes2Reader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{} [" , Self :: NAME ) ? ; for i in 0 .. self . len ( ) { if i == 0 { write ! ( f , "{}" , self . get_unchecked ( i ) ) ? ; } else { write ! ( f , ", {}" , self . get_unchecked ( i ) ) ? ; } } write ! ( f , "]" ) } } impl < 'r > Bytes2Reader < 'r > { pub fn total_size ( & self ) -> usize { molecule :: unpack_number ( self . as_slice ( ) ) as usize } pub fn item_count ( & self ) -> usize { if self . total_size ( ) == molecule :: NUMBER_SIZE { 0 } else { ( molecule :: unpack_number ( & self . as_slice ( ) [ molecule :: NUMBER_SIZE .. ] ) as usize / 4 ) - 1 } } pub fn len ( & self ) -> usize { self . item_count ( ) } pub fn is_empty ( & self ) -> bool { self . len ( ) == 0 } pub fn get ( & self , idx : usize ) -> Option < BytesReader < 'r > > { if idx >= self . len ( ) { None } else { Some ( self . get_unchecked ( idx ) ) } } pub fn get_unchecked ( & self , idx : usize ) -> BytesReader < 'r > { let slice = self . as_slice ( ) ; let start_idx = molecule :: NUMBER_SIZE * ( 1 + idx ) ; let start = molecule :: unpack_number ( & slice [ start_idx .. ] ) as usize ; if idx == self . len ( ) - 1 { BytesReader :: new_unchecked ( & self . as_slice ( ) [ start .. ] ) } else { let end_idx = start_idx + molecule :: NUMBER_SIZE ; let end = molecule :: unpack_number ( & slice [ end_idx .. ] ) as usize ; BytesReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } } } impl < 'r > molecule :: prelude :: Reader < 'r > for Bytes2Reader < 'r > { type Entity = Bytes2 ; const NAME : & 'static str = "Bytes2Reader" ; fn to_entity ( & self ) -> Self :: Entity { Self :: Entity :: new_unchecked ( self . as_slice ( ) . to_owned ( ) . into ( ) ) } fn new_unchecked ( slice : & 'r [ u8 ] ) -> Self { Bytes2Reader ( slice ) } fn as_slice ( & self ) -> & 'r [ u8 ] { self . 0 } fn verify ( slice : & [ u8 ] , compatible : bool ) -> molecule :: error :: VerificationResult < ( ) > { use molecule :: verification_error as ve ; let slice_len = slice . len ( ) ; if slice_len < molecule :: NUMBER_SIZE { return ve ! ( Self , HeaderIsBroken , molecule :: NUMBER_SIZE , slice_len ) ; } let total_size = molecule :: unpack_number ( slice ) as usize ; if slice_len != total_size { return ve ! ( Self , TotalSizeNotMatch , total_size , slice_len ) ; } if slice_len == molecule :: NUMBER_SIZE { return Ok ( ( ) ) ; } if slice_len < molecule :: NUMBER_SIZE * 2 { return ve ! ( Self , TotalSizeNotMatch , molecule :: NUMBER_SIZE * 2 , slice_len ) ; } let offset_first = molecule :: unpack_number ( & slice [ molecule :: NUMBER_SIZE .. ] ) as usize ; if offset_first % 4 != 0 || offset_first < molecule :: NUMBER_SIZE * 2 { return ve ! ( Self , OffsetsNotMatch ) ; } let item_count = offset_first / 4 - 1 ; let header_size = molecule :: NUMBER_SIZE * ( item_count + 1 ) ; if slice_len < header_size { return ve ! ( Self , HeaderIsBroken , header_size , slice_len ) ; } let mut offsets : Vec < usize > = slice [ molecule :: NUMBER_SIZE .. ] . chunks ( molecule :: NUMBER_SIZE ) . take ( item_count ) . map ( | x | molecule :: unpack_number ( x ) as usize ) . collect ( ) ; offsets . push ( total_size ) ; if offsets . windows ( 2 ) . any ( | i | i [ 0 ] > i [ 1 ] ) { return ve ! ( Self , OffsetsNotMatch ) ; } for pair in offsets . windows ( 2 ) { let start = pair [ 0 ] ; let end = pair [ 1 ] ; BytesReader :: verify ( & slice [ start .. end ] , compatible ) ? ; } Ok ( ( ) ) } } +# [ derive ( Debug , Default ) ] pub struct Bytes2Builder ( pub ( crate ) Vec < Bytes > ) ; impl Bytes2Builder { pub fn set ( mut self , v : Vec < Bytes > ) -> Self { self . 0 = v ; self } pub fn push ( mut self , v : Bytes ) -> Self { self . 0 . push ( v ) ; self } pub fn extend < T : :: core :: iter :: IntoIterator < Item = Bytes >> ( mut self , iter : T ) -> Self { for elem in iter { self . 0 . push ( elem ) ; } self } } impl molecule :: prelude :: Builder for Bytes2Builder { type Entity = Bytes2 ; const NAME : & 'static str = "Bytes2Builder" ; fn expected_length ( & self ) -> usize { molecule :: NUMBER_SIZE * ( self . 0 . len ( ) + 1 ) + self . 0 . iter ( ) . map ( | inner | inner . as_slice ( ) . len ( ) ) . sum :: < usize > ( ) } fn write < W : :: molecule :: io :: Write > ( & self , writer : & mut W , ) -> :: molecule :: io :: Result < ( ) > { let item_count = self . 0 . len ( ) ; if item_count == 0 { writer . write_all ( & molecule :: pack_number ( molecule :: NUMBER_SIZE as molecule :: Number , ) ) ? ; } else { let ( total_size , offsets ) = self . 0 . iter ( ) . fold ( ( molecule :: NUMBER_SIZE * ( item_count + 1 ) , Vec :: with_capacity ( item_count ) , ) , | ( start , mut offsets ) , inner | { offsets . push ( start ) ; ( start + inner . as_slice ( ) . len ( ) , offsets ) } , ) ; writer . write_all ( & molecule :: pack_number ( total_size as molecule :: Number ) ) ? ; for offset in offsets . into_iter ( ) { writer . write_all ( & molecule :: pack_number ( offset as molecule :: Number ) ) ? ; } for inner in self . 0 . iter ( ) { writer . write_all ( inner . as_slice ( ) ) ? ; } } Ok ( ( ) ) } fn build ( & self ) -> Self :: Entity { let mut inner = Vec :: with_capacity ( self . expected_length ( ) ) ; self . write ( & mut inner ) . unwrap_or_else ( | _ | panic ! ( "{} build should be ok" , Self :: NAME ) ) ; Bytes2 :: new_unchecked ( inner . into ( ) ) } } +pub struct Bytes2Iterator ( Bytes2 , usize , usize ) ; impl :: core :: iter :: Iterator for Bytes2Iterator { type Item = Bytes ; fn next ( & mut self ) -> Option < Self :: Item > { if self . 1 >= self . 2 { None } else { let ret = self . 0 . get_unchecked ( self . 1 ) ; self . 1 += 1 ; Some ( ret ) } } } impl :: core :: iter :: ExactSizeIterator for Bytes2Iterator { fn len ( & self ) -> usize { self . 2 - self . 1 } } impl :: core :: iter :: IntoIterator for Bytes2 { type Item = Bytes ; type IntoIter = Bytes2Iterator ; fn into_iter ( self ) -> Self :: IntoIter { let len = self . len ( ) ; Bytes2Iterator ( self , 0 , len ) } } impl < 'r > Bytes2Reader < 'r > { pub fn iter < 't > ( & 't self ) -> Bytes2ReaderIterator < 't , 'r > { Bytes2ReaderIterator ( & self , 0 , self . len ( ) ) } } pub struct Bytes2ReaderIterator < 't , 'r > ( & 't Bytes2Reader < 'r > , usize , usize ) ; impl < 't : 'r , 'r > :: core :: iter :: Iterator for Bytes2ReaderIterator < 't , 'r > { type Item = BytesReader < 't > ; fn next ( & mut self ) -> Option < Self :: Item > { if self . 1 >= self . 2 { None } else { let ret = self . 0 . get_unchecked ( self . 1 ) ; self . 1 += 1 ; Some ( ret ) } } } impl < 't : 'r , 'r > :: core :: iter :: ExactSizeIterator for Bytes2ReaderIterator < 't , 'r > { fn len ( & self ) -> usize { self . 2 - self . 1 } } +# [ derive ( Clone ) ] pub struct Script ( molecule :: bytes :: Bytes ) ; impl :: core :: fmt :: LowerHex for Script { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl :: core :: fmt :: Debug for Script { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl :: core :: fmt :: Display for Script { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{} {{ " , Self :: NAME ) ? ; write ! ( f , "{}: {}" , "code_hash" , self . code_hash ( ) ) ? ; write ! ( f , ", {}: {}" , "hash_type" , self . hash_type ( ) ) ? ; write ! ( f , ", {}: {}" , "args" , self . args ( ) ) ? ; let extra_count = self . count_extra_fields ( ) ; if extra_count != 0 { write ! ( f , ", .. ({} fields)" , extra_count ) ? ; } write ! ( f , " }}" ) } } impl :: core :: default :: Default for Script { fn default ( ) -> Self { let v : Vec < u8 > = vec ! [ 53 , 0 , 0 , 0 , 16 , 0 , 0 , 0 , 48 , 0 , 0 , 0 , 49 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , ] ; Script :: new_unchecked ( v . into ( ) ) } } impl Script { pub const FIELD_COUNT : usize = 3 ; pub fn total_size ( & self ) -> usize { molecule :: unpack_number ( self . as_slice ( ) ) as usize } pub fn field_count ( & self ) -> usize { if self . total_size ( ) == molecule :: NUMBER_SIZE { 0 } else { ( molecule :: unpack_number ( & self . as_slice ( ) [ molecule :: NUMBER_SIZE .. ] ) as usize / 4 ) - 1 } } pub fn count_extra_fields ( & self ) -> usize { self . field_count ( ) - Self :: FIELD_COUNT } pub fn has_extra_fields ( & self ) -> bool { Self :: FIELD_COUNT != self . field_count ( ) } pub fn code_hash ( & self ) -> Byte32 { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 4 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; Byte32 :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn hash_type ( & self ) -> Byte { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; Byte :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn args ( & self ) -> Bytes { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; if self . has_extra_fields ( ) { let end = molecule :: unpack_number ( & slice [ 16 .. ] ) as usize ; Bytes :: new_unchecked ( self . 0 . slice ( start .. end ) ) } else { Bytes :: new_unchecked ( self . 0 . slice ( start .. ) ) } } pub fn as_reader < 'r > ( & 'r self ) -> ScriptReader < 'r > { ScriptReader :: new_unchecked ( self . as_slice ( ) ) } } impl molecule :: prelude :: Entity for Script { type Builder = ScriptBuilder ; const NAME : & 'static str = "Script" ; fn new_unchecked ( data : molecule :: bytes :: Bytes ) -> Self { Script ( data ) } fn as_bytes ( & self ) -> molecule :: bytes :: Bytes { self . 0 . clone ( ) } fn as_slice ( & self ) -> & [ u8 ] { & self . 0 [ .. ] } fn from_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { ScriptReader :: from_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn from_compatible_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { ScriptReader :: from_compatible_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn new_builder ( ) -> Self :: Builder { :: core :: default :: Default :: default ( ) } fn as_builder ( self ) -> Self :: Builder { Self :: new_builder ( ) . code_hash ( self . code_hash ( ) ) . hash_type ( self . hash_type ( ) ) . args ( self . args ( ) ) } } +# [ derive ( Clone , Copy ) ] pub struct ScriptReader < 'r > ( & 'r [ u8 ] ) ; impl < 'r > :: core :: fmt :: LowerHex for ScriptReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl < 'r > :: core :: fmt :: Debug for ScriptReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl < 'r > :: core :: fmt :: Display for ScriptReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{} {{ " , Self :: NAME ) ? ; write ! ( f , "{}: {}" , "code_hash" , self . code_hash ( ) ) ? ; write ! ( f , ", {}: {}" , "hash_type" , self . hash_type ( ) ) ? ; write ! ( f , ", {}: {}" , "args" , self . args ( ) ) ? ; let extra_count = self . count_extra_fields ( ) ; if extra_count != 0 { write ! ( f , ", .. ({} fields)" , extra_count ) ? ; } write ! ( f , " }}" ) } } impl < 'r > ScriptReader < 'r > { pub const FIELD_COUNT : usize = 3 ; pub fn total_size ( & self ) -> usize { molecule :: unpack_number ( self . as_slice ( ) ) as usize } pub fn field_count ( & self ) -> usize { if self . total_size ( ) == molecule :: NUMBER_SIZE { 0 } else { ( molecule :: unpack_number ( & self . as_slice ( ) [ molecule :: NUMBER_SIZE .. ] ) as usize / 4 ) - 1 } } pub fn count_extra_fields ( & self ) -> usize { self . field_count ( ) - Self :: FIELD_COUNT } pub fn has_extra_fields ( & self ) -> bool { Self :: FIELD_COUNT != self . field_count ( ) } pub fn code_hash ( & self ) -> Byte32Reader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 4 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; Byte32Reader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn hash_type ( & self ) -> ByteReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; ByteReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn args ( & self ) -> BytesReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; if self . has_extra_fields ( ) { let end = molecule :: unpack_number ( & slice [ 16 .. ] ) as usize ; BytesReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } else { BytesReader :: new_unchecked ( & self . as_slice ( ) [ start .. ] ) } } } impl < 'r > molecule :: prelude :: Reader < 'r > for ScriptReader < 'r > { type Entity = Script ; const NAME : & 'static str = "ScriptReader" ; fn to_entity ( & self ) -> Self :: Entity { Self :: Entity :: new_unchecked ( self . as_slice ( ) . to_owned ( ) . into ( ) ) } fn new_unchecked ( slice : & 'r [ u8 ] ) -> Self { ScriptReader ( slice ) } fn as_slice ( & self ) -> & 'r [ u8 ] { self . 0 } fn verify ( slice : & [ u8 ] , compatible : bool ) -> molecule :: error :: VerificationResult < ( ) > { use molecule :: verification_error as ve ; let slice_len = slice . len ( ) ; if slice_len < molecule :: NUMBER_SIZE { return ve ! ( Self , HeaderIsBroken , molecule :: NUMBER_SIZE , slice_len ) ; } let total_size = molecule :: unpack_number ( slice ) as usize ; if slice_len != total_size { return ve ! ( Self , TotalSizeNotMatch , total_size , slice_len ) ; } if slice_len == molecule :: NUMBER_SIZE && Self :: FIELD_COUNT == 0 { return Ok ( ( ) ) ; } if slice_len < molecule :: NUMBER_SIZE * 2 { return ve ! ( Self , HeaderIsBroken , molecule :: NUMBER_SIZE * 2 , slice_len ) ; } let offset_first = molecule :: unpack_number ( & slice [ molecule :: NUMBER_SIZE .. ] ) as usize ; if offset_first % 4 != 0 || offset_first < molecule :: NUMBER_SIZE * 2 { return ve ! ( Self , OffsetsNotMatch ) ; } let field_count = offset_first / 4 - 1 ; if field_count < Self :: FIELD_COUNT { return ve ! ( Self , FieldCountNotMatch , Self :: FIELD_COUNT , field_count ) ; } else if ! compatible && field_count > Self :: FIELD_COUNT { return ve ! ( Self , FieldCountNotMatch , Self :: FIELD_COUNT , field_count ) ; } ; let header_size = molecule :: NUMBER_SIZE * ( field_count + 1 ) ; if slice_len < header_size { return ve ! ( Self , HeaderIsBroken , header_size , slice_len ) ; } let mut offsets : Vec < usize > = slice [ molecule :: NUMBER_SIZE .. ] . chunks ( molecule :: NUMBER_SIZE ) . take ( field_count ) . map ( | x | molecule :: unpack_number ( x ) as usize ) . collect ( ) ; offsets . push ( total_size ) ; if offsets . windows ( 2 ) . any ( | i | i [ 0 ] > i [ 1 ] ) { return ve ! ( Self , OffsetsNotMatch ) ; } Byte32Reader :: verify ( & slice [ offsets [ 0 ] .. offsets [ 1 ] ] , compatible ) ? ; ByteReader :: verify ( & slice [ offsets [ 1 ] .. offsets [ 2 ] ] , compatible ) ? ; BytesReader :: verify ( & slice [ offsets [ 2 ] .. offsets [ 3 ] ] , compatible ) ? ; Ok ( ( ) ) } } +# [ derive ( Debug , Default ) ] pub struct ScriptBuilder { pub ( crate ) code_hash : Byte32 , pub ( crate ) hash_type : Byte , pub ( crate ) args : Bytes , } impl ScriptBuilder { pub const FIELD_COUNT : usize = 3 ; pub fn code_hash ( mut self , v : Byte32 ) -> Self { self . code_hash = v ; self } pub fn hash_type ( mut self , v : Byte ) -> Self { self . hash_type = v ; self } pub fn args ( mut self , v : Bytes ) -> Self { self . args = v ; self } } impl molecule :: prelude :: Builder for ScriptBuilder { type Entity = Script ; const NAME : & 'static str = "ScriptBuilder" ; fn expected_length ( & self ) -> usize { molecule :: NUMBER_SIZE * ( Self :: FIELD_COUNT + 1 ) + self . code_hash . as_slice ( ) . len ( ) + self . hash_type . as_slice ( ) . len ( ) + self . args . as_slice ( ) . len ( ) } fn write < W : :: molecule :: io :: Write > ( & self , writer : & mut W ) -> :: molecule :: io :: Result < ( ) > { let mut total_size = molecule :: NUMBER_SIZE * ( Self :: FIELD_COUNT + 1 ) ; let mut offsets = Vec :: with_capacity ( Self :: FIELD_COUNT ) ; offsets . push ( total_size ) ; total_size += self . code_hash . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . hash_type . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . args . as_slice ( ) . len ( ) ; writer . write_all ( & molecule :: pack_number ( total_size as molecule :: Number ) ) ? ; for offset in offsets . into_iter ( ) { writer . write_all ( & molecule :: pack_number ( offset as molecule :: Number ) ) ? ; } writer . write_all ( self . code_hash . as_slice ( ) ) ? ; writer . write_all ( self . hash_type . as_slice ( ) ) ? ; writer . write_all ( self . args . as_slice ( ) ) ? ; Ok ( ( ) ) } fn build ( & self ) -> Self :: Entity { let mut inner = Vec :: with_capacity ( self . expected_length ( ) ) ; self . write ( & mut inner ) . unwrap_or_else ( | _ | panic ! ( "{} build should be ok" , Self :: NAME ) ) ; Script :: new_unchecked ( inner . into ( ) ) } } diff --git a/tests/src/toCKB_typescript/utils/types/generated/btc_difficulty.rs b/tests/src/toCKB_typescript/utils/types/generated/btc_difficulty.rs index 3976e02..8ddda9d 100644 --- a/tests/src/toCKB_typescript/utils/types/generated/btc_difficulty.rs +++ b/tests/src/toCKB_typescript/utils/types/generated/btc_difficulty.rs @@ -1,270 +1,7 @@ -// Generated by Molecule 0.6.0 +// Generated by Molecule 0.6.1 -use super::basic::*; -use molecule::prelude::*; -#[derive(Clone)] -pub struct BTCDifficulty(molecule::bytes::Bytes); -impl ::core::fmt::LowerHex for BTCDifficulty { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl ::core::fmt::Debug for BTCDifficulty { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl ::core::fmt::Display for BTCDifficulty { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{} {{ ", Self::NAME)?; - write!(f, "{}: {}", "current", self.current())?; - write!(f, ", {}: {}", "previous", self.previous())?; - let extra_count = self.count_extra_fields(); - if extra_count != 0 { - write!(f, ", .. ({} fields)", extra_count)?; - } - write!(f, " }}") - } -} -impl ::core::default::Default for BTCDifficulty { - fn default() -> Self { - let v: Vec = vec![ - 20, 0, 0, 0, 12, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ]; - BTCDifficulty::new_unchecked(v.into()) - } -} -impl BTCDifficulty { - pub const FIELD_COUNT: usize = 2; - pub fn total_size(&self) -> usize { - molecule::unpack_number(self.as_slice()) as usize - } - pub fn field_count(&self) -> usize { - if self.total_size() == molecule::NUMBER_SIZE { - 0 - } else { - (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 - } - } - pub fn count_extra_fields(&self) -> usize { - self.field_count() - Self::FIELD_COUNT - } - pub fn has_extra_fields(&self) -> bool { - Self::FIELD_COUNT != self.field_count() - } - pub fn current(&self) -> Bytes { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[4..]) as usize; - let end = molecule::unpack_number(&slice[8..]) as usize; - Bytes::new_unchecked(self.0.slice(start..end)) - } - pub fn previous(&self) -> Bytes { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[8..]) as usize; - if self.has_extra_fields() { - let end = molecule::unpack_number(&slice[12..]) as usize; - Bytes::new_unchecked(self.0.slice(start..end)) - } else { - Bytes::new_unchecked(self.0.slice(start..)) - } - } - pub fn as_reader<'r>(&'r self) -> BTCDifficultyReader<'r> { - BTCDifficultyReader::new_unchecked(self.as_slice()) - } -} -impl molecule::prelude::Entity for BTCDifficulty { - type Builder = BTCDifficultyBuilder; - const NAME: &'static str = "BTCDifficulty"; - fn new_unchecked(data: molecule::bytes::Bytes) -> Self { - BTCDifficulty(data) - } - fn as_bytes(&self) -> molecule::bytes::Bytes { - self.0.clone() - } - fn as_slice(&self) -> &[u8] { - &self.0[..] - } - fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { - BTCDifficultyReader::from_slice(slice).map(|reader| reader.to_entity()) - } - fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { - BTCDifficultyReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) - } - fn new_builder() -> Self::Builder { - ::core::default::Default::default() - } - fn as_builder(self) -> Self::Builder { - Self::new_builder() - .current(self.current()) - .previous(self.previous()) - } -} -#[derive(Clone, Copy)] -pub struct BTCDifficultyReader<'r>(&'r [u8]); -impl<'r> ::core::fmt::LowerHex for BTCDifficultyReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl<'r> ::core::fmt::Debug for BTCDifficultyReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl<'r> ::core::fmt::Display for BTCDifficultyReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{} {{ ", Self::NAME)?; - write!(f, "{}: {}", "current", self.current())?; - write!(f, ", {}: {}", "previous", self.previous())?; - let extra_count = self.count_extra_fields(); - if extra_count != 0 { - write!(f, ", .. ({} fields)", extra_count)?; - } - write!(f, " }}") - } -} -impl<'r> BTCDifficultyReader<'r> { - pub const FIELD_COUNT: usize = 2; - pub fn total_size(&self) -> usize { - molecule::unpack_number(self.as_slice()) as usize - } - pub fn field_count(&self) -> usize { - if self.total_size() == molecule::NUMBER_SIZE { - 0 - } else { - (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 - } - } - pub fn count_extra_fields(&self) -> usize { - self.field_count() - Self::FIELD_COUNT - } - pub fn has_extra_fields(&self) -> bool { - Self::FIELD_COUNT != self.field_count() - } - pub fn current(&self) -> BytesReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[4..]) as usize; - let end = molecule::unpack_number(&slice[8..]) as usize; - BytesReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn previous(&self) -> BytesReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[8..]) as usize; - if self.has_extra_fields() { - let end = molecule::unpack_number(&slice[12..]) as usize; - BytesReader::new_unchecked(&self.as_slice()[start..end]) - } else { - BytesReader::new_unchecked(&self.as_slice()[start..]) - } - } -} -impl<'r> molecule::prelude::Reader<'r> for BTCDifficultyReader<'r> { - type Entity = BTCDifficulty; - const NAME: &'static str = "BTCDifficultyReader"; - fn to_entity(&self) -> Self::Entity { - Self::Entity::new_unchecked(self.as_slice().to_owned().into()) - } - fn new_unchecked(slice: &'r [u8]) -> Self { - BTCDifficultyReader(slice) - } - fn as_slice(&self) -> &'r [u8] { - self.0 - } - fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { - use molecule::verification_error as ve; - let slice_len = slice.len(); - if slice_len < molecule::NUMBER_SIZE { - return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); - } - let total_size = molecule::unpack_number(slice) as usize; - if slice_len != total_size { - return ve!(Self, TotalSizeNotMatch, total_size, slice_len); - } - if slice_len == molecule::NUMBER_SIZE && Self::FIELD_COUNT == 0 { - return Ok(()); - } - if slice_len < molecule::NUMBER_SIZE * 2 { - return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); - } - let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; - if offset_first % 4 != 0 || offset_first < molecule::NUMBER_SIZE * 2 { - return ve!(Self, OffsetsNotMatch); - } - let field_count = offset_first / 4 - 1; - if field_count < Self::FIELD_COUNT { - return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); - } else if !compatible && field_count > Self::FIELD_COUNT { - return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); - }; - let header_size = molecule::NUMBER_SIZE * (field_count + 1); - if slice_len < header_size { - return ve!(Self, HeaderIsBroken, header_size, slice_len); - } - let mut offsets: Vec = slice[molecule::NUMBER_SIZE..] - .chunks(molecule::NUMBER_SIZE) - .take(field_count) - .map(|x| molecule::unpack_number(x) as usize) - .collect(); - offsets.push(total_size); - if offsets.windows(2).any(|i| i[0] > i[1]) { - return ve!(Self, OffsetsNotMatch); - } - BytesReader::verify(&slice[offsets[0]..offsets[1]], compatible)?; - BytesReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; - Ok(()) - } -} -#[derive(Debug, Default)] -pub struct BTCDifficultyBuilder { - pub(crate) current: Bytes, - pub(crate) previous: Bytes, -} -impl BTCDifficultyBuilder { - pub const FIELD_COUNT: usize = 2; - pub fn current(mut self, v: Bytes) -> Self { - self.current = v; - self - } - pub fn previous(mut self, v: Bytes) -> Self { - self.previous = v; - self - } -} -impl molecule::prelude::Builder for BTCDifficultyBuilder { - type Entity = BTCDifficulty; - const NAME: &'static str = "BTCDifficultyBuilder"; - fn expected_length(&self) -> usize { - molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) - + self.current.as_slice().len() - + self.previous.as_slice().len() - } - fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { - let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); - let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); - offsets.push(total_size); - total_size += self.current.as_slice().len(); - offsets.push(total_size); - total_size += self.previous.as_slice().len(); - writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; - for offset in offsets.into_iter() { - writer.write_all(&molecule::pack_number(offset as molecule::Number))?; - } - writer.write_all(self.current.as_slice())?; - writer.write_all(self.previous.as_slice())?; - Ok(()) - } - fn build(&self) -> Self::Entity { - let mut inner = Vec::with_capacity(self.expected_length()); - self.write(&mut inner) - .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); - BTCDifficulty::new_unchecked(inner.into()) - } -} +use molecule :: prelude :: * ; +use super :: basic :: * ; +# [ derive ( Clone ) ] pub struct BTCDifficulty ( molecule :: bytes :: Bytes ) ; impl :: core :: fmt :: LowerHex for BTCDifficulty { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl :: core :: fmt :: Debug for BTCDifficulty { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl :: core :: fmt :: Display for BTCDifficulty { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{} {{ " , Self :: NAME ) ? ; write ! ( f , "{}: {}" , "current" , self . current ( ) ) ? ; write ! ( f , ", {}: {}" , "previous" , self . previous ( ) ) ? ; let extra_count = self . count_extra_fields ( ) ; if extra_count != 0 { write ! ( f , ", .. ({} fields)" , extra_count ) ? ; } write ! ( f , " }}" ) } } impl :: core :: default :: Default for BTCDifficulty { fn default ( ) -> Self { let v : Vec < u8 > = vec ! [ 20 , 0 , 0 , 0 , 12 , 0 , 0 , 0 , 16 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , ] ; BTCDifficulty :: new_unchecked ( v . into ( ) ) } } impl BTCDifficulty { pub const FIELD_COUNT : usize = 2 ; pub fn total_size ( & self ) -> usize { molecule :: unpack_number ( self . as_slice ( ) ) as usize } pub fn field_count ( & self ) -> usize { if self . total_size ( ) == molecule :: NUMBER_SIZE { 0 } else { ( molecule :: unpack_number ( & self . as_slice ( ) [ molecule :: NUMBER_SIZE .. ] ) as usize / 4 ) - 1 } } pub fn count_extra_fields ( & self ) -> usize { self . field_count ( ) - Self :: FIELD_COUNT } pub fn has_extra_fields ( & self ) -> bool { Self :: FIELD_COUNT != self . field_count ( ) } pub fn current ( & self ) -> Bytes { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 4 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; Bytes :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn previous ( & self ) -> Bytes { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; if self . has_extra_fields ( ) { let end = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; Bytes :: new_unchecked ( self . 0 . slice ( start .. end ) ) } else { Bytes :: new_unchecked ( self . 0 . slice ( start .. ) ) } } pub fn as_reader < 'r > ( & 'r self ) -> BTCDifficultyReader < 'r > { BTCDifficultyReader :: new_unchecked ( self . as_slice ( ) ) } } impl molecule :: prelude :: Entity for BTCDifficulty { type Builder = BTCDifficultyBuilder ; const NAME : & 'static str = "BTCDifficulty" ; fn new_unchecked ( data : molecule :: bytes :: Bytes ) -> Self { BTCDifficulty ( data ) } fn as_bytes ( & self ) -> molecule :: bytes :: Bytes { self . 0 . clone ( ) } fn as_slice ( & self ) -> & [ u8 ] { & self . 0 [ .. ] } fn from_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { BTCDifficultyReader :: from_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn from_compatible_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { BTCDifficultyReader :: from_compatible_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn new_builder ( ) -> Self :: Builder { :: core :: default :: Default :: default ( ) } fn as_builder ( self ) -> Self :: Builder { Self :: new_builder ( ) . current ( self . current ( ) ) . previous ( self . previous ( ) ) } } +# [ derive ( Clone , Copy ) ] pub struct BTCDifficultyReader < 'r > ( & 'r [ u8 ] ) ; impl < 'r > :: core :: fmt :: LowerHex for BTCDifficultyReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl < 'r > :: core :: fmt :: Debug for BTCDifficultyReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl < 'r > :: core :: fmt :: Display for BTCDifficultyReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{} {{ " , Self :: NAME ) ? ; write ! ( f , "{}: {}" , "current" , self . current ( ) ) ? ; write ! ( f , ", {}: {}" , "previous" , self . previous ( ) ) ? ; let extra_count = self . count_extra_fields ( ) ; if extra_count != 0 { write ! ( f , ", .. ({} fields)" , extra_count ) ? ; } write ! ( f , " }}" ) } } impl < 'r > BTCDifficultyReader < 'r > { pub const FIELD_COUNT : usize = 2 ; pub fn total_size ( & self ) -> usize { molecule :: unpack_number ( self . as_slice ( ) ) as usize } pub fn field_count ( & self ) -> usize { if self . total_size ( ) == molecule :: NUMBER_SIZE { 0 } else { ( molecule :: unpack_number ( & self . as_slice ( ) [ molecule :: NUMBER_SIZE .. ] ) as usize / 4 ) - 1 } } pub fn count_extra_fields ( & self ) -> usize { self . field_count ( ) - Self :: FIELD_COUNT } pub fn has_extra_fields ( & self ) -> bool { Self :: FIELD_COUNT != self . field_count ( ) } pub fn current ( & self ) -> BytesReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 4 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; BytesReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn previous ( & self ) -> BytesReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; if self . has_extra_fields ( ) { let end = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; BytesReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } else { BytesReader :: new_unchecked ( & self . as_slice ( ) [ start .. ] ) } } } impl < 'r > molecule :: prelude :: Reader < 'r > for BTCDifficultyReader < 'r > { type Entity = BTCDifficulty ; const NAME : & 'static str = "BTCDifficultyReader" ; fn to_entity ( & self ) -> Self :: Entity { Self :: Entity :: new_unchecked ( self . as_slice ( ) . to_owned ( ) . into ( ) ) } fn new_unchecked ( slice : & 'r [ u8 ] ) -> Self { BTCDifficultyReader ( slice ) } fn as_slice ( & self ) -> & 'r [ u8 ] { self . 0 } fn verify ( slice : & [ u8 ] , compatible : bool ) -> molecule :: error :: VerificationResult < ( ) > { use molecule :: verification_error as ve ; let slice_len = slice . len ( ) ; if slice_len < molecule :: NUMBER_SIZE { return ve ! ( Self , HeaderIsBroken , molecule :: NUMBER_SIZE , slice_len ) ; } let total_size = molecule :: unpack_number ( slice ) as usize ; if slice_len != total_size { return ve ! ( Self , TotalSizeNotMatch , total_size , slice_len ) ; } if slice_len == molecule :: NUMBER_SIZE && Self :: FIELD_COUNT == 0 { return Ok ( ( ) ) ; } if slice_len < molecule :: NUMBER_SIZE * 2 { return ve ! ( Self , HeaderIsBroken , molecule :: NUMBER_SIZE * 2 , slice_len ) ; } let offset_first = molecule :: unpack_number ( & slice [ molecule :: NUMBER_SIZE .. ] ) as usize ; if offset_first % 4 != 0 || offset_first < molecule :: NUMBER_SIZE * 2 { return ve ! ( Self , OffsetsNotMatch ) ; } let field_count = offset_first / 4 - 1 ; if field_count < Self :: FIELD_COUNT { return ve ! ( Self , FieldCountNotMatch , Self :: FIELD_COUNT , field_count ) ; } else if ! compatible && field_count > Self :: FIELD_COUNT { return ve ! ( Self , FieldCountNotMatch , Self :: FIELD_COUNT , field_count ) ; } ; let header_size = molecule :: NUMBER_SIZE * ( field_count + 1 ) ; if slice_len < header_size { return ve ! ( Self , HeaderIsBroken , header_size , slice_len ) ; } let mut offsets : Vec < usize > = slice [ molecule :: NUMBER_SIZE .. ] . chunks ( molecule :: NUMBER_SIZE ) . take ( field_count ) . map ( | x | molecule :: unpack_number ( x ) as usize ) . collect ( ) ; offsets . push ( total_size ) ; if offsets . windows ( 2 ) . any ( | i | i [ 0 ] > i [ 1 ] ) { return ve ! ( Self , OffsetsNotMatch ) ; } BytesReader :: verify ( & slice [ offsets [ 0 ] .. offsets [ 1 ] ] , compatible ) ? ; BytesReader :: verify ( & slice [ offsets [ 1 ] .. offsets [ 2 ] ] , compatible ) ? ; Ok ( ( ) ) } } +# [ derive ( Debug , Default ) ] pub struct BTCDifficultyBuilder { pub ( crate ) current : Bytes , pub ( crate ) previous : Bytes , } impl BTCDifficultyBuilder { pub const FIELD_COUNT : usize = 2 ; pub fn current ( mut self , v : Bytes ) -> Self { self . current = v ; self } pub fn previous ( mut self , v : Bytes ) -> Self { self . previous = v ; self } } impl molecule :: prelude :: Builder for BTCDifficultyBuilder { type Entity = BTCDifficulty ; const NAME : & 'static str = "BTCDifficultyBuilder" ; fn expected_length ( & self ) -> usize { molecule :: NUMBER_SIZE * ( Self :: FIELD_COUNT + 1 ) + self . current . as_slice ( ) . len ( ) + self . previous . as_slice ( ) . len ( ) } fn write < W : :: molecule :: io :: Write > ( & self , writer : & mut W ) -> :: molecule :: io :: Result < ( ) > { let mut total_size = molecule :: NUMBER_SIZE * ( Self :: FIELD_COUNT + 1 ) ; let mut offsets = Vec :: with_capacity ( Self :: FIELD_COUNT ) ; offsets . push ( total_size ) ; total_size += self . current . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . previous . as_slice ( ) . len ( ) ; writer . write_all ( & molecule :: pack_number ( total_size as molecule :: Number ) ) ? ; for offset in offsets . into_iter ( ) { writer . write_all ( & molecule :: pack_number ( offset as molecule :: Number ) ) ? ; } writer . write_all ( self . current . as_slice ( ) ) ? ; writer . write_all ( self . previous . as_slice ( ) ) ? ; Ok ( ( ) ) } fn build ( & self ) -> Self :: Entity { let mut inner = Vec :: with_capacity ( self . expected_length ( ) ) ; self . write ( & mut inner ) . unwrap_or_else ( | _ | panic ! ( "{} build should be ok" , Self :: NAME ) ) ; BTCDifficulty :: new_unchecked ( inner . into ( ) ) } } diff --git a/tests/src/toCKB_typescript/utils/types/generated/mint_xt_witness.rs b/tests/src/toCKB_typescript/utils/types/generated/mint_xt_witness.rs index e8f86b0..fbb0ce9 100644 --- a/tests/src/toCKB_typescript/utils/types/generated/mint_xt_witness.rs +++ b/tests/src/toCKB_typescript/utils/types/generated/mint_xt_witness.rs @@ -1,744 +1,13 @@ -// Generated by Molecule 0.6.0 +// Generated by Molecule 0.6.1 -use super::basic::*; -use molecule::prelude::*; -#[derive(Clone)] -pub struct MintXTWitness(molecule::bytes::Bytes); -impl ::core::fmt::LowerHex for MintXTWitness { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl ::core::fmt::Debug for MintXTWitness { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl ::core::fmt::Display for MintXTWitness { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{} {{ ", Self::NAME)?; - write!(f, "{}: {}", "spv_proof", self.spv_proof())?; - write!( - f, - ", {}: {}", - "cell_dep_index_list", - self.cell_dep_index_list() - )?; - let extra_count = self.count_extra_fields(); - if extra_count != 0 { - write!(f, ", .. ({} fields)", extra_count)?; - } - write!(f, " }}") - } -} -impl ::core::default::Default for MintXTWitness { - fn default() -> Self { - let v: Vec = vec![ - 20, 0, 0, 0, 12, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ]; - MintXTWitness::new_unchecked(v.into()) - } -} -impl MintXTWitness { - pub const FIELD_COUNT: usize = 2; - pub fn total_size(&self) -> usize { - molecule::unpack_number(self.as_slice()) as usize - } - pub fn field_count(&self) -> usize { - if self.total_size() == molecule::NUMBER_SIZE { - 0 - } else { - (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 - } - } - pub fn count_extra_fields(&self) -> usize { - self.field_count() - Self::FIELD_COUNT - } - pub fn has_extra_fields(&self) -> bool { - Self::FIELD_COUNT != self.field_count() - } - pub fn spv_proof(&self) -> Bytes { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[4..]) as usize; - let end = molecule::unpack_number(&slice[8..]) as usize; - Bytes::new_unchecked(self.0.slice(start..end)) - } - pub fn cell_dep_index_list(&self) -> Bytes { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[8..]) as usize; - if self.has_extra_fields() { - let end = molecule::unpack_number(&slice[12..]) as usize; - Bytes::new_unchecked(self.0.slice(start..end)) - } else { - Bytes::new_unchecked(self.0.slice(start..)) - } - } - pub fn as_reader<'r>(&'r self) -> MintXTWitnessReader<'r> { - MintXTWitnessReader::new_unchecked(self.as_slice()) - } -} -impl molecule::prelude::Entity for MintXTWitness { - type Builder = MintXTWitnessBuilder; - const NAME: &'static str = "MintXTWitness"; - fn new_unchecked(data: molecule::bytes::Bytes) -> Self { - MintXTWitness(data) - } - fn as_bytes(&self) -> molecule::bytes::Bytes { - self.0.clone() - } - fn as_slice(&self) -> &[u8] { - &self.0[..] - } - fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { - MintXTWitnessReader::from_slice(slice).map(|reader| reader.to_entity()) - } - fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { - MintXTWitnessReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) - } - fn new_builder() -> Self::Builder { - ::core::default::Default::default() - } - fn as_builder(self) -> Self::Builder { - Self::new_builder() - .spv_proof(self.spv_proof()) - .cell_dep_index_list(self.cell_dep_index_list()) - } -} -#[derive(Clone, Copy)] -pub struct MintXTWitnessReader<'r>(&'r [u8]); -impl<'r> ::core::fmt::LowerHex for MintXTWitnessReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl<'r> ::core::fmt::Debug for MintXTWitnessReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl<'r> ::core::fmt::Display for MintXTWitnessReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{} {{ ", Self::NAME)?; - write!(f, "{}: {}", "spv_proof", self.spv_proof())?; - write!( - f, - ", {}: {}", - "cell_dep_index_list", - self.cell_dep_index_list() - )?; - let extra_count = self.count_extra_fields(); - if extra_count != 0 { - write!(f, ", .. ({} fields)", extra_count)?; - } - write!(f, " }}") - } -} -impl<'r> MintXTWitnessReader<'r> { - pub const FIELD_COUNT: usize = 2; - pub fn total_size(&self) -> usize { - molecule::unpack_number(self.as_slice()) as usize - } - pub fn field_count(&self) -> usize { - if self.total_size() == molecule::NUMBER_SIZE { - 0 - } else { - (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 - } - } - pub fn count_extra_fields(&self) -> usize { - self.field_count() - Self::FIELD_COUNT - } - pub fn has_extra_fields(&self) -> bool { - Self::FIELD_COUNT != self.field_count() - } - pub fn spv_proof(&self) -> BytesReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[4..]) as usize; - let end = molecule::unpack_number(&slice[8..]) as usize; - BytesReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn cell_dep_index_list(&self) -> BytesReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[8..]) as usize; - if self.has_extra_fields() { - let end = molecule::unpack_number(&slice[12..]) as usize; - BytesReader::new_unchecked(&self.as_slice()[start..end]) - } else { - BytesReader::new_unchecked(&self.as_slice()[start..]) - } - } -} -impl<'r> molecule::prelude::Reader<'r> for MintXTWitnessReader<'r> { - type Entity = MintXTWitness; - const NAME: &'static str = "MintXTWitnessReader"; - fn to_entity(&self) -> Self::Entity { - Self::Entity::new_unchecked(self.as_slice().to_owned().into()) - } - fn new_unchecked(slice: &'r [u8]) -> Self { - MintXTWitnessReader(slice) - } - fn as_slice(&self) -> &'r [u8] { - self.0 - } - fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { - use molecule::verification_error as ve; - let slice_len = slice.len(); - if slice_len < molecule::NUMBER_SIZE { - return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); - } - let total_size = molecule::unpack_number(slice) as usize; - if slice_len != total_size { - return ve!(Self, TotalSizeNotMatch, total_size, slice_len); - } - if slice_len == molecule::NUMBER_SIZE && Self::FIELD_COUNT == 0 { - return Ok(()); - } - if slice_len < molecule::NUMBER_SIZE * 2 { - return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); - } - let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; - if offset_first % 4 != 0 || offset_first < molecule::NUMBER_SIZE * 2 { - return ve!(Self, OffsetsNotMatch); - } - let field_count = offset_first / 4 - 1; - if field_count < Self::FIELD_COUNT { - return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); - } else if !compatible && field_count > Self::FIELD_COUNT { - return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); - }; - let header_size = molecule::NUMBER_SIZE * (field_count + 1); - if slice_len < header_size { - return ve!(Self, HeaderIsBroken, header_size, slice_len); - } - let mut offsets: Vec = slice[molecule::NUMBER_SIZE..] - .chunks(molecule::NUMBER_SIZE) - .take(field_count) - .map(|x| molecule::unpack_number(x) as usize) - .collect(); - offsets.push(total_size); - if offsets.windows(2).any(|i| i[0] > i[1]) { - return ve!(Self, OffsetsNotMatch); - } - BytesReader::verify(&slice[offsets[0]..offsets[1]], compatible)?; - BytesReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; - Ok(()) - } -} -#[derive(Debug, Default)] -pub struct MintXTWitnessBuilder { - pub(crate) spv_proof: Bytes, - pub(crate) cell_dep_index_list: Bytes, -} -impl MintXTWitnessBuilder { - pub const FIELD_COUNT: usize = 2; - pub fn spv_proof(mut self, v: Bytes) -> Self { - self.spv_proof = v; - self - } - pub fn cell_dep_index_list(mut self, v: Bytes) -> Self { - self.cell_dep_index_list = v; - self - } -} -impl molecule::prelude::Builder for MintXTWitnessBuilder { - type Entity = MintXTWitness; - const NAME: &'static str = "MintXTWitnessBuilder"; - fn expected_length(&self) -> usize { - molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) - + self.spv_proof.as_slice().len() - + self.cell_dep_index_list.as_slice().len() - } - fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { - let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); - let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); - offsets.push(total_size); - total_size += self.spv_proof.as_slice().len(); - offsets.push(total_size); - total_size += self.cell_dep_index_list.as_slice().len(); - writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; - for offset in offsets.into_iter() { - writer.write_all(&molecule::pack_number(offset as molecule::Number))?; - } - writer.write_all(self.spv_proof.as_slice())?; - writer.write_all(self.cell_dep_index_list.as_slice())?; - Ok(()) - } - fn build(&self) -> Self::Entity { - let mut inner = Vec::with_capacity(self.expected_length()); - self.write(&mut inner) - .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); - MintXTWitness::new_unchecked(inner.into()) - } -} -#[derive(Clone)] -pub struct BTCSPVProof(molecule::bytes::Bytes); -impl ::core::fmt::LowerHex for BTCSPVProof { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl ::core::fmt::Debug for BTCSPVProof { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl ::core::fmt::Display for BTCSPVProof { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{} {{ ", Self::NAME)?; - write!(f, "{}: {}", "version", self.version())?; - write!(f, ", {}: {}", "vin", self.vin())?; - write!(f, ", {}: {}", "vout", self.vout())?; - write!(f, ", {}: {}", "locktime", self.locktime())?; - write!(f, ", {}: {}", "tx_id", self.tx_id())?; - write!(f, ", {}: {}", "index", self.index())?; - write!(f, ", {}: {}", "headers", self.headers())?; - write!( - f, - ", {}: {}", - "intermediate_nodes", - self.intermediate_nodes() - )?; - write!( - f, - ", {}: {}", - "funding_output_index", - self.funding_output_index() - )?; - let extra_count = self.count_extra_fields(); - if extra_count != 0 { - write!(f, ", .. ({} fields)", extra_count)?; - } - write!(f, " }}") - } -} -impl ::core::default::Default for BTCSPVProof { - fn default() -> Self { - let v: Vec = vec![ - 105, 0, 0, 0, 40, 0, 0, 0, 44, 0, 0, 0, 48, 0, 0, 0, 52, 0, 0, 0, 56, 0, 0, 0, 88, 0, - 0, 0, 96, 0, 0, 0, 100, 0, 0, 0, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ]; - BTCSPVProof::new_unchecked(v.into()) - } -} -impl BTCSPVProof { - pub const FIELD_COUNT: usize = 9; - pub fn total_size(&self) -> usize { - molecule::unpack_number(self.as_slice()) as usize - } - pub fn field_count(&self) -> usize { - if self.total_size() == molecule::NUMBER_SIZE { - 0 - } else { - (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 - } - } - pub fn count_extra_fields(&self) -> usize { - self.field_count() - Self::FIELD_COUNT - } - pub fn has_extra_fields(&self) -> bool { - Self::FIELD_COUNT != self.field_count() - } - pub fn version(&self) -> Byte4 { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[4..]) as usize; - let end = molecule::unpack_number(&slice[8..]) as usize; - Byte4::new_unchecked(self.0.slice(start..end)) - } - pub fn vin(&self) -> Bytes { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[8..]) as usize; - let end = molecule::unpack_number(&slice[12..]) as usize; - Bytes::new_unchecked(self.0.slice(start..end)) - } - pub fn vout(&self) -> Bytes { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[12..]) as usize; - let end = molecule::unpack_number(&slice[16..]) as usize; - Bytes::new_unchecked(self.0.slice(start..end)) - } - pub fn locktime(&self) -> Byte4 { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[16..]) as usize; - let end = molecule::unpack_number(&slice[20..]) as usize; - Byte4::new_unchecked(self.0.slice(start..end)) - } - pub fn tx_id(&self) -> Byte32 { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[20..]) as usize; - let end = molecule::unpack_number(&slice[24..]) as usize; - Byte32::new_unchecked(self.0.slice(start..end)) - } - pub fn index(&self) -> Uint64 { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[24..]) as usize; - let end = molecule::unpack_number(&slice[28..]) as usize; - Uint64::new_unchecked(self.0.slice(start..end)) - } - pub fn headers(&self) -> Bytes { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[28..]) as usize; - let end = molecule::unpack_number(&slice[32..]) as usize; - Bytes::new_unchecked(self.0.slice(start..end)) - } - pub fn intermediate_nodes(&self) -> Bytes { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[32..]) as usize; - let end = molecule::unpack_number(&slice[36..]) as usize; - Bytes::new_unchecked(self.0.slice(start..end)) - } - pub fn funding_output_index(&self) -> Byte { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[36..]) as usize; - if self.has_extra_fields() { - let end = molecule::unpack_number(&slice[40..]) as usize; - Byte::new_unchecked(self.0.slice(start..end)) - } else { - Byte::new_unchecked(self.0.slice(start..)) - } - } - pub fn as_reader<'r>(&'r self) -> BTCSPVProofReader<'r> { - BTCSPVProofReader::new_unchecked(self.as_slice()) - } -} -impl molecule::prelude::Entity for BTCSPVProof { - type Builder = BTCSPVProofBuilder; - const NAME: &'static str = "BTCSPVProof"; - fn new_unchecked(data: molecule::bytes::Bytes) -> Self { - BTCSPVProof(data) - } - fn as_bytes(&self) -> molecule::bytes::Bytes { - self.0.clone() - } - fn as_slice(&self) -> &[u8] { - &self.0[..] - } - fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { - BTCSPVProofReader::from_slice(slice).map(|reader| reader.to_entity()) - } - fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { - BTCSPVProofReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) - } - fn new_builder() -> Self::Builder { - ::core::default::Default::default() - } - fn as_builder(self) -> Self::Builder { - Self::new_builder() - .version(self.version()) - .vin(self.vin()) - .vout(self.vout()) - .locktime(self.locktime()) - .tx_id(self.tx_id()) - .index(self.index()) - .headers(self.headers()) - .intermediate_nodes(self.intermediate_nodes()) - .funding_output_index(self.funding_output_index()) - } -} -#[derive(Clone, Copy)] -pub struct BTCSPVProofReader<'r>(&'r [u8]); -impl<'r> ::core::fmt::LowerHex for BTCSPVProofReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl<'r> ::core::fmt::Debug for BTCSPVProofReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl<'r> ::core::fmt::Display for BTCSPVProofReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{} {{ ", Self::NAME)?; - write!(f, "{}: {}", "version", self.version())?; - write!(f, ", {}: {}", "vin", self.vin())?; - write!(f, ", {}: {}", "vout", self.vout())?; - write!(f, ", {}: {}", "locktime", self.locktime())?; - write!(f, ", {}: {}", "tx_id", self.tx_id())?; - write!(f, ", {}: {}", "index", self.index())?; - write!(f, ", {}: {}", "headers", self.headers())?; - write!( - f, - ", {}: {}", - "intermediate_nodes", - self.intermediate_nodes() - )?; - write!( - f, - ", {}: {}", - "funding_output_index", - self.funding_output_index() - )?; - let extra_count = self.count_extra_fields(); - if extra_count != 0 { - write!(f, ", .. ({} fields)", extra_count)?; - } - write!(f, " }}") - } -} -impl<'r> BTCSPVProofReader<'r> { - pub const FIELD_COUNT: usize = 9; - pub fn total_size(&self) -> usize { - molecule::unpack_number(self.as_slice()) as usize - } - pub fn field_count(&self) -> usize { - if self.total_size() == molecule::NUMBER_SIZE { - 0 - } else { - (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 - } - } - pub fn count_extra_fields(&self) -> usize { - self.field_count() - Self::FIELD_COUNT - } - pub fn has_extra_fields(&self) -> bool { - Self::FIELD_COUNT != self.field_count() - } - pub fn version(&self) -> Byte4Reader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[4..]) as usize; - let end = molecule::unpack_number(&slice[8..]) as usize; - Byte4Reader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn vin(&self) -> BytesReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[8..]) as usize; - let end = molecule::unpack_number(&slice[12..]) as usize; - BytesReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn vout(&self) -> BytesReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[12..]) as usize; - let end = molecule::unpack_number(&slice[16..]) as usize; - BytesReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn locktime(&self) -> Byte4Reader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[16..]) as usize; - let end = molecule::unpack_number(&slice[20..]) as usize; - Byte4Reader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn tx_id(&self) -> Byte32Reader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[20..]) as usize; - let end = molecule::unpack_number(&slice[24..]) as usize; - Byte32Reader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn index(&self) -> Uint64Reader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[24..]) as usize; - let end = molecule::unpack_number(&slice[28..]) as usize; - Uint64Reader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn headers(&self) -> BytesReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[28..]) as usize; - let end = molecule::unpack_number(&slice[32..]) as usize; - BytesReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn intermediate_nodes(&self) -> BytesReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[32..]) as usize; - let end = molecule::unpack_number(&slice[36..]) as usize; - BytesReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn funding_output_index(&self) -> ByteReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[36..]) as usize; - if self.has_extra_fields() { - let end = molecule::unpack_number(&slice[40..]) as usize; - ByteReader::new_unchecked(&self.as_slice()[start..end]) - } else { - ByteReader::new_unchecked(&self.as_slice()[start..]) - } - } -} -impl<'r> molecule::prelude::Reader<'r> for BTCSPVProofReader<'r> { - type Entity = BTCSPVProof; - const NAME: &'static str = "BTCSPVProofReader"; - fn to_entity(&self) -> Self::Entity { - Self::Entity::new_unchecked(self.as_slice().to_owned().into()) - } - fn new_unchecked(slice: &'r [u8]) -> Self { - BTCSPVProofReader(slice) - } - fn as_slice(&self) -> &'r [u8] { - self.0 - } - fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { - use molecule::verification_error as ve; - let slice_len = slice.len(); - if slice_len < molecule::NUMBER_SIZE { - return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); - } - let total_size = molecule::unpack_number(slice) as usize; - if slice_len != total_size { - return ve!(Self, TotalSizeNotMatch, total_size, slice_len); - } - if slice_len == molecule::NUMBER_SIZE && Self::FIELD_COUNT == 0 { - return Ok(()); - } - if slice_len < molecule::NUMBER_SIZE * 2 { - return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); - } - let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; - if offset_first % 4 != 0 || offset_first < molecule::NUMBER_SIZE * 2 { - return ve!(Self, OffsetsNotMatch); - } - let field_count = offset_first / 4 - 1; - if field_count < Self::FIELD_COUNT { - return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); - } else if !compatible && field_count > Self::FIELD_COUNT { - return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); - }; - let header_size = molecule::NUMBER_SIZE * (field_count + 1); - if slice_len < header_size { - return ve!(Self, HeaderIsBroken, header_size, slice_len); - } - let mut offsets: Vec = slice[molecule::NUMBER_SIZE..] - .chunks(molecule::NUMBER_SIZE) - .take(field_count) - .map(|x| molecule::unpack_number(x) as usize) - .collect(); - offsets.push(total_size); - if offsets.windows(2).any(|i| i[0] > i[1]) { - return ve!(Self, OffsetsNotMatch); - } - Byte4Reader::verify(&slice[offsets[0]..offsets[1]], compatible)?; - BytesReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; - BytesReader::verify(&slice[offsets[2]..offsets[3]], compatible)?; - Byte4Reader::verify(&slice[offsets[3]..offsets[4]], compatible)?; - Byte32Reader::verify(&slice[offsets[4]..offsets[5]], compatible)?; - Uint64Reader::verify(&slice[offsets[5]..offsets[6]], compatible)?; - BytesReader::verify(&slice[offsets[6]..offsets[7]], compatible)?; - BytesReader::verify(&slice[offsets[7]..offsets[8]], compatible)?; - ByteReader::verify(&slice[offsets[8]..offsets[9]], compatible)?; - Ok(()) - } -} -#[derive(Debug, Default)] -pub struct BTCSPVProofBuilder { - pub(crate) version: Byte4, - pub(crate) vin: Bytes, - pub(crate) vout: Bytes, - pub(crate) locktime: Byte4, - pub(crate) tx_id: Byte32, - pub(crate) index: Uint64, - pub(crate) headers: Bytes, - pub(crate) intermediate_nodes: Bytes, - pub(crate) funding_output_index: Byte, -} -impl BTCSPVProofBuilder { - pub const FIELD_COUNT: usize = 9; - pub fn version(mut self, v: Byte4) -> Self { - self.version = v; - self - } - pub fn vin(mut self, v: Bytes) -> Self { - self.vin = v; - self - } - pub fn vout(mut self, v: Bytes) -> Self { - self.vout = v; - self - } - pub fn locktime(mut self, v: Byte4) -> Self { - self.locktime = v; - self - } - pub fn tx_id(mut self, v: Byte32) -> Self { - self.tx_id = v; - self - } - pub fn index(mut self, v: Uint64) -> Self { - self.index = v; - self - } - pub fn headers(mut self, v: Bytes) -> Self { - self.headers = v; - self - } - pub fn intermediate_nodes(mut self, v: Bytes) -> Self { - self.intermediate_nodes = v; - self - } - pub fn funding_output_index(mut self, v: Byte) -> Self { - self.funding_output_index = v; - self - } -} -impl molecule::prelude::Builder for BTCSPVProofBuilder { - type Entity = BTCSPVProof; - const NAME: &'static str = "BTCSPVProofBuilder"; - fn expected_length(&self) -> usize { - molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) - + self.version.as_slice().len() - + self.vin.as_slice().len() - + self.vout.as_slice().len() - + self.locktime.as_slice().len() - + self.tx_id.as_slice().len() - + self.index.as_slice().len() - + self.headers.as_slice().len() - + self.intermediate_nodes.as_slice().len() - + self.funding_output_index.as_slice().len() - } - fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { - let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); - let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); - offsets.push(total_size); - total_size += self.version.as_slice().len(); - offsets.push(total_size); - total_size += self.vin.as_slice().len(); - offsets.push(total_size); - total_size += self.vout.as_slice().len(); - offsets.push(total_size); - total_size += self.locktime.as_slice().len(); - offsets.push(total_size); - total_size += self.tx_id.as_slice().len(); - offsets.push(total_size); - total_size += self.index.as_slice().len(); - offsets.push(total_size); - total_size += self.headers.as_slice().len(); - offsets.push(total_size); - total_size += self.intermediate_nodes.as_slice().len(); - offsets.push(total_size); - total_size += self.funding_output_index.as_slice().len(); - writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; - for offset in offsets.into_iter() { - writer.write_all(&molecule::pack_number(offset as molecule::Number))?; - } - writer.write_all(self.version.as_slice())?; - writer.write_all(self.vin.as_slice())?; - writer.write_all(self.vout.as_slice())?; - writer.write_all(self.locktime.as_slice())?; - writer.write_all(self.tx_id.as_slice())?; - writer.write_all(self.index.as_slice())?; - writer.write_all(self.headers.as_slice())?; - writer.write_all(self.intermediate_nodes.as_slice())?; - writer.write_all(self.funding_output_index.as_slice())?; - Ok(()) - } - fn build(&self) -> Self::Entity { - let mut inner = Vec::with_capacity(self.expected_length()); - self.write(&mut inner) - .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); - BTCSPVProof::new_unchecked(inner.into()) - } -} +use molecule :: prelude :: * ; +use super :: basic :: * ; +# [ derive ( Clone ) ] pub struct MintXTWitness ( molecule :: bytes :: Bytes ) ; impl :: core :: fmt :: LowerHex for MintXTWitness { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl :: core :: fmt :: Debug for MintXTWitness { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl :: core :: fmt :: Display for MintXTWitness { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{} {{ " , Self :: NAME ) ? ; write ! ( f , "{}: {}" , "spv_proof" , self . spv_proof ( ) ) ? ; write ! ( f , ", {}: {}" , "cell_dep_index_list" , self . cell_dep_index_list ( ) ) ? ; let extra_count = self . count_extra_fields ( ) ; if extra_count != 0 { write ! ( f , ", .. ({} fields)" , extra_count ) ? ; } write ! ( f , " }}" ) } } impl :: core :: default :: Default for MintXTWitness { fn default ( ) -> Self { let v : Vec < u8 > = vec ! [ 20 , 0 , 0 , 0 , 12 , 0 , 0 , 0 , 16 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , ] ; MintXTWitness :: new_unchecked ( v . into ( ) ) } } impl MintXTWitness { pub const FIELD_COUNT : usize = 2 ; pub fn total_size ( & self ) -> usize { molecule :: unpack_number ( self . as_slice ( ) ) as usize } pub fn field_count ( & self ) -> usize { if self . total_size ( ) == molecule :: NUMBER_SIZE { 0 } else { ( molecule :: unpack_number ( & self . as_slice ( ) [ molecule :: NUMBER_SIZE .. ] ) as usize / 4 ) - 1 } } pub fn count_extra_fields ( & self ) -> usize { self . field_count ( ) - Self :: FIELD_COUNT } pub fn has_extra_fields ( & self ) -> bool { Self :: FIELD_COUNT != self . field_count ( ) } pub fn spv_proof ( & self ) -> Bytes { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 4 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; Bytes :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn cell_dep_index_list ( & self ) -> Bytes { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; if self . has_extra_fields ( ) { let end = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; Bytes :: new_unchecked ( self . 0 . slice ( start .. end ) ) } else { Bytes :: new_unchecked ( self . 0 . slice ( start .. ) ) } } pub fn as_reader < 'r > ( & 'r self ) -> MintXTWitnessReader < 'r > { MintXTWitnessReader :: new_unchecked ( self . as_slice ( ) ) } } impl molecule :: prelude :: Entity for MintXTWitness { type Builder = MintXTWitnessBuilder ; const NAME : & 'static str = "MintXTWitness" ; fn new_unchecked ( data : molecule :: bytes :: Bytes ) -> Self { MintXTWitness ( data ) } fn as_bytes ( & self ) -> molecule :: bytes :: Bytes { self . 0 . clone ( ) } fn as_slice ( & self ) -> & [ u8 ] { & self . 0 [ .. ] } fn from_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { MintXTWitnessReader :: from_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn from_compatible_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { MintXTWitnessReader :: from_compatible_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn new_builder ( ) -> Self :: Builder { :: core :: default :: Default :: default ( ) } fn as_builder ( self ) -> Self :: Builder { Self :: new_builder ( ) . spv_proof ( self . spv_proof ( ) ) . cell_dep_index_list ( self . cell_dep_index_list ( ) ) } } +# [ derive ( Clone , Copy ) ] pub struct MintXTWitnessReader < 'r > ( & 'r [ u8 ] ) ; impl < 'r > :: core :: fmt :: LowerHex for MintXTWitnessReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl < 'r > :: core :: fmt :: Debug for MintXTWitnessReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl < 'r > :: core :: fmt :: Display for MintXTWitnessReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{} {{ " , Self :: NAME ) ? ; write ! ( f , "{}: {}" , "spv_proof" , self . spv_proof ( ) ) ? ; write ! ( f , ", {}: {}" , "cell_dep_index_list" , self . cell_dep_index_list ( ) ) ? ; let extra_count = self . count_extra_fields ( ) ; if extra_count != 0 { write ! ( f , ", .. ({} fields)" , extra_count ) ? ; } write ! ( f , " }}" ) } } impl < 'r > MintXTWitnessReader < 'r > { pub const FIELD_COUNT : usize = 2 ; pub fn total_size ( & self ) -> usize { molecule :: unpack_number ( self . as_slice ( ) ) as usize } pub fn field_count ( & self ) -> usize { if self . total_size ( ) == molecule :: NUMBER_SIZE { 0 } else { ( molecule :: unpack_number ( & self . as_slice ( ) [ molecule :: NUMBER_SIZE .. ] ) as usize / 4 ) - 1 } } pub fn count_extra_fields ( & self ) -> usize { self . field_count ( ) - Self :: FIELD_COUNT } pub fn has_extra_fields ( & self ) -> bool { Self :: FIELD_COUNT != self . field_count ( ) } pub fn spv_proof ( & self ) -> BytesReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 4 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; BytesReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn cell_dep_index_list ( & self ) -> BytesReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; if self . has_extra_fields ( ) { let end = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; BytesReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } else { BytesReader :: new_unchecked ( & self . as_slice ( ) [ start .. ] ) } } } impl < 'r > molecule :: prelude :: Reader < 'r > for MintXTWitnessReader < 'r > { type Entity = MintXTWitness ; const NAME : & 'static str = "MintXTWitnessReader" ; fn to_entity ( & self ) -> Self :: Entity { Self :: Entity :: new_unchecked ( self . as_slice ( ) . to_owned ( ) . into ( ) ) } fn new_unchecked ( slice : & 'r [ u8 ] ) -> Self { MintXTWitnessReader ( slice ) } fn as_slice ( & self ) -> & 'r [ u8 ] { self . 0 } fn verify ( slice : & [ u8 ] , compatible : bool ) -> molecule :: error :: VerificationResult < ( ) > { use molecule :: verification_error as ve ; let slice_len = slice . len ( ) ; if slice_len < molecule :: NUMBER_SIZE { return ve ! ( Self , HeaderIsBroken , molecule :: NUMBER_SIZE , slice_len ) ; } let total_size = molecule :: unpack_number ( slice ) as usize ; if slice_len != total_size { return ve ! ( Self , TotalSizeNotMatch , total_size , slice_len ) ; } if slice_len == molecule :: NUMBER_SIZE && Self :: FIELD_COUNT == 0 { return Ok ( ( ) ) ; } if slice_len < molecule :: NUMBER_SIZE * 2 { return ve ! ( Self , HeaderIsBroken , molecule :: NUMBER_SIZE * 2 , slice_len ) ; } let offset_first = molecule :: unpack_number ( & slice [ molecule :: NUMBER_SIZE .. ] ) as usize ; if offset_first % 4 != 0 || offset_first < molecule :: NUMBER_SIZE * 2 { return ve ! ( Self , OffsetsNotMatch ) ; } let field_count = offset_first / 4 - 1 ; if field_count < Self :: FIELD_COUNT { return ve ! ( Self , FieldCountNotMatch , Self :: FIELD_COUNT , field_count ) ; } else if ! compatible && field_count > Self :: FIELD_COUNT { return ve ! ( Self , FieldCountNotMatch , Self :: FIELD_COUNT , field_count ) ; } ; let header_size = molecule :: NUMBER_SIZE * ( field_count + 1 ) ; if slice_len < header_size { return ve ! ( Self , HeaderIsBroken , header_size , slice_len ) ; } let mut offsets : Vec < usize > = slice [ molecule :: NUMBER_SIZE .. ] . chunks ( molecule :: NUMBER_SIZE ) . take ( field_count ) . map ( | x | molecule :: unpack_number ( x ) as usize ) . collect ( ) ; offsets . push ( total_size ) ; if offsets . windows ( 2 ) . any ( | i | i [ 0 ] > i [ 1 ] ) { return ve ! ( Self , OffsetsNotMatch ) ; } BytesReader :: verify ( & slice [ offsets [ 0 ] .. offsets [ 1 ] ] , compatible ) ? ; BytesReader :: verify ( & slice [ offsets [ 1 ] .. offsets [ 2 ] ] , compatible ) ? ; Ok ( ( ) ) } } +# [ derive ( Debug , Default ) ] pub struct MintXTWitnessBuilder { pub ( crate ) spv_proof : Bytes , pub ( crate ) cell_dep_index_list : Bytes , } impl MintXTWitnessBuilder { pub const FIELD_COUNT : usize = 2 ; pub fn spv_proof ( mut self , v : Bytes ) -> Self { self . spv_proof = v ; self } pub fn cell_dep_index_list ( mut self , v : Bytes ) -> Self { self . cell_dep_index_list = v ; self } } impl molecule :: prelude :: Builder for MintXTWitnessBuilder { type Entity = MintXTWitness ; const NAME : & 'static str = "MintXTWitnessBuilder" ; fn expected_length ( & self ) -> usize { molecule :: NUMBER_SIZE * ( Self :: FIELD_COUNT + 1 ) + self . spv_proof . as_slice ( ) . len ( ) + self . cell_dep_index_list . as_slice ( ) . len ( ) } fn write < W : :: molecule :: io :: Write > ( & self , writer : & mut W ) -> :: molecule :: io :: Result < ( ) > { let mut total_size = molecule :: NUMBER_SIZE * ( Self :: FIELD_COUNT + 1 ) ; let mut offsets = Vec :: with_capacity ( Self :: FIELD_COUNT ) ; offsets . push ( total_size ) ; total_size += self . spv_proof . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . cell_dep_index_list . as_slice ( ) . len ( ) ; writer . write_all ( & molecule :: pack_number ( total_size as molecule :: Number ) ) ? ; for offset in offsets . into_iter ( ) { writer . write_all ( & molecule :: pack_number ( offset as molecule :: Number ) ) ? ; } writer . write_all ( self . spv_proof . as_slice ( ) ) ? ; writer . write_all ( self . cell_dep_index_list . as_slice ( ) ) ? ; Ok ( ( ) ) } fn build ( & self ) -> Self :: Entity { let mut inner = Vec :: with_capacity ( self . expected_length ( ) ) ; self . write ( & mut inner ) . unwrap_or_else ( | _ | panic ! ( "{} build should be ok" , Self :: NAME ) ) ; MintXTWitness :: new_unchecked ( inner . into ( ) ) } } +# [ derive ( Clone ) ] pub struct BTCSPVProof ( molecule :: bytes :: Bytes ) ; impl :: core :: fmt :: LowerHex for BTCSPVProof { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl :: core :: fmt :: Debug for BTCSPVProof { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl :: core :: fmt :: Display for BTCSPVProof { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{} {{ " , Self :: NAME ) ? ; write ! ( f , "{}: {}" , "version" , self . version ( ) ) ? ; write ! ( f , ", {}: {}" , "vin" , self . vin ( ) ) ? ; write ! ( f , ", {}: {}" , "vout" , self . vout ( ) ) ? ; write ! ( f , ", {}: {}" , "locktime" , self . locktime ( ) ) ? ; write ! ( f , ", {}: {}" , "tx_id" , self . tx_id ( ) ) ? ; write ! ( f , ", {}: {}" , "index" , self . index ( ) ) ? ; write ! ( f , ", {}: {}" , "headers" , self . headers ( ) ) ? ; write ! ( f , ", {}: {}" , "intermediate_nodes" , self . intermediate_nodes ( ) ) ? ; write ! ( f , ", {}: {}" , "funding_output_index" , self . funding_output_index ( ) ) ? ; let extra_count = self . count_extra_fields ( ) ; if extra_count != 0 { write ! ( f , ", .. ({} fields)" , extra_count ) ? ; } write ! ( f , " }}" ) } } impl :: core :: default :: Default for BTCSPVProof { fn default ( ) -> Self { let v : Vec < u8 > = vec ! [ 105 , 0 , 0 , 0 , 40 , 0 , 0 , 0 , 44 , 0 , 0 , 0 , 48 , 0 , 0 , 0 , 52 , 0 , 0 , 0 , 56 , 0 , 0 , 0 , 88 , 0 , 0 , 0 , 96 , 0 , 0 , 0 , 100 , 0 , 0 , 0 , 104 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , ] ; BTCSPVProof :: new_unchecked ( v . into ( ) ) } } impl BTCSPVProof { pub const FIELD_COUNT : usize = 9 ; pub fn total_size ( & self ) -> usize { molecule :: unpack_number ( self . as_slice ( ) ) as usize } pub fn field_count ( & self ) -> usize { if self . total_size ( ) == molecule :: NUMBER_SIZE { 0 } else { ( molecule :: unpack_number ( & self . as_slice ( ) [ molecule :: NUMBER_SIZE .. ] ) as usize / 4 ) - 1 } } pub fn count_extra_fields ( & self ) -> usize { self . field_count ( ) - Self :: FIELD_COUNT } pub fn has_extra_fields ( & self ) -> bool { Self :: FIELD_COUNT != self . field_count ( ) } pub fn version ( & self ) -> Byte4 { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 4 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; Byte4 :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn vin ( & self ) -> Bytes { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; Bytes :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn vout ( & self ) -> Bytes { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 16 .. ] ) as usize ; Bytes :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn locktime ( & self ) -> Byte4 { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 16 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 20 .. ] ) as usize ; Byte4 :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn tx_id ( & self ) -> Byte32 { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 20 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 24 .. ] ) as usize ; Byte32 :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn index ( & self ) -> Uint64 { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 24 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 28 .. ] ) as usize ; Uint64 :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn headers ( & self ) -> Bytes { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 28 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 32 .. ] ) as usize ; Bytes :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn intermediate_nodes ( & self ) -> Bytes { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 32 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 36 .. ] ) as usize ; Bytes :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn funding_output_index ( & self ) -> Byte { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 36 .. ] ) as usize ; if self . has_extra_fields ( ) { let end = molecule :: unpack_number ( & slice [ 40 .. ] ) as usize ; Byte :: new_unchecked ( self . 0 . slice ( start .. end ) ) } else { Byte :: new_unchecked ( self . 0 . slice ( start .. ) ) } } pub fn as_reader < 'r > ( & 'r self ) -> BTCSPVProofReader < 'r > { BTCSPVProofReader :: new_unchecked ( self . as_slice ( ) ) } } impl molecule :: prelude :: Entity for BTCSPVProof { type Builder = BTCSPVProofBuilder ; const NAME : & 'static str = "BTCSPVProof" ; fn new_unchecked ( data : molecule :: bytes :: Bytes ) -> Self { BTCSPVProof ( data ) } fn as_bytes ( & self ) -> molecule :: bytes :: Bytes { self . 0 . clone ( ) } fn as_slice ( & self ) -> & [ u8 ] { & self . 0 [ .. ] } fn from_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { BTCSPVProofReader :: from_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn from_compatible_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { BTCSPVProofReader :: from_compatible_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn new_builder ( ) -> Self :: Builder { :: core :: default :: Default :: default ( ) } fn as_builder ( self ) -> Self :: Builder { Self :: new_builder ( ) . version ( self . version ( ) ) . vin ( self . vin ( ) ) . vout ( self . vout ( ) ) . locktime ( self . locktime ( ) ) . tx_id ( self . tx_id ( ) ) . index ( self . index ( ) ) . headers ( self . headers ( ) ) . intermediate_nodes ( self . intermediate_nodes ( ) ) . funding_output_index ( self . funding_output_index ( ) ) } } +# [ derive ( Clone , Copy ) ] pub struct BTCSPVProofReader < 'r > ( & 'r [ u8 ] ) ; impl < 'r > :: core :: fmt :: LowerHex for BTCSPVProofReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl < 'r > :: core :: fmt :: Debug for BTCSPVProofReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl < 'r > :: core :: fmt :: Display for BTCSPVProofReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{} {{ " , Self :: NAME ) ? ; write ! ( f , "{}: {}" , "version" , self . version ( ) ) ? ; write ! ( f , ", {}: {}" , "vin" , self . vin ( ) ) ? ; write ! ( f , ", {}: {}" , "vout" , self . vout ( ) ) ? ; write ! ( f , ", {}: {}" , "locktime" , self . locktime ( ) ) ? ; write ! ( f , ", {}: {}" , "tx_id" , self . tx_id ( ) ) ? ; write ! ( f , ", {}: {}" , "index" , self . index ( ) ) ? ; write ! ( f , ", {}: {}" , "headers" , self . headers ( ) ) ? ; write ! ( f , ", {}: {}" , "intermediate_nodes" , self . intermediate_nodes ( ) ) ? ; write ! ( f , ", {}: {}" , "funding_output_index" , self . funding_output_index ( ) ) ? ; let extra_count = self . count_extra_fields ( ) ; if extra_count != 0 { write ! ( f , ", .. ({} fields)" , extra_count ) ? ; } write ! ( f , " }}" ) } } impl < 'r > BTCSPVProofReader < 'r > { pub const FIELD_COUNT : usize = 9 ; pub fn total_size ( & self ) -> usize { molecule :: unpack_number ( self . as_slice ( ) ) as usize } pub fn field_count ( & self ) -> usize { if self . total_size ( ) == molecule :: NUMBER_SIZE { 0 } else { ( molecule :: unpack_number ( & self . as_slice ( ) [ molecule :: NUMBER_SIZE .. ] ) as usize / 4 ) - 1 } } pub fn count_extra_fields ( & self ) -> usize { self . field_count ( ) - Self :: FIELD_COUNT } pub fn has_extra_fields ( & self ) -> bool { Self :: FIELD_COUNT != self . field_count ( ) } pub fn version ( & self ) -> Byte4Reader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 4 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; Byte4Reader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn vin ( & self ) -> BytesReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; BytesReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn vout ( & self ) -> BytesReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 16 .. ] ) as usize ; BytesReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn locktime ( & self ) -> Byte4Reader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 16 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 20 .. ] ) as usize ; Byte4Reader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn tx_id ( & self ) -> Byte32Reader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 20 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 24 .. ] ) as usize ; Byte32Reader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn index ( & self ) -> Uint64Reader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 24 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 28 .. ] ) as usize ; Uint64Reader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn headers ( & self ) -> BytesReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 28 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 32 .. ] ) as usize ; BytesReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn intermediate_nodes ( & self ) -> BytesReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 32 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 36 .. ] ) as usize ; BytesReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn funding_output_index ( & self ) -> ByteReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 36 .. ] ) as usize ; if self . has_extra_fields ( ) { let end = molecule :: unpack_number ( & slice [ 40 .. ] ) as usize ; ByteReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } else { ByteReader :: new_unchecked ( & self . as_slice ( ) [ start .. ] ) } } } impl < 'r > molecule :: prelude :: Reader < 'r > for BTCSPVProofReader < 'r > { type Entity = BTCSPVProof ; const NAME : & 'static str = "BTCSPVProofReader" ; fn to_entity ( & self ) -> Self :: Entity { Self :: Entity :: new_unchecked ( self . as_slice ( ) . to_owned ( ) . into ( ) ) } fn new_unchecked ( slice : & 'r [ u8 ] ) -> Self { BTCSPVProofReader ( slice ) } fn as_slice ( & self ) -> & 'r [ u8 ] { self . 0 } fn verify ( slice : & [ u8 ] , compatible : bool ) -> molecule :: error :: VerificationResult < ( ) > { use molecule :: verification_error as ve ; let slice_len = slice . len ( ) ; if slice_len < molecule :: NUMBER_SIZE { return ve ! ( Self , HeaderIsBroken , molecule :: NUMBER_SIZE , slice_len ) ; } let total_size = molecule :: unpack_number ( slice ) as usize ; if slice_len != total_size { return ve ! ( Self , TotalSizeNotMatch , total_size , slice_len ) ; } if slice_len == molecule :: NUMBER_SIZE && Self :: FIELD_COUNT == 0 { return Ok ( ( ) ) ; } if slice_len < molecule :: NUMBER_SIZE * 2 { return ve ! ( Self , HeaderIsBroken , molecule :: NUMBER_SIZE * 2 , slice_len ) ; } let offset_first = molecule :: unpack_number ( & slice [ molecule :: NUMBER_SIZE .. ] ) as usize ; if offset_first % 4 != 0 || offset_first < molecule :: NUMBER_SIZE * 2 { return ve ! ( Self , OffsetsNotMatch ) ; } let field_count = offset_first / 4 - 1 ; if field_count < Self :: FIELD_COUNT { return ve ! ( Self , FieldCountNotMatch , Self :: FIELD_COUNT , field_count ) ; } else if ! compatible && field_count > Self :: FIELD_COUNT { return ve ! ( Self , FieldCountNotMatch , Self :: FIELD_COUNT , field_count ) ; } ; let header_size = molecule :: NUMBER_SIZE * ( field_count + 1 ) ; if slice_len < header_size { return ve ! ( Self , HeaderIsBroken , header_size , slice_len ) ; } let mut offsets : Vec < usize > = slice [ molecule :: NUMBER_SIZE .. ] . chunks ( molecule :: NUMBER_SIZE ) . take ( field_count ) . map ( | x | molecule :: unpack_number ( x ) as usize ) . collect ( ) ; offsets . push ( total_size ) ; if offsets . windows ( 2 ) . any ( | i | i [ 0 ] > i [ 1 ] ) { return ve ! ( Self , OffsetsNotMatch ) ; } Byte4Reader :: verify ( & slice [ offsets [ 0 ] .. offsets [ 1 ] ] , compatible ) ? ; BytesReader :: verify ( & slice [ offsets [ 1 ] .. offsets [ 2 ] ] , compatible ) ? ; BytesReader :: verify ( & slice [ offsets [ 2 ] .. offsets [ 3 ] ] , compatible ) ? ; Byte4Reader :: verify ( & slice [ offsets [ 3 ] .. offsets [ 4 ] ] , compatible ) ? ; Byte32Reader :: verify ( & slice [ offsets [ 4 ] .. offsets [ 5 ] ] , compatible ) ? ; Uint64Reader :: verify ( & slice [ offsets [ 5 ] .. offsets [ 6 ] ] , compatible ) ? ; BytesReader :: verify ( & slice [ offsets [ 6 ] .. offsets [ 7 ] ] , compatible ) ? ; BytesReader :: verify ( & slice [ offsets [ 7 ] .. offsets [ 8 ] ] , compatible ) ? ; ByteReader :: verify ( & slice [ offsets [ 8 ] .. offsets [ 9 ] ] , compatible ) ? ; Ok ( ( ) ) } } +# [ derive ( Debug , Default ) ] pub struct BTCSPVProofBuilder { pub ( crate ) version : Byte4 , pub ( crate ) vin : Bytes , pub ( crate ) vout : Bytes , pub ( crate ) locktime : Byte4 , pub ( crate ) tx_id : Byte32 , pub ( crate ) index : Uint64 , pub ( crate ) headers : Bytes , pub ( crate ) intermediate_nodes : Bytes , pub ( crate ) funding_output_index : Byte , } impl BTCSPVProofBuilder { pub const FIELD_COUNT : usize = 9 ; pub fn version ( mut self , v : Byte4 ) -> Self { self . version = v ; self } pub fn vin ( mut self , v : Bytes ) -> Self { self . vin = v ; self } pub fn vout ( mut self , v : Bytes ) -> Self { self . vout = v ; self } pub fn locktime ( mut self , v : Byte4 ) -> Self { self . locktime = v ; self } pub fn tx_id ( mut self , v : Byte32 ) -> Self { self . tx_id = v ; self } pub fn index ( mut self , v : Uint64 ) -> Self { self . index = v ; self } pub fn headers ( mut self , v : Bytes ) -> Self { self . headers = v ; self } pub fn intermediate_nodes ( mut self , v : Bytes ) -> Self { self . intermediate_nodes = v ; self } pub fn funding_output_index ( mut self , v : Byte ) -> Self { self . funding_output_index = v ; self } } impl molecule :: prelude :: Builder for BTCSPVProofBuilder { type Entity = BTCSPVProof ; const NAME : & 'static str = "BTCSPVProofBuilder" ; fn expected_length ( & self ) -> usize { molecule :: NUMBER_SIZE * ( Self :: FIELD_COUNT + 1 ) + self . version . as_slice ( ) . len ( ) + self . vin . as_slice ( ) . len ( ) + self . vout . as_slice ( ) . len ( ) + self . locktime . as_slice ( ) . len ( ) + self . tx_id . as_slice ( ) . len ( ) + self . index . as_slice ( ) . len ( ) + self . headers . as_slice ( ) . len ( ) + self . intermediate_nodes . as_slice ( ) . len ( ) + self . funding_output_index . as_slice ( ) . len ( ) } fn write < W : :: molecule :: io :: Write > ( & self , writer : & mut W ) -> :: molecule :: io :: Result < ( ) > { let mut total_size = molecule :: NUMBER_SIZE * ( Self :: FIELD_COUNT + 1 ) ; let mut offsets = Vec :: with_capacity ( Self :: FIELD_COUNT ) ; offsets . push ( total_size ) ; total_size += self . version . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . vin . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . vout . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . locktime . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . tx_id . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . index . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . headers . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . intermediate_nodes . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . funding_output_index . as_slice ( ) . len ( ) ; writer . write_all ( & molecule :: pack_number ( total_size as molecule :: Number ) ) ? ; for offset in offsets . into_iter ( ) { writer . write_all ( & molecule :: pack_number ( offset as molecule :: Number ) ) ? ; } writer . write_all ( self . version . as_slice ( ) ) ? ; writer . write_all ( self . vin . as_slice ( ) ) ? ; writer . write_all ( self . vout . as_slice ( ) ) ? ; writer . write_all ( self . locktime . as_slice ( ) ) ? ; writer . write_all ( self . tx_id . as_slice ( ) ) ? ; writer . write_all ( self . index . as_slice ( ) ) ? ; writer . write_all ( self . headers . as_slice ( ) ) ? ; writer . write_all ( self . intermediate_nodes . as_slice ( ) ) ? ; writer . write_all ( self . funding_output_index . as_slice ( ) ) ? ; Ok ( ( ) ) } fn build ( & self ) -> Self :: Entity { let mut inner = Vec :: with_capacity ( self . expected_length ( ) ) ; self . write ( & mut inner ) . unwrap_or_else ( | _ | panic ! ( "{} build should be ok" , Self :: NAME ) ) ; BTCSPVProof :: new_unchecked ( inner . into ( ) ) } } +# [ derive ( Clone ) ] pub struct ETHSPVProof ( molecule :: bytes :: Bytes ) ; impl :: core :: fmt :: LowerHex for ETHSPVProof { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl :: core :: fmt :: Debug for ETHSPVProof { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl :: core :: fmt :: Display for ETHSPVProof { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{} {{ " , Self :: NAME ) ? ; write ! ( f , "{}: {}" , "log_index" , self . log_index ( ) ) ? ; write ! ( f , ", {}: {}" , "log_entry_data" , self . log_entry_data ( ) ) ? ; write ! ( f , ", {}: {}" , "receipt_index" , self . receipt_index ( ) ) ? ; write ! ( f , ", {}: {}" , "receipt_data" , self . receipt_data ( ) ) ? ; write ! ( f , ", {}: {}" , "receipts_root" , self . receipts_root ( ) ) ? ; write ! ( f , ", {}: {}" , "header_data" , self . header_data ( ) ) ? ; write ! ( f , ", {}: {}" , "proof" , self . proof ( ) ) ? ; let extra_count = self . count_extra_fields ( ) ; if extra_count != 0 { write ! ( f , ", .. ({} fields)" , extra_count ) ? ; } write ! ( f , " }}" ) } } impl :: core :: default :: Default for ETHSPVProof { fn default ( ) -> Self { let v : Vec < u8 > = vec ! [ 68 , 0 , 0 , 0 , 32 , 0 , 0 , 0 , 40 , 0 , 0 , 0 , 44 , 0 , 0 , 0 , 52 , 0 , 0 , 0 , 56 , 0 , 0 , 0 , 60 , 0 , 0 , 0 , 64 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 4 , 0 , 0 , 0 , ] ; ETHSPVProof :: new_unchecked ( v . into ( ) ) } } impl ETHSPVProof { pub const FIELD_COUNT : usize = 7 ; pub fn total_size ( & self ) -> usize { molecule :: unpack_number ( self . as_slice ( ) ) as usize } pub fn field_count ( & self ) -> usize { if self . total_size ( ) == molecule :: NUMBER_SIZE { 0 } else { ( molecule :: unpack_number ( & self . as_slice ( ) [ molecule :: NUMBER_SIZE .. ] ) as usize / 4 ) - 1 } } pub fn count_extra_fields ( & self ) -> usize { self . field_count ( ) - Self :: FIELD_COUNT } pub fn has_extra_fields ( & self ) -> bool { Self :: FIELD_COUNT != self . field_count ( ) } pub fn log_index ( & self ) -> Uint64 { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 4 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; Uint64 :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn log_entry_data ( & self ) -> Bytes { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; Bytes :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn receipt_index ( & self ) -> Uint64 { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 16 .. ] ) as usize ; Uint64 :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn receipt_data ( & self ) -> Bytes { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 16 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 20 .. ] ) as usize ; Bytes :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn receipts_root ( & self ) -> Bytes { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 20 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 24 .. ] ) as usize ; Bytes :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn header_data ( & self ) -> Bytes { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 24 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 28 .. ] ) as usize ; Bytes :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn proof ( & self ) -> Bytes2 { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 28 .. ] ) as usize ; if self . has_extra_fields ( ) { let end = molecule :: unpack_number ( & slice [ 32 .. ] ) as usize ; Bytes2 :: new_unchecked ( self . 0 . slice ( start .. end ) ) } else { Bytes2 :: new_unchecked ( self . 0 . slice ( start .. ) ) } } pub fn as_reader < 'r > ( & 'r self ) -> ETHSPVProofReader < 'r > { ETHSPVProofReader :: new_unchecked ( self . as_slice ( ) ) } } impl molecule :: prelude :: Entity for ETHSPVProof { type Builder = ETHSPVProofBuilder ; const NAME : & 'static str = "ETHSPVProof" ; fn new_unchecked ( data : molecule :: bytes :: Bytes ) -> Self { ETHSPVProof ( data ) } fn as_bytes ( & self ) -> molecule :: bytes :: Bytes { self . 0 . clone ( ) } fn as_slice ( & self ) -> & [ u8 ] { & self . 0 [ .. ] } fn from_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { ETHSPVProofReader :: from_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn from_compatible_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { ETHSPVProofReader :: from_compatible_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn new_builder ( ) -> Self :: Builder { :: core :: default :: Default :: default ( ) } fn as_builder ( self ) -> Self :: Builder { Self :: new_builder ( ) . log_index ( self . log_index ( ) ) . log_entry_data ( self . log_entry_data ( ) ) . receipt_index ( self . receipt_index ( ) ) . receipt_data ( self . receipt_data ( ) ) . receipts_root ( self . receipts_root ( ) ) . header_data ( self . header_data ( ) ) . proof ( self . proof ( ) ) } } +# [ derive ( Clone , Copy ) ] pub struct ETHSPVProofReader < 'r > ( & 'r [ u8 ] ) ; impl < 'r > :: core :: fmt :: LowerHex for ETHSPVProofReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl < 'r > :: core :: fmt :: Debug for ETHSPVProofReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl < 'r > :: core :: fmt :: Display for ETHSPVProofReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{} {{ " , Self :: NAME ) ? ; write ! ( f , "{}: {}" , "log_index" , self . log_index ( ) ) ? ; write ! ( f , ", {}: {}" , "log_entry_data" , self . log_entry_data ( ) ) ? ; write ! ( f , ", {}: {}" , "receipt_index" , self . receipt_index ( ) ) ? ; write ! ( f , ", {}: {}" , "receipt_data" , self . receipt_data ( ) ) ? ; write ! ( f , ", {}: {}" , "receipts_root" , self . receipts_root ( ) ) ? ; write ! ( f , ", {}: {}" , "header_data" , self . header_data ( ) ) ? ; write ! ( f , ", {}: {}" , "proof" , self . proof ( ) ) ? ; let extra_count = self . count_extra_fields ( ) ; if extra_count != 0 { write ! ( f , ", .. ({} fields)" , extra_count ) ? ; } write ! ( f , " }}" ) } } impl < 'r > ETHSPVProofReader < 'r > { pub const FIELD_COUNT : usize = 7 ; pub fn total_size ( & self ) -> usize { molecule :: unpack_number ( self . as_slice ( ) ) as usize } pub fn field_count ( & self ) -> usize { if self . total_size ( ) == molecule :: NUMBER_SIZE { 0 } else { ( molecule :: unpack_number ( & self . as_slice ( ) [ molecule :: NUMBER_SIZE .. ] ) as usize / 4 ) - 1 } } pub fn count_extra_fields ( & self ) -> usize { self . field_count ( ) - Self :: FIELD_COUNT } pub fn has_extra_fields ( & self ) -> bool { Self :: FIELD_COUNT != self . field_count ( ) } pub fn log_index ( & self ) -> Uint64Reader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 4 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; Uint64Reader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn log_entry_data ( & self ) -> BytesReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; BytesReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn receipt_index ( & self ) -> Uint64Reader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 16 .. ] ) as usize ; Uint64Reader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn receipt_data ( & self ) -> BytesReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 16 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 20 .. ] ) as usize ; BytesReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn receipts_root ( & self ) -> BytesReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 20 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 24 .. ] ) as usize ; BytesReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn header_data ( & self ) -> BytesReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 24 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 28 .. ] ) as usize ; BytesReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn proof ( & self ) -> Bytes2Reader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 28 .. ] ) as usize ; if self . has_extra_fields ( ) { let end = molecule :: unpack_number ( & slice [ 32 .. ] ) as usize ; Bytes2Reader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } else { Bytes2Reader :: new_unchecked ( & self . as_slice ( ) [ start .. ] ) } } } impl < 'r > molecule :: prelude :: Reader < 'r > for ETHSPVProofReader < 'r > { type Entity = ETHSPVProof ; const NAME : & 'static str = "ETHSPVProofReader" ; fn to_entity ( & self ) -> Self :: Entity { Self :: Entity :: new_unchecked ( self . as_slice ( ) . to_owned ( ) . into ( ) ) } fn new_unchecked ( slice : & 'r [ u8 ] ) -> Self { ETHSPVProofReader ( slice ) } fn as_slice ( & self ) -> & 'r [ u8 ] { self . 0 } fn verify ( slice : & [ u8 ] , compatible : bool ) -> molecule :: error :: VerificationResult < ( ) > { use molecule :: verification_error as ve ; let slice_len = slice . len ( ) ; if slice_len < molecule :: NUMBER_SIZE { return ve ! ( Self , HeaderIsBroken , molecule :: NUMBER_SIZE , slice_len ) ; } let total_size = molecule :: unpack_number ( slice ) as usize ; if slice_len != total_size { return ve ! ( Self , TotalSizeNotMatch , total_size , slice_len ) ; } if slice_len == molecule :: NUMBER_SIZE && Self :: FIELD_COUNT == 0 { return Ok ( ( ) ) ; } if slice_len < molecule :: NUMBER_SIZE * 2 { return ve ! ( Self , HeaderIsBroken , molecule :: NUMBER_SIZE * 2 , slice_len ) ; } let offset_first = molecule :: unpack_number ( & slice [ molecule :: NUMBER_SIZE .. ] ) as usize ; if offset_first % 4 != 0 || offset_first < molecule :: NUMBER_SIZE * 2 { return ve ! ( Self , OffsetsNotMatch ) ; } let field_count = offset_first / 4 - 1 ; if field_count < Self :: FIELD_COUNT { return ve ! ( Self , FieldCountNotMatch , Self :: FIELD_COUNT , field_count ) ; } else if ! compatible && field_count > Self :: FIELD_COUNT { return ve ! ( Self , FieldCountNotMatch , Self :: FIELD_COUNT , field_count ) ; } ; let header_size = molecule :: NUMBER_SIZE * ( field_count + 1 ) ; if slice_len < header_size { return ve ! ( Self , HeaderIsBroken , header_size , slice_len ) ; } let mut offsets : Vec < usize > = slice [ molecule :: NUMBER_SIZE .. ] . chunks ( molecule :: NUMBER_SIZE ) . take ( field_count ) . map ( | x | molecule :: unpack_number ( x ) as usize ) . collect ( ) ; offsets . push ( total_size ) ; if offsets . windows ( 2 ) . any ( | i | i [ 0 ] > i [ 1 ] ) { return ve ! ( Self , OffsetsNotMatch ) ; } Uint64Reader :: verify ( & slice [ offsets [ 0 ] .. offsets [ 1 ] ] , compatible ) ? ; BytesReader :: verify ( & slice [ offsets [ 1 ] .. offsets [ 2 ] ] , compatible ) ? ; Uint64Reader :: verify ( & slice [ offsets [ 2 ] .. offsets [ 3 ] ] , compatible ) ? ; BytesReader :: verify ( & slice [ offsets [ 3 ] .. offsets [ 4 ] ] , compatible ) ? ; BytesReader :: verify ( & slice [ offsets [ 4 ] .. offsets [ 5 ] ] , compatible ) ? ; BytesReader :: verify ( & slice [ offsets [ 5 ] .. offsets [ 6 ] ] , compatible ) ? ; Bytes2Reader :: verify ( & slice [ offsets [ 6 ] .. offsets [ 7 ] ] , compatible ) ? ; Ok ( ( ) ) } } +# [ derive ( Debug , Default ) ] pub struct ETHSPVProofBuilder { pub ( crate ) log_index : Uint64 , pub ( crate ) log_entry_data : Bytes , pub ( crate ) receipt_index : Uint64 , pub ( crate ) receipt_data : Bytes , pub ( crate ) receipts_root : Bytes , pub ( crate ) header_data : Bytes , pub ( crate ) proof : Bytes2 , } impl ETHSPVProofBuilder { pub const FIELD_COUNT : usize = 7 ; pub fn log_index ( mut self , v : Uint64 ) -> Self { self . log_index = v ; self } pub fn log_entry_data ( mut self , v : Bytes ) -> Self { self . log_entry_data = v ; self } pub fn receipt_index ( mut self , v : Uint64 ) -> Self { self . receipt_index = v ; self } pub fn receipt_data ( mut self , v : Bytes ) -> Self { self . receipt_data = v ; self } pub fn receipts_root ( mut self , v : Bytes ) -> Self { self . receipts_root = v ; self } pub fn header_data ( mut self , v : Bytes ) -> Self { self . header_data = v ; self } pub fn proof ( mut self , v : Bytes2 ) -> Self { self . proof = v ; self } } impl molecule :: prelude :: Builder for ETHSPVProofBuilder { type Entity = ETHSPVProof ; const NAME : & 'static str = "ETHSPVProofBuilder" ; fn expected_length ( & self ) -> usize { molecule :: NUMBER_SIZE * ( Self :: FIELD_COUNT + 1 ) + self . log_index . as_slice ( ) . len ( ) + self . log_entry_data . as_slice ( ) . len ( ) + self . receipt_index . as_slice ( ) . len ( ) + self . receipt_data . as_slice ( ) . len ( ) + self . receipts_root . as_slice ( ) . len ( ) + self . header_data . as_slice ( ) . len ( ) + self . proof . as_slice ( ) . len ( ) } fn write < W : :: molecule :: io :: Write > ( & self , writer : & mut W ) -> :: molecule :: io :: Result < ( ) > { let mut total_size = molecule :: NUMBER_SIZE * ( Self :: FIELD_COUNT + 1 ) ; let mut offsets = Vec :: with_capacity ( Self :: FIELD_COUNT ) ; offsets . push ( total_size ) ; total_size += self . log_index . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . log_entry_data . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . receipt_index . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . receipt_data . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . receipts_root . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . header_data . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . proof . as_slice ( ) . len ( ) ; writer . write_all ( & molecule :: pack_number ( total_size as molecule :: Number ) ) ? ; for offset in offsets . into_iter ( ) { writer . write_all ( & molecule :: pack_number ( offset as molecule :: Number ) ) ? ; } writer . write_all ( self . log_index . as_slice ( ) ) ? ; writer . write_all ( self . log_entry_data . as_slice ( ) ) ? ; writer . write_all ( self . receipt_index . as_slice ( ) ) ? ; writer . write_all ( self . receipt_data . as_slice ( ) ) ? ; writer . write_all ( self . receipts_root . as_slice ( ) ) ? ; writer . write_all ( self . header_data . as_slice ( ) ) ? ; writer . write_all ( self . proof . as_slice ( ) ) ? ; Ok ( ( ) ) } fn build ( & self ) -> Self :: Entity { let mut inner = Vec :: with_capacity ( self . expected_length ( ) ) ; self . write ( & mut inner ) . unwrap_or_else ( | _ | panic ! ( "{} build should be ok" , Self :: NAME ) ) ; ETHSPVProof :: new_unchecked ( inner . into ( ) ) } } diff --git a/tests/src/toCKB_typescript/utils/types/generated/toCKB_cell_data.rs b/tests/src/toCKB_typescript/utils/types/generated/toCKB_cell_data.rs index 36fb162..2579507 100644 --- a/tests/src/toCKB_typescript/utils/types/generated/toCKB_cell_data.rs +++ b/tests/src/toCKB_typescript/utils/types/generated/toCKB_cell_data.rs @@ -1,449 +1,7 @@ -// Generated by Molecule 0.6.0 +// Generated by Molecule 0.6.1 -use super::basic::*; -use molecule::prelude::*; -#[derive(Clone)] -pub struct ToCKBCellData(molecule::bytes::Bytes); -impl ::core::fmt::LowerHex for ToCKBCellData { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl ::core::fmt::Debug for ToCKBCellData { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl ::core::fmt::Display for ToCKBCellData { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{} {{ ", Self::NAME)?; - write!(f, "{}: {}", "status", self.status())?; - write!(f, ", {}: {}", "lot_size", self.lot_size())?; - write!(f, ", {}: {}", "user_lockscript", self.user_lockscript())?; - write!(f, ", {}: {}", "x_lock_address", self.x_lock_address())?; - write!(f, ", {}: {}", "signer_lockscript", self.signer_lockscript())?; - write!(f, ", {}: {}", "x_unlock_address", self.x_unlock_address())?; - write!( - f, - ", {}: {}", - "redeemer_lockscript", - self.redeemer_lockscript() - )?; - write!( - f, - ", {}: {}", - "liquidation_trigger_lockscript", - self.liquidation_trigger_lockscript() - )?; - let extra_count = self.count_extra_fields(); - if extra_count != 0 { - write!(f, ", .. ({} fields)", extra_count)?; - } - write!(f, " }}") - } -} -impl ::core::default::Default for ToCKBCellData { - fn default() -> Self { - let v: Vec = vec![ - 2, 1, 0, 0, 36, 0, 0, 0, 37, 0, 0, 0, 38, 0, 0, 0, 91, 0, 0, 0, 95, 0, 0, 0, 148, 0, 0, - 0, 152, 0, 0, 0, 205, 0, 0, 0, 0, 0, 53, 0, 0, 0, 16, 0, 0, 0, 48, 0, 0, 0, 49, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 0, 0, 0, 16, 0, 0, 0, 48, 0, 0, 0, 49, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 0, 0, 0, 16, 0, 0, 0, 48, 0, 0, 0, 49, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 0, 0, 0, 16, 0, 0, 0, 48, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - ]; - ToCKBCellData::new_unchecked(v.into()) - } -} -impl ToCKBCellData { - pub const FIELD_COUNT: usize = 8; - pub fn total_size(&self) -> usize { - molecule::unpack_number(self.as_slice()) as usize - } - pub fn field_count(&self) -> usize { - if self.total_size() == molecule::NUMBER_SIZE { - 0 - } else { - (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 - } - } - pub fn count_extra_fields(&self) -> usize { - self.field_count() - Self::FIELD_COUNT - } - pub fn has_extra_fields(&self) -> bool { - Self::FIELD_COUNT != self.field_count() - } - pub fn status(&self) -> Byte { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[4..]) as usize; - let end = molecule::unpack_number(&slice[8..]) as usize; - Byte::new_unchecked(self.0.slice(start..end)) - } - pub fn lot_size(&self) -> Byte { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[8..]) as usize; - let end = molecule::unpack_number(&slice[12..]) as usize; - Byte::new_unchecked(self.0.slice(start..end)) - } - pub fn user_lockscript(&self) -> Script { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[12..]) as usize; - let end = molecule::unpack_number(&slice[16..]) as usize; - Script::new_unchecked(self.0.slice(start..end)) - } - pub fn x_lock_address(&self) -> Bytes { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[16..]) as usize; - let end = molecule::unpack_number(&slice[20..]) as usize; - Bytes::new_unchecked(self.0.slice(start..end)) - } - pub fn signer_lockscript(&self) -> Script { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[20..]) as usize; - let end = molecule::unpack_number(&slice[24..]) as usize; - Script::new_unchecked(self.0.slice(start..end)) - } - pub fn x_unlock_address(&self) -> Bytes { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[24..]) as usize; - let end = molecule::unpack_number(&slice[28..]) as usize; - Bytes::new_unchecked(self.0.slice(start..end)) - } - pub fn redeemer_lockscript(&self) -> Script { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[28..]) as usize; - let end = molecule::unpack_number(&slice[32..]) as usize; - Script::new_unchecked(self.0.slice(start..end)) - } - pub fn liquidation_trigger_lockscript(&self) -> Script { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[32..]) as usize; - if self.has_extra_fields() { - let end = molecule::unpack_number(&slice[36..]) as usize; - Script::new_unchecked(self.0.slice(start..end)) - } else { - Script::new_unchecked(self.0.slice(start..)) - } - } - pub fn as_reader<'r>(&'r self) -> ToCKBCellDataReader<'r> { - ToCKBCellDataReader::new_unchecked(self.as_slice()) - } -} -impl molecule::prelude::Entity for ToCKBCellData { - type Builder = ToCKBCellDataBuilder; - const NAME: &'static str = "ToCKBCellData"; - fn new_unchecked(data: molecule::bytes::Bytes) -> Self { - ToCKBCellData(data) - } - fn as_bytes(&self) -> molecule::bytes::Bytes { - self.0.clone() - } - fn as_slice(&self) -> &[u8] { - &self.0[..] - } - fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { - ToCKBCellDataReader::from_slice(slice).map(|reader| reader.to_entity()) - } - fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { - ToCKBCellDataReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) - } - fn new_builder() -> Self::Builder { - ::core::default::Default::default() - } - fn as_builder(self) -> Self::Builder { - Self::new_builder() - .status(self.status()) - .lot_size(self.lot_size()) - .user_lockscript(self.user_lockscript()) - .x_lock_address(self.x_lock_address()) - .signer_lockscript(self.signer_lockscript()) - .x_unlock_address(self.x_unlock_address()) - .redeemer_lockscript(self.redeemer_lockscript()) - .liquidation_trigger_lockscript(self.liquidation_trigger_lockscript()) - } -} -#[derive(Clone, Copy)] -pub struct ToCKBCellDataReader<'r>(&'r [u8]); -impl<'r> ::core::fmt::LowerHex for ToCKBCellDataReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl<'r> ::core::fmt::Debug for ToCKBCellDataReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl<'r> ::core::fmt::Display for ToCKBCellDataReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{} {{ ", Self::NAME)?; - write!(f, "{}: {}", "status", self.status())?; - write!(f, ", {}: {}", "lot_size", self.lot_size())?; - write!(f, ", {}: {}", "user_lockscript", self.user_lockscript())?; - write!(f, ", {}: {}", "x_lock_address", self.x_lock_address())?; - write!(f, ", {}: {}", "signer_lockscript", self.signer_lockscript())?; - write!(f, ", {}: {}", "x_unlock_address", self.x_unlock_address())?; - write!( - f, - ", {}: {}", - "redeemer_lockscript", - self.redeemer_lockscript() - )?; - write!( - f, - ", {}: {}", - "liquidation_trigger_lockscript", - self.liquidation_trigger_lockscript() - )?; - let extra_count = self.count_extra_fields(); - if extra_count != 0 { - write!(f, ", .. ({} fields)", extra_count)?; - } - write!(f, " }}") - } -} -impl<'r> ToCKBCellDataReader<'r> { - pub const FIELD_COUNT: usize = 8; - pub fn total_size(&self) -> usize { - molecule::unpack_number(self.as_slice()) as usize - } - pub fn field_count(&self) -> usize { - if self.total_size() == molecule::NUMBER_SIZE { - 0 - } else { - (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 - } - } - pub fn count_extra_fields(&self) -> usize { - self.field_count() - Self::FIELD_COUNT - } - pub fn has_extra_fields(&self) -> bool { - Self::FIELD_COUNT != self.field_count() - } - pub fn status(&self) -> ByteReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[4..]) as usize; - let end = molecule::unpack_number(&slice[8..]) as usize; - ByteReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn lot_size(&self) -> ByteReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[8..]) as usize; - let end = molecule::unpack_number(&slice[12..]) as usize; - ByteReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn user_lockscript(&self) -> ScriptReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[12..]) as usize; - let end = molecule::unpack_number(&slice[16..]) as usize; - ScriptReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn x_lock_address(&self) -> BytesReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[16..]) as usize; - let end = molecule::unpack_number(&slice[20..]) as usize; - BytesReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn signer_lockscript(&self) -> ScriptReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[20..]) as usize; - let end = molecule::unpack_number(&slice[24..]) as usize; - ScriptReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn x_unlock_address(&self) -> BytesReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[24..]) as usize; - let end = molecule::unpack_number(&slice[28..]) as usize; - BytesReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn redeemer_lockscript(&self) -> ScriptReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[28..]) as usize; - let end = molecule::unpack_number(&slice[32..]) as usize; - ScriptReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn liquidation_trigger_lockscript(&self) -> ScriptReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[32..]) as usize; - if self.has_extra_fields() { - let end = molecule::unpack_number(&slice[36..]) as usize; - ScriptReader::new_unchecked(&self.as_slice()[start..end]) - } else { - ScriptReader::new_unchecked(&self.as_slice()[start..]) - } - } -} -impl<'r> molecule::prelude::Reader<'r> for ToCKBCellDataReader<'r> { - type Entity = ToCKBCellData; - const NAME: &'static str = "ToCKBCellDataReader"; - fn to_entity(&self) -> Self::Entity { - Self::Entity::new_unchecked(self.as_slice().to_owned().into()) - } - fn new_unchecked(slice: &'r [u8]) -> Self { - ToCKBCellDataReader(slice) - } - fn as_slice(&self) -> &'r [u8] { - self.0 - } - fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { - use molecule::verification_error as ve; - let slice_len = slice.len(); - if slice_len < molecule::NUMBER_SIZE { - return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); - } - let total_size = molecule::unpack_number(slice) as usize; - if slice_len != total_size { - return ve!(Self, TotalSizeNotMatch, total_size, slice_len); - } - if slice_len == molecule::NUMBER_SIZE && Self::FIELD_COUNT == 0 { - return Ok(()); - } - if slice_len < molecule::NUMBER_SIZE * 2 { - return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); - } - let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; - if offset_first % 4 != 0 || offset_first < molecule::NUMBER_SIZE * 2 { - return ve!(Self, OffsetsNotMatch); - } - let field_count = offset_first / 4 - 1; - if field_count < Self::FIELD_COUNT { - return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); - } else if !compatible && field_count > Self::FIELD_COUNT { - return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); - }; - let header_size = molecule::NUMBER_SIZE * (field_count + 1); - if slice_len < header_size { - return ve!(Self, HeaderIsBroken, header_size, slice_len); - } - let mut offsets: Vec = slice[molecule::NUMBER_SIZE..] - .chunks(molecule::NUMBER_SIZE) - .take(field_count) - .map(|x| molecule::unpack_number(x) as usize) - .collect(); - offsets.push(total_size); - if offsets.windows(2).any(|i| i[0] > i[1]) { - return ve!(Self, OffsetsNotMatch); - } - ByteReader::verify(&slice[offsets[0]..offsets[1]], compatible)?; - ByteReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; - ScriptReader::verify(&slice[offsets[2]..offsets[3]], compatible)?; - BytesReader::verify(&slice[offsets[3]..offsets[4]], compatible)?; - ScriptReader::verify(&slice[offsets[4]..offsets[5]], compatible)?; - BytesReader::verify(&slice[offsets[5]..offsets[6]], compatible)?; - ScriptReader::verify(&slice[offsets[6]..offsets[7]], compatible)?; - ScriptReader::verify(&slice[offsets[7]..offsets[8]], compatible)?; - Ok(()) - } -} -#[derive(Debug, Default)] -pub struct ToCKBCellDataBuilder { - pub(crate) status: Byte, - pub(crate) lot_size: Byte, - pub(crate) user_lockscript: Script, - pub(crate) x_lock_address: Bytes, - pub(crate) signer_lockscript: Script, - pub(crate) x_unlock_address: Bytes, - pub(crate) redeemer_lockscript: Script, - pub(crate) liquidation_trigger_lockscript: Script, -} -impl ToCKBCellDataBuilder { - pub const FIELD_COUNT: usize = 8; - pub fn status(mut self, v: Byte) -> Self { - self.status = v; - self - } - pub fn lot_size(mut self, v: Byte) -> Self { - self.lot_size = v; - self - } - pub fn user_lockscript(mut self, v: Script) -> Self { - self.user_lockscript = v; - self - } - pub fn x_lock_address(mut self, v: Bytes) -> Self { - self.x_lock_address = v; - self - } - pub fn signer_lockscript(mut self, v: Script) -> Self { - self.signer_lockscript = v; - self - } - pub fn x_unlock_address(mut self, v: Bytes) -> Self { - self.x_unlock_address = v; - self - } - pub fn redeemer_lockscript(mut self, v: Script) -> Self { - self.redeemer_lockscript = v; - self - } - pub fn liquidation_trigger_lockscript(mut self, v: Script) -> Self { - self.liquidation_trigger_lockscript = v; - self - } -} -impl molecule::prelude::Builder for ToCKBCellDataBuilder { - type Entity = ToCKBCellData; - const NAME: &'static str = "ToCKBCellDataBuilder"; - fn expected_length(&self) -> usize { - molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) - + self.status.as_slice().len() - + self.lot_size.as_slice().len() - + self.user_lockscript.as_slice().len() - + self.x_lock_address.as_slice().len() - + self.signer_lockscript.as_slice().len() - + self.x_unlock_address.as_slice().len() - + self.redeemer_lockscript.as_slice().len() - + self.liquidation_trigger_lockscript.as_slice().len() - } - fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { - let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); - let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); - offsets.push(total_size); - total_size += self.status.as_slice().len(); - offsets.push(total_size); - total_size += self.lot_size.as_slice().len(); - offsets.push(total_size); - total_size += self.user_lockscript.as_slice().len(); - offsets.push(total_size); - total_size += self.x_lock_address.as_slice().len(); - offsets.push(total_size); - total_size += self.signer_lockscript.as_slice().len(); - offsets.push(total_size); - total_size += self.x_unlock_address.as_slice().len(); - offsets.push(total_size); - total_size += self.redeemer_lockscript.as_slice().len(); - offsets.push(total_size); - total_size += self.liquidation_trigger_lockscript.as_slice().len(); - writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; - for offset in offsets.into_iter() { - writer.write_all(&molecule::pack_number(offset as molecule::Number))?; - } - writer.write_all(self.status.as_slice())?; - writer.write_all(self.lot_size.as_slice())?; - writer.write_all(self.user_lockscript.as_slice())?; - writer.write_all(self.x_lock_address.as_slice())?; - writer.write_all(self.signer_lockscript.as_slice())?; - writer.write_all(self.x_unlock_address.as_slice())?; - writer.write_all(self.redeemer_lockscript.as_slice())?; - writer.write_all(self.liquidation_trigger_lockscript.as_slice())?; - Ok(()) - } - fn build(&self) -> Self::Entity { - let mut inner = Vec::with_capacity(self.expected_length()); - self.write(&mut inner) - .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); - ToCKBCellData::new_unchecked(inner.into()) - } -} +use molecule :: prelude :: * ; +use super :: basic :: * ; +# [ derive ( Clone ) ] pub struct ToCKBCellData ( molecule :: bytes :: Bytes ) ; impl :: core :: fmt :: LowerHex for ToCKBCellData { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl :: core :: fmt :: Debug for ToCKBCellData { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl :: core :: fmt :: Display for ToCKBCellData { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{} {{ " , Self :: NAME ) ? ; write ! ( f , "{}: {}" , "status" , self . status ( ) ) ? ; write ! ( f , ", {}: {}" , "lot_size" , self . lot_size ( ) ) ? ; write ! ( f , ", {}: {}" , "user_lockscript" , self . user_lockscript ( ) ) ? ; write ! ( f , ", {}: {}" , "x_lock_address" , self . x_lock_address ( ) ) ? ; write ! ( f , ", {}: {}" , "signer_lockscript" , self . signer_lockscript ( ) ) ? ; write ! ( f , ", {}: {}" , "x_unlock_address" , self . x_unlock_address ( ) ) ? ; write ! ( f , ", {}: {}" , "redeemer_lockscript" , self . redeemer_lockscript ( ) ) ? ; write ! ( f , ", {}: {}" , "liquidation_trigger_lockscript" , self . liquidation_trigger_lockscript ( ) ) ? ; let extra_count = self . count_extra_fields ( ) ; if extra_count != 0 { write ! ( f , ", .. ({} fields)" , extra_count ) ? ; } write ! ( f , " }}" ) } } impl :: core :: default :: Default for ToCKBCellData { fn default ( ) -> Self { let v : Vec < u8 > = vec ! [ 2 , 1 , 0 , 0 , 36 , 0 , 0 , 0 , 37 , 0 , 0 , 0 , 38 , 0 , 0 , 0 , 91 , 0 , 0 , 0 , 95 , 0 , 0 , 0 , 148 , 0 , 0 , 0 , 152 , 0 , 0 , 0 , 205 , 0 , 0 , 0 , 0 , 0 , 53 , 0 , 0 , 0 , 16 , 0 , 0 , 0 , 48 , 0 , 0 , 0 , 49 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 53 , 0 , 0 , 0 , 16 , 0 , 0 , 0 , 48 , 0 , 0 , 0 , 49 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 53 , 0 , 0 , 0 , 16 , 0 , 0 , 0 , 48 , 0 , 0 , 0 , 49 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 53 , 0 , 0 , 0 , 16 , 0 , 0 , 0 , 48 , 0 , 0 , 0 , 49 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , ] ; ToCKBCellData :: new_unchecked ( v . into ( ) ) } } impl ToCKBCellData { pub const FIELD_COUNT : usize = 8 ; pub fn total_size ( & self ) -> usize { molecule :: unpack_number ( self . as_slice ( ) ) as usize } pub fn field_count ( & self ) -> usize { if self . total_size ( ) == molecule :: NUMBER_SIZE { 0 } else { ( molecule :: unpack_number ( & self . as_slice ( ) [ molecule :: NUMBER_SIZE .. ] ) as usize / 4 ) - 1 } } pub fn count_extra_fields ( & self ) -> usize { self . field_count ( ) - Self :: FIELD_COUNT } pub fn has_extra_fields ( & self ) -> bool { Self :: FIELD_COUNT != self . field_count ( ) } pub fn status ( & self ) -> Byte { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 4 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; Byte :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn lot_size ( & self ) -> Byte { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; Byte :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn user_lockscript ( & self ) -> Script { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 16 .. ] ) as usize ; Script :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn x_lock_address ( & self ) -> Bytes { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 16 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 20 .. ] ) as usize ; Bytes :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn signer_lockscript ( & self ) -> Script { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 20 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 24 .. ] ) as usize ; Script :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn x_unlock_address ( & self ) -> Bytes { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 24 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 28 .. ] ) as usize ; Bytes :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn redeemer_lockscript ( & self ) -> Script { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 28 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 32 .. ] ) as usize ; Script :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn liquidation_trigger_lockscript ( & self ) -> Script { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 32 .. ] ) as usize ; if self . has_extra_fields ( ) { let end = molecule :: unpack_number ( & slice [ 36 .. ] ) as usize ; Script :: new_unchecked ( self . 0 . slice ( start .. end ) ) } else { Script :: new_unchecked ( self . 0 . slice ( start .. ) ) } } pub fn as_reader < 'r > ( & 'r self ) -> ToCKBCellDataReader < 'r > { ToCKBCellDataReader :: new_unchecked ( self . as_slice ( ) ) } } impl molecule :: prelude :: Entity for ToCKBCellData { type Builder = ToCKBCellDataBuilder ; const NAME : & 'static str = "ToCKBCellData" ; fn new_unchecked ( data : molecule :: bytes :: Bytes ) -> Self { ToCKBCellData ( data ) } fn as_bytes ( & self ) -> molecule :: bytes :: Bytes { self . 0 . clone ( ) } fn as_slice ( & self ) -> & [ u8 ] { & self . 0 [ .. ] } fn from_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { ToCKBCellDataReader :: from_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn from_compatible_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { ToCKBCellDataReader :: from_compatible_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn new_builder ( ) -> Self :: Builder { :: core :: default :: Default :: default ( ) } fn as_builder ( self ) -> Self :: Builder { Self :: new_builder ( ) . status ( self . status ( ) ) . lot_size ( self . lot_size ( ) ) . user_lockscript ( self . user_lockscript ( ) ) . x_lock_address ( self . x_lock_address ( ) ) . signer_lockscript ( self . signer_lockscript ( ) ) . x_unlock_address ( self . x_unlock_address ( ) ) . redeemer_lockscript ( self . redeemer_lockscript ( ) ) . liquidation_trigger_lockscript ( self . liquidation_trigger_lockscript ( ) ) } } +# [ derive ( Clone , Copy ) ] pub struct ToCKBCellDataReader < 'r > ( & 'r [ u8 ] ) ; impl < 'r > :: core :: fmt :: LowerHex for ToCKBCellDataReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl < 'r > :: core :: fmt :: Debug for ToCKBCellDataReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl < 'r > :: core :: fmt :: Display for ToCKBCellDataReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{} {{ " , Self :: NAME ) ? ; write ! ( f , "{}: {}" , "status" , self . status ( ) ) ? ; write ! ( f , ", {}: {}" , "lot_size" , self . lot_size ( ) ) ? ; write ! ( f , ", {}: {}" , "user_lockscript" , self . user_lockscript ( ) ) ? ; write ! ( f , ", {}: {}" , "x_lock_address" , self . x_lock_address ( ) ) ? ; write ! ( f , ", {}: {}" , "signer_lockscript" , self . signer_lockscript ( ) ) ? ; write ! ( f , ", {}: {}" , "x_unlock_address" , self . x_unlock_address ( ) ) ? ; write ! ( f , ", {}: {}" , "redeemer_lockscript" , self . redeemer_lockscript ( ) ) ? ; write ! ( f , ", {}: {}" , "liquidation_trigger_lockscript" , self . liquidation_trigger_lockscript ( ) ) ? ; let extra_count = self . count_extra_fields ( ) ; if extra_count != 0 { write ! ( f , ", .. ({} fields)" , extra_count ) ? ; } write ! ( f , " }}" ) } } impl < 'r > ToCKBCellDataReader < 'r > { pub const FIELD_COUNT : usize = 8 ; pub fn total_size ( & self ) -> usize { molecule :: unpack_number ( self . as_slice ( ) ) as usize } pub fn field_count ( & self ) -> usize { if self . total_size ( ) == molecule :: NUMBER_SIZE { 0 } else { ( molecule :: unpack_number ( & self . as_slice ( ) [ molecule :: NUMBER_SIZE .. ] ) as usize / 4 ) - 1 } } pub fn count_extra_fields ( & self ) -> usize { self . field_count ( ) - Self :: FIELD_COUNT } pub fn has_extra_fields ( & self ) -> bool { Self :: FIELD_COUNT != self . field_count ( ) } pub fn status ( & self ) -> ByteReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 4 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; ByteReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn lot_size ( & self ) -> ByteReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; ByteReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn user_lockscript ( & self ) -> ScriptReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 16 .. ] ) as usize ; ScriptReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn x_lock_address ( & self ) -> BytesReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 16 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 20 .. ] ) as usize ; BytesReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn signer_lockscript ( & self ) -> ScriptReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 20 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 24 .. ] ) as usize ; ScriptReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn x_unlock_address ( & self ) -> BytesReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 24 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 28 .. ] ) as usize ; BytesReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn redeemer_lockscript ( & self ) -> ScriptReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 28 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 32 .. ] ) as usize ; ScriptReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn liquidation_trigger_lockscript ( & self ) -> ScriptReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 32 .. ] ) as usize ; if self . has_extra_fields ( ) { let end = molecule :: unpack_number ( & slice [ 36 .. ] ) as usize ; ScriptReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } else { ScriptReader :: new_unchecked ( & self . as_slice ( ) [ start .. ] ) } } } impl < 'r > molecule :: prelude :: Reader < 'r > for ToCKBCellDataReader < 'r > { type Entity = ToCKBCellData ; const NAME : & 'static str = "ToCKBCellDataReader" ; fn to_entity ( & self ) -> Self :: Entity { Self :: Entity :: new_unchecked ( self . as_slice ( ) . to_owned ( ) . into ( ) ) } fn new_unchecked ( slice : & 'r [ u8 ] ) -> Self { ToCKBCellDataReader ( slice ) } fn as_slice ( & self ) -> & 'r [ u8 ] { self . 0 } fn verify ( slice : & [ u8 ] , compatible : bool ) -> molecule :: error :: VerificationResult < ( ) > { use molecule :: verification_error as ve ; let slice_len = slice . len ( ) ; if slice_len < molecule :: NUMBER_SIZE { return ve ! ( Self , HeaderIsBroken , molecule :: NUMBER_SIZE , slice_len ) ; } let total_size = molecule :: unpack_number ( slice ) as usize ; if slice_len != total_size { return ve ! ( Self , TotalSizeNotMatch , total_size , slice_len ) ; } if slice_len == molecule :: NUMBER_SIZE && Self :: FIELD_COUNT == 0 { return Ok ( ( ) ) ; } if slice_len < molecule :: NUMBER_SIZE * 2 { return ve ! ( Self , HeaderIsBroken , molecule :: NUMBER_SIZE * 2 , slice_len ) ; } let offset_first = molecule :: unpack_number ( & slice [ molecule :: NUMBER_SIZE .. ] ) as usize ; if offset_first % 4 != 0 || offset_first < molecule :: NUMBER_SIZE * 2 { return ve ! ( Self , OffsetsNotMatch ) ; } let field_count = offset_first / 4 - 1 ; if field_count < Self :: FIELD_COUNT { return ve ! ( Self , FieldCountNotMatch , Self :: FIELD_COUNT , field_count ) ; } else if ! compatible && field_count > Self :: FIELD_COUNT { return ve ! ( Self , FieldCountNotMatch , Self :: FIELD_COUNT , field_count ) ; } ; let header_size = molecule :: NUMBER_SIZE * ( field_count + 1 ) ; if slice_len < header_size { return ve ! ( Self , HeaderIsBroken , header_size , slice_len ) ; } let mut offsets : Vec < usize > = slice [ molecule :: NUMBER_SIZE .. ] . chunks ( molecule :: NUMBER_SIZE ) . take ( field_count ) . map ( | x | molecule :: unpack_number ( x ) as usize ) . collect ( ) ; offsets . push ( total_size ) ; if offsets . windows ( 2 ) . any ( | i | i [ 0 ] > i [ 1 ] ) { return ve ! ( Self , OffsetsNotMatch ) ; } ByteReader :: verify ( & slice [ offsets [ 0 ] .. offsets [ 1 ] ] , compatible ) ? ; ByteReader :: verify ( & slice [ offsets [ 1 ] .. offsets [ 2 ] ] , compatible ) ? ; ScriptReader :: verify ( & slice [ offsets [ 2 ] .. offsets [ 3 ] ] , compatible ) ? ; BytesReader :: verify ( & slice [ offsets [ 3 ] .. offsets [ 4 ] ] , compatible ) ? ; ScriptReader :: verify ( & slice [ offsets [ 4 ] .. offsets [ 5 ] ] , compatible ) ? ; BytesReader :: verify ( & slice [ offsets [ 5 ] .. offsets [ 6 ] ] , compatible ) ? ; ScriptReader :: verify ( & slice [ offsets [ 6 ] .. offsets [ 7 ] ] , compatible ) ? ; ScriptReader :: verify ( & slice [ offsets [ 7 ] .. offsets [ 8 ] ] , compatible ) ? ; Ok ( ( ) ) } } +# [ derive ( Debug , Default ) ] pub struct ToCKBCellDataBuilder { pub ( crate ) status : Byte , pub ( crate ) lot_size : Byte , pub ( crate ) user_lockscript : Script , pub ( crate ) x_lock_address : Bytes , pub ( crate ) signer_lockscript : Script , pub ( crate ) x_unlock_address : Bytes , pub ( crate ) redeemer_lockscript : Script , pub ( crate ) liquidation_trigger_lockscript : Script , } impl ToCKBCellDataBuilder { pub const FIELD_COUNT : usize = 8 ; pub fn status ( mut self , v : Byte ) -> Self { self . status = v ; self } pub fn lot_size ( mut self , v : Byte ) -> Self { self . lot_size = v ; self } pub fn user_lockscript ( mut self , v : Script ) -> Self { self . user_lockscript = v ; self } pub fn x_lock_address ( mut self , v : Bytes ) -> Self { self . x_lock_address = v ; self } pub fn signer_lockscript ( mut self , v : Script ) -> Self { self . signer_lockscript = v ; self } pub fn x_unlock_address ( mut self , v : Bytes ) -> Self { self . x_unlock_address = v ; self } pub fn redeemer_lockscript ( mut self , v : Script ) -> Self { self . redeemer_lockscript = v ; self } pub fn liquidation_trigger_lockscript ( mut self , v : Script ) -> Self { self . liquidation_trigger_lockscript = v ; self } } impl molecule :: prelude :: Builder for ToCKBCellDataBuilder { type Entity = ToCKBCellData ; const NAME : & 'static str = "ToCKBCellDataBuilder" ; fn expected_length ( & self ) -> usize { molecule :: NUMBER_SIZE * ( Self :: FIELD_COUNT + 1 ) + self . status . as_slice ( ) . len ( ) + self . lot_size . as_slice ( ) . len ( ) + self . user_lockscript . as_slice ( ) . len ( ) + self . x_lock_address . as_slice ( ) . len ( ) + self . signer_lockscript . as_slice ( ) . len ( ) + self . x_unlock_address . as_slice ( ) . len ( ) + self . redeemer_lockscript . as_slice ( ) . len ( ) + self . liquidation_trigger_lockscript . as_slice ( ) . len ( ) } fn write < W : :: molecule :: io :: Write > ( & self , writer : & mut W ) -> :: molecule :: io :: Result < ( ) > { let mut total_size = molecule :: NUMBER_SIZE * ( Self :: FIELD_COUNT + 1 ) ; let mut offsets = Vec :: with_capacity ( Self :: FIELD_COUNT ) ; offsets . push ( total_size ) ; total_size += self . status . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . lot_size . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . user_lockscript . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . x_lock_address . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . signer_lockscript . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . x_unlock_address . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . redeemer_lockscript . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . liquidation_trigger_lockscript . as_slice ( ) . len ( ) ; writer . write_all ( & molecule :: pack_number ( total_size as molecule :: Number ) ) ? ; for offset in offsets . into_iter ( ) { writer . write_all ( & molecule :: pack_number ( offset as molecule :: Number ) ) ? ; } writer . write_all ( self . status . as_slice ( ) ) ? ; writer . write_all ( self . lot_size . as_slice ( ) ) ? ; writer . write_all ( self . user_lockscript . as_slice ( ) ) ? ; writer . write_all ( self . x_lock_address . as_slice ( ) ) ? ; writer . write_all ( self . signer_lockscript . as_slice ( ) ) ? ; writer . write_all ( self . x_unlock_address . as_slice ( ) ) ? ; writer . write_all ( self . redeemer_lockscript . as_slice ( ) ) ? ; writer . write_all ( self . liquidation_trigger_lockscript . as_slice ( ) ) ? ; Ok ( ( ) ) } fn build ( & self ) -> Self :: Entity { let mut inner = Vec :: with_capacity ( self . expected_length ( ) ) ; self . write ( & mut inner ) . unwrap_or_else ( | _ | panic ! ( "{} build should be ok" , Self :: NAME ) ) ; ToCKBCellData :: new_unchecked ( inner . into ( ) ) } } From 36edad18a97b170b1d86271c979855c534c48bfa Mon Sep 17 00:00:00 2001 From: LeonLi000 Date: Mon, 7 Sep 2020 22:23:44 +0800 Subject: [PATCH 35/45] feat(MintXT): add eth-spv testcase for mintXT --- Cargo.lock | 8 +- contracts/toCKB-typescript/Cargo.lock | 5 +- contracts/toCKB-typescript/Cargo.toml | 2 +- .../src/switch/mint_xt/mod.rs | 20 +- tests/Cargo.toml | 4 +- .../toCKB_typescript/tests/mint_xt/helper.rs | 24 +- .../src/toCKB_typescript/tests/mint_xt/mod.rs | 67 + .../toCKB_typescript/tests/mint_xt/types.rs | 32 + .../utils/types/generated/mint_xt_witness.rs | 1146 ++++++++++++++++- 9 files changed, 1268 insertions(+), 40 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3defc02..73d463e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -599,8 +599,8 @@ dependencies = [ [[package]] name = "ckb-testtool" -version = "0.1.1" -source = "git+https://github.com/jjyr/ckb-tool.git?tag=v0.1.1#1f9b008ec3ca241c953b320b4c1d5642c35ae1be" +version = "0.1.2" +source = "git+https://github.com/jjyr/ckb-tool.git?tag=v0.1.2#b9b629c298bfaa680838c5a2e38d31639b98a081" dependencies = [ "ckb-always-success-script", "ckb-tool", @@ -610,8 +610,8 @@ dependencies = [ [[package]] name = "ckb-tool" -version = "0.1.1" -source = "git+https://github.com/jjyr/ckb-tool.git?tag=v0.1.1#1f9b008ec3ca241c953b320b4c1d5642c35ae1be" +version = "0.1.2" +source = "git+https://github.com/jjyr/ckb-tool.git?tag=v0.1.2#b9b629c298bfaa680838c5a2e38d31639b98a081" dependencies = [ "ckb-chain-spec", "ckb-crypto", diff --git a/contracts/toCKB-typescript/Cargo.lock b/contracts/toCKB-typescript/Cargo.lock index 4e82f7e..f8142d5 100644 --- a/contracts/toCKB-typescript/Cargo.lock +++ b/contracts/toCKB-typescript/Cargo.lock @@ -103,9 +103,8 @@ dependencies = [ [[package]] name = "ckb-std" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4919733c5e3591ccdf892f0e29c5f5a220de5aef7f90e1a2a21bf03f707662f6" +version = "0.6.1" +source = "git+https://github.com/LeonLi000/ckb-std.git#830a1260c800385f9bd8191ef7e71e6ff7cfd49b" dependencies = [ "cc", "ckb-allocator", diff --git a/contracts/toCKB-typescript/Cargo.toml b/contracts/toCKB-typescript/Cargo.toml index 0ba0b9a..1759adc 100644 --- a/contracts/toCKB-typescript/Cargo.toml +++ b/contracts/toCKB-typescript/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -ckb-std = "0.6" +ckb-std = { git = "https://github.com/LeonLi000/ckb-std.git" } molecule = { version = "0.6.0", default-features = false } int-enum = { version = "0.4", default-features = false } bitcoin-spv = { git = "https://github.com/summa-tx/bitcoin-spv.git", branch = "rust/dep-change", default-features = false } diff --git a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs index c397115..c5ba4a3 100644 --- a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs +++ b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs @@ -91,6 +91,8 @@ fn verify_eth_witness( debug!("log_index is {:?}", &log_index); let log_entry_data = proof_reader.log_entry_data().raw_data().to_vec(); debug!("log_entry_data is {:?}", &log_entry_data); + let receipt_data = proof_reader.receipt_data().raw_data().to_vec(); + debug!("receipt_data is {:?}", &receipt_data); let mut receipt_index = [0u8; 8]; receipt_index.copy_from_slice(proof_reader.receipt_index().raw_data()); debug!("receipt_index is {:?}", &receipt_index); @@ -104,25 +106,25 @@ fn verify_eth_witness( debug!("proof is {:?}", &proof); //FIXME: check x_lock_address let log_entry: LogEntry = rlp::decode(log_entry_data.as_slice()).unwrap(); + debug!("log_entry is {:?}", &log_entry); + let receipt: Receipt = rlp::decode(receipt_data.as_slice()).unwrap(); + debug!("receipt_data is {:?}", &receipt); let locker_address = (log_entry.address.clone().0).0; debug!( - "hex format: addr: {}, x_lock_address: {}", + "addr: {:?}, x_lock_address: {}", hex::encode(locker_address.to_vec()), - hex::encode(data.x_lock_address.as_ref().to_vec()) - ); - debug!( - "addr: {}, x_lock_address: {}", - String::from_utf8(locker_address.to_vec()).unwrap(), String::from_utf8(data.x_lock_address.as_ref().to_vec()).unwrap() ); - if locker_address != data.x_lock_address.as_ref() { + if hex::encode(locker_address.to_vec()) + != String::from_utf8(data.x_lock_address.as_ref().to_vec()).unwrap() + { return Err(Error::WrongFundingAddr); } if !ethspv::verify_log_entry( u64::from_le_bytes(log_index), log_entry_data, u64::from_le_bytes(receipt_index), - proof_reader.receipt_data().raw_data().to_vec(), + receipt_data, H256(receipts_root.into()), proof, ) { @@ -270,7 +272,7 @@ fn verify_btc_spv(proof: BTCSPVProofReader, difficulty: BTCDifficultyReader) -> fn verify_xt_issue(data: &ToCKBCellDataView) -> Result<(), Error> { match get_xchain_kind()? { XChainKind::Btc => verify_btc_xt_issue(data), - XChainKind::Eth => todo!(), + XChainKind::Eth => verify_btc_xt_issue(data), } } diff --git a/tests/Cargo.toml b/tests/Cargo.toml index 0b2a03b..140639f 100644 --- a/tests/Cargo.toml +++ b/tests/Cargo.toml @@ -6,8 +6,8 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -ckb-tool = { git = "https://github.com/jjyr/ckb-tool.git", tag = "v0.1.1" } -ckb-testtool = { git = "https://github.com/jjyr/ckb-tool.git", tag = "v0.1.1" } +ckb-tool = { git = "https://github.com/jjyr/ckb-tool.git", tag = "v0.1.2" } +ckb-testtool = { git = "https://github.com/jjyr/ckb-tool.git", tag = "v0.1.2" } molecule = { version = "=0.6.0", default-features = false } int-enum = { version = "0.4", default-features = false } anyhow = "1.0" diff --git a/tests/src/toCKB_typescript/tests/mint_xt/helper.rs b/tests/src/toCKB_typescript/tests/mint_xt/helper.rs index 0790eb5..1fd2443 100644 --- a/tests/src/toCKB_typescript/tests/mint_xt/helper.rs +++ b/tests/src/toCKB_typescript/tests/mint_xt/helper.rs @@ -48,16 +48,19 @@ pub fn run_test_case(case: TestCase) { // prepare cells let x_lock_address_str = case.tockb_cell_data.x_lock_address; - let x_lock_address = basic::Bytes::new_builder() - .set( - x_lock_address_str - .as_bytes() - .iter() - .map(|c| Byte::new(*c)) - .collect::>() - .into(), - ) - .build(); + let x_lock_address: basic::Bytes = x_lock_address_str.as_bytes().to_vec().into(); + // let x_lock_address = basic::Bytes::new_builder() + // .set( + // x_lock_address_str + // .as_bytes() + // .iter() + // .map(|c| Byte::new(*c)) + // .collect::>() + // .into(), + // ) + // .build(); + dbg!(&x_lock_address_str); + dbg!(&x_lock_address); let signer_lockscript = basic::Script::from_slice(case.tockb_cell_data.signer_lockscript.as_slice()).unwrap(); let user_lockscript = @@ -106,6 +109,7 @@ pub fn run_test_case(case: TestCase) { } let spv_proof = match case.witness.spv_proof { SpvProof::BTC(btc_spv_proof) => btc_spv_proof.as_slice().to_vec(), + SpvProof::ETH(btc_spv_proof) => btc_spv_proof.as_slice().to_vec(), }; let witness_data = mint_xt_witness::MintXTWitness::new_builder() .spv_proof(spv_proof.into()) diff --git a/tests/src/toCKB_typescript/tests/mint_xt/mod.rs b/tests/src/toCKB_typescript/tests/mint_xt/mod.rs index d5c6c1f..20d78a9 100644 --- a/tests/src/toCKB_typescript/tests/mint_xt/mod.rs +++ b/tests/src/toCKB_typescript/tests/mint_xt/mod.rs @@ -67,6 +67,73 @@ fn generate_btc_corrent_case() -> TestCase { case } +fn generate_eth_corrent_case() -> TestCase { + let kind = 2; + let DeployResult { + context: _, + toCKB_typescript: _, + always_success_lockscript, + sudt_typescript, + } = deploy(kind); + let user_lockscript = always_success_lockscript.clone(); + let signer_lockscript = always_success_lockscript.clone(); + let case = TestCase { + kind, + input_capacity: 100000, + output_capacity: 100000 - XT_CELL_CAPACITY, + tockb_cell_data: ToCKBCellDataTest { + lot_size: 1, + x_lock_address: "c4c7497fbe1a886841a195a5d622cd60053c1376".to_owned(), + user_lockscript: user_lockscript.clone(), + signer_lockscript: signer_lockscript.clone(), + }, + outputs: vec![ + Output { + typescript: sudt_typescript.clone(), + lockscript: always_success_lockscript.clone(), + amount: 24950000, + capacity: PLEDGE, + }, + Output { + typescript: sudt_typescript.clone(), + lockscript: always_success_lockscript.clone(), + amount: 50000, + capacity: XT_CELL_CAPACITY, + }, + ], + witness: Witness { + cell_dep_index_list: vec![0], + spv_proof: SpvProof::ETH( + ETHSPVProofJson { + log_index: 2, + log_entry_data: "f9011c94c4c7497fbe1a886841a195a5d622cd60053c1376f863a0dd85dc56b5b4da387bf69c28ec19b1d66e793e0d51b567882fa31dc50bbd32c5a00000000000000000000000007cc4b1851c35959d34e635a470f6b5c43ba3c9c9a0000000000000000000000000df08f82de32b8d460adbe8d72043e3a7e25a3b39b8a000000000000000000000000000000000000000000000000000000000000003e8000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000217261696e626f775f6272696467655f6574685f6f6e5f6e6561725f70726f76657200000000000000000000000000000000000000000000000000000000000000".to_owned(), + receipt_index: 0, + receipt_data: "f903630182cf73b9010000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000080000000000000200000000000000200000000000000000000000100008040400000000000000000000000000000000000000000000000000000000000000000000000000400000000000200010000000000100000000000000000000000000000000000080000000000000000000200000020000000000000080000000000000000000000000000010000000004000000000000002000000000000000000000000000004000000080000000004000000000010000000000000000000000000000000000000100000000000000000000000f90259f89b947cc4b1851c35959d34e635a470f6b5c43ba3c9c9f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000df08f82de32b8d460adbe8d72043e3a7e25a3b39a0000000000000000000000000c4c7497fbe1a886841a195a5d622cd60053c1376a000000000000000000000000000000000000000000000000000000000000003e8f89b947cc4b1851c35959d34e635a470f6b5c43ba3c9c9f863a08c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925a0000000000000000000000000df08f82de32b8d460adbe8d72043e3a7e25a3b39a0000000000000000000000000c4c7497fbe1a886841a195a5d622cd60053c1376a00000000000000000000000000000000000000000000000000000000000000000f9011c94c4c7497fbe1a886841a195a5d622cd60053c1376f863a0dd85dc56b5b4da387bf69c28ec19b1d66e793e0d51b567882fa31dc50bbd32c5a00000000000000000000000007cc4b1851c35959d34e635a470f6b5c43ba3c9c9a0000000000000000000000000df08f82de32b8d460adbe8d72043e3a7e25a3b39b8a000000000000000000000000000000000000000000000000000000000000003e8000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000217261696e626f775f6272696467655f6574685f6f6e5f6e6561725f70726f76657200000000000000000000000000000000000000000000000000000000000000".to_owned(), + receipts_root: + "0x335f738baae5dc1f99d785641ed7f18ab96e3c09d3eac414cef1421425928b87" + .to_owned(), + header_data: "0x02000000".to_owned(), + proof: vec!["f9036c822080b90366f903630182cf73b9010000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000080000000000000200000000000000200000000000000000000000100008040400000000000000000000000000000000000000000000000000000000000000000000000000400000000000200010000000000100000000000000000000000000000000000080000000000000000000200000020000000000000080000000000000000000000000000010000000004000000000000002000000000000000000000000000004000000080000000004000000000010000000000000000000000000000000000000100000000000000000000000f90259f89b947cc4b1851c35959d34e635a470f6b5c43ba3c9c9f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000df08f82de32b8d460adbe8d72043e3a7e25a3b39a0000000000000000000000000c4c7497fbe1a886841a195a5d622cd60053c1376a000000000000000000000000000000000000000000000000000000000000003e8f89b947cc4b1851c35959d34e635a470f6b5c43ba3c9c9f863a08c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925a0000000000000000000000000df08f82de32b8d460adbe8d72043e3a7e25a3b39a0000000000000000000000000c4c7497fbe1a886841a195a5d622cd60053c1376a00000000000000000000000000000000000000000000000000000000000000000f9011c94c4c7497fbe1a886841a195a5d622cd60053c1376f863a0dd85dc56b5b4da387bf69c28ec19b1d66e793e0d51b567882fa31dc50bbd32c5a00000000000000000000000007cc4b1851c35959d34e635a470f6b5c43ba3c9c9a0000000000000000000000000df08f82de32b8d460adbe8d72043e3a7e25a3b39b8a000000000000000000000000000000000000000000000000000000000000003e8000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000217261696e626f775f6272696467655f6574685f6f6e5f6e6561725f70726f76657200000000000000000000000000000000000000000000000000000000000000".to_owned()], + } + .try_into() + .unwrap(), + ), + }, + cell_deps_data: CellDepsData::BTC(BtcDifficultyTest { + previous: 17557993035167u64, + current: 17557993035167u64, + }), + expect_return_code: 0, + }; + case +} + +#[test] +fn test_eth_correct_case() { + let case = generate_eth_corrent_case(); + run_test_case(case); +} + #[test] fn test_btc_correct_case() { let case = generate_btc_corrent_case(); diff --git a/tests/src/toCKB_typescript/tests/mint_xt/types.rs b/tests/src/toCKB_typescript/tests/mint_xt/types.rs index 0678ec6..2a74313 100644 --- a/tests/src/toCKB_typescript/tests/mint_xt/types.rs +++ b/tests/src/toCKB_typescript/tests/mint_xt/types.rs @@ -1,4 +1,5 @@ use crate::toCKB_typescript::utils::types::generated::mint_xt_witness; +use crate::toCKB_typescript::utils::types::generated::{Bytes, Bytes2}; use anyhow::Result; use ckb_tool::ckb_types::{packed::*, prelude::*}; use molecule::prelude::*; @@ -21,6 +22,7 @@ pub struct Output { pub enum SpvProof { BTC(mint_xt_witness::BTCSPVProof), + ETH(mint_xt_witness::ETHSPVProof), } pub struct BtcDifficultyTest { @@ -61,6 +63,36 @@ pub struct BTCSPVProofJson { pub funding_output_index: u8, } +#[derive(Serialize, Deserialize, Default)] +pub struct ETHSPVProofJson { + pub log_index: u64, + pub log_entry_data: String, + pub receipt_index: u64, + pub receipt_data: String, + pub receipts_root: String, + pub header_data: String, + pub proof: Vec, +} + +impl TryFrom for mint_xt_witness::ETHSPVProof { + type Error = anyhow::Error; + fn try_from(proof: ETHSPVProofJson) -> Result { + let mut proofVec: Vec = vec![]; + for i in 0..proof.proof.len() { + proofVec.push(hex::decode(clear_0x(&proof.proof[i]))?.into()) + } + Ok(mint_xt_witness::ETHSPVProof::new_builder() + .log_index(proof.log_index.into()) + .log_entry_data(hex::decode(clear_0x(&proof.log_entry_data))?.into()) + .receipt_index(proof.receipt_index.into()) + .receipt_data(hex::decode(clear_0x(&proof.receipt_data))?.into()) + .receipts_root(hex::decode(clear_0x(&proof.receipts_root))?.into()) + .header_data(hex::decode(clear_0x(&proof.header_data))?.into()) + .proof(Bytes2::new_builder().set(proofVec).build()) + .build()) + } +} + impl TryFrom for mint_xt_witness::BTCSPVProof { type Error = anyhow::Error; diff --git a/tests/src/toCKB_typescript/utils/types/generated/mint_xt_witness.rs b/tests/src/toCKB_typescript/utils/types/generated/mint_xt_witness.rs index fbb0ce9..d57ff10 100644 --- a/tests/src/toCKB_typescript/utils/types/generated/mint_xt_witness.rs +++ b/tests/src/toCKB_typescript/utils/types/generated/mint_xt_witness.rs @@ -1,13 +1,1137 @@ // Generated by Molecule 0.6.1 -use molecule :: prelude :: * ; -use super :: basic :: * ; -# [ derive ( Clone ) ] pub struct MintXTWitness ( molecule :: bytes :: Bytes ) ; impl :: core :: fmt :: LowerHex for MintXTWitness { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl :: core :: fmt :: Debug for MintXTWitness { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl :: core :: fmt :: Display for MintXTWitness { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{} {{ " , Self :: NAME ) ? ; write ! ( f , "{}: {}" , "spv_proof" , self . spv_proof ( ) ) ? ; write ! ( f , ", {}: {}" , "cell_dep_index_list" , self . cell_dep_index_list ( ) ) ? ; let extra_count = self . count_extra_fields ( ) ; if extra_count != 0 { write ! ( f , ", .. ({} fields)" , extra_count ) ? ; } write ! ( f , " }}" ) } } impl :: core :: default :: Default for MintXTWitness { fn default ( ) -> Self { let v : Vec < u8 > = vec ! [ 20 , 0 , 0 , 0 , 12 , 0 , 0 , 0 , 16 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , ] ; MintXTWitness :: new_unchecked ( v . into ( ) ) } } impl MintXTWitness { pub const FIELD_COUNT : usize = 2 ; pub fn total_size ( & self ) -> usize { molecule :: unpack_number ( self . as_slice ( ) ) as usize } pub fn field_count ( & self ) -> usize { if self . total_size ( ) == molecule :: NUMBER_SIZE { 0 } else { ( molecule :: unpack_number ( & self . as_slice ( ) [ molecule :: NUMBER_SIZE .. ] ) as usize / 4 ) - 1 } } pub fn count_extra_fields ( & self ) -> usize { self . field_count ( ) - Self :: FIELD_COUNT } pub fn has_extra_fields ( & self ) -> bool { Self :: FIELD_COUNT != self . field_count ( ) } pub fn spv_proof ( & self ) -> Bytes { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 4 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; Bytes :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn cell_dep_index_list ( & self ) -> Bytes { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; if self . has_extra_fields ( ) { let end = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; Bytes :: new_unchecked ( self . 0 . slice ( start .. end ) ) } else { Bytes :: new_unchecked ( self . 0 . slice ( start .. ) ) } } pub fn as_reader < 'r > ( & 'r self ) -> MintXTWitnessReader < 'r > { MintXTWitnessReader :: new_unchecked ( self . as_slice ( ) ) } } impl molecule :: prelude :: Entity for MintXTWitness { type Builder = MintXTWitnessBuilder ; const NAME : & 'static str = "MintXTWitness" ; fn new_unchecked ( data : molecule :: bytes :: Bytes ) -> Self { MintXTWitness ( data ) } fn as_bytes ( & self ) -> molecule :: bytes :: Bytes { self . 0 . clone ( ) } fn as_slice ( & self ) -> & [ u8 ] { & self . 0 [ .. ] } fn from_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { MintXTWitnessReader :: from_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn from_compatible_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { MintXTWitnessReader :: from_compatible_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn new_builder ( ) -> Self :: Builder { :: core :: default :: Default :: default ( ) } fn as_builder ( self ) -> Self :: Builder { Self :: new_builder ( ) . spv_proof ( self . spv_proof ( ) ) . cell_dep_index_list ( self . cell_dep_index_list ( ) ) } } -# [ derive ( Clone , Copy ) ] pub struct MintXTWitnessReader < 'r > ( & 'r [ u8 ] ) ; impl < 'r > :: core :: fmt :: LowerHex for MintXTWitnessReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl < 'r > :: core :: fmt :: Debug for MintXTWitnessReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl < 'r > :: core :: fmt :: Display for MintXTWitnessReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{} {{ " , Self :: NAME ) ? ; write ! ( f , "{}: {}" , "spv_proof" , self . spv_proof ( ) ) ? ; write ! ( f , ", {}: {}" , "cell_dep_index_list" , self . cell_dep_index_list ( ) ) ? ; let extra_count = self . count_extra_fields ( ) ; if extra_count != 0 { write ! ( f , ", .. ({} fields)" , extra_count ) ? ; } write ! ( f , " }}" ) } } impl < 'r > MintXTWitnessReader < 'r > { pub const FIELD_COUNT : usize = 2 ; pub fn total_size ( & self ) -> usize { molecule :: unpack_number ( self . as_slice ( ) ) as usize } pub fn field_count ( & self ) -> usize { if self . total_size ( ) == molecule :: NUMBER_SIZE { 0 } else { ( molecule :: unpack_number ( & self . as_slice ( ) [ molecule :: NUMBER_SIZE .. ] ) as usize / 4 ) - 1 } } pub fn count_extra_fields ( & self ) -> usize { self . field_count ( ) - Self :: FIELD_COUNT } pub fn has_extra_fields ( & self ) -> bool { Self :: FIELD_COUNT != self . field_count ( ) } pub fn spv_proof ( & self ) -> BytesReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 4 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; BytesReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn cell_dep_index_list ( & self ) -> BytesReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; if self . has_extra_fields ( ) { let end = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; BytesReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } else { BytesReader :: new_unchecked ( & self . as_slice ( ) [ start .. ] ) } } } impl < 'r > molecule :: prelude :: Reader < 'r > for MintXTWitnessReader < 'r > { type Entity = MintXTWitness ; const NAME : & 'static str = "MintXTWitnessReader" ; fn to_entity ( & self ) -> Self :: Entity { Self :: Entity :: new_unchecked ( self . as_slice ( ) . to_owned ( ) . into ( ) ) } fn new_unchecked ( slice : & 'r [ u8 ] ) -> Self { MintXTWitnessReader ( slice ) } fn as_slice ( & self ) -> & 'r [ u8 ] { self . 0 } fn verify ( slice : & [ u8 ] , compatible : bool ) -> molecule :: error :: VerificationResult < ( ) > { use molecule :: verification_error as ve ; let slice_len = slice . len ( ) ; if slice_len < molecule :: NUMBER_SIZE { return ve ! ( Self , HeaderIsBroken , molecule :: NUMBER_SIZE , slice_len ) ; } let total_size = molecule :: unpack_number ( slice ) as usize ; if slice_len != total_size { return ve ! ( Self , TotalSizeNotMatch , total_size , slice_len ) ; } if slice_len == molecule :: NUMBER_SIZE && Self :: FIELD_COUNT == 0 { return Ok ( ( ) ) ; } if slice_len < molecule :: NUMBER_SIZE * 2 { return ve ! ( Self , HeaderIsBroken , molecule :: NUMBER_SIZE * 2 , slice_len ) ; } let offset_first = molecule :: unpack_number ( & slice [ molecule :: NUMBER_SIZE .. ] ) as usize ; if offset_first % 4 != 0 || offset_first < molecule :: NUMBER_SIZE * 2 { return ve ! ( Self , OffsetsNotMatch ) ; } let field_count = offset_first / 4 - 1 ; if field_count < Self :: FIELD_COUNT { return ve ! ( Self , FieldCountNotMatch , Self :: FIELD_COUNT , field_count ) ; } else if ! compatible && field_count > Self :: FIELD_COUNT { return ve ! ( Self , FieldCountNotMatch , Self :: FIELD_COUNT , field_count ) ; } ; let header_size = molecule :: NUMBER_SIZE * ( field_count + 1 ) ; if slice_len < header_size { return ve ! ( Self , HeaderIsBroken , header_size , slice_len ) ; } let mut offsets : Vec < usize > = slice [ molecule :: NUMBER_SIZE .. ] . chunks ( molecule :: NUMBER_SIZE ) . take ( field_count ) . map ( | x | molecule :: unpack_number ( x ) as usize ) . collect ( ) ; offsets . push ( total_size ) ; if offsets . windows ( 2 ) . any ( | i | i [ 0 ] > i [ 1 ] ) { return ve ! ( Self , OffsetsNotMatch ) ; } BytesReader :: verify ( & slice [ offsets [ 0 ] .. offsets [ 1 ] ] , compatible ) ? ; BytesReader :: verify ( & slice [ offsets [ 1 ] .. offsets [ 2 ] ] , compatible ) ? ; Ok ( ( ) ) } } -# [ derive ( Debug , Default ) ] pub struct MintXTWitnessBuilder { pub ( crate ) spv_proof : Bytes , pub ( crate ) cell_dep_index_list : Bytes , } impl MintXTWitnessBuilder { pub const FIELD_COUNT : usize = 2 ; pub fn spv_proof ( mut self , v : Bytes ) -> Self { self . spv_proof = v ; self } pub fn cell_dep_index_list ( mut self , v : Bytes ) -> Self { self . cell_dep_index_list = v ; self } } impl molecule :: prelude :: Builder for MintXTWitnessBuilder { type Entity = MintXTWitness ; const NAME : & 'static str = "MintXTWitnessBuilder" ; fn expected_length ( & self ) -> usize { molecule :: NUMBER_SIZE * ( Self :: FIELD_COUNT + 1 ) + self . spv_proof . as_slice ( ) . len ( ) + self . cell_dep_index_list . as_slice ( ) . len ( ) } fn write < W : :: molecule :: io :: Write > ( & self , writer : & mut W ) -> :: molecule :: io :: Result < ( ) > { let mut total_size = molecule :: NUMBER_SIZE * ( Self :: FIELD_COUNT + 1 ) ; let mut offsets = Vec :: with_capacity ( Self :: FIELD_COUNT ) ; offsets . push ( total_size ) ; total_size += self . spv_proof . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . cell_dep_index_list . as_slice ( ) . len ( ) ; writer . write_all ( & molecule :: pack_number ( total_size as molecule :: Number ) ) ? ; for offset in offsets . into_iter ( ) { writer . write_all ( & molecule :: pack_number ( offset as molecule :: Number ) ) ? ; } writer . write_all ( self . spv_proof . as_slice ( ) ) ? ; writer . write_all ( self . cell_dep_index_list . as_slice ( ) ) ? ; Ok ( ( ) ) } fn build ( & self ) -> Self :: Entity { let mut inner = Vec :: with_capacity ( self . expected_length ( ) ) ; self . write ( & mut inner ) . unwrap_or_else ( | _ | panic ! ( "{} build should be ok" , Self :: NAME ) ) ; MintXTWitness :: new_unchecked ( inner . into ( ) ) } } -# [ derive ( Clone ) ] pub struct BTCSPVProof ( molecule :: bytes :: Bytes ) ; impl :: core :: fmt :: LowerHex for BTCSPVProof { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl :: core :: fmt :: Debug for BTCSPVProof { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl :: core :: fmt :: Display for BTCSPVProof { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{} {{ " , Self :: NAME ) ? ; write ! ( f , "{}: {}" , "version" , self . version ( ) ) ? ; write ! ( f , ", {}: {}" , "vin" , self . vin ( ) ) ? ; write ! ( f , ", {}: {}" , "vout" , self . vout ( ) ) ? ; write ! ( f , ", {}: {}" , "locktime" , self . locktime ( ) ) ? ; write ! ( f , ", {}: {}" , "tx_id" , self . tx_id ( ) ) ? ; write ! ( f , ", {}: {}" , "index" , self . index ( ) ) ? ; write ! ( f , ", {}: {}" , "headers" , self . headers ( ) ) ? ; write ! ( f , ", {}: {}" , "intermediate_nodes" , self . intermediate_nodes ( ) ) ? ; write ! ( f , ", {}: {}" , "funding_output_index" , self . funding_output_index ( ) ) ? ; let extra_count = self . count_extra_fields ( ) ; if extra_count != 0 { write ! ( f , ", .. ({} fields)" , extra_count ) ? ; } write ! ( f , " }}" ) } } impl :: core :: default :: Default for BTCSPVProof { fn default ( ) -> Self { let v : Vec < u8 > = vec ! [ 105 , 0 , 0 , 0 , 40 , 0 , 0 , 0 , 44 , 0 , 0 , 0 , 48 , 0 , 0 , 0 , 52 , 0 , 0 , 0 , 56 , 0 , 0 , 0 , 88 , 0 , 0 , 0 , 96 , 0 , 0 , 0 , 100 , 0 , 0 , 0 , 104 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , ] ; BTCSPVProof :: new_unchecked ( v . into ( ) ) } } impl BTCSPVProof { pub const FIELD_COUNT : usize = 9 ; pub fn total_size ( & self ) -> usize { molecule :: unpack_number ( self . as_slice ( ) ) as usize } pub fn field_count ( & self ) -> usize { if self . total_size ( ) == molecule :: NUMBER_SIZE { 0 } else { ( molecule :: unpack_number ( & self . as_slice ( ) [ molecule :: NUMBER_SIZE .. ] ) as usize / 4 ) - 1 } } pub fn count_extra_fields ( & self ) -> usize { self . field_count ( ) - Self :: FIELD_COUNT } pub fn has_extra_fields ( & self ) -> bool { Self :: FIELD_COUNT != self . field_count ( ) } pub fn version ( & self ) -> Byte4 { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 4 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; Byte4 :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn vin ( & self ) -> Bytes { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; Bytes :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn vout ( & self ) -> Bytes { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 16 .. ] ) as usize ; Bytes :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn locktime ( & self ) -> Byte4 { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 16 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 20 .. ] ) as usize ; Byte4 :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn tx_id ( & self ) -> Byte32 { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 20 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 24 .. ] ) as usize ; Byte32 :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn index ( & self ) -> Uint64 { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 24 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 28 .. ] ) as usize ; Uint64 :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn headers ( & self ) -> Bytes { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 28 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 32 .. ] ) as usize ; Bytes :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn intermediate_nodes ( & self ) -> Bytes { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 32 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 36 .. ] ) as usize ; Bytes :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn funding_output_index ( & self ) -> Byte { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 36 .. ] ) as usize ; if self . has_extra_fields ( ) { let end = molecule :: unpack_number ( & slice [ 40 .. ] ) as usize ; Byte :: new_unchecked ( self . 0 . slice ( start .. end ) ) } else { Byte :: new_unchecked ( self . 0 . slice ( start .. ) ) } } pub fn as_reader < 'r > ( & 'r self ) -> BTCSPVProofReader < 'r > { BTCSPVProofReader :: new_unchecked ( self . as_slice ( ) ) } } impl molecule :: prelude :: Entity for BTCSPVProof { type Builder = BTCSPVProofBuilder ; const NAME : & 'static str = "BTCSPVProof" ; fn new_unchecked ( data : molecule :: bytes :: Bytes ) -> Self { BTCSPVProof ( data ) } fn as_bytes ( & self ) -> molecule :: bytes :: Bytes { self . 0 . clone ( ) } fn as_slice ( & self ) -> & [ u8 ] { & self . 0 [ .. ] } fn from_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { BTCSPVProofReader :: from_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn from_compatible_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { BTCSPVProofReader :: from_compatible_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn new_builder ( ) -> Self :: Builder { :: core :: default :: Default :: default ( ) } fn as_builder ( self ) -> Self :: Builder { Self :: new_builder ( ) . version ( self . version ( ) ) . vin ( self . vin ( ) ) . vout ( self . vout ( ) ) . locktime ( self . locktime ( ) ) . tx_id ( self . tx_id ( ) ) . index ( self . index ( ) ) . headers ( self . headers ( ) ) . intermediate_nodes ( self . intermediate_nodes ( ) ) . funding_output_index ( self . funding_output_index ( ) ) } } -# [ derive ( Clone , Copy ) ] pub struct BTCSPVProofReader < 'r > ( & 'r [ u8 ] ) ; impl < 'r > :: core :: fmt :: LowerHex for BTCSPVProofReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl < 'r > :: core :: fmt :: Debug for BTCSPVProofReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl < 'r > :: core :: fmt :: Display for BTCSPVProofReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{} {{ " , Self :: NAME ) ? ; write ! ( f , "{}: {}" , "version" , self . version ( ) ) ? ; write ! ( f , ", {}: {}" , "vin" , self . vin ( ) ) ? ; write ! ( f , ", {}: {}" , "vout" , self . vout ( ) ) ? ; write ! ( f , ", {}: {}" , "locktime" , self . locktime ( ) ) ? ; write ! ( f , ", {}: {}" , "tx_id" , self . tx_id ( ) ) ? ; write ! ( f , ", {}: {}" , "index" , self . index ( ) ) ? ; write ! ( f , ", {}: {}" , "headers" , self . headers ( ) ) ? ; write ! ( f , ", {}: {}" , "intermediate_nodes" , self . intermediate_nodes ( ) ) ? ; write ! ( f , ", {}: {}" , "funding_output_index" , self . funding_output_index ( ) ) ? ; let extra_count = self . count_extra_fields ( ) ; if extra_count != 0 { write ! ( f , ", .. ({} fields)" , extra_count ) ? ; } write ! ( f , " }}" ) } } impl < 'r > BTCSPVProofReader < 'r > { pub const FIELD_COUNT : usize = 9 ; pub fn total_size ( & self ) -> usize { molecule :: unpack_number ( self . as_slice ( ) ) as usize } pub fn field_count ( & self ) -> usize { if self . total_size ( ) == molecule :: NUMBER_SIZE { 0 } else { ( molecule :: unpack_number ( & self . as_slice ( ) [ molecule :: NUMBER_SIZE .. ] ) as usize / 4 ) - 1 } } pub fn count_extra_fields ( & self ) -> usize { self . field_count ( ) - Self :: FIELD_COUNT } pub fn has_extra_fields ( & self ) -> bool { Self :: FIELD_COUNT != self . field_count ( ) } pub fn version ( & self ) -> Byte4Reader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 4 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; Byte4Reader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn vin ( & self ) -> BytesReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; BytesReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn vout ( & self ) -> BytesReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 16 .. ] ) as usize ; BytesReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn locktime ( & self ) -> Byte4Reader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 16 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 20 .. ] ) as usize ; Byte4Reader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn tx_id ( & self ) -> Byte32Reader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 20 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 24 .. ] ) as usize ; Byte32Reader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn index ( & self ) -> Uint64Reader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 24 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 28 .. ] ) as usize ; Uint64Reader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn headers ( & self ) -> BytesReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 28 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 32 .. ] ) as usize ; BytesReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn intermediate_nodes ( & self ) -> BytesReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 32 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 36 .. ] ) as usize ; BytesReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn funding_output_index ( & self ) -> ByteReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 36 .. ] ) as usize ; if self . has_extra_fields ( ) { let end = molecule :: unpack_number ( & slice [ 40 .. ] ) as usize ; ByteReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } else { ByteReader :: new_unchecked ( & self . as_slice ( ) [ start .. ] ) } } } impl < 'r > molecule :: prelude :: Reader < 'r > for BTCSPVProofReader < 'r > { type Entity = BTCSPVProof ; const NAME : & 'static str = "BTCSPVProofReader" ; fn to_entity ( & self ) -> Self :: Entity { Self :: Entity :: new_unchecked ( self . as_slice ( ) . to_owned ( ) . into ( ) ) } fn new_unchecked ( slice : & 'r [ u8 ] ) -> Self { BTCSPVProofReader ( slice ) } fn as_slice ( & self ) -> & 'r [ u8 ] { self . 0 } fn verify ( slice : & [ u8 ] , compatible : bool ) -> molecule :: error :: VerificationResult < ( ) > { use molecule :: verification_error as ve ; let slice_len = slice . len ( ) ; if slice_len < molecule :: NUMBER_SIZE { return ve ! ( Self , HeaderIsBroken , molecule :: NUMBER_SIZE , slice_len ) ; } let total_size = molecule :: unpack_number ( slice ) as usize ; if slice_len != total_size { return ve ! ( Self , TotalSizeNotMatch , total_size , slice_len ) ; } if slice_len == molecule :: NUMBER_SIZE && Self :: FIELD_COUNT == 0 { return Ok ( ( ) ) ; } if slice_len < molecule :: NUMBER_SIZE * 2 { return ve ! ( Self , HeaderIsBroken , molecule :: NUMBER_SIZE * 2 , slice_len ) ; } let offset_first = molecule :: unpack_number ( & slice [ molecule :: NUMBER_SIZE .. ] ) as usize ; if offset_first % 4 != 0 || offset_first < molecule :: NUMBER_SIZE * 2 { return ve ! ( Self , OffsetsNotMatch ) ; } let field_count = offset_first / 4 - 1 ; if field_count < Self :: FIELD_COUNT { return ve ! ( Self , FieldCountNotMatch , Self :: FIELD_COUNT , field_count ) ; } else if ! compatible && field_count > Self :: FIELD_COUNT { return ve ! ( Self , FieldCountNotMatch , Self :: FIELD_COUNT , field_count ) ; } ; let header_size = molecule :: NUMBER_SIZE * ( field_count + 1 ) ; if slice_len < header_size { return ve ! ( Self , HeaderIsBroken , header_size , slice_len ) ; } let mut offsets : Vec < usize > = slice [ molecule :: NUMBER_SIZE .. ] . chunks ( molecule :: NUMBER_SIZE ) . take ( field_count ) . map ( | x | molecule :: unpack_number ( x ) as usize ) . collect ( ) ; offsets . push ( total_size ) ; if offsets . windows ( 2 ) . any ( | i | i [ 0 ] > i [ 1 ] ) { return ve ! ( Self , OffsetsNotMatch ) ; } Byte4Reader :: verify ( & slice [ offsets [ 0 ] .. offsets [ 1 ] ] , compatible ) ? ; BytesReader :: verify ( & slice [ offsets [ 1 ] .. offsets [ 2 ] ] , compatible ) ? ; BytesReader :: verify ( & slice [ offsets [ 2 ] .. offsets [ 3 ] ] , compatible ) ? ; Byte4Reader :: verify ( & slice [ offsets [ 3 ] .. offsets [ 4 ] ] , compatible ) ? ; Byte32Reader :: verify ( & slice [ offsets [ 4 ] .. offsets [ 5 ] ] , compatible ) ? ; Uint64Reader :: verify ( & slice [ offsets [ 5 ] .. offsets [ 6 ] ] , compatible ) ? ; BytesReader :: verify ( & slice [ offsets [ 6 ] .. offsets [ 7 ] ] , compatible ) ? ; BytesReader :: verify ( & slice [ offsets [ 7 ] .. offsets [ 8 ] ] , compatible ) ? ; ByteReader :: verify ( & slice [ offsets [ 8 ] .. offsets [ 9 ] ] , compatible ) ? ; Ok ( ( ) ) } } -# [ derive ( Debug , Default ) ] pub struct BTCSPVProofBuilder { pub ( crate ) version : Byte4 , pub ( crate ) vin : Bytes , pub ( crate ) vout : Bytes , pub ( crate ) locktime : Byte4 , pub ( crate ) tx_id : Byte32 , pub ( crate ) index : Uint64 , pub ( crate ) headers : Bytes , pub ( crate ) intermediate_nodes : Bytes , pub ( crate ) funding_output_index : Byte , } impl BTCSPVProofBuilder { pub const FIELD_COUNT : usize = 9 ; pub fn version ( mut self , v : Byte4 ) -> Self { self . version = v ; self } pub fn vin ( mut self , v : Bytes ) -> Self { self . vin = v ; self } pub fn vout ( mut self , v : Bytes ) -> Self { self . vout = v ; self } pub fn locktime ( mut self , v : Byte4 ) -> Self { self . locktime = v ; self } pub fn tx_id ( mut self , v : Byte32 ) -> Self { self . tx_id = v ; self } pub fn index ( mut self , v : Uint64 ) -> Self { self . index = v ; self } pub fn headers ( mut self , v : Bytes ) -> Self { self . headers = v ; self } pub fn intermediate_nodes ( mut self , v : Bytes ) -> Self { self . intermediate_nodes = v ; self } pub fn funding_output_index ( mut self , v : Byte ) -> Self { self . funding_output_index = v ; self } } impl molecule :: prelude :: Builder for BTCSPVProofBuilder { type Entity = BTCSPVProof ; const NAME : & 'static str = "BTCSPVProofBuilder" ; fn expected_length ( & self ) -> usize { molecule :: NUMBER_SIZE * ( Self :: FIELD_COUNT + 1 ) + self . version . as_slice ( ) . len ( ) + self . vin . as_slice ( ) . len ( ) + self . vout . as_slice ( ) . len ( ) + self . locktime . as_slice ( ) . len ( ) + self . tx_id . as_slice ( ) . len ( ) + self . index . as_slice ( ) . len ( ) + self . headers . as_slice ( ) . len ( ) + self . intermediate_nodes . as_slice ( ) . len ( ) + self . funding_output_index . as_slice ( ) . len ( ) } fn write < W : :: molecule :: io :: Write > ( & self , writer : & mut W ) -> :: molecule :: io :: Result < ( ) > { let mut total_size = molecule :: NUMBER_SIZE * ( Self :: FIELD_COUNT + 1 ) ; let mut offsets = Vec :: with_capacity ( Self :: FIELD_COUNT ) ; offsets . push ( total_size ) ; total_size += self . version . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . vin . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . vout . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . locktime . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . tx_id . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . index . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . headers . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . intermediate_nodes . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . funding_output_index . as_slice ( ) . len ( ) ; writer . write_all ( & molecule :: pack_number ( total_size as molecule :: Number ) ) ? ; for offset in offsets . into_iter ( ) { writer . write_all ( & molecule :: pack_number ( offset as molecule :: Number ) ) ? ; } writer . write_all ( self . version . as_slice ( ) ) ? ; writer . write_all ( self . vin . as_slice ( ) ) ? ; writer . write_all ( self . vout . as_slice ( ) ) ? ; writer . write_all ( self . locktime . as_slice ( ) ) ? ; writer . write_all ( self . tx_id . as_slice ( ) ) ? ; writer . write_all ( self . index . as_slice ( ) ) ? ; writer . write_all ( self . headers . as_slice ( ) ) ? ; writer . write_all ( self . intermediate_nodes . as_slice ( ) ) ? ; writer . write_all ( self . funding_output_index . as_slice ( ) ) ? ; Ok ( ( ) ) } fn build ( & self ) -> Self :: Entity { let mut inner = Vec :: with_capacity ( self . expected_length ( ) ) ; self . write ( & mut inner ) . unwrap_or_else ( | _ | panic ! ( "{} build should be ok" , Self :: NAME ) ) ; BTCSPVProof :: new_unchecked ( inner . into ( ) ) } } -# [ derive ( Clone ) ] pub struct ETHSPVProof ( molecule :: bytes :: Bytes ) ; impl :: core :: fmt :: LowerHex for ETHSPVProof { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl :: core :: fmt :: Debug for ETHSPVProof { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl :: core :: fmt :: Display for ETHSPVProof { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{} {{ " , Self :: NAME ) ? ; write ! ( f , "{}: {}" , "log_index" , self . log_index ( ) ) ? ; write ! ( f , ", {}: {}" , "log_entry_data" , self . log_entry_data ( ) ) ? ; write ! ( f , ", {}: {}" , "receipt_index" , self . receipt_index ( ) ) ? ; write ! ( f , ", {}: {}" , "receipt_data" , self . receipt_data ( ) ) ? ; write ! ( f , ", {}: {}" , "receipts_root" , self . receipts_root ( ) ) ? ; write ! ( f , ", {}: {}" , "header_data" , self . header_data ( ) ) ? ; write ! ( f , ", {}: {}" , "proof" , self . proof ( ) ) ? ; let extra_count = self . count_extra_fields ( ) ; if extra_count != 0 { write ! ( f , ", .. ({} fields)" , extra_count ) ? ; } write ! ( f , " }}" ) } } impl :: core :: default :: Default for ETHSPVProof { fn default ( ) -> Self { let v : Vec < u8 > = vec ! [ 68 , 0 , 0 , 0 , 32 , 0 , 0 , 0 , 40 , 0 , 0 , 0 , 44 , 0 , 0 , 0 , 52 , 0 , 0 , 0 , 56 , 0 , 0 , 0 , 60 , 0 , 0 , 0 , 64 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 4 , 0 , 0 , 0 , ] ; ETHSPVProof :: new_unchecked ( v . into ( ) ) } } impl ETHSPVProof { pub const FIELD_COUNT : usize = 7 ; pub fn total_size ( & self ) -> usize { molecule :: unpack_number ( self . as_slice ( ) ) as usize } pub fn field_count ( & self ) -> usize { if self . total_size ( ) == molecule :: NUMBER_SIZE { 0 } else { ( molecule :: unpack_number ( & self . as_slice ( ) [ molecule :: NUMBER_SIZE .. ] ) as usize / 4 ) - 1 } } pub fn count_extra_fields ( & self ) -> usize { self . field_count ( ) - Self :: FIELD_COUNT } pub fn has_extra_fields ( & self ) -> bool { Self :: FIELD_COUNT != self . field_count ( ) } pub fn log_index ( & self ) -> Uint64 { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 4 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; Uint64 :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn log_entry_data ( & self ) -> Bytes { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; Bytes :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn receipt_index ( & self ) -> Uint64 { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 16 .. ] ) as usize ; Uint64 :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn receipt_data ( & self ) -> Bytes { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 16 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 20 .. ] ) as usize ; Bytes :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn receipts_root ( & self ) -> Bytes { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 20 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 24 .. ] ) as usize ; Bytes :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn header_data ( & self ) -> Bytes { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 24 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 28 .. ] ) as usize ; Bytes :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn proof ( & self ) -> Bytes2 { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 28 .. ] ) as usize ; if self . has_extra_fields ( ) { let end = molecule :: unpack_number ( & slice [ 32 .. ] ) as usize ; Bytes2 :: new_unchecked ( self . 0 . slice ( start .. end ) ) } else { Bytes2 :: new_unchecked ( self . 0 . slice ( start .. ) ) } } pub fn as_reader < 'r > ( & 'r self ) -> ETHSPVProofReader < 'r > { ETHSPVProofReader :: new_unchecked ( self . as_slice ( ) ) } } impl molecule :: prelude :: Entity for ETHSPVProof { type Builder = ETHSPVProofBuilder ; const NAME : & 'static str = "ETHSPVProof" ; fn new_unchecked ( data : molecule :: bytes :: Bytes ) -> Self { ETHSPVProof ( data ) } fn as_bytes ( & self ) -> molecule :: bytes :: Bytes { self . 0 . clone ( ) } fn as_slice ( & self ) -> & [ u8 ] { & self . 0 [ .. ] } fn from_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { ETHSPVProofReader :: from_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn from_compatible_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { ETHSPVProofReader :: from_compatible_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn new_builder ( ) -> Self :: Builder { :: core :: default :: Default :: default ( ) } fn as_builder ( self ) -> Self :: Builder { Self :: new_builder ( ) . log_index ( self . log_index ( ) ) . log_entry_data ( self . log_entry_data ( ) ) . receipt_index ( self . receipt_index ( ) ) . receipt_data ( self . receipt_data ( ) ) . receipts_root ( self . receipts_root ( ) ) . header_data ( self . header_data ( ) ) . proof ( self . proof ( ) ) } } -# [ derive ( Clone , Copy ) ] pub struct ETHSPVProofReader < 'r > ( & 'r [ u8 ] ) ; impl < 'r > :: core :: fmt :: LowerHex for ETHSPVProofReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl < 'r > :: core :: fmt :: Debug for ETHSPVProofReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl < 'r > :: core :: fmt :: Display for ETHSPVProofReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{} {{ " , Self :: NAME ) ? ; write ! ( f , "{}: {}" , "log_index" , self . log_index ( ) ) ? ; write ! ( f , ", {}: {}" , "log_entry_data" , self . log_entry_data ( ) ) ? ; write ! ( f , ", {}: {}" , "receipt_index" , self . receipt_index ( ) ) ? ; write ! ( f , ", {}: {}" , "receipt_data" , self . receipt_data ( ) ) ? ; write ! ( f , ", {}: {}" , "receipts_root" , self . receipts_root ( ) ) ? ; write ! ( f , ", {}: {}" , "header_data" , self . header_data ( ) ) ? ; write ! ( f , ", {}: {}" , "proof" , self . proof ( ) ) ? ; let extra_count = self . count_extra_fields ( ) ; if extra_count != 0 { write ! ( f , ", .. ({} fields)" , extra_count ) ? ; } write ! ( f , " }}" ) } } impl < 'r > ETHSPVProofReader < 'r > { pub const FIELD_COUNT : usize = 7 ; pub fn total_size ( & self ) -> usize { molecule :: unpack_number ( self . as_slice ( ) ) as usize } pub fn field_count ( & self ) -> usize { if self . total_size ( ) == molecule :: NUMBER_SIZE { 0 } else { ( molecule :: unpack_number ( & self . as_slice ( ) [ molecule :: NUMBER_SIZE .. ] ) as usize / 4 ) - 1 } } pub fn count_extra_fields ( & self ) -> usize { self . field_count ( ) - Self :: FIELD_COUNT } pub fn has_extra_fields ( & self ) -> bool { Self :: FIELD_COUNT != self . field_count ( ) } pub fn log_index ( & self ) -> Uint64Reader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 4 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; Uint64Reader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn log_entry_data ( & self ) -> BytesReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; BytesReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn receipt_index ( & self ) -> Uint64Reader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 16 .. ] ) as usize ; Uint64Reader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn receipt_data ( & self ) -> BytesReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 16 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 20 .. ] ) as usize ; BytesReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn receipts_root ( & self ) -> BytesReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 20 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 24 .. ] ) as usize ; BytesReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn header_data ( & self ) -> BytesReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 24 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 28 .. ] ) as usize ; BytesReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn proof ( & self ) -> Bytes2Reader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 28 .. ] ) as usize ; if self . has_extra_fields ( ) { let end = molecule :: unpack_number ( & slice [ 32 .. ] ) as usize ; Bytes2Reader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } else { Bytes2Reader :: new_unchecked ( & self . as_slice ( ) [ start .. ] ) } } } impl < 'r > molecule :: prelude :: Reader < 'r > for ETHSPVProofReader < 'r > { type Entity = ETHSPVProof ; const NAME : & 'static str = "ETHSPVProofReader" ; fn to_entity ( & self ) -> Self :: Entity { Self :: Entity :: new_unchecked ( self . as_slice ( ) . to_owned ( ) . into ( ) ) } fn new_unchecked ( slice : & 'r [ u8 ] ) -> Self { ETHSPVProofReader ( slice ) } fn as_slice ( & self ) -> & 'r [ u8 ] { self . 0 } fn verify ( slice : & [ u8 ] , compatible : bool ) -> molecule :: error :: VerificationResult < ( ) > { use molecule :: verification_error as ve ; let slice_len = slice . len ( ) ; if slice_len < molecule :: NUMBER_SIZE { return ve ! ( Self , HeaderIsBroken , molecule :: NUMBER_SIZE , slice_len ) ; } let total_size = molecule :: unpack_number ( slice ) as usize ; if slice_len != total_size { return ve ! ( Self , TotalSizeNotMatch , total_size , slice_len ) ; } if slice_len == molecule :: NUMBER_SIZE && Self :: FIELD_COUNT == 0 { return Ok ( ( ) ) ; } if slice_len < molecule :: NUMBER_SIZE * 2 { return ve ! ( Self , HeaderIsBroken , molecule :: NUMBER_SIZE * 2 , slice_len ) ; } let offset_first = molecule :: unpack_number ( & slice [ molecule :: NUMBER_SIZE .. ] ) as usize ; if offset_first % 4 != 0 || offset_first < molecule :: NUMBER_SIZE * 2 { return ve ! ( Self , OffsetsNotMatch ) ; } let field_count = offset_first / 4 - 1 ; if field_count < Self :: FIELD_COUNT { return ve ! ( Self , FieldCountNotMatch , Self :: FIELD_COUNT , field_count ) ; } else if ! compatible && field_count > Self :: FIELD_COUNT { return ve ! ( Self , FieldCountNotMatch , Self :: FIELD_COUNT , field_count ) ; } ; let header_size = molecule :: NUMBER_SIZE * ( field_count + 1 ) ; if slice_len < header_size { return ve ! ( Self , HeaderIsBroken , header_size , slice_len ) ; } let mut offsets : Vec < usize > = slice [ molecule :: NUMBER_SIZE .. ] . chunks ( molecule :: NUMBER_SIZE ) . take ( field_count ) . map ( | x | molecule :: unpack_number ( x ) as usize ) . collect ( ) ; offsets . push ( total_size ) ; if offsets . windows ( 2 ) . any ( | i | i [ 0 ] > i [ 1 ] ) { return ve ! ( Self , OffsetsNotMatch ) ; } Uint64Reader :: verify ( & slice [ offsets [ 0 ] .. offsets [ 1 ] ] , compatible ) ? ; BytesReader :: verify ( & slice [ offsets [ 1 ] .. offsets [ 2 ] ] , compatible ) ? ; Uint64Reader :: verify ( & slice [ offsets [ 2 ] .. offsets [ 3 ] ] , compatible ) ? ; BytesReader :: verify ( & slice [ offsets [ 3 ] .. offsets [ 4 ] ] , compatible ) ? ; BytesReader :: verify ( & slice [ offsets [ 4 ] .. offsets [ 5 ] ] , compatible ) ? ; BytesReader :: verify ( & slice [ offsets [ 5 ] .. offsets [ 6 ] ] , compatible ) ? ; Bytes2Reader :: verify ( & slice [ offsets [ 6 ] .. offsets [ 7 ] ] , compatible ) ? ; Ok ( ( ) ) } } -# [ derive ( Debug , Default ) ] pub struct ETHSPVProofBuilder { pub ( crate ) log_index : Uint64 , pub ( crate ) log_entry_data : Bytes , pub ( crate ) receipt_index : Uint64 , pub ( crate ) receipt_data : Bytes , pub ( crate ) receipts_root : Bytes , pub ( crate ) header_data : Bytes , pub ( crate ) proof : Bytes2 , } impl ETHSPVProofBuilder { pub const FIELD_COUNT : usize = 7 ; pub fn log_index ( mut self , v : Uint64 ) -> Self { self . log_index = v ; self } pub fn log_entry_data ( mut self , v : Bytes ) -> Self { self . log_entry_data = v ; self } pub fn receipt_index ( mut self , v : Uint64 ) -> Self { self . receipt_index = v ; self } pub fn receipt_data ( mut self , v : Bytes ) -> Self { self . receipt_data = v ; self } pub fn receipts_root ( mut self , v : Bytes ) -> Self { self . receipts_root = v ; self } pub fn header_data ( mut self , v : Bytes ) -> Self { self . header_data = v ; self } pub fn proof ( mut self , v : Bytes2 ) -> Self { self . proof = v ; self } } impl molecule :: prelude :: Builder for ETHSPVProofBuilder { type Entity = ETHSPVProof ; const NAME : & 'static str = "ETHSPVProofBuilder" ; fn expected_length ( & self ) -> usize { molecule :: NUMBER_SIZE * ( Self :: FIELD_COUNT + 1 ) + self . log_index . as_slice ( ) . len ( ) + self . log_entry_data . as_slice ( ) . len ( ) + self . receipt_index . as_slice ( ) . len ( ) + self . receipt_data . as_slice ( ) . len ( ) + self . receipts_root . as_slice ( ) . len ( ) + self . header_data . as_slice ( ) . len ( ) + self . proof . as_slice ( ) . len ( ) } fn write < W : :: molecule :: io :: Write > ( & self , writer : & mut W ) -> :: molecule :: io :: Result < ( ) > { let mut total_size = molecule :: NUMBER_SIZE * ( Self :: FIELD_COUNT + 1 ) ; let mut offsets = Vec :: with_capacity ( Self :: FIELD_COUNT ) ; offsets . push ( total_size ) ; total_size += self . log_index . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . log_entry_data . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . receipt_index . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . receipt_data . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . receipts_root . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . header_data . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . proof . as_slice ( ) . len ( ) ; writer . write_all ( & molecule :: pack_number ( total_size as molecule :: Number ) ) ? ; for offset in offsets . into_iter ( ) { writer . write_all ( & molecule :: pack_number ( offset as molecule :: Number ) ) ? ; } writer . write_all ( self . log_index . as_slice ( ) ) ? ; writer . write_all ( self . log_entry_data . as_slice ( ) ) ? ; writer . write_all ( self . receipt_index . as_slice ( ) ) ? ; writer . write_all ( self . receipt_data . as_slice ( ) ) ? ; writer . write_all ( self . receipts_root . as_slice ( ) ) ? ; writer . write_all ( self . header_data . as_slice ( ) ) ? ; writer . write_all ( self . proof . as_slice ( ) ) ? ; Ok ( ( ) ) } fn build ( & self ) -> Self :: Entity { let mut inner = Vec :: with_capacity ( self . expected_length ( ) ) ; self . write ( & mut inner ) . unwrap_or_else ( | _ | panic ! ( "{} build should be ok" , Self :: NAME ) ) ; ETHSPVProof :: new_unchecked ( inner . into ( ) ) } } +use super::basic::*; +use molecule::prelude::*; +#[derive(Clone)] +pub struct MintXTWitness(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for MintXTWitness { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for MintXTWitness { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for MintXTWitness { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "spv_proof", self.spv_proof())?; + write!( + f, + ", {}: {}", + "cell_dep_index_list", + self.cell_dep_index_list() + )?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl ::core::default::Default for MintXTWitness { + fn default() -> Self { + let v: Vec = vec![ + 20, 0, 0, 0, 12, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ]; + MintXTWitness::new_unchecked(v.into()) + } +} +impl MintXTWitness { + pub const FIELD_COUNT: usize = 2; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn spv_proof(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } + pub fn cell_dep_index_list(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[12..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } else { + Bytes::new_unchecked(self.0.slice(start..)) + } + } + pub fn as_reader<'r>(&'r self) -> MintXTWitnessReader<'r> { + MintXTWitnessReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for MintXTWitness { + type Builder = MintXTWitnessBuilder; + const NAME: &'static str = "MintXTWitness"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + MintXTWitness(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + MintXTWitnessReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + MintXTWitnessReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder() + .spv_proof(self.spv_proof()) + .cell_dep_index_list(self.cell_dep_index_list()) + } +} +#[derive(Clone, Copy)] +pub struct MintXTWitnessReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for MintXTWitnessReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for MintXTWitnessReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for MintXTWitnessReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "spv_proof", self.spv_proof())?; + write!( + f, + ", {}: {}", + "cell_dep_index_list", + self.cell_dep_index_list() + )?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl<'r> MintXTWitnessReader<'r> { + pub const FIELD_COUNT: usize = 2; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn spv_proof(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn cell_dep_index_list(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[12..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } else { + BytesReader::new_unchecked(&self.as_slice()[start..]) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for MintXTWitnessReader<'r> { + type Entity = MintXTWitness; + const NAME: &'static str = "MintXTWitnessReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + MintXTWitnessReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let total_size = molecule::unpack_number(slice) as usize; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + if slice_len == molecule::NUMBER_SIZE && Self::FIELD_COUNT == 0 { + return Ok(()); + } + if slice_len < molecule::NUMBER_SIZE * 2 { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); + } + let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; + if offset_first % 4 != 0 || offset_first < molecule::NUMBER_SIZE * 2 { + return ve!(Self, OffsetsNotMatch); + } + let field_count = offset_first / 4 - 1; + if field_count < Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + } else if !compatible && field_count > Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + }; + let header_size = molecule::NUMBER_SIZE * (field_count + 1); + if slice_len < header_size { + return ve!(Self, HeaderIsBroken, header_size, slice_len); + } + let mut offsets: Vec = slice[molecule::NUMBER_SIZE..] + .chunks(molecule::NUMBER_SIZE) + .take(field_count) + .map(|x| molecule::unpack_number(x) as usize) + .collect(); + offsets.push(total_size); + if offsets.windows(2).any(|i| i[0] > i[1]) { + return ve!(Self, OffsetsNotMatch); + } + BytesReader::verify(&slice[offsets[0]..offsets[1]], compatible)?; + BytesReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct MintXTWitnessBuilder { + pub(crate) spv_proof: Bytes, + pub(crate) cell_dep_index_list: Bytes, +} +impl MintXTWitnessBuilder { + pub const FIELD_COUNT: usize = 2; + pub fn spv_proof(mut self, v: Bytes) -> Self { + self.spv_proof = v; + self + } + pub fn cell_dep_index_list(mut self, v: Bytes) -> Self { + self.cell_dep_index_list = v; + self + } +} +impl molecule::prelude::Builder for MintXTWitnessBuilder { + type Entity = MintXTWitness; + const NAME: &'static str = "MintXTWitnessBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) + + self.spv_proof.as_slice().len() + + self.cell_dep_index_list.as_slice().len() + } + fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { + let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); + let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); + offsets.push(total_size); + total_size += self.spv_proof.as_slice().len(); + offsets.push(total_size); + total_size += self.cell_dep_index_list.as_slice().len(); + writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; + for offset in offsets.into_iter() { + writer.write_all(&molecule::pack_number(offset as molecule::Number))?; + } + writer.write_all(self.spv_proof.as_slice())?; + writer.write_all(self.cell_dep_index_list.as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + MintXTWitness::new_unchecked(inner.into()) + } +} +#[derive(Clone)] +pub struct BTCSPVProof(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for BTCSPVProof { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for BTCSPVProof { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for BTCSPVProof { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "version", self.version())?; + write!(f, ", {}: {}", "vin", self.vin())?; + write!(f, ", {}: {}", "vout", self.vout())?; + write!(f, ", {}: {}", "locktime", self.locktime())?; + write!(f, ", {}: {}", "tx_id", self.tx_id())?; + write!(f, ", {}: {}", "index", self.index())?; + write!(f, ", {}: {}", "headers", self.headers())?; + write!( + f, + ", {}: {}", + "intermediate_nodes", + self.intermediate_nodes() + )?; + write!( + f, + ", {}: {}", + "funding_output_index", + self.funding_output_index() + )?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl ::core::default::Default for BTCSPVProof { + fn default() -> Self { + let v: Vec = vec![ + 105, 0, 0, 0, 40, 0, 0, 0, 44, 0, 0, 0, 48, 0, 0, 0, 52, 0, 0, 0, 56, 0, 0, 0, 88, 0, + 0, 0, 96, 0, 0, 0, 100, 0, 0, 0, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ]; + BTCSPVProof::new_unchecked(v.into()) + } +} +impl BTCSPVProof { + pub const FIELD_COUNT: usize = 9; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn version(&self) -> Byte4 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + Byte4::new_unchecked(self.0.slice(start..end)) + } + pub fn vin(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + let end = molecule::unpack_number(&slice[12..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } + pub fn vout(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[12..]) as usize; + let end = molecule::unpack_number(&slice[16..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } + pub fn locktime(&self) -> Byte4 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[16..]) as usize; + let end = molecule::unpack_number(&slice[20..]) as usize; + Byte4::new_unchecked(self.0.slice(start..end)) + } + pub fn tx_id(&self) -> Byte32 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[20..]) as usize; + let end = molecule::unpack_number(&slice[24..]) as usize; + Byte32::new_unchecked(self.0.slice(start..end)) + } + pub fn index(&self) -> Uint64 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[24..]) as usize; + let end = molecule::unpack_number(&slice[28..]) as usize; + Uint64::new_unchecked(self.0.slice(start..end)) + } + pub fn headers(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[28..]) as usize; + let end = molecule::unpack_number(&slice[32..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } + pub fn intermediate_nodes(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[32..]) as usize; + let end = molecule::unpack_number(&slice[36..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } + pub fn funding_output_index(&self) -> Byte { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[36..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[40..]) as usize; + Byte::new_unchecked(self.0.slice(start..end)) + } else { + Byte::new_unchecked(self.0.slice(start..)) + } + } + pub fn as_reader<'r>(&'r self) -> BTCSPVProofReader<'r> { + BTCSPVProofReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for BTCSPVProof { + type Builder = BTCSPVProofBuilder; + const NAME: &'static str = "BTCSPVProof"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + BTCSPVProof(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + BTCSPVProofReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + BTCSPVProofReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder() + .version(self.version()) + .vin(self.vin()) + .vout(self.vout()) + .locktime(self.locktime()) + .tx_id(self.tx_id()) + .index(self.index()) + .headers(self.headers()) + .intermediate_nodes(self.intermediate_nodes()) + .funding_output_index(self.funding_output_index()) + } +} +#[derive(Clone, Copy)] +pub struct BTCSPVProofReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for BTCSPVProofReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for BTCSPVProofReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for BTCSPVProofReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "version", self.version())?; + write!(f, ", {}: {}", "vin", self.vin())?; + write!(f, ", {}: {}", "vout", self.vout())?; + write!(f, ", {}: {}", "locktime", self.locktime())?; + write!(f, ", {}: {}", "tx_id", self.tx_id())?; + write!(f, ", {}: {}", "index", self.index())?; + write!(f, ", {}: {}", "headers", self.headers())?; + write!( + f, + ", {}: {}", + "intermediate_nodes", + self.intermediate_nodes() + )?; + write!( + f, + ", {}: {}", + "funding_output_index", + self.funding_output_index() + )?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl<'r> BTCSPVProofReader<'r> { + pub const FIELD_COUNT: usize = 9; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn version(&self) -> Byte4Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + Byte4Reader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn vin(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + let end = molecule::unpack_number(&slice[12..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn vout(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[12..]) as usize; + let end = molecule::unpack_number(&slice[16..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn locktime(&self) -> Byte4Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[16..]) as usize; + let end = molecule::unpack_number(&slice[20..]) as usize; + Byte4Reader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn tx_id(&self) -> Byte32Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[20..]) as usize; + let end = molecule::unpack_number(&slice[24..]) as usize; + Byte32Reader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn index(&self) -> Uint64Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[24..]) as usize; + let end = molecule::unpack_number(&slice[28..]) as usize; + Uint64Reader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn headers(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[28..]) as usize; + let end = molecule::unpack_number(&slice[32..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn intermediate_nodes(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[32..]) as usize; + let end = molecule::unpack_number(&slice[36..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn funding_output_index(&self) -> ByteReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[36..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[40..]) as usize; + ByteReader::new_unchecked(&self.as_slice()[start..end]) + } else { + ByteReader::new_unchecked(&self.as_slice()[start..]) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for BTCSPVProofReader<'r> { + type Entity = BTCSPVProof; + const NAME: &'static str = "BTCSPVProofReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + BTCSPVProofReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let total_size = molecule::unpack_number(slice) as usize; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + if slice_len == molecule::NUMBER_SIZE && Self::FIELD_COUNT == 0 { + return Ok(()); + } + if slice_len < molecule::NUMBER_SIZE * 2 { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); + } + let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; + if offset_first % 4 != 0 || offset_first < molecule::NUMBER_SIZE * 2 { + return ve!(Self, OffsetsNotMatch); + } + let field_count = offset_first / 4 - 1; + if field_count < Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + } else if !compatible && field_count > Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + }; + let header_size = molecule::NUMBER_SIZE * (field_count + 1); + if slice_len < header_size { + return ve!(Self, HeaderIsBroken, header_size, slice_len); + } + let mut offsets: Vec = slice[molecule::NUMBER_SIZE..] + .chunks(molecule::NUMBER_SIZE) + .take(field_count) + .map(|x| molecule::unpack_number(x) as usize) + .collect(); + offsets.push(total_size); + if offsets.windows(2).any(|i| i[0] > i[1]) { + return ve!(Self, OffsetsNotMatch); + } + Byte4Reader::verify(&slice[offsets[0]..offsets[1]], compatible)?; + BytesReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; + BytesReader::verify(&slice[offsets[2]..offsets[3]], compatible)?; + Byte4Reader::verify(&slice[offsets[3]..offsets[4]], compatible)?; + Byte32Reader::verify(&slice[offsets[4]..offsets[5]], compatible)?; + Uint64Reader::verify(&slice[offsets[5]..offsets[6]], compatible)?; + BytesReader::verify(&slice[offsets[6]..offsets[7]], compatible)?; + BytesReader::verify(&slice[offsets[7]..offsets[8]], compatible)?; + ByteReader::verify(&slice[offsets[8]..offsets[9]], compatible)?; + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct BTCSPVProofBuilder { + pub(crate) version: Byte4, + pub(crate) vin: Bytes, + pub(crate) vout: Bytes, + pub(crate) locktime: Byte4, + pub(crate) tx_id: Byte32, + pub(crate) index: Uint64, + pub(crate) headers: Bytes, + pub(crate) intermediate_nodes: Bytes, + pub(crate) funding_output_index: Byte, +} +impl BTCSPVProofBuilder { + pub const FIELD_COUNT: usize = 9; + pub fn version(mut self, v: Byte4) -> Self { + self.version = v; + self + } + pub fn vin(mut self, v: Bytes) -> Self { + self.vin = v; + self + } + pub fn vout(mut self, v: Bytes) -> Self { + self.vout = v; + self + } + pub fn locktime(mut self, v: Byte4) -> Self { + self.locktime = v; + self + } + pub fn tx_id(mut self, v: Byte32) -> Self { + self.tx_id = v; + self + } + pub fn index(mut self, v: Uint64) -> Self { + self.index = v; + self + } + pub fn headers(mut self, v: Bytes) -> Self { + self.headers = v; + self + } + pub fn intermediate_nodes(mut self, v: Bytes) -> Self { + self.intermediate_nodes = v; + self + } + pub fn funding_output_index(mut self, v: Byte) -> Self { + self.funding_output_index = v; + self + } +} +impl molecule::prelude::Builder for BTCSPVProofBuilder { + type Entity = BTCSPVProof; + const NAME: &'static str = "BTCSPVProofBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) + + self.version.as_slice().len() + + self.vin.as_slice().len() + + self.vout.as_slice().len() + + self.locktime.as_slice().len() + + self.tx_id.as_slice().len() + + self.index.as_slice().len() + + self.headers.as_slice().len() + + self.intermediate_nodes.as_slice().len() + + self.funding_output_index.as_slice().len() + } + fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { + let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); + let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); + offsets.push(total_size); + total_size += self.version.as_slice().len(); + offsets.push(total_size); + total_size += self.vin.as_slice().len(); + offsets.push(total_size); + total_size += self.vout.as_slice().len(); + offsets.push(total_size); + total_size += self.locktime.as_slice().len(); + offsets.push(total_size); + total_size += self.tx_id.as_slice().len(); + offsets.push(total_size); + total_size += self.index.as_slice().len(); + offsets.push(total_size); + total_size += self.headers.as_slice().len(); + offsets.push(total_size); + total_size += self.intermediate_nodes.as_slice().len(); + offsets.push(total_size); + total_size += self.funding_output_index.as_slice().len(); + writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; + for offset in offsets.into_iter() { + writer.write_all(&molecule::pack_number(offset as molecule::Number))?; + } + writer.write_all(self.version.as_slice())?; + writer.write_all(self.vin.as_slice())?; + writer.write_all(self.vout.as_slice())?; + writer.write_all(self.locktime.as_slice())?; + writer.write_all(self.tx_id.as_slice())?; + writer.write_all(self.index.as_slice())?; + writer.write_all(self.headers.as_slice())?; + writer.write_all(self.intermediate_nodes.as_slice())?; + writer.write_all(self.funding_output_index.as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + BTCSPVProof::new_unchecked(inner.into()) + } +} +#[derive(Clone)] +pub struct ETHSPVProof(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for ETHSPVProof { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for ETHSPVProof { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for ETHSPVProof { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "log_index", self.log_index())?; + write!(f, ", {}: {}", "log_entry_data", self.log_entry_data())?; + write!(f, ", {}: {}", "receipt_index", self.receipt_index())?; + write!(f, ", {}: {}", "receipt_data", self.receipt_data())?; + write!(f, ", {}: {}", "receipts_root", self.receipts_root())?; + write!(f, ", {}: {}", "header_data", self.header_data())?; + write!(f, ", {}: {}", "proof", self.proof())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl ::core::default::Default for ETHSPVProof { + fn default() -> Self { + let v: Vec = vec![ + 68, 0, 0, 0, 32, 0, 0, 0, 40, 0, 0, 0, 44, 0, 0, 0, 52, 0, 0, 0, 56, 0, 0, 0, 60, 0, 0, + 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, + ]; + ETHSPVProof::new_unchecked(v.into()) + } +} +impl ETHSPVProof { + pub const FIELD_COUNT: usize = 7; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn log_index(&self) -> Uint64 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + Uint64::new_unchecked(self.0.slice(start..end)) + } + pub fn log_entry_data(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + let end = molecule::unpack_number(&slice[12..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } + pub fn receipt_index(&self) -> Uint64 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[12..]) as usize; + let end = molecule::unpack_number(&slice[16..]) as usize; + Uint64::new_unchecked(self.0.slice(start..end)) + } + pub fn receipt_data(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[16..]) as usize; + let end = molecule::unpack_number(&slice[20..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } + pub fn receipts_root(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[20..]) as usize; + let end = molecule::unpack_number(&slice[24..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } + pub fn header_data(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[24..]) as usize; + let end = molecule::unpack_number(&slice[28..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } + pub fn proof(&self) -> Bytes2 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[28..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[32..]) as usize; + Bytes2::new_unchecked(self.0.slice(start..end)) + } else { + Bytes2::new_unchecked(self.0.slice(start..)) + } + } + pub fn as_reader<'r>(&'r self) -> ETHSPVProofReader<'r> { + ETHSPVProofReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for ETHSPVProof { + type Builder = ETHSPVProofBuilder; + const NAME: &'static str = "ETHSPVProof"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + ETHSPVProof(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + ETHSPVProofReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + ETHSPVProofReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder() + .log_index(self.log_index()) + .log_entry_data(self.log_entry_data()) + .receipt_index(self.receipt_index()) + .receipt_data(self.receipt_data()) + .receipts_root(self.receipts_root()) + .header_data(self.header_data()) + .proof(self.proof()) + } +} +#[derive(Clone, Copy)] +pub struct ETHSPVProofReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for ETHSPVProofReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for ETHSPVProofReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for ETHSPVProofReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "log_index", self.log_index())?; + write!(f, ", {}: {}", "log_entry_data", self.log_entry_data())?; + write!(f, ", {}: {}", "receipt_index", self.receipt_index())?; + write!(f, ", {}: {}", "receipt_data", self.receipt_data())?; + write!(f, ", {}: {}", "receipts_root", self.receipts_root())?; + write!(f, ", {}: {}", "header_data", self.header_data())?; + write!(f, ", {}: {}", "proof", self.proof())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl<'r> ETHSPVProofReader<'r> { + pub const FIELD_COUNT: usize = 7; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn log_index(&self) -> Uint64Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + Uint64Reader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn log_entry_data(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + let end = molecule::unpack_number(&slice[12..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn receipt_index(&self) -> Uint64Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[12..]) as usize; + let end = molecule::unpack_number(&slice[16..]) as usize; + Uint64Reader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn receipt_data(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[16..]) as usize; + let end = molecule::unpack_number(&slice[20..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn receipts_root(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[20..]) as usize; + let end = molecule::unpack_number(&slice[24..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn header_data(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[24..]) as usize; + let end = molecule::unpack_number(&slice[28..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn proof(&self) -> Bytes2Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[28..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[32..]) as usize; + Bytes2Reader::new_unchecked(&self.as_slice()[start..end]) + } else { + Bytes2Reader::new_unchecked(&self.as_slice()[start..]) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for ETHSPVProofReader<'r> { + type Entity = ETHSPVProof; + const NAME: &'static str = "ETHSPVProofReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + ETHSPVProofReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let total_size = molecule::unpack_number(slice) as usize; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + if slice_len == molecule::NUMBER_SIZE && Self::FIELD_COUNT == 0 { + return Ok(()); + } + if slice_len < molecule::NUMBER_SIZE * 2 { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); + } + let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; + if offset_first % 4 != 0 || offset_first < molecule::NUMBER_SIZE * 2 { + return ve!(Self, OffsetsNotMatch); + } + let field_count = offset_first / 4 - 1; + if field_count < Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + } else if !compatible && field_count > Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + }; + let header_size = molecule::NUMBER_SIZE * (field_count + 1); + if slice_len < header_size { + return ve!(Self, HeaderIsBroken, header_size, slice_len); + } + let mut offsets: Vec = slice[molecule::NUMBER_SIZE..] + .chunks(molecule::NUMBER_SIZE) + .take(field_count) + .map(|x| molecule::unpack_number(x) as usize) + .collect(); + offsets.push(total_size); + if offsets.windows(2).any(|i| i[0] > i[1]) { + return ve!(Self, OffsetsNotMatch); + } + Uint64Reader::verify(&slice[offsets[0]..offsets[1]], compatible)?; + BytesReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; + Uint64Reader::verify(&slice[offsets[2]..offsets[3]], compatible)?; + BytesReader::verify(&slice[offsets[3]..offsets[4]], compatible)?; + BytesReader::verify(&slice[offsets[4]..offsets[5]], compatible)?; + BytesReader::verify(&slice[offsets[5]..offsets[6]], compatible)?; + Bytes2Reader::verify(&slice[offsets[6]..offsets[7]], compatible)?; + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct ETHSPVProofBuilder { + pub(crate) log_index: Uint64, + pub(crate) log_entry_data: Bytes, + pub(crate) receipt_index: Uint64, + pub(crate) receipt_data: Bytes, + pub(crate) receipts_root: Bytes, + pub(crate) header_data: Bytes, + pub(crate) proof: Bytes2, +} +impl ETHSPVProofBuilder { + pub const FIELD_COUNT: usize = 7; + pub fn log_index(mut self, v: Uint64) -> Self { + self.log_index = v; + self + } + pub fn log_entry_data(mut self, v: Bytes) -> Self { + self.log_entry_data = v; + self + } + pub fn receipt_index(mut self, v: Uint64) -> Self { + self.receipt_index = v; + self + } + pub fn receipt_data(mut self, v: Bytes) -> Self { + self.receipt_data = v; + self + } + pub fn receipts_root(mut self, v: Bytes) -> Self { + self.receipts_root = v; + self + } + pub fn header_data(mut self, v: Bytes) -> Self { + self.header_data = v; + self + } + pub fn proof(mut self, v: Bytes2) -> Self { + self.proof = v; + self + } +} +impl molecule::prelude::Builder for ETHSPVProofBuilder { + type Entity = ETHSPVProof; + const NAME: &'static str = "ETHSPVProofBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) + + self.log_index.as_slice().len() + + self.log_entry_data.as_slice().len() + + self.receipt_index.as_slice().len() + + self.receipt_data.as_slice().len() + + self.receipts_root.as_slice().len() + + self.header_data.as_slice().len() + + self.proof.as_slice().len() + } + fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { + let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); + let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); + offsets.push(total_size); + total_size += self.log_index.as_slice().len(); + offsets.push(total_size); + total_size += self.log_entry_data.as_slice().len(); + offsets.push(total_size); + total_size += self.receipt_index.as_slice().len(); + offsets.push(total_size); + total_size += self.receipt_data.as_slice().len(); + offsets.push(total_size); + total_size += self.receipts_root.as_slice().len(); + offsets.push(total_size); + total_size += self.header_data.as_slice().len(); + offsets.push(total_size); + total_size += self.proof.as_slice().len(); + writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; + for offset in offsets.into_iter() { + writer.write_all(&molecule::pack_number(offset as molecule::Number))?; + } + writer.write_all(self.log_index.as_slice())?; + writer.write_all(self.log_entry_data.as_slice())?; + writer.write_all(self.receipt_index.as_slice())?; + writer.write_all(self.receipt_data.as_slice())?; + writer.write_all(self.receipts_root.as_slice())?; + writer.write_all(self.header_data.as_slice())?; + writer.write_all(self.proof.as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + ETHSPVProof::new_unchecked(inner.into()) + } +} From 2617497a6be3b0338e007d3a820ec0ff9d0c4fc3 Mon Sep 17 00:00:00 2001 From: LeonLi000 Date: Tue, 8 Sep 2020 11:21:05 +0800 Subject: [PATCH 36/45] minor change --- .../src/switch/mint_xt/mod.rs | 13 ++++----- .../src/toCKB_typescript/tests/mint_xt/mod.rs | 28 +++++++++++++++++-- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs index c5ba4a3..e626e85 100644 --- a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs +++ b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs @@ -270,13 +270,6 @@ fn verify_btc_spv(proof: BTCSPVProofReader, difficulty: BTCDifficultyReader) -> } fn verify_xt_issue(data: &ToCKBCellDataView) -> Result<(), Error> { - match get_xchain_kind()? { - XChainKind::Btc => verify_btc_xt_issue(data), - XChainKind::Eth => verify_btc_xt_issue(data), - } -} - -fn verify_btc_xt_issue(data: &ToCKBCellDataView) -> Result<(), Error> { let lock_hash = load_cell_lock_hash(0, Source::GroupInput)?; debug!("lockscript hash: {:?}", hex::encode(lock_hash)); let input_xt_num = QueryIter::new(load_cell_type, Source::Input) @@ -304,7 +297,11 @@ fn verify_btc_xt_issue(data: &ToCKBCellDataView) -> Result<(), Error> { if output_xt_num != 2 { return Err(Error::InvalidXTInInputOrOutput); } - let xt_amount = data.get_btc_lot_size()?.get_sudt_amount(); + let xt_amount = match get_xchain_kind()? { + XChainKind::Btc => data.get_btc_lot_size()?.get_sudt_amount(), + XChainKind::Eth => data.get_eth_lot_size()?.get_sudt_amount(), + }; + // data.get_btc_lot_size()?.get_sudt_amount(); debug!("xt_amount: {}", xt_amount); // fixed order of output cells is required // user-sudt-cell should be outputs[1] diff --git a/tests/src/toCKB_typescript/tests/mint_xt/mod.rs b/tests/src/toCKB_typescript/tests/mint_xt/mod.rs index 20d78a9..bd6f280 100644 --- a/tests/src/toCKB_typescript/tests/mint_xt/mod.rs +++ b/tests/src/toCKB_typescript/tests/mint_xt/mod.rs @@ -91,13 +91,13 @@ fn generate_eth_corrent_case() -> TestCase { Output { typescript: sudt_typescript.clone(), lockscript: always_success_lockscript.clone(), - amount: 24950000, + amount: 249500000000000000, capacity: PLEDGE, }, Output { typescript: sudt_typescript.clone(), lockscript: always_success_lockscript.clone(), - amount: 50000, + amount: 500000000000000, capacity: XT_CELL_CAPACITY, }, ], @@ -146,6 +146,10 @@ fn test_wrong_lot_size() { case.tockb_cell_data.lot_size = 100; case.expect_return_code = LotSizeInvalid as i8; run_test_case(case); + let mut case = generate_eth_corrent_case(); + case.tockb_cell_data.lot_size = 100; + case.expect_return_code = LotSizeInvalid as i8; + run_test_case(case); } #[test] @@ -154,6 +158,10 @@ fn test_wrong_x_lock_address() { case.tockb_cell_data.x_lock_address = "wrong_addr".to_owned(); case.expect_return_code = WrongFundingAddr as i8; run_test_case(case); + let mut case = generate_eth_corrent_case(); + case.tockb_cell_data.x_lock_address = "wrong_addr".to_owned(); + case.expect_return_code = WrongFundingAddr as i8; + run_test_case(case); } #[test] @@ -162,6 +170,10 @@ fn test_wrong_mint_xt_amount() { case.outputs[0].amount = 1; case.expect_return_code = InvalidMintOutput as i8; run_test_case(case); + let mut case = generate_eth_corrent_case(); + case.outputs[0].amount = 1; + case.expect_return_code = InvalidMintOutput as i8; + run_test_case(case); } #[test] @@ -180,6 +192,14 @@ fn test_wrong_btc_spv() { run_test_case(case); } +#[test] +fn test_wrong_eth_spv() { + let mut case = generate_eth_corrent_case(); + case.witness.spv_proof = SpvProof::ETH(mint_xt_witness::ETHSPVProof::default()); + case.expect_return_code = -1; + run_test_case(case); +} + #[test] fn test_wrong_btc_difficulty() { let mut case = generate_btc_corrent_case(); @@ -197,6 +217,10 @@ fn test_wrong_toCKB_capacity() { case.output_capacity = 10000; case.expect_return_code = CapacityInvalid as i8; run_test_case(case); + let mut case = generate_eth_corrent_case(); + case.output_capacity = 10000; + case.expect_return_code = CapacityInvalid as i8; + run_test_case(case); } #[test] From 2a23a950735ae89a496054020e7718512a524672 Mon Sep 17 00:00:00 2001 From: LeonLi000 Date: Tue, 8 Sep 2020 11:25:57 +0800 Subject: [PATCH 37/45] rename testcase --- .../src/toCKB_typescript/tests/mint_xt/mod.rs | 44 +++++++++++-------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/tests/src/toCKB_typescript/tests/mint_xt/mod.rs b/tests/src/toCKB_typescript/tests/mint_xt/mod.rs index bd6f280..d450e19 100644 --- a/tests/src/toCKB_typescript/tests/mint_xt/mod.rs +++ b/tests/src/toCKB_typescript/tests/mint_xt/mod.rs @@ -8,7 +8,7 @@ use crate::toCKB_typescript::utils::types::{generated::mint_xt_witness, Error::* use molecule::prelude::*; use std::convert::TryInto; -fn generate_btc_corrent_case() -> TestCase { +fn generate_btc_correct_case() -> TestCase { let kind = 1; let DeployResult { context: _, @@ -67,7 +67,7 @@ fn generate_btc_corrent_case() -> TestCase { case } -fn generate_eth_corrent_case() -> TestCase { +fn generate_eth_correct_case() -> TestCase { let kind = 2; let DeployResult { context: _, @@ -130,23 +130,23 @@ fn generate_eth_corrent_case() -> TestCase { #[test] fn test_eth_correct_case() { - let case = generate_eth_corrent_case(); + let case = generate_eth_correct_case(); run_test_case(case); } #[test] fn test_btc_correct_case() { - let case = generate_btc_corrent_case(); + let case = generate_btc_correct_case(); run_test_case(case); } #[test] fn test_wrong_lot_size() { - let mut case = generate_btc_corrent_case(); + let mut case = generate_btc_correct_case(); case.tockb_cell_data.lot_size = 100; case.expect_return_code = LotSizeInvalid as i8; run_test_case(case); - let mut case = generate_eth_corrent_case(); + let mut case = generate_eth_correct_case(); case.tockb_cell_data.lot_size = 100; case.expect_return_code = LotSizeInvalid as i8; run_test_case(case); @@ -154,11 +154,11 @@ fn test_wrong_lot_size() { #[test] fn test_wrong_x_lock_address() { - let mut case = generate_btc_corrent_case(); + let mut case = generate_btc_correct_case(); case.tockb_cell_data.x_lock_address = "wrong_addr".to_owned(); case.expect_return_code = WrongFundingAddr as i8; run_test_case(case); - let mut case = generate_eth_corrent_case(); + let mut case = generate_eth_correct_case(); case.tockb_cell_data.x_lock_address = "wrong_addr".to_owned(); case.expect_return_code = WrongFundingAddr as i8; run_test_case(case); @@ -166,11 +166,11 @@ fn test_wrong_x_lock_address() { #[test] fn test_wrong_mint_xt_amount() { - let mut case = generate_btc_corrent_case(); + let mut case = generate_btc_correct_case(); case.outputs[0].amount = 1; case.expect_return_code = InvalidMintOutput as i8; run_test_case(case); - let mut case = generate_eth_corrent_case(); + let mut case = generate_eth_correct_case(); case.outputs[0].amount = 1; case.expect_return_code = InvalidMintOutput as i8; run_test_case(case); @@ -178,7 +178,7 @@ fn test_wrong_mint_xt_amount() { #[test] fn test_wrong_cell_dep_index_list_len() { - let mut case = generate_btc_corrent_case(); + let mut case = generate_btc_correct_case(); case.witness.cell_dep_index_list = vec![1, 2]; case.expect_return_code = InvalidWitness as i8; run_test_case(case); @@ -186,7 +186,7 @@ fn test_wrong_cell_dep_index_list_len() { #[test] fn test_wrong_btc_spv() { - let mut case = generate_btc_corrent_case(); + let mut case = generate_btc_correct_case(); case.witness.spv_proof = SpvProof::BTC(mint_xt_witness::BTCSPVProof::default()); case.expect_return_code = -1; run_test_case(case); @@ -194,7 +194,7 @@ fn test_wrong_btc_spv() { #[test] fn test_wrong_eth_spv() { - let mut case = generate_eth_corrent_case(); + let mut case = generate_eth_correct_case(); case.witness.spv_proof = SpvProof::ETH(mint_xt_witness::ETHSPVProof::default()); case.expect_return_code = -1; run_test_case(case); @@ -202,7 +202,7 @@ fn test_wrong_eth_spv() { #[test] fn test_wrong_btc_difficulty() { - let mut case = generate_btc_corrent_case(); + let mut case = generate_btc_correct_case(); case.cell_deps_data = CellDepsData::BTC(BtcDifficultyTest { previous: 1, current: 1, @@ -213,11 +213,11 @@ fn test_wrong_btc_difficulty() { #[test] fn test_wrong_toCKB_capacity() { - let mut case = generate_btc_corrent_case(); + let mut case = generate_btc_correct_case(); case.output_capacity = 10000; case.expect_return_code = CapacityInvalid as i8; run_test_case(case); - let mut case = generate_eth_corrent_case(); + let mut case = generate_eth_correct_case(); case.output_capacity = 10000; case.expect_return_code = CapacityInvalid as i8; run_test_case(case); @@ -225,7 +225,11 @@ fn test_wrong_toCKB_capacity() { #[test] fn test_wrong_pledge_refund() { - let mut case = generate_btc_corrent_case(); + let mut case = generate_btc_correct_case(); + case.outputs[0].capacity = 1; + case.expect_return_code = CapacityInvalid as i8; + run_test_case(case); + let mut case = generate_eth_correct_case(); case.outputs[0].capacity = 1; case.expect_return_code = CapacityInvalid as i8; run_test_case(case); @@ -233,7 +237,11 @@ fn test_wrong_pledge_refund() { #[test] fn test_wrong_signer_xt_cell_capacity() { - let mut case = generate_btc_corrent_case(); + let mut case = generate_btc_correct_case(); + case.outputs[1].capacity = 1; + case.expect_return_code = CapacityInvalid as i8; + run_test_case(case); + let mut case = generate_eth_correct_case(); case.outputs[1].capacity = 1; case.expect_return_code = CapacityInvalid as i8; run_test_case(case); From 0a3a34b8de39b0e584d6c9e99324fff054d97f00 Mon Sep 17 00:00:00 2001 From: LeonLi000 Date: Tue, 8 Sep 2020 11:42:27 +0800 Subject: [PATCH 38/45] bugfix --- tests/src/toCKB_typescript/tests/mint_xt/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/src/toCKB_typescript/tests/mint_xt/mod.rs b/tests/src/toCKB_typescript/tests/mint_xt/mod.rs index 279d570..71e2090 100644 --- a/tests/src/toCKB_typescript/tests/mint_xt/mod.rs +++ b/tests/src/toCKB_typescript/tests/mint_xt/mod.rs @@ -80,7 +80,7 @@ fn generate_eth_correct_case() -> TestCase { let case = TestCase { kind, input_capacity: 100000, - output_capacity: 100000 - XT_CELL_CAPACITY, + output_capacity: 100000 - PLEDGE - XT_CELL_CAPACITY, tockb_cell_data: ToCKBCellDataTest { lot_size: 1, x_lock_address: "c4c7497fbe1a886841a195a5d622cd60053c1376".to_owned(), From bed317374fa85c09841579211ac30720e5650727 Mon Sep 17 00:00:00 2001 From: LeonLi000 Date: Sat, 26 Sep 2020 22:16:01 +0800 Subject: [PATCH 39/45] fmt code --- .../src/switch/mint_xt/mod.rs | 14 +++-- contracts/toCKB-typescript/src/utils/tools.rs | 52 ++++++++++++++----- tests/src/toCKB_typescript/tests/mint_xt.rs | 8 ++- tests/src/toCKB_typescript/tests/mod.rs | 2 +- .../toCKB_typescript/utils/case_builder.rs | 38 ++++++++++---- 5 files changed, 77 insertions(+), 37 deletions(-) diff --git a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs index de52ad6..4c56251 100644 --- a/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs +++ b/contracts/toCKB-typescript/src/switch/mint_xt/mod.rs @@ -1,13 +1,10 @@ use crate::switch::ToCKBCellDataTuple; use crate::utils::{ - config::{ - PLEDGE, SIGNER_FEE_RATE, SUDT_CODE_HASH, XT_CELL_CAPACITY, - }, - tools::{get_xchain_kind, is_XT_typescript, verify_btc_witness, verify_eth_witness, XChainKind}, - types::{ - mint_xt_witness::MintXTWitnessReader, - Error, ToCKBCellDataView, XExtraView + config::{PLEDGE, SIGNER_FEE_RATE, SUDT_CODE_HASH, XT_CELL_CAPACITY}, + tools::{ + get_xchain_kind, is_XT_typescript, verify_btc_witness, verify_eth_witness, XChainKind, }, + types::{mint_xt_witness::MintXTWitnessReader, Error, ToCKBCellDataView, XExtraView}, }; use ckb_std::{ ckb_constants::Source, @@ -66,7 +63,8 @@ fn verify_witness(data: &ToCKBCellDataView) -> Result { } XChainKind::Eth => { let eth_extra = verify_eth_witness(data, proof, cell_dep_index_list)?; - Ok(XExtraView::Eth(eth_extra))}, + Ok(XExtraView::Eth(eth_extra)) + } } } diff --git a/contracts/toCKB-typescript/src/utils/tools.rs b/contracts/toCKB-typescript/src/utils/tools.rs index 179e800..2868ae6 100644 --- a/contracts/toCKB-typescript/src/utils/tools.rs +++ b/contracts/toCKB-typescript/src/utils/tools.rs @@ -1,8 +1,9 @@ use crate::utils::{ config::{SUDT_CODE_HASH, TX_PROOF_DIFFICULTY_FACTOR, UDT_LEN}, types::{ - btc_difficulty::BTCDifficultyReader, mint_xt_witness::BTCSPVProofReader, mint_xt_witness::ETHSPVProofReader, BtcExtraView, EthExtraView, - Error, ToCKBCellDataView, XExtraView, + btc_difficulty::BTCDifficultyReader, mint_xt_witness::BTCSPVProofReader, + mint_xt_witness::ETHSPVProofReader, BtcExtraView, Error, EthExtraView, ToCKBCellDataView, + XExtraView, }, }; use alloc::{string::String, vec, vec::Vec}; @@ -20,13 +21,13 @@ use ckb_std::{ high_level::{load_cell_capacity, load_cell_data, load_cell_type, load_script}, }; use core::{convert::From, result::Result}; +use eth_spv_lib::{eth_types::*, ethspv}; +use hex; use molecule::prelude::Reader; use primitive_types::U256; use tockb_types::generated::basic::OutPoint; -pub use tockb_types::tockb_cell::{ToCKBTypeArgsView, XChainKind}; -use eth_spv_lib::{eth_types::*, ethspv}; use tockb_types::generated::tockb_cell_data::{EthCellDataReader, HeaderInfoReader}; -use hex; +pub use tockb_types::tockb_cell::{ToCKBTypeArgsView, XChainKind}; pub fn get_toCKB_type_args() -> Result { let toCKB_type_args = load_script()?.args().raw_data(); @@ -194,7 +195,10 @@ pub fn verify_btc_witness( } } -pub fn verify_header_is_on_main_chain(header: &BlockHeader, cell_dep_index_list: &[u8]) -> Result<(), Error> { +pub fn verify_header_is_on_main_chain( + header: &BlockHeader, + cell_dep_index_list: &[u8], +) -> Result<(), Error> { let dep_data = load_cell_data(cell_dep_index_list[0].into(), Source::CellDep)?; debug!("dep data is {:?}", &dep_data); if EthCellDataReader::verify(&dep_data, false).is_err() { @@ -202,7 +206,11 @@ pub fn verify_header_is_on_main_chain(header: &BlockHeader, cell_dep_index_list: } let eth_cell_data_reader = EthCellDataReader::new_unchecked(&dep_data); debug!("eth_cell_data_reader: {:?}", eth_cell_data_reader); - let tail_raw = eth_cell_data_reader.headers().main().get_unchecked(eth_cell_data_reader.headers().main().len()-1).raw_data(); + let tail_raw = eth_cell_data_reader + .headers() + .main() + .get_unchecked(eth_cell_data_reader.headers().main().len() - 1) + .raw_data(); if HeaderInfoReader::verify(&tail_raw, false).is_err() { return Err(Error::EthHeadersDataInvalid); } @@ -213,12 +221,20 @@ pub fn verify_header_is_on_main_chain(header: &BlockHeader, cell_dep_index_list: return Err(Error::HeaderIsNotOnMainChain); } let offset = (tail.number - header.number) as usize; - if offset > eth_cell_data_reader.headers().main().len()-1 { + if offset > eth_cell_data_reader.headers().main().len() - 1 { return Err(Error::HeaderIsNotOnMainChain); } - let target_raw = eth_cell_data_reader.headers().main().get_unchecked(eth_cell_data_reader.headers().main().len()-1-offset).raw_data(); + let target_raw = eth_cell_data_reader + .headers() + .main() + .get_unchecked(eth_cell_data_reader.headers().main().len() - 1 - offset) + .raw_data(); let target_info_reader = HeaderInfoReader::new_unchecked(target_raw); - debug!("main chain hash: {:?}, witness header hash: {:?}", hex::encode(target_info_reader.hash().raw_data()), hex::encode(header.hash.expect("invalid hash").0.as_bytes())); + debug!( + "main chain hash: {:?}, witness header hash: {:?}", + hex::encode(target_info_reader.hash().raw_data()), + hex::encode(header.hash.expect("invalid hash").0.as_bytes()) + ); if target_info_reader.hash().raw_data() != header.hash.expect("invalid hash").0.as_bytes() { return Err(Error::HeaderIsNotOnMainChain); } @@ -243,9 +259,15 @@ pub fn verify_eth_witness( log_index.copy_from_slice(proof_reader.log_index().raw_data()); debug!("log_index is {:?}", &log_index); let log_entry_data = proof_reader.log_entry_data().raw_data().to_vec(); - debug!("log_entry_data is {:?}", hex::encode(&log_entry_data.as_slice())); + debug!( + "log_entry_data is {:?}", + hex::encode(&log_entry_data.as_slice()) + ); let receipt_data = proof_reader.receipt_data().raw_data().to_vec(); - debug!("receipt_data is {:?}", hex::encode(&receipt_data.as_slice())); + debug!( + "receipt_data is {:?}", + hex::encode(&receipt_data.as_slice()) + ); let mut receipt_index = [0u8; 8]; receipt_index.copy_from_slice(proof_reader.receipt_index().raw_data()); debug!("receipt_index is {:?}", &receipt_index); @@ -263,8 +285,10 @@ pub fn verify_eth_witness( hex::encode(locker_address.to_vec()), String::from_utf8(data.x_lock_address.as_ref().to_vec()).unwrap() ); - if hex::encode(locker_address.to_vec()) != String::from_utf8(data.x_lock_address.as_ref().to_vec()).unwrap() { - return Err(Error::WrongFundingAddr) + if hex::encode(locker_address.to_vec()) + != String::from_utf8(data.x_lock_address.as_ref().to_vec()).unwrap() + { + return Err(Error::WrongFundingAddr); } if !ethspv::verify_log_entry( u64::from_le_bytes(log_index), diff --git a/tests/src/toCKB_typescript/tests/mint_xt.rs b/tests/src/toCKB_typescript/tests/mint_xt.rs index 3fab163..b0e250c 100644 --- a/tests/src/toCKB_typescript/tests/mint_xt.rs +++ b/tests/src/toCKB_typescript/tests/mint_xt.rs @@ -1,11 +1,11 @@ use crate::toCKB_typescript::utils::{case_builder::*, case_runner}; +use hex::FromHex; +use rlp; +use rlp::RlpStream; use tockb_types::{ config::{CKB_UNITS, PLEDGE, XT_CELL_CAPACITY}, Error::*, }; -use hex::FromHex; -use rlp; -use rlp::RlpStream; const COLLATERAL: u64 = 100_000 * CKB_UNITS; @@ -33,7 +33,6 @@ fn test_wrong_lot_size() { case.toCKB_cells.outputs[0].data.lot_size = 100; case.expect_return_code = LotSizeInvalid as i8; case_runner::run_test(case); - } #[test] @@ -347,4 +346,3 @@ fn get_correct_eth_case() -> TestCase { expect_return_code: 0, } } - diff --git a/tests/src/toCKB_typescript/tests/mod.rs b/tests/src/toCKB_typescript/tests/mod.rs index 8d31955..c7e9682 100644 --- a/tests/src/toCKB_typescript/tests/mod.rs +++ b/tests/src/toCKB_typescript/tests/mod.rs @@ -9,12 +9,12 @@ mod liquidation_faulty_redeeming; mod liquidation_faulty_warranty; mod liquidation_signertimeout; mod liquidation_undercollateral; +mod mint_xt; mod pre_undercollateral_redeem; mod preterm_redeem; mod withdraw_collateral; mod withdraw_pledge; mod withdraw_pledge_collateral; -mod mint_xt; pub use tockb_types::{ basic::{Byte32, Bytes, Script}, diff --git a/tests/src/toCKB_typescript/utils/case_builder.rs b/tests/src/toCKB_typescript/utils/case_builder.rs index 5fda9e8..3057e9c 100644 --- a/tests/src/toCKB_typescript/utils/case_builder.rs +++ b/tests/src/toCKB_typescript/utils/case_builder.rs @@ -1,16 +1,21 @@ use crate::toCKB_typescript::utils::types::generated::{ - basic, btc_difficulty, mint_xt_witness, basic::Bytes2, - tockb_cell_data::{BtcExtra, EthExtra, ToCKBCellData, ToCKBTypeArgs, XExtra, XExtraUnion, EthCellData, HeaderInfo, Chain}, + basic, + basic::Bytes2, + btc_difficulty, mint_xt_witness, + tockb_cell_data::{ + BtcExtra, Chain, EthCellData, EthExtra, HeaderInfo, ToCKBCellData, ToCKBTypeArgs, XExtra, + XExtraUnion, + }, }; use anyhow::Result; use ckb_testtool::context::Context; pub use ckb_tool::ckb_types::bytes::Bytes; use ckb_tool::ckb_types::{packed::*, prelude::*}; +use eth_spv_lib::eth_types::BlockHeader; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::convert::{TryFrom, TryInto}; use std::vec::Vec; -use eth_spv_lib::eth_types::BlockHeader; pub const USER_LOCKSCRIPT_OUTPOINT_KEY: &str = "user_lockscript_outpoint_key"; pub const TOCKB_TYPESCRIPT_OUTPOINT_KEY: &str = "toCKB_typescript_outpoint_key"; @@ -80,17 +85,32 @@ impl CellDepView { let headers_data = &headersOracle.headers; let mut headers: Vec = vec![]; for header_str in headers_data { - let header: BlockHeader = rlp::decode(hex::decode(&header_str).expect("invalid header rlp string.").as_slice()).expect("invalid header rlp string."); - let header_info = HeaderInfo::new_builder().header(hex::decode(&header_str).expect("invalid header rlp string.").as_slice().to_vec().into()) + let header: BlockHeader = rlp::decode( + hex::decode(&header_str) + .expect("invalid header rlp string.") + .as_slice(), + ) + .expect("invalid header rlp string."); + let header_info = HeaderInfo::new_builder() + .header( + hex::decode(&header_str) + .expect("invalid header rlp string.") + .as_slice() + .to_vec() + .into(), + ) // .total_difficulty(header.difficulty.0.as_u64().into()) - .hash(basic::Byte32::from_slice(header.hash.unwrap().0.as_bytes()).unwrap() ) + .hash(basic::Byte32::from_slice(header.hash.unwrap().0.as_bytes()).unwrap()) .build(); headers.push(header_info.as_slice().to_vec().into()); } let eth_cell_data = EthCellData::new_builder() - .headers(Chain::new_builder() - .main(Bytes2::new_builder().set(headers).build()) - .build()).build(); + .headers( + Chain::new_builder() + .main(Bytes2::new_builder().set(headers).build()) + .build(), + ) + .build(); let headers_outpoint = context.deploy_cell(eth_cell_data.as_bytes()); CellDep::new_builder().out_point(headers_outpoint).build() } From 992b5ba9b1799ae577a7349f385330b829285520 Mon Sep 17 00:00:00 2001 From: LeonLi000 Date: Sat, 26 Sep 2020 22:23:59 +0800 Subject: [PATCH 40/45] remove unused code --- tests/src/toCKB_typescript/utils/helper.rs | 243 ---- tests/src/toCKB_typescript/utils/test_case.rs | 158 --- .../toCKB_typescript/utils/types/convert.rs | 62 - .../utils/types/generated/btc_difficulty.rs | 7 - .../utils/types/generated/mint_xt_witness.rs | 1137 ----------------- .../utils/types/generated/mod.rs | 7 - .../utils/types/generated/toCKB_cell_data.rs | 7 - tests/src/toCKB_typescript/utils/types/mod.rs | 69 - 8 files changed, 1690 deletions(-) delete mode 100644 tests/src/toCKB_typescript/utils/helper.rs delete mode 100644 tests/src/toCKB_typescript/utils/test_case.rs delete mode 100644 tests/src/toCKB_typescript/utils/types/convert.rs delete mode 100644 tests/src/toCKB_typescript/utils/types/generated/btc_difficulty.rs delete mode 100644 tests/src/toCKB_typescript/utils/types/generated/mint_xt_witness.rs delete mode 100644 tests/src/toCKB_typescript/utils/types/generated/mod.rs delete mode 100644 tests/src/toCKB_typescript/utils/types/generated/toCKB_cell_data.rs delete mode 100644 tests/src/toCKB_typescript/utils/types/mod.rs diff --git a/tests/src/toCKB_typescript/utils/helper.rs b/tests/src/toCKB_typescript/utils/helper.rs deleted file mode 100644 index a45bd31..0000000 --- a/tests/src/toCKB_typescript/utils/helper.rs +++ /dev/null @@ -1,243 +0,0 @@ -use crate::toCKB_typescript::utils::test_case::*; -use crate::*; -use ckb_testtool::{builtin::ALWAYS_SUCCESS, context::Context}; -use ckb_tool::ckb_types::{bytes::Bytes, core::TransactionBuilder, packed::*, prelude::*}; -use molecule::prelude::*; -use std::vec::Vec; -use tockb_types::{ - generated::{basic, btc_difficulty, mint_xt_witness}, - tockb_cell_data::{BtcExtra, EthExtra, ToCKBCellData, XExtra, XExtraUnion}, -}; - -// use tockb_types::generated::tockb_cell_data::XExtraUnion::EthExtra; - -pub const MAX_CYCLES: u64 = 100_000_000; - -fn build_toCKB_data(status: u8, data: ToCKBCellDataTest) -> Bytes { - let x_lock_address_str = &data.x_lock_address; - let x_lock_address:basic::Bytes = x_lock_address_str.as_bytes().to_vec().into(); - let x_unlock_address_str = &data.x_unlock_address; - let x_unlock_address:basic::Bytes = x_unlock_address_str.as_bytes().to_vec().into(); - let signer_lockscript = basic::Script::from_slice(data.signer_lockscript.as_slice()).unwrap(); - let user_lockscript = basic::Script::from_slice(data.user_lockscript.as_slice()).unwrap(); - - let x_extra = match data.x_extra { - XExtraView::Btc(btc_extra) => { - let lock_tx_hash = basic::Byte32::new_unchecked(btc_extra.lock_tx_hash); - let lock_vout_index = Vec::::from(&btc_extra.lock_vout_index.to_le_bytes()[..]); - let lock_vout_index = basic::Uint32::new_unchecked(Bytes::from(lock_vout_index)); - let btc_extra = BtcExtra::new_builder() - .lock_tx_hash(lock_tx_hash) - .lock_vout_index(lock_vout_index) - .build(); - let x_extra = XExtraUnion::BtcExtra(btc_extra); - XExtra::new_builder().set(x_extra).build() - } - XExtraView::Eth(_eth_extra) => { - let eth_extra = EthExtra::new_builder().dummy(Default::default()).build(); - let x_extra = XExtraUnion::EthExtra(eth_extra); - XExtra::new_builder().set(x_extra).build() - }, - }; - - ToCKBCellData::new_builder() - .status(Byte::new(status)) - .lot_size(Byte::new(data.lot_size)) - .signer_lockscript(signer_lockscript.clone()) - .user_lockscript(user_lockscript.clone()) - .x_lock_address(x_lock_address.clone()) - .x_unlock_address(x_unlock_address.clone()) - .x_extra(x_extra.clone()) - .build() - .as_bytes() -} - -pub fn run_test_case(case: TestCase) { - let mut allow_toCKB_cell_input = false; - let mut allow_toCKB_cell_output = false; - - if case.input_status.is_some() { - allow_toCKB_cell_input = true; - } - if case.output_status.is_some() { - allow_toCKB_cell_output = true; - } - - let kind = case.kind; - - let mut context = Context::default(); - let toCKB_typescript_bin: Bytes = Loader::default().load_binary("toCKB-typescript"); - let toCKB_typescript_out_point = context.deploy_cell(toCKB_typescript_bin); - // let toCKB_lockscript_bin: Bytes = Loader::default().load_binary("toCKB-lockscript"); - // let toCKB_lockscript_out_point = context.deploy_cell(toCKB_lockscript_bin); - let always_success_out_point = context.deploy_cell(ALWAYS_SUCCESS.clone()); - let sudt_bin = include_bytes!("../../../deps/simple_udt"); - let sudt_out_point = context.deploy_cell(Bytes::from(sudt_bin.as_ref())); - - // prepare scripts - let toCKB_typescript = context - .build_script(&toCKB_typescript_out_point, [kind; 1].to_vec().into()) - .expect("script"); - let toCKB_typescript_dep = CellDep::new_builder() - .out_point(toCKB_typescript_out_point) - .build(); - let always_success_lockscript = context - .build_script(&always_success_out_point, Default::default()) - .expect("script"); - let always_success_lockscript_dep = CellDep::new_builder() - .out_point(always_success_out_point) - .build(); - let lock_hash: [u8; 32] = always_success_lockscript.calc_script_hash().unpack(); - // let lock_hash = [0u8; 32]; - dbg!(hex::encode(lock_hash)); - let sudt_script_args: Bytes = lock_hash.to_vec().into(); - let _sudt_typescript = context - .build_script(&sudt_out_point, sudt_script_args) - .expect("script"); - let sudt_typescript_dep = CellDep::new_builder().out_point(sudt_out_point).build(); - - // prepare cells - let mut inputs = vec![]; - if allow_toCKB_cell_input { - let data = build_toCKB_data(case.input_status.unwrap(), case.input_tockb_cell_data); - let input_ckb_cell_out_point = context.create_cell( - CellOutput::new_builder() - .capacity(case.input_capacity.pack()) - .lock(always_success_lockscript.clone()) - .type_(Some(toCKB_typescript.clone()).pack()) - .build(), - data, - ); - let input_ckb_cell = CellInput::new_builder() - .previous_output(input_ckb_cell_out_point) - .build(); - inputs.push(input_ckb_cell); - } - - for input in case.inputs.into_iter() { - let input_cell_out_point = context.create_cell( - CellOutput::new_builder() - .capacity(input.capacity.pack()) - .lock(input.lockscript.clone()) - .type_(Some(input.typescript).pack()) - .build(), - input.amount.to_le_bytes().to_vec().into(), - ); - let input_cell = CellInput::new_builder() - .previous_output(input_cell_out_point) - .build(); - inputs.push(input_cell); - } - - let mut outputs = vec![]; - let mut outputs_data = vec![]; - if allow_toCKB_cell_output { - let data = build_toCKB_data(case.output_status.unwrap(), case.output_tockb_cell_data); - outputs.push( - CellOutput::new_builder() - .capacity(case.output_capacity.pack()) - .type_(Some(toCKB_typescript.clone()).pack()) - .lock(always_success_lockscript.clone()) - .build(), - ); - outputs_data.push(data); - } - - for output in case.outputs.into_iter() { - let cell_output = CellOutput::new_builder() - .capacity(output.capacity.pack()) - .type_(Some(output.typescript).pack()) - .lock(output.lockscript) - .build(); - outputs.push(cell_output); - outputs_data.push(output.amount.to_le_bytes().to_vec().into()) - } - - let case_witness = case.witness; - let spv_proof = match case_witness.spv_proof { - SpvProof::BTC(btc_spv_proof) => btc_spv_proof.as_slice().to_vec(), - SpvProof::ETH(eth_spv_proof) => eth_spv_proof.as_slice().to_vec(), - }; - let witness_data = mint_xt_witness::MintXTWitness::new_builder() - .spv_proof(spv_proof.into()) - .cell_dep_index_list(case_witness.cell_dep_index_list.into()) - .build(); - let witness = WitnessArgs::new_builder() - .input_type(Some(witness_data.as_bytes()).pack()) - .build(); - - let dep_data = match case.cell_deps_data { - CellDepsData::BTC(difficulty_data) => { - let data = btc_difficulty::BTCDifficulty::new_builder() - .previous(difficulty_data.previous.to_le_bytes().to_vec().into()) - .current(difficulty_data.current.to_le_bytes().to_vec().into()) - .build(); - dbg!(&data); - data.as_bytes() - } - CellDepsData::ETH() => {Default::default()} - }; - let data_out_point = context.deploy_cell(dep_data); - let data_dep = CellDep::new_builder().out_point(data_out_point).build(); - - let tx = TransactionBuilder::default() - .inputs(inputs) - .outputs(outputs) - .outputs_data(outputs_data.pack()) - .cell_dep(data_dep) - .cell_dep(toCKB_typescript_dep) - .cell_dep(always_success_lockscript_dep) - .cell_dep(sudt_typescript_dep) - .witness(witness.as_bytes().pack()) - .build(); - - let res = context.verify_tx(&tx, MAX_CYCLES); - dbg!(&res); - match res { - Ok(_cycles) => assert_eq!(case.expect_return_code, 0), - Err(err) => assert!(check_err(err, case.expect_return_code)), - } -} - -pub fn check_err(err: ckb_tool::ckb_error::Error, code: i8) -> bool { - let get = format!("{}", err); - let expected = format!("Script(ValidationFailure({}))", code); - dbg!(&get, &expected); - get == expected -} - -pub struct DeployResult { - pub context: Context, - pub toCKB_typescript: Script, - pub always_success_lockscript: Script, - pub sudt_typescript: Script, -} - -pub fn deploy(kind: u8) -> DeployResult { - let mut context = Context::default(); - let toCKB_typescript_bin: Bytes = Loader::default().load_binary("toCKB-typescript"); - let toCKB_typescript_out_point = context.deploy_cell(toCKB_typescript_bin); - let always_success_out_point = context.deploy_cell(ALWAYS_SUCCESS.clone()); - let sudt_bin = include_bytes!("../../../deps/simple_udt"); - let sudt_out_point = context.deploy_cell(Bytes::from(sudt_bin.as_ref())); - - // prepare scripts - let toCKB_typescript = context - .build_script(&toCKB_typescript_out_point, [kind; 1].to_vec().into()) - .expect("script"); - let always_success_lockscript = context - .build_script(&always_success_out_point, Default::default()) - .expect("script"); - let lock_hash: [u8; 32] = always_success_lockscript.calc_script_hash().unpack(); - let sudt_script_args: Bytes = lock_hash.to_vec().into(); - let sudt_typescript = context - .build_script(&sudt_out_point, sudt_script_args) - .expect("script"); - - DeployResult { - context, - toCKB_typescript, - always_success_lockscript, - sudt_typescript, - } -} diff --git a/tests/src/toCKB_typescript/utils/test_case.rs b/tests/src/toCKB_typescript/utils/test_case.rs deleted file mode 100644 index 031766a..0000000 --- a/tests/src/toCKB_typescript/utils/test_case.rs +++ /dev/null @@ -1,158 +0,0 @@ -use crate::toCKB_typescript::utils::types::generated::{mint_xt_witness, basic, basic::Bytes2}; -use anyhow::Result; -use ckb_tool::ckb_types::{bytes::Bytes, packed::*, prelude::*}; -use molecule::prelude::*; -use serde::{Deserialize, Serialize}; -use std::convert::{TryFrom, TryInto}; - -#[derive(Clone)] -pub struct ToCKBCellDataTest { - pub lot_size: u8, - pub x_lock_address: String, - pub x_unlock_address: String, - pub user_lockscript: Script, - pub signer_lockscript: Script, - pub x_extra: XExtraView, -} - -#[derive(Clone)] -pub enum XExtraView { - Btc(BtcExtraView), - Eth(EthExtraView), -} - -#[derive(Clone)] -pub struct BtcExtraView { - pub lock_tx_hash: Bytes, - pub lock_vout_index: u32, -} - -#[derive(Clone)] -pub struct EthExtraView { - pub dummy: Bytes, -} - -pub struct Input { - pub typescript: Script, - pub lockscript: Script, - pub amount: u128, - pub capacity: u64, -} - -pub struct Output { - pub typescript: Script, - pub lockscript: Script, - pub amount: u128, - pub capacity: u64, -} - -pub enum SpvProof { - BTC(mint_xt_witness::BTCSPVProof), - ETH(mint_xt_witness::ETHSPVProof), -} - -pub struct BtcDifficultyTest { - pub previous: u64, - pub current: u64, -} - -pub struct Witness { - pub cell_dep_index_list: Vec, - pub spv_proof: SpvProof, -} - -pub enum CellDepsData { - BTC(BtcDifficultyTest), - ETH(), -} - -pub struct TestCase { - pub kind: u8, - pub input_status: Option, - pub output_status: Option, - pub input_capacity: u64, - pub output_capacity: u64, - pub input_tockb_cell_data: ToCKBCellDataTest, - pub output_tockb_cell_data: ToCKBCellDataTest, - pub inputs: Vec, - pub outputs: Vec, - pub witness: Witness, - pub cell_deps_data: CellDepsData, - pub expect_return_code: i8, -} - -#[derive(Serialize, Deserialize, Default)] -pub struct BTCSPVProofJson { - pub version: u32, - pub vin: String, - pub vout: String, - pub locktime: u32, - pub tx_id: String, - pub index: u64, - pub headers: String, - pub intermediate_nodes: String, - pub funding_output_index: u32, - pub funding_input_index: u32, -} - -impl TryFrom for mint_xt_witness::BTCSPVProof { - type Error = anyhow::Error; - - fn try_from(proof: BTCSPVProofJson) -> Result { - Ok(mint_xt_witness::BTCSPVProof::new_builder() - .version(proof.version.into()) - .vin(hex::decode(clear_0x(&proof.vin))?.into()) - .vout(hex::decode(clear_0x(&proof.vout))?.into()) - .locktime(proof.locktime.into()) - .tx_id(hex::decode(clear_0x(&proof.tx_id))?.into()) - .index(proof.index.into()) - .headers(hex::decode(clear_0x(&proof.headers))?.into()) - .intermediate_nodes(hex::decode(clear_0x(&proof.intermediate_nodes))?.into()) - .funding_output_index(proof.funding_output_index.into()) - .funding_input_index(proof.funding_input_index.into()) - .build()) - } -} - -#[derive(Serialize, Deserialize, Default)] -pub struct ETHSPVProofJson { - pub log_index: u64, - pub log_entry_data: String, - pub receipt_index: u64, - pub receipt_data: String, - pub receipts_root: String, - pub header_data: String, - pub proof: Vec, -} - -impl TryFrom for mint_xt_witness::ETHSPVProof { - type Error = anyhow::Error; - fn try_from(proof: ETHSPVProofJson) -> Result { - let mut proofVec: Vec = vec![]; - for i in 0..proof.proof.len() { - proofVec.push(hex::decode(clear_0x(&proof.proof[i]))?.into()) - } - Ok(mint_xt_witness::ETHSPVProof::new_builder() - .log_index(proof.log_index.into()) - .log_entry_data(hex::decode(clear_0x(&proof.log_entry_data))?.into()) - .receipt_index(proof.receipt_index.into()) - .receipt_data(hex::decode(clear_0x(&proof.receipt_data))?.into()) - .receipts_root(hex::decode(clear_0x(&proof.receipts_root))?.into()) - .header_data(hex::decode(clear_0x(&proof.header_data))?.into()) - .proof(Bytes2::new_builder().set(proofVec).build()) - .build()) - } -} - -pub fn clear_0x(s: &str) -> &str { - if &s[..2] == "0x" || &s[..2] == "0X" { - &s[2..] - } else { - s - } -} - -pub fn json_to_btc_proof(proof: &str) -> Result { - let proof: BTCSPVProofJson = serde_json::from_str(proof)?; - proof.try_into() -} diff --git a/tests/src/toCKB_typescript/utils/types/convert.rs b/tests/src/toCKB_typescript/utils/types/convert.rs deleted file mode 100644 index 38b56c8..0000000 --- a/tests/src/toCKB_typescript/utils/types/convert.rs +++ /dev/null @@ -1,62 +0,0 @@ -use super::generated::basic::{Byte32, Byte4, Bytes, Uint32, Uint64}; -use molecule::prelude::{Builder, Byte, Entity}; - -impl From> for Bytes { - fn from(v: Vec) -> Self { - Bytes::new_builder() - .set(v.into_iter().map(Byte::new).collect()) - .build() - } -} - -impl From> for Byte4 { - fn from(v: Vec) -> Self { - if v.len() != 4 { - panic!("length for Byte4 should be 4") - } - let mut inner = [Byte::new(0); 4]; - let v = v.into_iter().map(Byte::new).collect::>(); - inner.copy_from_slice(&v); - Self::new_builder().set(inner).build() - } -} - -impl From> for Byte32 { - fn from(v: Vec) -> Self { - if v.len() != 32 { - panic!("length for Byte32 should be 32") - } - let mut inner = [Byte::new(0); 32]; - let v = v.into_iter().map(Byte::new).collect::>(); - inner.copy_from_slice(&v); - Self::new_builder().set(inner).build() - } -} - -impl From for Uint32 { - fn from(v: u32) -> Self { - let mut inner = [Byte::new(0); 4]; - let v = v - .to_le_bytes() - .to_vec() - .into_iter() - .map(Byte::new) - .collect::>(); - inner.copy_from_slice(&v); - Self::new_builder().set(inner).build() - } -} - -impl From for Uint64 { - fn from(v: u64) -> Self { - let mut inner = [Byte::new(0); 8]; - let v = v - .to_le_bytes() - .to_vec() - .into_iter() - .map(Byte::new) - .collect::>(); - inner.copy_from_slice(&v); - Self::new_builder().set(inner).build() - } -} diff --git a/tests/src/toCKB_typescript/utils/types/generated/btc_difficulty.rs b/tests/src/toCKB_typescript/utils/types/generated/btc_difficulty.rs deleted file mode 100644 index 8ddda9d..0000000 --- a/tests/src/toCKB_typescript/utils/types/generated/btc_difficulty.rs +++ /dev/null @@ -1,7 +0,0 @@ -// Generated by Molecule 0.6.1 - -use molecule :: prelude :: * ; -use super :: basic :: * ; -# [ derive ( Clone ) ] pub struct BTCDifficulty ( molecule :: bytes :: Bytes ) ; impl :: core :: fmt :: LowerHex for BTCDifficulty { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl :: core :: fmt :: Debug for BTCDifficulty { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl :: core :: fmt :: Display for BTCDifficulty { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{} {{ " , Self :: NAME ) ? ; write ! ( f , "{}: {}" , "current" , self . current ( ) ) ? ; write ! ( f , ", {}: {}" , "previous" , self . previous ( ) ) ? ; let extra_count = self . count_extra_fields ( ) ; if extra_count != 0 { write ! ( f , ", .. ({} fields)" , extra_count ) ? ; } write ! ( f , " }}" ) } } impl :: core :: default :: Default for BTCDifficulty { fn default ( ) -> Self { let v : Vec < u8 > = vec ! [ 20 , 0 , 0 , 0 , 12 , 0 , 0 , 0 , 16 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , ] ; BTCDifficulty :: new_unchecked ( v . into ( ) ) } } impl BTCDifficulty { pub const FIELD_COUNT : usize = 2 ; pub fn total_size ( & self ) -> usize { molecule :: unpack_number ( self . as_slice ( ) ) as usize } pub fn field_count ( & self ) -> usize { if self . total_size ( ) == molecule :: NUMBER_SIZE { 0 } else { ( molecule :: unpack_number ( & self . as_slice ( ) [ molecule :: NUMBER_SIZE .. ] ) as usize / 4 ) - 1 } } pub fn count_extra_fields ( & self ) -> usize { self . field_count ( ) - Self :: FIELD_COUNT } pub fn has_extra_fields ( & self ) -> bool { Self :: FIELD_COUNT != self . field_count ( ) } pub fn current ( & self ) -> Bytes { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 4 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; Bytes :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn previous ( & self ) -> Bytes { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; if self . has_extra_fields ( ) { let end = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; Bytes :: new_unchecked ( self . 0 . slice ( start .. end ) ) } else { Bytes :: new_unchecked ( self . 0 . slice ( start .. ) ) } } pub fn as_reader < 'r > ( & 'r self ) -> BTCDifficultyReader < 'r > { BTCDifficultyReader :: new_unchecked ( self . as_slice ( ) ) } } impl molecule :: prelude :: Entity for BTCDifficulty { type Builder = BTCDifficultyBuilder ; const NAME : & 'static str = "BTCDifficulty" ; fn new_unchecked ( data : molecule :: bytes :: Bytes ) -> Self { BTCDifficulty ( data ) } fn as_bytes ( & self ) -> molecule :: bytes :: Bytes { self . 0 . clone ( ) } fn as_slice ( & self ) -> & [ u8 ] { & self . 0 [ .. ] } fn from_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { BTCDifficultyReader :: from_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn from_compatible_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { BTCDifficultyReader :: from_compatible_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn new_builder ( ) -> Self :: Builder { :: core :: default :: Default :: default ( ) } fn as_builder ( self ) -> Self :: Builder { Self :: new_builder ( ) . current ( self . current ( ) ) . previous ( self . previous ( ) ) } } -# [ derive ( Clone , Copy ) ] pub struct BTCDifficultyReader < 'r > ( & 'r [ u8 ] ) ; impl < 'r > :: core :: fmt :: LowerHex for BTCDifficultyReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl < 'r > :: core :: fmt :: Debug for BTCDifficultyReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl < 'r > :: core :: fmt :: Display for BTCDifficultyReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{} {{ " , Self :: NAME ) ? ; write ! ( f , "{}: {}" , "current" , self . current ( ) ) ? ; write ! ( f , ", {}: {}" , "previous" , self . previous ( ) ) ? ; let extra_count = self . count_extra_fields ( ) ; if extra_count != 0 { write ! ( f , ", .. ({} fields)" , extra_count ) ? ; } write ! ( f , " }}" ) } } impl < 'r > BTCDifficultyReader < 'r > { pub const FIELD_COUNT : usize = 2 ; pub fn total_size ( & self ) -> usize { molecule :: unpack_number ( self . as_slice ( ) ) as usize } pub fn field_count ( & self ) -> usize { if self . total_size ( ) == molecule :: NUMBER_SIZE { 0 } else { ( molecule :: unpack_number ( & self . as_slice ( ) [ molecule :: NUMBER_SIZE .. ] ) as usize / 4 ) - 1 } } pub fn count_extra_fields ( & self ) -> usize { self . field_count ( ) - Self :: FIELD_COUNT } pub fn has_extra_fields ( & self ) -> bool { Self :: FIELD_COUNT != self . field_count ( ) } pub fn current ( & self ) -> BytesReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 4 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; BytesReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn previous ( & self ) -> BytesReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; if self . has_extra_fields ( ) { let end = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; BytesReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } else { BytesReader :: new_unchecked ( & self . as_slice ( ) [ start .. ] ) } } } impl < 'r > molecule :: prelude :: Reader < 'r > for BTCDifficultyReader < 'r > { type Entity = BTCDifficulty ; const NAME : & 'static str = "BTCDifficultyReader" ; fn to_entity ( & self ) -> Self :: Entity { Self :: Entity :: new_unchecked ( self . as_slice ( ) . to_owned ( ) . into ( ) ) } fn new_unchecked ( slice : & 'r [ u8 ] ) -> Self { BTCDifficultyReader ( slice ) } fn as_slice ( & self ) -> & 'r [ u8 ] { self . 0 } fn verify ( slice : & [ u8 ] , compatible : bool ) -> molecule :: error :: VerificationResult < ( ) > { use molecule :: verification_error as ve ; let slice_len = slice . len ( ) ; if slice_len < molecule :: NUMBER_SIZE { return ve ! ( Self , HeaderIsBroken , molecule :: NUMBER_SIZE , slice_len ) ; } let total_size = molecule :: unpack_number ( slice ) as usize ; if slice_len != total_size { return ve ! ( Self , TotalSizeNotMatch , total_size , slice_len ) ; } if slice_len == molecule :: NUMBER_SIZE && Self :: FIELD_COUNT == 0 { return Ok ( ( ) ) ; } if slice_len < molecule :: NUMBER_SIZE * 2 { return ve ! ( Self , HeaderIsBroken , molecule :: NUMBER_SIZE * 2 , slice_len ) ; } let offset_first = molecule :: unpack_number ( & slice [ molecule :: NUMBER_SIZE .. ] ) as usize ; if offset_first % 4 != 0 || offset_first < molecule :: NUMBER_SIZE * 2 { return ve ! ( Self , OffsetsNotMatch ) ; } let field_count = offset_first / 4 - 1 ; if field_count < Self :: FIELD_COUNT { return ve ! ( Self , FieldCountNotMatch , Self :: FIELD_COUNT , field_count ) ; } else if ! compatible && field_count > Self :: FIELD_COUNT { return ve ! ( Self , FieldCountNotMatch , Self :: FIELD_COUNT , field_count ) ; } ; let header_size = molecule :: NUMBER_SIZE * ( field_count + 1 ) ; if slice_len < header_size { return ve ! ( Self , HeaderIsBroken , header_size , slice_len ) ; } let mut offsets : Vec < usize > = slice [ molecule :: NUMBER_SIZE .. ] . chunks ( molecule :: NUMBER_SIZE ) . take ( field_count ) . map ( | x | molecule :: unpack_number ( x ) as usize ) . collect ( ) ; offsets . push ( total_size ) ; if offsets . windows ( 2 ) . any ( | i | i [ 0 ] > i [ 1 ] ) { return ve ! ( Self , OffsetsNotMatch ) ; } BytesReader :: verify ( & slice [ offsets [ 0 ] .. offsets [ 1 ] ] , compatible ) ? ; BytesReader :: verify ( & slice [ offsets [ 1 ] .. offsets [ 2 ] ] , compatible ) ? ; Ok ( ( ) ) } } -# [ derive ( Debug , Default ) ] pub struct BTCDifficultyBuilder { pub ( crate ) current : Bytes , pub ( crate ) previous : Bytes , } impl BTCDifficultyBuilder { pub const FIELD_COUNT : usize = 2 ; pub fn current ( mut self , v : Bytes ) -> Self { self . current = v ; self } pub fn previous ( mut self , v : Bytes ) -> Self { self . previous = v ; self } } impl molecule :: prelude :: Builder for BTCDifficultyBuilder { type Entity = BTCDifficulty ; const NAME : & 'static str = "BTCDifficultyBuilder" ; fn expected_length ( & self ) -> usize { molecule :: NUMBER_SIZE * ( Self :: FIELD_COUNT + 1 ) + self . current . as_slice ( ) . len ( ) + self . previous . as_slice ( ) . len ( ) } fn write < W : :: molecule :: io :: Write > ( & self , writer : & mut W ) -> :: molecule :: io :: Result < ( ) > { let mut total_size = molecule :: NUMBER_SIZE * ( Self :: FIELD_COUNT + 1 ) ; let mut offsets = Vec :: with_capacity ( Self :: FIELD_COUNT ) ; offsets . push ( total_size ) ; total_size += self . current . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . previous . as_slice ( ) . len ( ) ; writer . write_all ( & molecule :: pack_number ( total_size as molecule :: Number ) ) ? ; for offset in offsets . into_iter ( ) { writer . write_all ( & molecule :: pack_number ( offset as molecule :: Number ) ) ? ; } writer . write_all ( self . current . as_slice ( ) ) ? ; writer . write_all ( self . previous . as_slice ( ) ) ? ; Ok ( ( ) ) } fn build ( & self ) -> Self :: Entity { let mut inner = Vec :: with_capacity ( self . expected_length ( ) ) ; self . write ( & mut inner ) . unwrap_or_else ( | _ | panic ! ( "{} build should be ok" , Self :: NAME ) ) ; BTCDifficulty :: new_unchecked ( inner . into ( ) ) } } diff --git a/tests/src/toCKB_typescript/utils/types/generated/mint_xt_witness.rs b/tests/src/toCKB_typescript/utils/types/generated/mint_xt_witness.rs deleted file mode 100644 index d57ff10..0000000 --- a/tests/src/toCKB_typescript/utils/types/generated/mint_xt_witness.rs +++ /dev/null @@ -1,1137 +0,0 @@ -// Generated by Molecule 0.6.1 - -use super::basic::*; -use molecule::prelude::*; -#[derive(Clone)] -pub struct MintXTWitness(molecule::bytes::Bytes); -impl ::core::fmt::LowerHex for MintXTWitness { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl ::core::fmt::Debug for MintXTWitness { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl ::core::fmt::Display for MintXTWitness { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{} {{ ", Self::NAME)?; - write!(f, "{}: {}", "spv_proof", self.spv_proof())?; - write!( - f, - ", {}: {}", - "cell_dep_index_list", - self.cell_dep_index_list() - )?; - let extra_count = self.count_extra_fields(); - if extra_count != 0 { - write!(f, ", .. ({} fields)", extra_count)?; - } - write!(f, " }}") - } -} -impl ::core::default::Default for MintXTWitness { - fn default() -> Self { - let v: Vec = vec![ - 20, 0, 0, 0, 12, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ]; - MintXTWitness::new_unchecked(v.into()) - } -} -impl MintXTWitness { - pub const FIELD_COUNT: usize = 2; - pub fn total_size(&self) -> usize { - molecule::unpack_number(self.as_slice()) as usize - } - pub fn field_count(&self) -> usize { - if self.total_size() == molecule::NUMBER_SIZE { - 0 - } else { - (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 - } - } - pub fn count_extra_fields(&self) -> usize { - self.field_count() - Self::FIELD_COUNT - } - pub fn has_extra_fields(&self) -> bool { - Self::FIELD_COUNT != self.field_count() - } - pub fn spv_proof(&self) -> Bytes { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[4..]) as usize; - let end = molecule::unpack_number(&slice[8..]) as usize; - Bytes::new_unchecked(self.0.slice(start..end)) - } - pub fn cell_dep_index_list(&self) -> Bytes { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[8..]) as usize; - if self.has_extra_fields() { - let end = molecule::unpack_number(&slice[12..]) as usize; - Bytes::new_unchecked(self.0.slice(start..end)) - } else { - Bytes::new_unchecked(self.0.slice(start..)) - } - } - pub fn as_reader<'r>(&'r self) -> MintXTWitnessReader<'r> { - MintXTWitnessReader::new_unchecked(self.as_slice()) - } -} -impl molecule::prelude::Entity for MintXTWitness { - type Builder = MintXTWitnessBuilder; - const NAME: &'static str = "MintXTWitness"; - fn new_unchecked(data: molecule::bytes::Bytes) -> Self { - MintXTWitness(data) - } - fn as_bytes(&self) -> molecule::bytes::Bytes { - self.0.clone() - } - fn as_slice(&self) -> &[u8] { - &self.0[..] - } - fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { - MintXTWitnessReader::from_slice(slice).map(|reader| reader.to_entity()) - } - fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { - MintXTWitnessReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) - } - fn new_builder() -> Self::Builder { - ::core::default::Default::default() - } - fn as_builder(self) -> Self::Builder { - Self::new_builder() - .spv_proof(self.spv_proof()) - .cell_dep_index_list(self.cell_dep_index_list()) - } -} -#[derive(Clone, Copy)] -pub struct MintXTWitnessReader<'r>(&'r [u8]); -impl<'r> ::core::fmt::LowerHex for MintXTWitnessReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl<'r> ::core::fmt::Debug for MintXTWitnessReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl<'r> ::core::fmt::Display for MintXTWitnessReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{} {{ ", Self::NAME)?; - write!(f, "{}: {}", "spv_proof", self.spv_proof())?; - write!( - f, - ", {}: {}", - "cell_dep_index_list", - self.cell_dep_index_list() - )?; - let extra_count = self.count_extra_fields(); - if extra_count != 0 { - write!(f, ", .. ({} fields)", extra_count)?; - } - write!(f, " }}") - } -} -impl<'r> MintXTWitnessReader<'r> { - pub const FIELD_COUNT: usize = 2; - pub fn total_size(&self) -> usize { - molecule::unpack_number(self.as_slice()) as usize - } - pub fn field_count(&self) -> usize { - if self.total_size() == molecule::NUMBER_SIZE { - 0 - } else { - (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 - } - } - pub fn count_extra_fields(&self) -> usize { - self.field_count() - Self::FIELD_COUNT - } - pub fn has_extra_fields(&self) -> bool { - Self::FIELD_COUNT != self.field_count() - } - pub fn spv_proof(&self) -> BytesReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[4..]) as usize; - let end = molecule::unpack_number(&slice[8..]) as usize; - BytesReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn cell_dep_index_list(&self) -> BytesReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[8..]) as usize; - if self.has_extra_fields() { - let end = molecule::unpack_number(&slice[12..]) as usize; - BytesReader::new_unchecked(&self.as_slice()[start..end]) - } else { - BytesReader::new_unchecked(&self.as_slice()[start..]) - } - } -} -impl<'r> molecule::prelude::Reader<'r> for MintXTWitnessReader<'r> { - type Entity = MintXTWitness; - const NAME: &'static str = "MintXTWitnessReader"; - fn to_entity(&self) -> Self::Entity { - Self::Entity::new_unchecked(self.as_slice().to_owned().into()) - } - fn new_unchecked(slice: &'r [u8]) -> Self { - MintXTWitnessReader(slice) - } - fn as_slice(&self) -> &'r [u8] { - self.0 - } - fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { - use molecule::verification_error as ve; - let slice_len = slice.len(); - if slice_len < molecule::NUMBER_SIZE { - return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); - } - let total_size = molecule::unpack_number(slice) as usize; - if slice_len != total_size { - return ve!(Self, TotalSizeNotMatch, total_size, slice_len); - } - if slice_len == molecule::NUMBER_SIZE && Self::FIELD_COUNT == 0 { - return Ok(()); - } - if slice_len < molecule::NUMBER_SIZE * 2 { - return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); - } - let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; - if offset_first % 4 != 0 || offset_first < molecule::NUMBER_SIZE * 2 { - return ve!(Self, OffsetsNotMatch); - } - let field_count = offset_first / 4 - 1; - if field_count < Self::FIELD_COUNT { - return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); - } else if !compatible && field_count > Self::FIELD_COUNT { - return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); - }; - let header_size = molecule::NUMBER_SIZE * (field_count + 1); - if slice_len < header_size { - return ve!(Self, HeaderIsBroken, header_size, slice_len); - } - let mut offsets: Vec = slice[molecule::NUMBER_SIZE..] - .chunks(molecule::NUMBER_SIZE) - .take(field_count) - .map(|x| molecule::unpack_number(x) as usize) - .collect(); - offsets.push(total_size); - if offsets.windows(2).any(|i| i[0] > i[1]) { - return ve!(Self, OffsetsNotMatch); - } - BytesReader::verify(&slice[offsets[0]..offsets[1]], compatible)?; - BytesReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; - Ok(()) - } -} -#[derive(Debug, Default)] -pub struct MintXTWitnessBuilder { - pub(crate) spv_proof: Bytes, - pub(crate) cell_dep_index_list: Bytes, -} -impl MintXTWitnessBuilder { - pub const FIELD_COUNT: usize = 2; - pub fn spv_proof(mut self, v: Bytes) -> Self { - self.spv_proof = v; - self - } - pub fn cell_dep_index_list(mut self, v: Bytes) -> Self { - self.cell_dep_index_list = v; - self - } -} -impl molecule::prelude::Builder for MintXTWitnessBuilder { - type Entity = MintXTWitness; - const NAME: &'static str = "MintXTWitnessBuilder"; - fn expected_length(&self) -> usize { - molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) - + self.spv_proof.as_slice().len() - + self.cell_dep_index_list.as_slice().len() - } - fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { - let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); - let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); - offsets.push(total_size); - total_size += self.spv_proof.as_slice().len(); - offsets.push(total_size); - total_size += self.cell_dep_index_list.as_slice().len(); - writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; - for offset in offsets.into_iter() { - writer.write_all(&molecule::pack_number(offset as molecule::Number))?; - } - writer.write_all(self.spv_proof.as_slice())?; - writer.write_all(self.cell_dep_index_list.as_slice())?; - Ok(()) - } - fn build(&self) -> Self::Entity { - let mut inner = Vec::with_capacity(self.expected_length()); - self.write(&mut inner) - .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); - MintXTWitness::new_unchecked(inner.into()) - } -} -#[derive(Clone)] -pub struct BTCSPVProof(molecule::bytes::Bytes); -impl ::core::fmt::LowerHex for BTCSPVProof { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl ::core::fmt::Debug for BTCSPVProof { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl ::core::fmt::Display for BTCSPVProof { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{} {{ ", Self::NAME)?; - write!(f, "{}: {}", "version", self.version())?; - write!(f, ", {}: {}", "vin", self.vin())?; - write!(f, ", {}: {}", "vout", self.vout())?; - write!(f, ", {}: {}", "locktime", self.locktime())?; - write!(f, ", {}: {}", "tx_id", self.tx_id())?; - write!(f, ", {}: {}", "index", self.index())?; - write!(f, ", {}: {}", "headers", self.headers())?; - write!( - f, - ", {}: {}", - "intermediate_nodes", - self.intermediate_nodes() - )?; - write!( - f, - ", {}: {}", - "funding_output_index", - self.funding_output_index() - )?; - let extra_count = self.count_extra_fields(); - if extra_count != 0 { - write!(f, ", .. ({} fields)", extra_count)?; - } - write!(f, " }}") - } -} -impl ::core::default::Default for BTCSPVProof { - fn default() -> Self { - let v: Vec = vec![ - 105, 0, 0, 0, 40, 0, 0, 0, 44, 0, 0, 0, 48, 0, 0, 0, 52, 0, 0, 0, 56, 0, 0, 0, 88, 0, - 0, 0, 96, 0, 0, 0, 100, 0, 0, 0, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ]; - BTCSPVProof::new_unchecked(v.into()) - } -} -impl BTCSPVProof { - pub const FIELD_COUNT: usize = 9; - pub fn total_size(&self) -> usize { - molecule::unpack_number(self.as_slice()) as usize - } - pub fn field_count(&self) -> usize { - if self.total_size() == molecule::NUMBER_SIZE { - 0 - } else { - (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 - } - } - pub fn count_extra_fields(&self) -> usize { - self.field_count() - Self::FIELD_COUNT - } - pub fn has_extra_fields(&self) -> bool { - Self::FIELD_COUNT != self.field_count() - } - pub fn version(&self) -> Byte4 { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[4..]) as usize; - let end = molecule::unpack_number(&slice[8..]) as usize; - Byte4::new_unchecked(self.0.slice(start..end)) - } - pub fn vin(&self) -> Bytes { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[8..]) as usize; - let end = molecule::unpack_number(&slice[12..]) as usize; - Bytes::new_unchecked(self.0.slice(start..end)) - } - pub fn vout(&self) -> Bytes { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[12..]) as usize; - let end = molecule::unpack_number(&slice[16..]) as usize; - Bytes::new_unchecked(self.0.slice(start..end)) - } - pub fn locktime(&self) -> Byte4 { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[16..]) as usize; - let end = molecule::unpack_number(&slice[20..]) as usize; - Byte4::new_unchecked(self.0.slice(start..end)) - } - pub fn tx_id(&self) -> Byte32 { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[20..]) as usize; - let end = molecule::unpack_number(&slice[24..]) as usize; - Byte32::new_unchecked(self.0.slice(start..end)) - } - pub fn index(&self) -> Uint64 { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[24..]) as usize; - let end = molecule::unpack_number(&slice[28..]) as usize; - Uint64::new_unchecked(self.0.slice(start..end)) - } - pub fn headers(&self) -> Bytes { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[28..]) as usize; - let end = molecule::unpack_number(&slice[32..]) as usize; - Bytes::new_unchecked(self.0.slice(start..end)) - } - pub fn intermediate_nodes(&self) -> Bytes { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[32..]) as usize; - let end = molecule::unpack_number(&slice[36..]) as usize; - Bytes::new_unchecked(self.0.slice(start..end)) - } - pub fn funding_output_index(&self) -> Byte { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[36..]) as usize; - if self.has_extra_fields() { - let end = molecule::unpack_number(&slice[40..]) as usize; - Byte::new_unchecked(self.0.slice(start..end)) - } else { - Byte::new_unchecked(self.0.slice(start..)) - } - } - pub fn as_reader<'r>(&'r self) -> BTCSPVProofReader<'r> { - BTCSPVProofReader::new_unchecked(self.as_slice()) - } -} -impl molecule::prelude::Entity for BTCSPVProof { - type Builder = BTCSPVProofBuilder; - const NAME: &'static str = "BTCSPVProof"; - fn new_unchecked(data: molecule::bytes::Bytes) -> Self { - BTCSPVProof(data) - } - fn as_bytes(&self) -> molecule::bytes::Bytes { - self.0.clone() - } - fn as_slice(&self) -> &[u8] { - &self.0[..] - } - fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { - BTCSPVProofReader::from_slice(slice).map(|reader| reader.to_entity()) - } - fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { - BTCSPVProofReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) - } - fn new_builder() -> Self::Builder { - ::core::default::Default::default() - } - fn as_builder(self) -> Self::Builder { - Self::new_builder() - .version(self.version()) - .vin(self.vin()) - .vout(self.vout()) - .locktime(self.locktime()) - .tx_id(self.tx_id()) - .index(self.index()) - .headers(self.headers()) - .intermediate_nodes(self.intermediate_nodes()) - .funding_output_index(self.funding_output_index()) - } -} -#[derive(Clone, Copy)] -pub struct BTCSPVProofReader<'r>(&'r [u8]); -impl<'r> ::core::fmt::LowerHex for BTCSPVProofReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl<'r> ::core::fmt::Debug for BTCSPVProofReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl<'r> ::core::fmt::Display for BTCSPVProofReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{} {{ ", Self::NAME)?; - write!(f, "{}: {}", "version", self.version())?; - write!(f, ", {}: {}", "vin", self.vin())?; - write!(f, ", {}: {}", "vout", self.vout())?; - write!(f, ", {}: {}", "locktime", self.locktime())?; - write!(f, ", {}: {}", "tx_id", self.tx_id())?; - write!(f, ", {}: {}", "index", self.index())?; - write!(f, ", {}: {}", "headers", self.headers())?; - write!( - f, - ", {}: {}", - "intermediate_nodes", - self.intermediate_nodes() - )?; - write!( - f, - ", {}: {}", - "funding_output_index", - self.funding_output_index() - )?; - let extra_count = self.count_extra_fields(); - if extra_count != 0 { - write!(f, ", .. ({} fields)", extra_count)?; - } - write!(f, " }}") - } -} -impl<'r> BTCSPVProofReader<'r> { - pub const FIELD_COUNT: usize = 9; - pub fn total_size(&self) -> usize { - molecule::unpack_number(self.as_slice()) as usize - } - pub fn field_count(&self) -> usize { - if self.total_size() == molecule::NUMBER_SIZE { - 0 - } else { - (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 - } - } - pub fn count_extra_fields(&self) -> usize { - self.field_count() - Self::FIELD_COUNT - } - pub fn has_extra_fields(&self) -> bool { - Self::FIELD_COUNT != self.field_count() - } - pub fn version(&self) -> Byte4Reader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[4..]) as usize; - let end = molecule::unpack_number(&slice[8..]) as usize; - Byte4Reader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn vin(&self) -> BytesReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[8..]) as usize; - let end = molecule::unpack_number(&slice[12..]) as usize; - BytesReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn vout(&self) -> BytesReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[12..]) as usize; - let end = molecule::unpack_number(&slice[16..]) as usize; - BytesReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn locktime(&self) -> Byte4Reader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[16..]) as usize; - let end = molecule::unpack_number(&slice[20..]) as usize; - Byte4Reader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn tx_id(&self) -> Byte32Reader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[20..]) as usize; - let end = molecule::unpack_number(&slice[24..]) as usize; - Byte32Reader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn index(&self) -> Uint64Reader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[24..]) as usize; - let end = molecule::unpack_number(&slice[28..]) as usize; - Uint64Reader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn headers(&self) -> BytesReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[28..]) as usize; - let end = molecule::unpack_number(&slice[32..]) as usize; - BytesReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn intermediate_nodes(&self) -> BytesReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[32..]) as usize; - let end = molecule::unpack_number(&slice[36..]) as usize; - BytesReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn funding_output_index(&self) -> ByteReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[36..]) as usize; - if self.has_extra_fields() { - let end = molecule::unpack_number(&slice[40..]) as usize; - ByteReader::new_unchecked(&self.as_slice()[start..end]) - } else { - ByteReader::new_unchecked(&self.as_slice()[start..]) - } - } -} -impl<'r> molecule::prelude::Reader<'r> for BTCSPVProofReader<'r> { - type Entity = BTCSPVProof; - const NAME: &'static str = "BTCSPVProofReader"; - fn to_entity(&self) -> Self::Entity { - Self::Entity::new_unchecked(self.as_slice().to_owned().into()) - } - fn new_unchecked(slice: &'r [u8]) -> Self { - BTCSPVProofReader(slice) - } - fn as_slice(&self) -> &'r [u8] { - self.0 - } - fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { - use molecule::verification_error as ve; - let slice_len = slice.len(); - if slice_len < molecule::NUMBER_SIZE { - return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); - } - let total_size = molecule::unpack_number(slice) as usize; - if slice_len != total_size { - return ve!(Self, TotalSizeNotMatch, total_size, slice_len); - } - if slice_len == molecule::NUMBER_SIZE && Self::FIELD_COUNT == 0 { - return Ok(()); - } - if slice_len < molecule::NUMBER_SIZE * 2 { - return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); - } - let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; - if offset_first % 4 != 0 || offset_first < molecule::NUMBER_SIZE * 2 { - return ve!(Self, OffsetsNotMatch); - } - let field_count = offset_first / 4 - 1; - if field_count < Self::FIELD_COUNT { - return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); - } else if !compatible && field_count > Self::FIELD_COUNT { - return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); - }; - let header_size = molecule::NUMBER_SIZE * (field_count + 1); - if slice_len < header_size { - return ve!(Self, HeaderIsBroken, header_size, slice_len); - } - let mut offsets: Vec = slice[molecule::NUMBER_SIZE..] - .chunks(molecule::NUMBER_SIZE) - .take(field_count) - .map(|x| molecule::unpack_number(x) as usize) - .collect(); - offsets.push(total_size); - if offsets.windows(2).any(|i| i[0] > i[1]) { - return ve!(Self, OffsetsNotMatch); - } - Byte4Reader::verify(&slice[offsets[0]..offsets[1]], compatible)?; - BytesReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; - BytesReader::verify(&slice[offsets[2]..offsets[3]], compatible)?; - Byte4Reader::verify(&slice[offsets[3]..offsets[4]], compatible)?; - Byte32Reader::verify(&slice[offsets[4]..offsets[5]], compatible)?; - Uint64Reader::verify(&slice[offsets[5]..offsets[6]], compatible)?; - BytesReader::verify(&slice[offsets[6]..offsets[7]], compatible)?; - BytesReader::verify(&slice[offsets[7]..offsets[8]], compatible)?; - ByteReader::verify(&slice[offsets[8]..offsets[9]], compatible)?; - Ok(()) - } -} -#[derive(Debug, Default)] -pub struct BTCSPVProofBuilder { - pub(crate) version: Byte4, - pub(crate) vin: Bytes, - pub(crate) vout: Bytes, - pub(crate) locktime: Byte4, - pub(crate) tx_id: Byte32, - pub(crate) index: Uint64, - pub(crate) headers: Bytes, - pub(crate) intermediate_nodes: Bytes, - pub(crate) funding_output_index: Byte, -} -impl BTCSPVProofBuilder { - pub const FIELD_COUNT: usize = 9; - pub fn version(mut self, v: Byte4) -> Self { - self.version = v; - self - } - pub fn vin(mut self, v: Bytes) -> Self { - self.vin = v; - self - } - pub fn vout(mut self, v: Bytes) -> Self { - self.vout = v; - self - } - pub fn locktime(mut self, v: Byte4) -> Self { - self.locktime = v; - self - } - pub fn tx_id(mut self, v: Byte32) -> Self { - self.tx_id = v; - self - } - pub fn index(mut self, v: Uint64) -> Self { - self.index = v; - self - } - pub fn headers(mut self, v: Bytes) -> Self { - self.headers = v; - self - } - pub fn intermediate_nodes(mut self, v: Bytes) -> Self { - self.intermediate_nodes = v; - self - } - pub fn funding_output_index(mut self, v: Byte) -> Self { - self.funding_output_index = v; - self - } -} -impl molecule::prelude::Builder for BTCSPVProofBuilder { - type Entity = BTCSPVProof; - const NAME: &'static str = "BTCSPVProofBuilder"; - fn expected_length(&self) -> usize { - molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) - + self.version.as_slice().len() - + self.vin.as_slice().len() - + self.vout.as_slice().len() - + self.locktime.as_slice().len() - + self.tx_id.as_slice().len() - + self.index.as_slice().len() - + self.headers.as_slice().len() - + self.intermediate_nodes.as_slice().len() - + self.funding_output_index.as_slice().len() - } - fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { - let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); - let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); - offsets.push(total_size); - total_size += self.version.as_slice().len(); - offsets.push(total_size); - total_size += self.vin.as_slice().len(); - offsets.push(total_size); - total_size += self.vout.as_slice().len(); - offsets.push(total_size); - total_size += self.locktime.as_slice().len(); - offsets.push(total_size); - total_size += self.tx_id.as_slice().len(); - offsets.push(total_size); - total_size += self.index.as_slice().len(); - offsets.push(total_size); - total_size += self.headers.as_slice().len(); - offsets.push(total_size); - total_size += self.intermediate_nodes.as_slice().len(); - offsets.push(total_size); - total_size += self.funding_output_index.as_slice().len(); - writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; - for offset in offsets.into_iter() { - writer.write_all(&molecule::pack_number(offset as molecule::Number))?; - } - writer.write_all(self.version.as_slice())?; - writer.write_all(self.vin.as_slice())?; - writer.write_all(self.vout.as_slice())?; - writer.write_all(self.locktime.as_slice())?; - writer.write_all(self.tx_id.as_slice())?; - writer.write_all(self.index.as_slice())?; - writer.write_all(self.headers.as_slice())?; - writer.write_all(self.intermediate_nodes.as_slice())?; - writer.write_all(self.funding_output_index.as_slice())?; - Ok(()) - } - fn build(&self) -> Self::Entity { - let mut inner = Vec::with_capacity(self.expected_length()); - self.write(&mut inner) - .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); - BTCSPVProof::new_unchecked(inner.into()) - } -} -#[derive(Clone)] -pub struct ETHSPVProof(molecule::bytes::Bytes); -impl ::core::fmt::LowerHex for ETHSPVProof { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl ::core::fmt::Debug for ETHSPVProof { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl ::core::fmt::Display for ETHSPVProof { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{} {{ ", Self::NAME)?; - write!(f, "{}: {}", "log_index", self.log_index())?; - write!(f, ", {}: {}", "log_entry_data", self.log_entry_data())?; - write!(f, ", {}: {}", "receipt_index", self.receipt_index())?; - write!(f, ", {}: {}", "receipt_data", self.receipt_data())?; - write!(f, ", {}: {}", "receipts_root", self.receipts_root())?; - write!(f, ", {}: {}", "header_data", self.header_data())?; - write!(f, ", {}: {}", "proof", self.proof())?; - let extra_count = self.count_extra_fields(); - if extra_count != 0 { - write!(f, ", .. ({} fields)", extra_count)?; - } - write!(f, " }}") - } -} -impl ::core::default::Default for ETHSPVProof { - fn default() -> Self { - let v: Vec = vec![ - 68, 0, 0, 0, 32, 0, 0, 0, 40, 0, 0, 0, 44, 0, 0, 0, 52, 0, 0, 0, 56, 0, 0, 0, 60, 0, 0, - 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, - ]; - ETHSPVProof::new_unchecked(v.into()) - } -} -impl ETHSPVProof { - pub const FIELD_COUNT: usize = 7; - pub fn total_size(&self) -> usize { - molecule::unpack_number(self.as_slice()) as usize - } - pub fn field_count(&self) -> usize { - if self.total_size() == molecule::NUMBER_SIZE { - 0 - } else { - (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 - } - } - pub fn count_extra_fields(&self) -> usize { - self.field_count() - Self::FIELD_COUNT - } - pub fn has_extra_fields(&self) -> bool { - Self::FIELD_COUNT != self.field_count() - } - pub fn log_index(&self) -> Uint64 { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[4..]) as usize; - let end = molecule::unpack_number(&slice[8..]) as usize; - Uint64::new_unchecked(self.0.slice(start..end)) - } - pub fn log_entry_data(&self) -> Bytes { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[8..]) as usize; - let end = molecule::unpack_number(&slice[12..]) as usize; - Bytes::new_unchecked(self.0.slice(start..end)) - } - pub fn receipt_index(&self) -> Uint64 { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[12..]) as usize; - let end = molecule::unpack_number(&slice[16..]) as usize; - Uint64::new_unchecked(self.0.slice(start..end)) - } - pub fn receipt_data(&self) -> Bytes { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[16..]) as usize; - let end = molecule::unpack_number(&slice[20..]) as usize; - Bytes::new_unchecked(self.0.slice(start..end)) - } - pub fn receipts_root(&self) -> Bytes { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[20..]) as usize; - let end = molecule::unpack_number(&slice[24..]) as usize; - Bytes::new_unchecked(self.0.slice(start..end)) - } - pub fn header_data(&self) -> Bytes { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[24..]) as usize; - let end = molecule::unpack_number(&slice[28..]) as usize; - Bytes::new_unchecked(self.0.slice(start..end)) - } - pub fn proof(&self) -> Bytes2 { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[28..]) as usize; - if self.has_extra_fields() { - let end = molecule::unpack_number(&slice[32..]) as usize; - Bytes2::new_unchecked(self.0.slice(start..end)) - } else { - Bytes2::new_unchecked(self.0.slice(start..)) - } - } - pub fn as_reader<'r>(&'r self) -> ETHSPVProofReader<'r> { - ETHSPVProofReader::new_unchecked(self.as_slice()) - } -} -impl molecule::prelude::Entity for ETHSPVProof { - type Builder = ETHSPVProofBuilder; - const NAME: &'static str = "ETHSPVProof"; - fn new_unchecked(data: molecule::bytes::Bytes) -> Self { - ETHSPVProof(data) - } - fn as_bytes(&self) -> molecule::bytes::Bytes { - self.0.clone() - } - fn as_slice(&self) -> &[u8] { - &self.0[..] - } - fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { - ETHSPVProofReader::from_slice(slice).map(|reader| reader.to_entity()) - } - fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { - ETHSPVProofReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) - } - fn new_builder() -> Self::Builder { - ::core::default::Default::default() - } - fn as_builder(self) -> Self::Builder { - Self::new_builder() - .log_index(self.log_index()) - .log_entry_data(self.log_entry_data()) - .receipt_index(self.receipt_index()) - .receipt_data(self.receipt_data()) - .receipts_root(self.receipts_root()) - .header_data(self.header_data()) - .proof(self.proof()) - } -} -#[derive(Clone, Copy)] -pub struct ETHSPVProofReader<'r>(&'r [u8]); -impl<'r> ::core::fmt::LowerHex for ETHSPVProofReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl<'r> ::core::fmt::Debug for ETHSPVProofReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl<'r> ::core::fmt::Display for ETHSPVProofReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{} {{ ", Self::NAME)?; - write!(f, "{}: {}", "log_index", self.log_index())?; - write!(f, ", {}: {}", "log_entry_data", self.log_entry_data())?; - write!(f, ", {}: {}", "receipt_index", self.receipt_index())?; - write!(f, ", {}: {}", "receipt_data", self.receipt_data())?; - write!(f, ", {}: {}", "receipts_root", self.receipts_root())?; - write!(f, ", {}: {}", "header_data", self.header_data())?; - write!(f, ", {}: {}", "proof", self.proof())?; - let extra_count = self.count_extra_fields(); - if extra_count != 0 { - write!(f, ", .. ({} fields)", extra_count)?; - } - write!(f, " }}") - } -} -impl<'r> ETHSPVProofReader<'r> { - pub const FIELD_COUNT: usize = 7; - pub fn total_size(&self) -> usize { - molecule::unpack_number(self.as_slice()) as usize - } - pub fn field_count(&self) -> usize { - if self.total_size() == molecule::NUMBER_SIZE { - 0 - } else { - (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 - } - } - pub fn count_extra_fields(&self) -> usize { - self.field_count() - Self::FIELD_COUNT - } - pub fn has_extra_fields(&self) -> bool { - Self::FIELD_COUNT != self.field_count() - } - pub fn log_index(&self) -> Uint64Reader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[4..]) as usize; - let end = molecule::unpack_number(&slice[8..]) as usize; - Uint64Reader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn log_entry_data(&self) -> BytesReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[8..]) as usize; - let end = molecule::unpack_number(&slice[12..]) as usize; - BytesReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn receipt_index(&self) -> Uint64Reader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[12..]) as usize; - let end = molecule::unpack_number(&slice[16..]) as usize; - Uint64Reader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn receipt_data(&self) -> BytesReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[16..]) as usize; - let end = molecule::unpack_number(&slice[20..]) as usize; - BytesReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn receipts_root(&self) -> BytesReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[20..]) as usize; - let end = molecule::unpack_number(&slice[24..]) as usize; - BytesReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn header_data(&self) -> BytesReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[24..]) as usize; - let end = molecule::unpack_number(&slice[28..]) as usize; - BytesReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn proof(&self) -> Bytes2Reader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[28..]) as usize; - if self.has_extra_fields() { - let end = molecule::unpack_number(&slice[32..]) as usize; - Bytes2Reader::new_unchecked(&self.as_slice()[start..end]) - } else { - Bytes2Reader::new_unchecked(&self.as_slice()[start..]) - } - } -} -impl<'r> molecule::prelude::Reader<'r> for ETHSPVProofReader<'r> { - type Entity = ETHSPVProof; - const NAME: &'static str = "ETHSPVProofReader"; - fn to_entity(&self) -> Self::Entity { - Self::Entity::new_unchecked(self.as_slice().to_owned().into()) - } - fn new_unchecked(slice: &'r [u8]) -> Self { - ETHSPVProofReader(slice) - } - fn as_slice(&self) -> &'r [u8] { - self.0 - } - fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { - use molecule::verification_error as ve; - let slice_len = slice.len(); - if slice_len < molecule::NUMBER_SIZE { - return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); - } - let total_size = molecule::unpack_number(slice) as usize; - if slice_len != total_size { - return ve!(Self, TotalSizeNotMatch, total_size, slice_len); - } - if slice_len == molecule::NUMBER_SIZE && Self::FIELD_COUNT == 0 { - return Ok(()); - } - if slice_len < molecule::NUMBER_SIZE * 2 { - return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); - } - let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; - if offset_first % 4 != 0 || offset_first < molecule::NUMBER_SIZE * 2 { - return ve!(Self, OffsetsNotMatch); - } - let field_count = offset_first / 4 - 1; - if field_count < Self::FIELD_COUNT { - return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); - } else if !compatible && field_count > Self::FIELD_COUNT { - return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); - }; - let header_size = molecule::NUMBER_SIZE * (field_count + 1); - if slice_len < header_size { - return ve!(Self, HeaderIsBroken, header_size, slice_len); - } - let mut offsets: Vec = slice[molecule::NUMBER_SIZE..] - .chunks(molecule::NUMBER_SIZE) - .take(field_count) - .map(|x| molecule::unpack_number(x) as usize) - .collect(); - offsets.push(total_size); - if offsets.windows(2).any(|i| i[0] > i[1]) { - return ve!(Self, OffsetsNotMatch); - } - Uint64Reader::verify(&slice[offsets[0]..offsets[1]], compatible)?; - BytesReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; - Uint64Reader::verify(&slice[offsets[2]..offsets[3]], compatible)?; - BytesReader::verify(&slice[offsets[3]..offsets[4]], compatible)?; - BytesReader::verify(&slice[offsets[4]..offsets[5]], compatible)?; - BytesReader::verify(&slice[offsets[5]..offsets[6]], compatible)?; - Bytes2Reader::verify(&slice[offsets[6]..offsets[7]], compatible)?; - Ok(()) - } -} -#[derive(Debug, Default)] -pub struct ETHSPVProofBuilder { - pub(crate) log_index: Uint64, - pub(crate) log_entry_data: Bytes, - pub(crate) receipt_index: Uint64, - pub(crate) receipt_data: Bytes, - pub(crate) receipts_root: Bytes, - pub(crate) header_data: Bytes, - pub(crate) proof: Bytes2, -} -impl ETHSPVProofBuilder { - pub const FIELD_COUNT: usize = 7; - pub fn log_index(mut self, v: Uint64) -> Self { - self.log_index = v; - self - } - pub fn log_entry_data(mut self, v: Bytes) -> Self { - self.log_entry_data = v; - self - } - pub fn receipt_index(mut self, v: Uint64) -> Self { - self.receipt_index = v; - self - } - pub fn receipt_data(mut self, v: Bytes) -> Self { - self.receipt_data = v; - self - } - pub fn receipts_root(mut self, v: Bytes) -> Self { - self.receipts_root = v; - self - } - pub fn header_data(mut self, v: Bytes) -> Self { - self.header_data = v; - self - } - pub fn proof(mut self, v: Bytes2) -> Self { - self.proof = v; - self - } -} -impl molecule::prelude::Builder for ETHSPVProofBuilder { - type Entity = ETHSPVProof; - const NAME: &'static str = "ETHSPVProofBuilder"; - fn expected_length(&self) -> usize { - molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) - + self.log_index.as_slice().len() - + self.log_entry_data.as_slice().len() - + self.receipt_index.as_slice().len() - + self.receipt_data.as_slice().len() - + self.receipts_root.as_slice().len() - + self.header_data.as_slice().len() - + self.proof.as_slice().len() - } - fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { - let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); - let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); - offsets.push(total_size); - total_size += self.log_index.as_slice().len(); - offsets.push(total_size); - total_size += self.log_entry_data.as_slice().len(); - offsets.push(total_size); - total_size += self.receipt_index.as_slice().len(); - offsets.push(total_size); - total_size += self.receipt_data.as_slice().len(); - offsets.push(total_size); - total_size += self.receipts_root.as_slice().len(); - offsets.push(total_size); - total_size += self.header_data.as_slice().len(); - offsets.push(total_size); - total_size += self.proof.as_slice().len(); - writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; - for offset in offsets.into_iter() { - writer.write_all(&molecule::pack_number(offset as molecule::Number))?; - } - writer.write_all(self.log_index.as_slice())?; - writer.write_all(self.log_entry_data.as_slice())?; - writer.write_all(self.receipt_index.as_slice())?; - writer.write_all(self.receipt_data.as_slice())?; - writer.write_all(self.receipts_root.as_slice())?; - writer.write_all(self.header_data.as_slice())?; - writer.write_all(self.proof.as_slice())?; - Ok(()) - } - fn build(&self) -> Self::Entity { - let mut inner = Vec::with_capacity(self.expected_length()); - self.write(&mut inner) - .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); - ETHSPVProof::new_unchecked(inner.into()) - } -} diff --git a/tests/src/toCKB_typescript/utils/types/generated/mod.rs b/tests/src/toCKB_typescript/utils/types/generated/mod.rs deleted file mode 100644 index 148def6..0000000 --- a/tests/src/toCKB_typescript/utils/types/generated/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -pub mod basic; -pub mod btc_difficulty; -pub mod mint_xt_witness; -pub mod toCKB_cell_data; - -pub use basic::*; -pub use toCKB_cell_data::*; diff --git a/tests/src/toCKB_typescript/utils/types/generated/toCKB_cell_data.rs b/tests/src/toCKB_typescript/utils/types/generated/toCKB_cell_data.rs deleted file mode 100644 index 2579507..0000000 --- a/tests/src/toCKB_typescript/utils/types/generated/toCKB_cell_data.rs +++ /dev/null @@ -1,7 +0,0 @@ -// Generated by Molecule 0.6.1 - -use molecule :: prelude :: * ; -use super :: basic :: * ; -# [ derive ( Clone ) ] pub struct ToCKBCellData ( molecule :: bytes :: Bytes ) ; impl :: core :: fmt :: LowerHex for ToCKBCellData { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl :: core :: fmt :: Debug for ToCKBCellData { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl :: core :: fmt :: Display for ToCKBCellData { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{} {{ " , Self :: NAME ) ? ; write ! ( f , "{}: {}" , "status" , self . status ( ) ) ? ; write ! ( f , ", {}: {}" , "lot_size" , self . lot_size ( ) ) ? ; write ! ( f , ", {}: {}" , "user_lockscript" , self . user_lockscript ( ) ) ? ; write ! ( f , ", {}: {}" , "x_lock_address" , self . x_lock_address ( ) ) ? ; write ! ( f , ", {}: {}" , "signer_lockscript" , self . signer_lockscript ( ) ) ? ; write ! ( f , ", {}: {}" , "x_unlock_address" , self . x_unlock_address ( ) ) ? ; write ! ( f , ", {}: {}" , "redeemer_lockscript" , self . redeemer_lockscript ( ) ) ? ; write ! ( f , ", {}: {}" , "liquidation_trigger_lockscript" , self . liquidation_trigger_lockscript ( ) ) ? ; let extra_count = self . count_extra_fields ( ) ; if extra_count != 0 { write ! ( f , ", .. ({} fields)" , extra_count ) ? ; } write ! ( f , " }}" ) } } impl :: core :: default :: Default for ToCKBCellData { fn default ( ) -> Self { let v : Vec < u8 > = vec ! [ 2 , 1 , 0 , 0 , 36 , 0 , 0 , 0 , 37 , 0 , 0 , 0 , 38 , 0 , 0 , 0 , 91 , 0 , 0 , 0 , 95 , 0 , 0 , 0 , 148 , 0 , 0 , 0 , 152 , 0 , 0 , 0 , 205 , 0 , 0 , 0 , 0 , 0 , 53 , 0 , 0 , 0 , 16 , 0 , 0 , 0 , 48 , 0 , 0 , 0 , 49 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 53 , 0 , 0 , 0 , 16 , 0 , 0 , 0 , 48 , 0 , 0 , 0 , 49 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 53 , 0 , 0 , 0 , 16 , 0 , 0 , 0 , 48 , 0 , 0 , 0 , 49 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 53 , 0 , 0 , 0 , 16 , 0 , 0 , 0 , 48 , 0 , 0 , 0 , 49 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , ] ; ToCKBCellData :: new_unchecked ( v . into ( ) ) } } impl ToCKBCellData { pub const FIELD_COUNT : usize = 8 ; pub fn total_size ( & self ) -> usize { molecule :: unpack_number ( self . as_slice ( ) ) as usize } pub fn field_count ( & self ) -> usize { if self . total_size ( ) == molecule :: NUMBER_SIZE { 0 } else { ( molecule :: unpack_number ( & self . as_slice ( ) [ molecule :: NUMBER_SIZE .. ] ) as usize / 4 ) - 1 } } pub fn count_extra_fields ( & self ) -> usize { self . field_count ( ) - Self :: FIELD_COUNT } pub fn has_extra_fields ( & self ) -> bool { Self :: FIELD_COUNT != self . field_count ( ) } pub fn status ( & self ) -> Byte { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 4 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; Byte :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn lot_size ( & self ) -> Byte { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; Byte :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn user_lockscript ( & self ) -> Script { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 16 .. ] ) as usize ; Script :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn x_lock_address ( & self ) -> Bytes { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 16 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 20 .. ] ) as usize ; Bytes :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn signer_lockscript ( & self ) -> Script { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 20 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 24 .. ] ) as usize ; Script :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn x_unlock_address ( & self ) -> Bytes { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 24 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 28 .. ] ) as usize ; Bytes :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn redeemer_lockscript ( & self ) -> Script { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 28 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 32 .. ] ) as usize ; Script :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn liquidation_trigger_lockscript ( & self ) -> Script { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 32 .. ] ) as usize ; if self . has_extra_fields ( ) { let end = molecule :: unpack_number ( & slice [ 36 .. ] ) as usize ; Script :: new_unchecked ( self . 0 . slice ( start .. end ) ) } else { Script :: new_unchecked ( self . 0 . slice ( start .. ) ) } } pub fn as_reader < 'r > ( & 'r self ) -> ToCKBCellDataReader < 'r > { ToCKBCellDataReader :: new_unchecked ( self . as_slice ( ) ) } } impl molecule :: prelude :: Entity for ToCKBCellData { type Builder = ToCKBCellDataBuilder ; const NAME : & 'static str = "ToCKBCellData" ; fn new_unchecked ( data : molecule :: bytes :: Bytes ) -> Self { ToCKBCellData ( data ) } fn as_bytes ( & self ) -> molecule :: bytes :: Bytes { self . 0 . clone ( ) } fn as_slice ( & self ) -> & [ u8 ] { & self . 0 [ .. ] } fn from_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { ToCKBCellDataReader :: from_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn from_compatible_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { ToCKBCellDataReader :: from_compatible_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn new_builder ( ) -> Self :: Builder { :: core :: default :: Default :: default ( ) } fn as_builder ( self ) -> Self :: Builder { Self :: new_builder ( ) . status ( self . status ( ) ) . lot_size ( self . lot_size ( ) ) . user_lockscript ( self . user_lockscript ( ) ) . x_lock_address ( self . x_lock_address ( ) ) . signer_lockscript ( self . signer_lockscript ( ) ) . x_unlock_address ( self . x_unlock_address ( ) ) . redeemer_lockscript ( self . redeemer_lockscript ( ) ) . liquidation_trigger_lockscript ( self . liquidation_trigger_lockscript ( ) ) } } -# [ derive ( Clone , Copy ) ] pub struct ToCKBCellDataReader < 'r > ( & 'r [ u8 ] ) ; impl < 'r > :: core :: fmt :: LowerHex for ToCKBCellDataReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl < 'r > :: core :: fmt :: Debug for ToCKBCellDataReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl < 'r > :: core :: fmt :: Display for ToCKBCellDataReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{} {{ " , Self :: NAME ) ? ; write ! ( f , "{}: {}" , "status" , self . status ( ) ) ? ; write ! ( f , ", {}: {}" , "lot_size" , self . lot_size ( ) ) ? ; write ! ( f , ", {}: {}" , "user_lockscript" , self . user_lockscript ( ) ) ? ; write ! ( f , ", {}: {}" , "x_lock_address" , self . x_lock_address ( ) ) ? ; write ! ( f , ", {}: {}" , "signer_lockscript" , self . signer_lockscript ( ) ) ? ; write ! ( f , ", {}: {}" , "x_unlock_address" , self . x_unlock_address ( ) ) ? ; write ! ( f , ", {}: {}" , "redeemer_lockscript" , self . redeemer_lockscript ( ) ) ? ; write ! ( f , ", {}: {}" , "liquidation_trigger_lockscript" , self . liquidation_trigger_lockscript ( ) ) ? ; let extra_count = self . count_extra_fields ( ) ; if extra_count != 0 { write ! ( f , ", .. ({} fields)" , extra_count ) ? ; } write ! ( f , " }}" ) } } impl < 'r > ToCKBCellDataReader < 'r > { pub const FIELD_COUNT : usize = 8 ; pub fn total_size ( & self ) -> usize { molecule :: unpack_number ( self . as_slice ( ) ) as usize } pub fn field_count ( & self ) -> usize { if self . total_size ( ) == molecule :: NUMBER_SIZE { 0 } else { ( molecule :: unpack_number ( & self . as_slice ( ) [ molecule :: NUMBER_SIZE .. ] ) as usize / 4 ) - 1 } } pub fn count_extra_fields ( & self ) -> usize { self . field_count ( ) - Self :: FIELD_COUNT } pub fn has_extra_fields ( & self ) -> bool { Self :: FIELD_COUNT != self . field_count ( ) } pub fn status ( & self ) -> ByteReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 4 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; ByteReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn lot_size ( & self ) -> ByteReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; ByteReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn user_lockscript ( & self ) -> ScriptReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 16 .. ] ) as usize ; ScriptReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn x_lock_address ( & self ) -> BytesReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 16 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 20 .. ] ) as usize ; BytesReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn signer_lockscript ( & self ) -> ScriptReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 20 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 24 .. ] ) as usize ; ScriptReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn x_unlock_address ( & self ) -> BytesReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 24 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 28 .. ] ) as usize ; BytesReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn redeemer_lockscript ( & self ) -> ScriptReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 28 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 32 .. ] ) as usize ; ScriptReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn liquidation_trigger_lockscript ( & self ) -> ScriptReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 32 .. ] ) as usize ; if self . has_extra_fields ( ) { let end = molecule :: unpack_number ( & slice [ 36 .. ] ) as usize ; ScriptReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } else { ScriptReader :: new_unchecked ( & self . as_slice ( ) [ start .. ] ) } } } impl < 'r > molecule :: prelude :: Reader < 'r > for ToCKBCellDataReader < 'r > { type Entity = ToCKBCellData ; const NAME : & 'static str = "ToCKBCellDataReader" ; fn to_entity ( & self ) -> Self :: Entity { Self :: Entity :: new_unchecked ( self . as_slice ( ) . to_owned ( ) . into ( ) ) } fn new_unchecked ( slice : & 'r [ u8 ] ) -> Self { ToCKBCellDataReader ( slice ) } fn as_slice ( & self ) -> & 'r [ u8 ] { self . 0 } fn verify ( slice : & [ u8 ] , compatible : bool ) -> molecule :: error :: VerificationResult < ( ) > { use molecule :: verification_error as ve ; let slice_len = slice . len ( ) ; if slice_len < molecule :: NUMBER_SIZE { return ve ! ( Self , HeaderIsBroken , molecule :: NUMBER_SIZE , slice_len ) ; } let total_size = molecule :: unpack_number ( slice ) as usize ; if slice_len != total_size { return ve ! ( Self , TotalSizeNotMatch , total_size , slice_len ) ; } if slice_len == molecule :: NUMBER_SIZE && Self :: FIELD_COUNT == 0 { return Ok ( ( ) ) ; } if slice_len < molecule :: NUMBER_SIZE * 2 { return ve ! ( Self , HeaderIsBroken , molecule :: NUMBER_SIZE * 2 , slice_len ) ; } let offset_first = molecule :: unpack_number ( & slice [ molecule :: NUMBER_SIZE .. ] ) as usize ; if offset_first % 4 != 0 || offset_first < molecule :: NUMBER_SIZE * 2 { return ve ! ( Self , OffsetsNotMatch ) ; } let field_count = offset_first / 4 - 1 ; if field_count < Self :: FIELD_COUNT { return ve ! ( Self , FieldCountNotMatch , Self :: FIELD_COUNT , field_count ) ; } else if ! compatible && field_count > Self :: FIELD_COUNT { return ve ! ( Self , FieldCountNotMatch , Self :: FIELD_COUNT , field_count ) ; } ; let header_size = molecule :: NUMBER_SIZE * ( field_count + 1 ) ; if slice_len < header_size { return ve ! ( Self , HeaderIsBroken , header_size , slice_len ) ; } let mut offsets : Vec < usize > = slice [ molecule :: NUMBER_SIZE .. ] . chunks ( molecule :: NUMBER_SIZE ) . take ( field_count ) . map ( | x | molecule :: unpack_number ( x ) as usize ) . collect ( ) ; offsets . push ( total_size ) ; if offsets . windows ( 2 ) . any ( | i | i [ 0 ] > i [ 1 ] ) { return ve ! ( Self , OffsetsNotMatch ) ; } ByteReader :: verify ( & slice [ offsets [ 0 ] .. offsets [ 1 ] ] , compatible ) ? ; ByteReader :: verify ( & slice [ offsets [ 1 ] .. offsets [ 2 ] ] , compatible ) ? ; ScriptReader :: verify ( & slice [ offsets [ 2 ] .. offsets [ 3 ] ] , compatible ) ? ; BytesReader :: verify ( & slice [ offsets [ 3 ] .. offsets [ 4 ] ] , compatible ) ? ; ScriptReader :: verify ( & slice [ offsets [ 4 ] .. offsets [ 5 ] ] , compatible ) ? ; BytesReader :: verify ( & slice [ offsets [ 5 ] .. offsets [ 6 ] ] , compatible ) ? ; ScriptReader :: verify ( & slice [ offsets [ 6 ] .. offsets [ 7 ] ] , compatible ) ? ; ScriptReader :: verify ( & slice [ offsets [ 7 ] .. offsets [ 8 ] ] , compatible ) ? ; Ok ( ( ) ) } } -# [ derive ( Debug , Default ) ] pub struct ToCKBCellDataBuilder { pub ( crate ) status : Byte , pub ( crate ) lot_size : Byte , pub ( crate ) user_lockscript : Script , pub ( crate ) x_lock_address : Bytes , pub ( crate ) signer_lockscript : Script , pub ( crate ) x_unlock_address : Bytes , pub ( crate ) redeemer_lockscript : Script , pub ( crate ) liquidation_trigger_lockscript : Script , } impl ToCKBCellDataBuilder { pub const FIELD_COUNT : usize = 8 ; pub fn status ( mut self , v : Byte ) -> Self { self . status = v ; self } pub fn lot_size ( mut self , v : Byte ) -> Self { self . lot_size = v ; self } pub fn user_lockscript ( mut self , v : Script ) -> Self { self . user_lockscript = v ; self } pub fn x_lock_address ( mut self , v : Bytes ) -> Self { self . x_lock_address = v ; self } pub fn signer_lockscript ( mut self , v : Script ) -> Self { self . signer_lockscript = v ; self } pub fn x_unlock_address ( mut self , v : Bytes ) -> Self { self . x_unlock_address = v ; self } pub fn redeemer_lockscript ( mut self , v : Script ) -> Self { self . redeemer_lockscript = v ; self } pub fn liquidation_trigger_lockscript ( mut self , v : Script ) -> Self { self . liquidation_trigger_lockscript = v ; self } } impl molecule :: prelude :: Builder for ToCKBCellDataBuilder { type Entity = ToCKBCellData ; const NAME : & 'static str = "ToCKBCellDataBuilder" ; fn expected_length ( & self ) -> usize { molecule :: NUMBER_SIZE * ( Self :: FIELD_COUNT + 1 ) + self . status . as_slice ( ) . len ( ) + self . lot_size . as_slice ( ) . len ( ) + self . user_lockscript . as_slice ( ) . len ( ) + self . x_lock_address . as_slice ( ) . len ( ) + self . signer_lockscript . as_slice ( ) . len ( ) + self . x_unlock_address . as_slice ( ) . len ( ) + self . redeemer_lockscript . as_slice ( ) . len ( ) + self . liquidation_trigger_lockscript . as_slice ( ) . len ( ) } fn write < W : :: molecule :: io :: Write > ( & self , writer : & mut W ) -> :: molecule :: io :: Result < ( ) > { let mut total_size = molecule :: NUMBER_SIZE * ( Self :: FIELD_COUNT + 1 ) ; let mut offsets = Vec :: with_capacity ( Self :: FIELD_COUNT ) ; offsets . push ( total_size ) ; total_size += self . status . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . lot_size . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . user_lockscript . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . x_lock_address . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . signer_lockscript . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . x_unlock_address . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . redeemer_lockscript . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . liquidation_trigger_lockscript . as_slice ( ) . len ( ) ; writer . write_all ( & molecule :: pack_number ( total_size as molecule :: Number ) ) ? ; for offset in offsets . into_iter ( ) { writer . write_all ( & molecule :: pack_number ( offset as molecule :: Number ) ) ? ; } writer . write_all ( self . status . as_slice ( ) ) ? ; writer . write_all ( self . lot_size . as_slice ( ) ) ? ; writer . write_all ( self . user_lockscript . as_slice ( ) ) ? ; writer . write_all ( self . x_lock_address . as_slice ( ) ) ? ; writer . write_all ( self . signer_lockscript . as_slice ( ) ) ? ; writer . write_all ( self . x_unlock_address . as_slice ( ) ) ? ; writer . write_all ( self . redeemer_lockscript . as_slice ( ) ) ? ; writer . write_all ( self . liquidation_trigger_lockscript . as_slice ( ) ) ? ; Ok ( ( ) ) } fn build ( & self ) -> Self :: Entity { let mut inner = Vec :: with_capacity ( self . expected_length ( ) ) ; self . write ( & mut inner ) . unwrap_or_else ( | _ | panic ! ( "{} build should be ok" , Self :: NAME ) ) ; ToCKBCellData :: new_unchecked ( inner . into ( ) ) } } diff --git a/tests/src/toCKB_typescript/utils/types/mod.rs b/tests/src/toCKB_typescript/utils/types/mod.rs deleted file mode 100644 index 6247374..0000000 --- a/tests/src/toCKB_typescript/utils/types/mod.rs +++ /dev/null @@ -1,69 +0,0 @@ -pub mod convert; -pub mod generated; - -#[repr(i8)] -pub enum Error { - IndexOutOfBound = 1, - ItemMissing, - LengthNotEnough, - Encoding, - // Add customized errors here... - XChainMismatch, - TxInvalid, - LotSizeInvalid, - PledgeInvalid, - // MintXT Error - InvalidDataChange, - InvalidWitness, - DifficultyDataInvalid, - SpvProofInvalid, - InsufficientDifficulty, - BadMerkleProof, - NotAtCurrentOrPreviousDifficulty, - WrongTxId, - FundingNotEnough, - UnsupportedFundingType, - InvalidMintOutput, - WrongFundingAddr, - InvalidXTInInputOrOutput, - InvalidXTMint, - - CapacityInvalid, - InvariantDataMutated, - InputSinceInvalid, -} - -#[repr(u8)] -pub enum ToCKBStatus { - Initial = 1, - Bonded = 2, - Warranty = 3, - Redeeming = 4, - SignerTimeout = 5, - Undercollateral = 6, - FaultyWhenWarranty = 7, - FaultyWhenRedeeming = 8, -} - -#[repr(u8)] -pub enum BtcLotSize { - Quarter = 1, - Half = 2, - Single = 3, -} - -#[repr(u8)] -pub enum EthLotSize { - Quarter = 1, - Half = 2, - Single = 3, - Two = 4, - Three = 5, - Four = 6, -} - -#[repr(u8)] -pub enum XChainKind { - Btc = 1, - Eth = 2, -} From 6fda51994ee1823a1efff2ef185efe7319cfcc04 Mon Sep 17 00:00:00 2001 From: LeonLi000 Date: Mon, 28 Sep 2020 15:23:11 +0800 Subject: [PATCH 41/45] add comment --- contracts/toCKB-typescript/src/utils/tools.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/contracts/toCKB-typescript/src/utils/tools.rs b/contracts/toCKB-typescript/src/utils/tools.rs index 2868ae6..90aef2d 100644 --- a/contracts/toCKB-typescript/src/utils/tools.rs +++ b/contracts/toCKB-typescript/src/utils/tools.rs @@ -195,6 +195,7 @@ pub fn verify_btc_witness( } } +/// Verify that the header of the user's cross-chain tx is on the main chain. pub fn verify_header_is_on_main_chain( header: &BlockHeader, cell_dep_index_list: &[u8], @@ -241,6 +242,13 @@ pub fn verify_header_is_on_main_chain( Ok(()) } +/// Verify eth witness data. +/// 1. Verify that the header of the user's cross-chain tx is on the main chain. +/// 2. Verify that the user's cross-chain transaction is legal and really exists (based spv proof). +/// @param data is used to get the real lock address. +/// @param proof is the spv proof data for cross-chain tx. +/// @param cell_dep_index_list is used to get the headers oracle information to verify the cross-chain tx is really exists on the main chain. +/// pub fn verify_eth_witness( data: &ToCKBCellDataView, proof: &[u8], @@ -290,6 +298,7 @@ pub fn verify_eth_witness( { return Err(Error::WrongFundingAddr); } + // verify the spv proof is valid. if !ethspv::verify_log_entry( u64::from_le_bytes(log_index), log_entry_data, @@ -300,9 +309,7 @@ pub fn verify_eth_witness( ) { return Err(Error::BadMerkleProof); } - Ok(EthExtraView { - // dummy: Default::default(), - }) + Ok(EthExtraView {}) } pub fn verify_btc_faulty_witness( From f7004921088f9420587d20a512cbcb0f3f3a1804 Mon Sep 17 00:00:00 2001 From: LeonLi000 Date: Mon, 28 Sep 2020 18:14:50 +0800 Subject: [PATCH 42/45] fix: use nervos cdk-std --- Cargo.lock | 8 ++--- contracts/toCKB-typescript/Cargo.lock | 42 +++++++++++++-------------- contracts/toCKB-typescript/Cargo.toml | 3 +- types/Cargo.toml | 4 +-- 4 files changed, 27 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3665883..0879d88 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -636,8 +636,8 @@ dependencies = [ [[package]] name = "ckb-std" -version = "0.6.2" -source = "git+https://github.com/LeonLi000/ckb-std.git#de3b859609462b6ca93bf7cf6ecafc3a0eb44035" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", "ckb-allocator 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3181,7 +3181,7 @@ version = "0.1.0" dependencies = [ "bitcoin-spv 5.0.0 (git+https://github.com/summa-tx/bitcoin-spv.git?branch=rust/dep-change)", "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "ckb-std 0.6.2 (git+https://github.com/LeonLi000/ckb-std.git)", + "ckb-std 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "ckb-types 0.34.1 (git+https://github.com/nervosnetwork/ckb?tag=v0.34.1)", "int-enum 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "molecule 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3804,7 +3804,7 @@ dependencies = [ "checksum ckb-script 0.34.1 (git+https://github.com/nervosnetwork/ckb?tag=v0.34.1)" = "" "checksum ckb-script-data-loader 0.34.1 (git+https://github.com/nervosnetwork/ckb?tag=v0.34.1)" = "" "checksum ckb-standalone-types 0.0.1-pre.1 (registry+https://github.com/rust-lang/crates.io-index)" = "af2cdbdf65ee5b1da71504f5a03d6984bce77d0b4b46daff63f4ba4a3b0eef08" -"checksum ckb-std 0.6.2 (git+https://github.com/LeonLi000/ckb-std.git)" = "" +"checksum ckb-std 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f40fb1a5a0049abb71ff043629517089ef256b8e63c403b9359f73b7040ac9c6" "checksum ckb-store 0.34.1 (git+https://github.com/nervosnetwork/ckb?tag=v0.34.1)" = "" "checksum ckb-system-scripts 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "261dd95a93c09ea24397c85b4fbca061e1da2d6573189749aeb99fe840aaf0c9" "checksum ckb-testtool 0.1.3 (git+https://github.com/jjyr/ckb-tool.git?tag=v0.1.3)" = "" diff --git a/contracts/toCKB-typescript/Cargo.lock b/contracts/toCKB-typescript/Cargo.lock index feec926..c915e4b 100644 --- a/contracts/toCKB-typescript/Cargo.lock +++ b/contracts/toCKB-typescript/Cargo.lock @@ -65,7 +65,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cc" -version = "1.0.59" +version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -92,10 +92,10 @@ dependencies = [ [[package]] name = "ckb-std" -version = "0.6.2" -source = "git+https://github.com/LeonLi000/ckb-std.git#de3b859609462b6ca93bf7cf6ecafc3a0eb44035" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.59 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.60 (registry+https://github.com/rust-lang/crates.io-index)", "ckb-allocator 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "ckb-standalone-types 0.0.1-pre.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -110,9 +110,9 @@ name = "derive_more" version = "0.99.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -134,7 +134,7 @@ dependencies = [ [[package]] name = "eth-spv-lib" version = "0.1.0" -source = "git+https://github.com/LeonLi000/eth-spv-lib.git#e11c40ef692601967faacf52665e82de687a8a30" +source = "git+https://github.com/LeonLi000/eth-spv-lib.git#1f8c2d3b75cf2e10bcc65d7e82ad6449a93b0f94" dependencies = [ "derive_more 0.99.10 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -228,9 +228,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro-crate 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -276,7 +276,7 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.21" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -287,7 +287,7 @@ name = "quote" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -313,9 +313,9 @@ name = "rlp-derive" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -357,10 +357,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "1.0.41" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -379,7 +379,7 @@ version = "0.1.0" dependencies = [ "bech32 0.7.2 (git+https://github.com/reuvenpo/rust-bech32.git?branch=support-no_std)", "bitcoin-spv 5.0.0 (git+https://github.com/summa-tx/bitcoin-spv.git?branch=rust/dep-change)", - "ckb-std 0.6.2 (git+https://github.com/LeonLi000/ckb-std.git)", + "ckb-std 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "eth-spv-lib 0.1.0 (git+https://github.com/LeonLi000/eth-spv-lib.git)", "hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "int-enum 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -395,7 +395,7 @@ version = "0.1.0" dependencies = [ "bitcoin-spv 5.0.0 (git+https://github.com/summa-tx/bitcoin-spv.git?branch=rust/dep-change)", "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "ckb-std 0.6.2 (git+https://github.com/LeonLi000/ckb-std.git)", + "ckb-std 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "int-enum 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "molecule 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -444,11 +444,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum buddy-alloc 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efba9eaa9fdf9fddf408904e3dc3dc414411053ef48c06edd3aac53d2d919e0e" "checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" "checksum byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" -"checksum cc 1.0.59 (registry+https://github.com/rust-lang/crates.io-index)" = "66120af515773fb005778dc07c261bd201ec8ce50bd6e7144c927753fe013381" +"checksum cc 1.0.60 (registry+https://github.com/rust-lang/crates.io-index)" = "ef611cc68ff783f18535d77ddd080185275713d852c4f5cbb6122c462a7a825c" "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" "checksum ckb-allocator 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "572ce0405d93e105d547f6d362c70c4b744e5e0984f9b9877c81afd070c8e2cc" "checksum ckb-standalone-types 0.0.1-pre.1 (registry+https://github.com/rust-lang/crates.io-index)" = "af2cdbdf65ee5b1da71504f5a03d6984bce77d0b4b46daff63f4ba4a3b0eef08" -"checksum ckb-std 0.6.2 (git+https://github.com/LeonLi000/ckb-std.git)" = "" +"checksum ckb-std 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f40fb1a5a0049abb71ff043629517089ef256b8e63c403b9359f73b7040ac9c6" "checksum crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" "checksum derive_more 0.99.10 (registry+https://github.com/rust-lang/crates.io-index)" = "1dcfabdab475c16a93d669dddfc393027803e347d09663f524447f642fbb84ba" "checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" @@ -470,7 +470,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum opaque-debug 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" "checksum primitive-types 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c55c21c64d0eaa4d7ed885d959ef2d62d9e488c27c0e02d9aa5ce6c877b7d5f8" "checksum proc-macro-crate 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" -"checksum proc-macro2 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)" = "36e28516df94f3dd551a587da5357459d9b36d945a7c37c3557928c1c2ff2a2c" +"checksum proc-macro2 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)" = "51ef7cd2518ead700af67bf9d1a658d90b6037d77110fd9c0445429d0ba1c6c9" "checksum quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" "checksum ripemd160 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad5112e0dbbb87577bfbc56c42450235e3012ce336e29c5befd7807bd626da4a" "checksum rlp 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4a7d3f9bed94764eac15b8f14af59fac420c236adaff743b7bcc88e265cb4345" @@ -480,7 +480,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum sha2 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" "checksum sha3 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" "checksum static_assertions 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" -"checksum syn 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "6690e3e9f692504b941dc6c3b188fd28df054f7fb8469ab40680df52fdcc842b" +"checksum syn 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)" = "9c51d92969d209b54a98397e1b91c8ae82d8c87a7bb87df0b29aa2ad81454228" "checksum tiny-keccak 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" "checksum toml 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a" "checksum typenum 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" diff --git a/contracts/toCKB-typescript/Cargo.toml b/contracts/toCKB-typescript/Cargo.toml index 0245f06..626fce3 100644 --- a/contracts/toCKB-typescript/Cargo.toml +++ b/contracts/toCKB-typescript/Cargo.toml @@ -6,8 +6,7 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -ckb-std = { git = "https://github.com/LeonLi000/ckb-std.git"} -#ckb-std = "0.6.0" +ckb-std = "0.6" molecule = { version = "0.6.1", default-features = false } int-enum = { version = "0.4", default-features = false } bitcoin-spv = { git = "https://github.com/summa-tx/bitcoin-spv.git", branch = "rust/dep-change", default-features = false } diff --git a/types/Cargo.toml b/types/Cargo.toml index ec80917..bece9eb 100644 --- a/types/Cargo.toml +++ b/types/Cargo.toml @@ -14,8 +14,6 @@ contract = ["ckb-std", "bitcoin-spv"] molecule = { version = "0.6", default-features = false } int-enum = { version = "0.4", default-features = false } cfg-if = "0.1" -#ckb-std = { version = "0.6", optional = true } -ckb-std = { git = "https://github.com/LeonLi000/ckb-std.git", optional = true } -#ckb-std = { version = "0.6", optional = true } +ckb-std = { version = "0.6", optional = true } ckb-types = { git = "https://github.com/nervosnetwork/ckb", tag = "v0.34.1", optional = true } bitcoin-spv = { git = "https://github.com/summa-tx/bitcoin-spv.git", branch = "rust/dep-change", default-features = false, optional = true } From 24e77d00837ccf710ebb10e2b2999c6118de9b4f Mon Sep 17 00:00:00 2001 From: LeonLi000 Date: Mon, 28 Sep 2020 19:46:09 +0800 Subject: [PATCH 43/45] format code --- contracts/toCKB-typescript/src/utils/tools.rs | 12 +- .../toCKB-typescript/src/utils/tools.rs.bak | 521 ------------ .../toCKB_typescript/utils/case_builder.rs | 5 +- types/Makefile | 1 + types/schemas/eth_header_cell_data.mol | 16 + types/schemas/tockb_cell_data.mol | 15 - types/src/error.rs | 2 + types/src/generated/eth_header_cell_data.rs | 13 + types/src/generated/mod.rs | 1 + types/src/generated/tockb_cell_data.rs | 796 ------------------ 10 files changed, 42 insertions(+), 1340 deletions(-) delete mode 100644 contracts/toCKB-typescript/src/utils/tools.rs.bak create mode 100644 types/schemas/eth_header_cell_data.mol create mode 100644 types/src/generated/eth_header_cell_data.rs diff --git a/contracts/toCKB-typescript/src/utils/tools.rs b/contracts/toCKB-typescript/src/utils/tools.rs index 90aef2d..26b9e6c 100644 --- a/contracts/toCKB-typescript/src/utils/tools.rs +++ b/contracts/toCKB-typescript/src/utils/tools.rs @@ -26,7 +26,7 @@ use hex; use molecule::prelude::Reader; use primitive_types::U256; use tockb_types::generated::basic::OutPoint; -use tockb_types::generated::tockb_cell_data::{EthCellDataReader, HeaderInfoReader}; +use tockb_types::generated::eth_header_cell_data::{EthCellDataReader, HeaderInfoReader}; pub use tockb_types::tockb_cell::{ToCKBTypeArgsView, XChainKind}; pub fn get_toCKB_type_args() -> Result { @@ -196,7 +196,7 @@ pub fn verify_btc_witness( } /// Verify that the header of the user's cross-chain tx is on the main chain. -pub fn verify_header_is_on_main_chain( +pub fn verify_eth_header_on_main_chain( header: &BlockHeader, cell_dep_index_list: &[u8], ) -> Result<(), Error> { @@ -217,7 +217,7 @@ pub fn verify_header_is_on_main_chain( } let tail_info_reader = HeaderInfoReader::new_unchecked(tail_raw); let tail_info_raw = tail_info_reader.header().raw_data(); - let tail: BlockHeader = rlp::decode(tail_info_raw.to_vec().as_slice()).unwrap(); + let tail: BlockHeader = rlp::decode(tail_info_raw.to_vec().as_slice()).expect("invalid tail info."); if header.number > tail.number { return Err(Error::HeaderIsNotOnMainChain); } @@ -261,7 +261,7 @@ pub fn verify_eth_witness( let header_data = proof_reader.header_data().raw_data().to_vec(); let header: BlockHeader = rlp::decode(header_data.as_slice()).expect("invalid header data"); //verify the header is on main chain. - verify_header_is_on_main_chain(&header, cell_dep_index_list)?; + verify_eth_header_on_main_chain(&header, cell_dep_index_list)?; let mut log_index = [0u8; 8]; log_index.copy_from_slice(proof_reader.log_index().raw_data()); @@ -283,9 +283,9 @@ pub fn verify_eth_witness( for i in 0..proof_reader.proof().len() { proof.push(proof_reader.proof().get_unchecked(i).raw_data().to_vec()); } - let log_entry: LogEntry = rlp::decode(log_entry_data.as_slice()).unwrap(); + let log_entry: LogEntry = rlp::decode(log_entry_data.as_slice()).map_err(|_e| Error::LogEntryInvalid)?; debug!("log_entry is {:?}", &log_entry); - let receipt: Receipt = rlp::decode(receipt_data.as_slice()).unwrap(); + let receipt: Receipt = rlp::decode(receipt_data.as_slice()).map_err(|_e| Error::ReceiptInvalid)?; debug!("receipt_data is {:?}", &receipt); let locker_address = (log_entry.address.clone().0).0; debug!( diff --git a/contracts/toCKB-typescript/src/utils/tools.rs.bak b/contracts/toCKB-typescript/src/utils/tools.rs.bak deleted file mode 100644 index f50812c..0000000 --- a/contracts/toCKB-typescript/src/utils/tools.rs.bak +++ /dev/null @@ -1,521 +0,0 @@ -use crate::utils::{ - config::{SUDT_CODE_HASH, TX_PROOF_DIFFICULTY_FACTOR, UDT_LEN}, - types::{ - btc_difficulty::BTCDifficultyReader, mint_xt_witness::BTCSPVProofReader, mint_xt_witness::ETHSPVProofReader, BtcExtraView, EthExtraView, - Error, ToCKBCellDataView, XExtraView, - }, -}; -use alloc::{string::String, vec, vec::Vec}; - -use bech32::ToBase32; -use bitcoin_spv::{ - btcspv, - types::{HeaderArray, MerkleArray, PayloadType, Vin, Vout}, - validatespv, -}; -use ckb_std::{ - ckb_constants::Source, - ckb_types::{bytes::Bytes, packed::Script}, - debug, - high_level::{load_cell_capacity, load_cell_data, load_cell_type, load_script}, -}; -use core::{convert::From, result::Result}; -use molecule::prelude::Reader; -use primitive_types::U256; -use tockb_types::generated::basic::OutPoint; -pub use tockb_types::tockb_cell::{ToCKBTypeArgsView, XChainKind}; -use eth_spv_lib::{eth_types::*, ethspv}; -use tockb_types::generated::tockb_cell_data::{EthCellDataReader, HeaderInfoReader}; -use hex; - -pub fn get_toCKB_type_args() -> Result { - let toCKB_type_args = load_script()?.args().raw_data(); - debug!("before molecule decode toCKB type args"); - let toCKB_type_args = ToCKBTypeArgsView::from_slice(toCKB_type_args.as_ref())?; - debug!("molecule decode toCKB type args succ"); - Ok(toCKB_type_args) -} - -pub fn get_xchain_kind() -> Result { - Ok(get_toCKB_type_args()?.xchain_kind) -} - -pub fn get_cell_id() -> Result { - Ok(get_toCKB_type_args()?.cell_id) -} - -pub fn get_price() -> Result { - let price_cell_data = load_cell_data(0, Source::CellDep)?; - if price_cell_data.len() != 16 { - return Err(Error::Encoding); - } - let mut buf = [0u8; 16]; - buf.copy_from_slice(&price_cell_data); - let price: u128 = u128::from_le_bytes(buf); - Ok(price) -} - -pub fn check_capacity() -> Result<(), Error> { - let input_capacity = load_cell_capacity(0, Source::GroupInput)?; - let output_capacity = load_cell_capacity(0, Source::GroupOutput)?; - if input_capacity != output_capacity { - return Err(Error::CapacityInvalid); - } - Ok(()) -} - -pub fn is_XT_typescript(script: &Script, toCKB_lock_hash: &[u8]) -> bool { - if script.code_hash().raw_data().as_ref() == SUDT_CODE_HASH.as_ref() - && script.args().raw_data().as_ref() == toCKB_lock_hash - && script.hash_type() == 0u8.into() - { - return true; - } - false -} - -pub fn get_sum_sudt_amount( - start_index: usize, - source: Source, - toCKB_lock_hash: &[u8], -) -> Result { - let mut index = start_index; - let mut sum_amount = 0; - loop { - let res = load_cell_type(index, source); - if res.is_err() { - break; - } - let script = res.unwrap(); - if script.is_none() || !is_XT_typescript(&script.unwrap(), toCKB_lock_hash) { - continue; - } - - let cell_data = load_cell_data(index, source)?; - let mut data = [0u8; UDT_LEN]; - data.copy_from_slice(&cell_data); - let amount = u128::from_le_bytes(data); - sum_amount += amount; - - index += 1; - } - - Ok(sum_amount) -} - -pub fn verify_btc_witness( - _data: &ToCKBCellDataView, - proof: &[u8], - cell_dep_index_list: &[u8], - expect_address: &[u8], - expect_value: u128, - is_return_vin: bool, -) -> Result { - debug!( - "proof: {:?}, cell_dep_index_list: {:?}", - proof, cell_dep_index_list - ); - // parse difficulty - if cell_dep_index_list.len() != 1 { - return Err(Error::InvalidWitness); - } - let dep_data = load_cell_data(cell_dep_index_list[0].into(), Source::CellDep)?; - debug!("dep data is {:?}", &dep_data); - if BTCDifficultyReader::verify(&dep_data, false).is_err() { - return Err(Error::DifficultyDataInvalid); - } - let difficulty_reader = BTCDifficultyReader::new_unchecked(&dep_data); - debug!("difficulty_reader: {:?}", difficulty_reader); - // parse witness - if BTCSPVProofReader::verify(proof, false).is_err() { - return Err(Error::InvalidWitness); - } - let proof_reader = BTCSPVProofReader::new_unchecked(proof); - debug!("proof_reader: {:?}", proof_reader); - - // verify btc spv - let tx_hash = verify_btc_spv(proof_reader, difficulty_reader)?; - - // verify transfer amount, to matches - let funding_output_index = proof_reader.funding_output_index().into(); - - let vout = Vout::new(proof_reader.vout().raw_data())?; - let tx_out = vout.index(funding_output_index as usize)?; - let script_pubkey = tx_out.script_pubkey(); - debug!("script_pubkey payload: {:?}", script_pubkey.payload()?); - match script_pubkey.payload()? { - PayloadType::WPKH(pkh) => { - let mut addr_u5 = Vec::with_capacity(33); - addr_u5.push(bech32::u5::try_from_u8(0).unwrap()); - addr_u5.extend(pkh.to_base32()); - debug!("addr_u5: {:?}", &addr_u5); - let addr = - bech32::encode("bc", addr_u5).expect("bech32 encode should not return error"); - debug!( - "hex format: addr: {}, expect_address: {}", - hex::encode(addr.as_bytes().to_vec()), - hex::encode(expect_address.as_ref().to_vec()) - ); - debug!( - "addr: {}, expect_address: {}", - String::from_utf8(addr.as_bytes().to_vec()).unwrap(), - String::from_utf8(expect_address.as_ref().to_vec()).unwrap() - ); - if addr.as_bytes() != expect_address { - return Err(Error::WrongFundingAddr); - } - } - _ => return Err(Error::UnsupportedFundingType), - } - - let value = tx_out.value() as u128; - debug!("actual value: {}, expect: {}", value, expect_value); - if value < expect_value { - return Err(Error::FundingNotEnough); - } - if is_return_vin { - let funding_input_index: u32 = proof_reader.funding_input_index().into(); - let vin = Vin::new(proof_reader.vin().raw_data())?; - let tx_in = vin.index(funding_input_index as usize)?; - debug!( - "vin tx_id {}", - hex::encode(tx_in.outpoint().txid_le().as_ref().as_ref()) - ); - debug!("vin output index {}", tx_in.outpoint().vout_index()); - Ok(BtcExtraView { - lock_tx_hash: tx_in.outpoint().txid_le().as_ref().as_ref().into(), - lock_vout_index: tx_in.outpoint().vout_index(), - }) - } else { - Ok(BtcExtraView { - lock_tx_hash: tx_hash, - lock_vout_index: funding_output_index, - }) - } -} - -pub fn verify_header_main_chain(header: &BlockHeader, cell_dep_index_list: &[u8]) -> Result<(), Error> { - let dep_data = load_cell_data(cell_dep_index_list[0].into(), Source::CellDep)?; - debug!("dep data is {:?}", &dep_data); - if EthCellDataReader::verify(&dep_data, false).is_err() { - return Err(Error::EthHeadersDataInvalid); - } - let eth_cell_data_reader = EthCellDataReader::new_unchecked(&dep_data); - debug!("eth_cell_data_reader: {:?}", eth_cell_data_reader); - let tail_raw = eth_cell_data_reader.headers().main().get_unchecked(0).raw_data(); - if HeaderInfoReader::verify(&tail_raw, false).is_err() { - return Err(Error::EthHeadersDataInvalid); - } - let tail_info_reader = HeaderInfoReader::new_unchecked(tail_raw); - let tail_info_raw = tail_info_reader.header().raw_data(); - let tail: BlockHeader = rlp::decode(tail_info_raw.to_vec().as_slice()).unwrap(); - if header.number > tail.number { - return Err(Error::EthHeadersDataInvalid); - } - let offset = (tail.number - header.number) as usize; - let target_raw = eth_cell_data_reader.headers().main().get_unchecked(eth_cell_data_reader.headers().main().len()-1-offset).raw_data(); - let target_info_reader = HeaderInfoReader::new_unchecked(target_raw); - // let main_chain_hash = target_info_reader.hash().raw_data(); - // let witness_hash = header.hash.expect("invalid hash").0.as_bytes(); - debug!("main chain hash: {:?}, witness header hash: {:?}", hex::encode(target_info_reader.hash().raw_data()), hex::encode(header.hash.expect("invalid hash").0.as_bytes())); - if target_info_reader.hash().raw_data() != header.hash.expect("invalid hash").0.as_bytes() { - return Err(Error::HeaderIsNotOnMainChain); - } - Ok(()) -} - -pub fn verify_eth_witness( - data: &ToCKBCellDataView, - proof: &[u8], - cell_dep_index_list: &[u8], -) -> Result { - debug!( - "proof: {:?}, cell_dep_index_list: {:?}", - proof, cell_dep_index_list - ); - if ETHSPVProofReader::verify(proof, false).is_err() { - return Err(Error::InvalidWitness); - } - let proof_reader = ETHSPVProofReader::new_unchecked(proof); - debug!("proof_reader: {:?}", proof_reader); - let header_data = proof_reader.header_data().raw_data().to_vec(); - let header: BlockHeader = rlp::decode(header_data.as_slice()).expect("invalid header data"); - //verify the header is on main chain. - // verify_header_main_chain(&header, cell_dep_index_list)?; - let dep_data = load_cell_data(cell_dep_index_list[0].into(), Source::CellDep)?; - debug!("dep data is {:?}", &dep_data); - if EthCellDataReader::verify(&dep_data, false).is_err() { - return Err(Error::EthHeadersDataInvalid); - } - let eth_cell_data_reader = EthCellDataReader::new_unchecked(&dep_data); - debug!("eth_cell_data_reader: {:?}", eth_cell_data_reader); - let tail_raw = eth_cell_data_reader.headers().main().get_unchecked(0).raw_data(); - if HeaderInfoReader::verify(&tail_raw, false).is_err() { - return Err(Error::EthHeadersDataInvalid); - } - let tail_info_reader = HeaderInfoReader::new_unchecked(tail_raw); - let tail_info_raw = tail_info_reader.header().raw_data(); - let tail: BlockHeader = rlp::decode(tail_info_raw.to_vec().as_slice()).unwrap(); - if &tail.hash != &header.hash { - return Err(Error::HeaderIsNotOnMainChain); - } - let mut log_index = [0u8; 8]; - log_index.copy_from_slice(proof_reader.log_index().raw_data()); - debug!("log_index is {:?}", &log_index); - let log_entry_data = proof_reader.log_entry_data().raw_data().to_vec(); - debug!("log_entry_data is {:?}", &log_entry_data); - let receipt_data = proof_reader.receipt_data().raw_data().to_vec(); - debug!("receipt_data is {:?}", &receipt_data); - let mut receipt_index = [0u8; 8]; - receipt_index.copy_from_slice(proof_reader.receipt_index().raw_data()); - debug!("receipt_index is {:?}", &receipt_index); - let mut proof = vec![]; - for i in 0..proof_reader.proof().len() { - proof.push(proof_reader.proof().get_unchecked(i).raw_data().to_vec()); - } - debug!("proof is {:?}", &proof); - let log_entry: LogEntry = rlp::decode(log_entry_data.as_slice()).unwrap(); - debug!("log_entry is {:?}", &log_entry); - let receipt: Receipt = rlp::decode(receipt_data.as_slice()).unwrap(); - debug!("receipt_data is {:?}", &receipt); - let locker_address = (log_entry.address.clone().0).0; - debug!( - "addr: {:?}, x_lock_address: {}", - hex::encode(locker_address.to_vec()), - String::from_utf8(data.x_lock_address.as_ref().to_vec()).unwrap() - ); - if hex::encode(locker_address.to_vec()) != String::from_utf8(data.x_lock_address.as_ref().to_vec()).unwrap() { - return Err(Error::WrongFundingAddr) - } - if !ethspv::verify_log_entry( - u64::from_le_bytes(log_index), - log_entry_data, - u64::from_le_bytes(receipt_index), - receipt_data, - header.receipts_root, - proof, - ) { - return Err(Error::BadMerkleProof); - } - Ok(EthExtraView { - dummy: Default::default(), - }) -} - -pub fn verify_btc_faulty_witness( - data: &ToCKBCellDataView, - proof: &[u8], - cell_dep_index_list: &[u8], - is_when_redeeming: bool, -) -> Result<(), Error> { - debug!( - "proof: {:?}, cell_dep_index_list: {:?}", - proof, cell_dep_index_list - ); - // parse difficulty - if cell_dep_index_list.len() != 1 { - return Err(Error::InvalidWitness); - } - let dep_data = load_cell_data(cell_dep_index_list[0].into(), Source::CellDep)?; - debug!("dep data is {:?}", &dep_data); - if BTCDifficultyReader::verify(&dep_data, false).is_err() { - return Err(Error::DifficultyDataInvalid); - } - let difficulty_reader = BTCDifficultyReader::new_unchecked(&dep_data); - debug!("difficulty_reader: {:?}", difficulty_reader); - // parse witness - if BTCSPVProofReader::verify(proof, false).is_err() { - return Err(Error::InvalidWitness); - } - let proof_reader = BTCSPVProofReader::new_unchecked(proof); - debug!("proof_reader: {:?}", proof_reader); - - // verify btc spv - verify_btc_spv(proof_reader, difficulty_reader)?; - - // get tx in - let funding_input_index: u32 = proof_reader.funding_input_index().into(); - - let vin = Vin::new(proof_reader.vin().raw_data())?; - let tx_in = vin.index(funding_input_index as usize)?; - - // get mint_xt's funding_output info from cell_data - let btc_extra = match &data.x_extra { - XExtraView::Btc(extra) => Ok(extra), - _ => Err(Error::FaultyBtcWitnessInvalid), - }?; - - // check if the locked btc is transferred by signer - let btc_extra_txid: Vec = btc_extra.lock_tx_hash.clone().into(); - debug!( - "btc_extra_txid: {}, tx_in.outpoint().txid_le(): {}", - hex::encode(btc_extra_txid.as_slice()), - hex::encode(tx_in.outpoint().txid_le().as_ref().as_ref()) - ); - - debug!( - "btc_extra.lock_vout_index: {}, tx_in.outpoint().vout_index(): {}", - btc_extra.lock_vout_index, - tx_in.outpoint().vout_index() - ); - - if tx_in.outpoint().txid_le().as_ref().as_ref() != btc_extra_txid.as_slice() - || tx_in.outpoint().vout_index() != btc_extra.lock_vout_index - { - return Err(Error::FaultyBtcWitnessInvalid); - } - - // if is_when_redeeming, check if signer transferred insufficient btc_amount to user_unlock_addr - if is_when_redeeming { - debug!("verify_btc_faulty_witness is_when_redeeming"); - // verify transfer amount, to matches - let vout = Vout::new(proof_reader.vout().raw_data())?; - let mut index: usize = 0; - let mut sum_amount: u128 = 0; - let expect_address = data.x_unlock_address.as_ref(); - let lot_amount = data.get_btc_lot_size()?.get_sudt_amount(); - - // calc sum_amount which signer transferred to user - debug!("begin calc sum_amount which signer transferred to user"); - loop { - let tx_out = match vout.index(index.into()) { - Ok(out) => out, - Err(_) => { - break; - } - }; - index += 1; - - let script_pubkey = tx_out.script_pubkey(); - match script_pubkey.payload()? { - PayloadType::WPKH(pkh) => { - let mut addr_u5 = Vec::with_capacity(33); - addr_u5.push(bech32::u5::try_from_u8(0).unwrap()); - addr_u5.extend(pkh.to_base32()); - debug!("addr_u5: {:?}", &addr_u5); - let addr = bech32::encode("bc", addr_u5) - .expect("bech32 encode should not return error"); - debug!( - "hex format: addr: {}, x_lock_address: {}", - hex::encode(addr.as_bytes().to_vec()), - hex::encode(data.x_lock_address.as_ref().to_vec()) - ); - debug!( - "addr: {}, x_unlock_address: {}", - String::from_utf8(addr.as_bytes().to_vec()).unwrap(), - String::from_utf8(expect_address.to_vec()).unwrap() - ); - if addr.as_bytes() != expect_address { - continue; - } - } - _ => continue, - } - - sum_amount += tx_out.value() as u128; - } - - debug!( - "calc sum_amount: {}, lot_amount: {}", - sum_amount, lot_amount - ); - if sum_amount >= lot_amount { - // it means signer transferred enough amount to user, mismatch FaultyWhenRedeeming condition - return Err(Error::FaultyBtcWitnessInvalid); - } - } - Ok(()) -} - -pub fn verify_btc_spv( - proof: BTCSPVProofReader, - difficulty: BTCDifficultyReader, -) -> Result { - debug!("start verify_btc_spv"); - if !btcspv::validate_vin(proof.vin().raw_data()) { - return Err(Error::SpvProofInvalid); - } - debug!("finish validate_vin"); - if !btcspv::validate_vout(proof.vout().raw_data()) { - return Err(Error::SpvProofInvalid); - } - debug!("finish validate_vout"); - let mut ver = [0u8; 4]; - ver.copy_from_slice(proof.version().raw_data()); - let mut lock = [0u8; 4]; - lock.copy_from_slice(proof.locktime().raw_data()); - debug!("ver: {:?}, lock: {:?}", ver, lock); - // btcspv::hash256(&[version, vin.as_ref(), vout.as_ref(), locktime]) - let vin = Vin::new(proof.vin().raw_data())?; - let vout = Vout::new(proof.vout().raw_data())?; - debug!("{:?}", &[&ver, vin.as_ref(), vout.as_ref(), &lock]); - let tx_id = validatespv::calculate_txid(&ver, &vin, &vout, &lock); - debug!("tx_id: {:?}", tx_id); - if tx_id.as_ref() != proof.tx_id().raw_data() { - return Err(Error::WrongTxId); - } - - // verify difficulty - let raw_headers = proof.headers(); - let headers = HeaderArray::new(raw_headers.raw_data())?; - let observed_diff = validatespv::validate_header_chain(&headers, false)?; - let previous_diff = U256::from_little_endian(difficulty.previous().raw_data()); - let current_diff = U256::from_little_endian(difficulty.current().raw_data()); - let first_header_diff = headers.index(0).difficulty(); - debug!( - "previous: {:?}, current: {:?}, first_header_diff: {:?}", - previous_diff, current_diff, first_header_diff - ); - - let req_diff = if first_header_diff == current_diff { - current_diff - } else if first_header_diff == previous_diff { - previous_diff - } else { - return Err(Error::NotAtCurrentOrPreviousDifficulty); - }; - - if observed_diff < req_diff * TX_PROOF_DIFFICULTY_FACTOR { - return Err(Error::InsufficientDifficulty); - } - debug!("finish diff verify"); - - // verify tx - let header = headers.index(headers.len() - 1); - let mut idx = [0u8; 8]; - idx.copy_from_slice(proof.index().raw_data()); - debug!("tx_id: {}", hex::encode(tx_id.as_ref())); - debug!("merkle_root: {}", hex::encode(header.tx_root().as_ref())); - debug!( - "proof: {}", - hex::encode(proof.intermediate_nodes().raw_data()) - ); - debug!("index: {}", u64::from_le_bytes(idx)); - if !validatespv::prove( - tx_id, - header.tx_root(), - &MerkleArray::new(proof.intermediate_nodes().raw_data())?, - u64::from_le_bytes(idx), - ) { - return Err(Error::BadMerkleProof); - } - debug!("finish merkle proof verify"); - - Ok(Bytes::from(&tx_id.as_ref()[..])) -} - -pub fn verify_btc_address(addr: &[u8]) -> Result<(), Error> { - let (hrp, data) = - bech32::decode(core::str::from_utf8(addr).map_err(|_| Error::XChainAddressInvalid)?) - .map_err(|_| Error::XChainAddressInvalid)?; - if hrp != "bc" { - return Err(Error::XChainAddressInvalid); - } - if data.len() != 33 { - return Err(Error::XChainAddressInvalid); - } - if data[0].to_u8() != 0 { - return Err(Error::XChainAddressInvalid); - } - Ok(()) -} diff --git a/tests/src/toCKB_typescript/utils/case_builder.rs b/tests/src/toCKB_typescript/utils/case_builder.rs index 3057e9c..4b340a8 100644 --- a/tests/src/toCKB_typescript/utils/case_builder.rs +++ b/tests/src/toCKB_typescript/utils/case_builder.rs @@ -3,9 +3,10 @@ use crate::toCKB_typescript::utils::types::generated::{ basic::Bytes2, btc_difficulty, mint_xt_witness, tockb_cell_data::{ - BtcExtra, Chain, EthCellData, EthExtra, HeaderInfo, ToCKBCellData, ToCKBTypeArgs, XExtra, + BtcExtra, EthExtra, ToCKBCellData, ToCKBTypeArgs, XExtra, XExtraUnion, }, + eth_header_cell_data::{Chain, EthCellData, HeaderInfo}, }; use anyhow::Result; use ckb_testtool::context::Context; @@ -100,7 +101,7 @@ impl CellDepView { .into(), ) // .total_difficulty(header.difficulty.0.as_u64().into()) - .hash(basic::Byte32::from_slice(header.hash.unwrap().0.as_bytes()).unwrap()) + .hash(basic::Byte32::from_slice(header.hash.expect("invalid hash.").0.as_bytes()).expect("invalid hash.")) .build(); headers.push(header_info.as_slice().to_vec().into()); } diff --git a/types/Makefile b/types/Makefile index 03373d7..32c187c 100644 --- a/types/Makefile +++ b/types/Makefile @@ -6,4 +6,5 @@ schema: moleculec --language rust --schema-file ${SCHEMA_PATH}/tockb_cell_data.mol > ${SCHEMA_DEST_PATH}/tockb_cell_data.rs moleculec --language rust --schema-file ${SCHEMA_PATH}/btc_difficulty.mol > ${SCHEMA_DEST_PATH}/btc_difficulty.rs moleculec --language rust --schema-file ${SCHEMA_PATH}/mint_xt_witness.mol > ${SCHEMA_DEST_PATH}/mint_xt_witness.rs + moleculec --language rust --schema-file ${SCHEMA_PATH}/eth_header_cell_data.mol > ${SCHEMA_DEST_PATH}/eth_header_cell_data.rs cargo fmt diff --git a/types/schemas/eth_header_cell_data.mol b/types/schemas/eth_header_cell_data.mol new file mode 100644 index 0000000..a5d2b91 --- /dev/null +++ b/types/schemas/eth_header_cell_data.mol @@ -0,0 +1,16 @@ +import basic; + +table EthCellData { + headers: Chain, +} + +table Chain { + main: Bytes2, + uncle: Bytes2, +} + +table HeaderInfo { + header: Bytes, + total_difficulty: Uint64, + hash: Byte32, +} diff --git a/types/schemas/tockb_cell_data.mol b/types/schemas/tockb_cell_data.mol index 45725e6..61eae44 100644 --- a/types/schemas/tockb_cell_data.mol +++ b/types/schemas/tockb_cell_data.mol @@ -30,18 +30,3 @@ struct ToCKBTypeArgs { xchain_kind: byte, cell_id: OutPoint, } - -table EthCellData { - headers: Chain, -} - -table Chain { - main: Bytes2, - uncle: Bytes2, -} - -table HeaderInfo { - header: Bytes, - total_difficulty: Uint64, - hash: Byte32, -} diff --git a/types/src/error.rs b/types/src/error.rs index 7e790a6..383c837 100644 --- a/types/src/error.rs +++ b/types/src/error.rs @@ -42,6 +42,8 @@ pub enum Error { InvalidTriggerOrSignerCell, InvalidAuctionXTCell, XTAmountInvalid, + LogEntryInvalid, + ReceiptInvalid, } impl From> for Error { diff --git a/types/src/generated/eth_header_cell_data.rs b/types/src/generated/eth_header_cell_data.rs new file mode 100644 index 0000000..cee51dd --- /dev/null +++ b/types/src/generated/eth_header_cell_data.rs @@ -0,0 +1,13 @@ +// Generated by Molecule 0.6.1 + +use molecule :: prelude :: * ; +use super :: basic :: * ; +# [ derive ( Clone ) ] pub struct EthCellData ( molecule :: bytes :: Bytes ) ; impl :: core :: fmt :: LowerHex for EthCellData { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl :: core :: fmt :: Debug for EthCellData { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl :: core :: fmt :: Display for EthCellData { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{} {{ " , Self :: NAME ) ? ; write ! ( f , "{}: {}" , "headers" , self . headers ( ) ) ? ; let extra_count = self . count_extra_fields ( ) ; if extra_count != 0 { write ! ( f , ", .. ({} fields)" , extra_count ) ? ; } write ! ( f , " }}" ) } } impl :: core :: default :: Default for EthCellData { fn default ( ) -> Self { let v : Vec < u8 > = vec ! [ 28 , 0 , 0 , 0 , 8 , 0 , 0 , 0 , 20 , 0 , 0 , 0 , 12 , 0 , 0 , 0 , 16 , 0 , 0 , 0 , 4 , 0 , 0 , 0 , 4 , 0 , 0 , 0 , ] ; EthCellData :: new_unchecked ( v . into ( ) ) } } impl EthCellData { pub const FIELD_COUNT : usize = 1 ; pub fn total_size ( & self ) -> usize { molecule :: unpack_number ( self . as_slice ( ) ) as usize } pub fn field_count ( & self ) -> usize { if self . total_size ( ) == molecule :: NUMBER_SIZE { 0 } else { ( molecule :: unpack_number ( & self . as_slice ( ) [ molecule :: NUMBER_SIZE .. ] ) as usize / 4 ) - 1 } } pub fn count_extra_fields ( & self ) -> usize { self . field_count ( ) - Self :: FIELD_COUNT } pub fn has_extra_fields ( & self ) -> bool { Self :: FIELD_COUNT != self . field_count ( ) } pub fn headers ( & self ) -> Chain { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 4 .. ] ) as usize ; if self . has_extra_fields ( ) { let end = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; Chain :: new_unchecked ( self . 0 . slice ( start .. end ) ) } else { Chain :: new_unchecked ( self . 0 . slice ( start .. ) ) } } pub fn as_reader < 'r > ( & 'r self ) -> EthCellDataReader < 'r > { EthCellDataReader :: new_unchecked ( self . as_slice ( ) ) } } impl molecule :: prelude :: Entity for EthCellData { type Builder = EthCellDataBuilder ; const NAME : & 'static str = "EthCellData" ; fn new_unchecked ( data : molecule :: bytes :: Bytes ) -> Self { EthCellData ( data ) } fn as_bytes ( & self ) -> molecule :: bytes :: Bytes { self . 0 . clone ( ) } fn as_slice ( & self ) -> & [ u8 ] { & self . 0 [ .. ] } fn from_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { EthCellDataReader :: from_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn from_compatible_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { EthCellDataReader :: from_compatible_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn new_builder ( ) -> Self :: Builder { :: core :: default :: Default :: default ( ) } fn as_builder ( self ) -> Self :: Builder { Self :: new_builder ( ) . headers ( self . headers ( ) ) } } +# [ derive ( Clone , Copy ) ] pub struct EthCellDataReader < 'r > ( & 'r [ u8 ] ) ; impl < 'r > :: core :: fmt :: LowerHex for EthCellDataReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl < 'r > :: core :: fmt :: Debug for EthCellDataReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl < 'r > :: core :: fmt :: Display for EthCellDataReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{} {{ " , Self :: NAME ) ? ; write ! ( f , "{}: {}" , "headers" , self . headers ( ) ) ? ; let extra_count = self . count_extra_fields ( ) ; if extra_count != 0 { write ! ( f , ", .. ({} fields)" , extra_count ) ? ; } write ! ( f , " }}" ) } } impl < 'r > EthCellDataReader < 'r > { pub const FIELD_COUNT : usize = 1 ; pub fn total_size ( & self ) -> usize { molecule :: unpack_number ( self . as_slice ( ) ) as usize } pub fn field_count ( & self ) -> usize { if self . total_size ( ) == molecule :: NUMBER_SIZE { 0 } else { ( molecule :: unpack_number ( & self . as_slice ( ) [ molecule :: NUMBER_SIZE .. ] ) as usize / 4 ) - 1 } } pub fn count_extra_fields ( & self ) -> usize { self . field_count ( ) - Self :: FIELD_COUNT } pub fn has_extra_fields ( & self ) -> bool { Self :: FIELD_COUNT != self . field_count ( ) } pub fn headers ( & self ) -> ChainReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 4 .. ] ) as usize ; if self . has_extra_fields ( ) { let end = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; ChainReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } else { ChainReader :: new_unchecked ( & self . as_slice ( ) [ start .. ] ) } } } impl < 'r > molecule :: prelude :: Reader < 'r > for EthCellDataReader < 'r > { type Entity = EthCellData ; const NAME : & 'static str = "EthCellDataReader" ; fn to_entity ( & self ) -> Self :: Entity { Self :: Entity :: new_unchecked ( self . as_slice ( ) . to_owned ( ) . into ( ) ) } fn new_unchecked ( slice : & 'r [ u8 ] ) -> Self { EthCellDataReader ( slice ) } fn as_slice ( & self ) -> & 'r [ u8 ] { self . 0 } fn verify ( slice : & [ u8 ] , compatible : bool ) -> molecule :: error :: VerificationResult < ( ) > { use molecule :: verification_error as ve ; let slice_len = slice . len ( ) ; if slice_len < molecule :: NUMBER_SIZE { return ve ! ( Self , HeaderIsBroken , molecule :: NUMBER_SIZE , slice_len ) ; } let total_size = molecule :: unpack_number ( slice ) as usize ; if slice_len != total_size { return ve ! ( Self , TotalSizeNotMatch , total_size , slice_len ) ; } if slice_len == molecule :: NUMBER_SIZE && Self :: FIELD_COUNT == 0 { return Ok ( ( ) ) ; } if slice_len < molecule :: NUMBER_SIZE * 2 { return ve ! ( Self , HeaderIsBroken , molecule :: NUMBER_SIZE * 2 , slice_len ) ; } let offset_first = molecule :: unpack_number ( & slice [ molecule :: NUMBER_SIZE .. ] ) as usize ; if offset_first % 4 != 0 || offset_first < molecule :: NUMBER_SIZE * 2 { return ve ! ( Self , OffsetsNotMatch ) ; } let field_count = offset_first / 4 - 1 ; if field_count < Self :: FIELD_COUNT { return ve ! ( Self , FieldCountNotMatch , Self :: FIELD_COUNT , field_count ) ; } else if ! compatible && field_count > Self :: FIELD_COUNT { return ve ! ( Self , FieldCountNotMatch , Self :: FIELD_COUNT , field_count ) ; } ; let header_size = molecule :: NUMBER_SIZE * ( field_count + 1 ) ; if slice_len < header_size { return ve ! ( Self , HeaderIsBroken , header_size , slice_len ) ; } let mut offsets : Vec < usize > = slice [ molecule :: NUMBER_SIZE .. ] . chunks ( molecule :: NUMBER_SIZE ) . take ( field_count ) . map ( | x | molecule :: unpack_number ( x ) as usize ) . collect ( ) ; offsets . push ( total_size ) ; if offsets . windows ( 2 ) . any ( | i | i [ 0 ] > i [ 1 ] ) { return ve ! ( Self , OffsetsNotMatch ) ; } ChainReader :: verify ( & slice [ offsets [ 0 ] .. offsets [ 1 ] ] , compatible ) ? ; Ok ( ( ) ) } } +# [ derive ( Debug , Default ) ] pub struct EthCellDataBuilder { pub ( crate ) headers : Chain , } impl EthCellDataBuilder { pub const FIELD_COUNT : usize = 1 ; pub fn headers ( mut self , v : Chain ) -> Self { self . headers = v ; self } } impl molecule :: prelude :: Builder for EthCellDataBuilder { type Entity = EthCellData ; const NAME : & 'static str = "EthCellDataBuilder" ; fn expected_length ( & self ) -> usize { molecule :: NUMBER_SIZE * ( Self :: FIELD_COUNT + 1 ) + self . headers . as_slice ( ) . len ( ) } fn write < W : :: molecule :: io :: Write > ( & self , writer : & mut W ) -> :: molecule :: io :: Result < ( ) > { let mut total_size = molecule :: NUMBER_SIZE * ( Self :: FIELD_COUNT + 1 ) ; let mut offsets = Vec :: with_capacity ( Self :: FIELD_COUNT ) ; offsets . push ( total_size ) ; total_size += self . headers . as_slice ( ) . len ( ) ; writer . write_all ( & molecule :: pack_number ( total_size as molecule :: Number ) ) ? ; for offset in offsets . into_iter ( ) { writer . write_all ( & molecule :: pack_number ( offset as molecule :: Number ) ) ? ; } writer . write_all ( self . headers . as_slice ( ) ) ? ; Ok ( ( ) ) } fn build ( & self ) -> Self :: Entity { let mut inner = Vec :: with_capacity ( self . expected_length ( ) ) ; self . write ( & mut inner ) . unwrap_or_else ( | _ | panic ! ( "{} build should be ok" , Self :: NAME ) ) ; EthCellData :: new_unchecked ( inner . into ( ) ) } } +# [ derive ( Clone ) ] pub struct Chain ( molecule :: bytes :: Bytes ) ; impl :: core :: fmt :: LowerHex for Chain { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl :: core :: fmt :: Debug for Chain { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl :: core :: fmt :: Display for Chain { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{} {{ " , Self :: NAME ) ? ; write ! ( f , "{}: {}" , "main" , self . main ( ) ) ? ; write ! ( f , ", {}: {}" , "uncle" , self . uncle ( ) ) ? ; let extra_count = self . count_extra_fields ( ) ; if extra_count != 0 { write ! ( f , ", .. ({} fields)" , extra_count ) ? ; } write ! ( f , " }}" ) } } impl :: core :: default :: Default for Chain { fn default ( ) -> Self { let v : Vec < u8 > = vec ! [ 20 , 0 , 0 , 0 , 12 , 0 , 0 , 0 , 16 , 0 , 0 , 0 , 4 , 0 , 0 , 0 , 4 , 0 , 0 , 0 , ] ; Chain :: new_unchecked ( v . into ( ) ) } } impl Chain { pub const FIELD_COUNT : usize = 2 ; pub fn total_size ( & self ) -> usize { molecule :: unpack_number ( self . as_slice ( ) ) as usize } pub fn field_count ( & self ) -> usize { if self . total_size ( ) == molecule :: NUMBER_SIZE { 0 } else { ( molecule :: unpack_number ( & self . as_slice ( ) [ molecule :: NUMBER_SIZE .. ] ) as usize / 4 ) - 1 } } pub fn count_extra_fields ( & self ) -> usize { self . field_count ( ) - Self :: FIELD_COUNT } pub fn has_extra_fields ( & self ) -> bool { Self :: FIELD_COUNT != self . field_count ( ) } pub fn main ( & self ) -> Bytes2 { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 4 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; Bytes2 :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn uncle ( & self ) -> Bytes2 { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; if self . has_extra_fields ( ) { let end = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; Bytes2 :: new_unchecked ( self . 0 . slice ( start .. end ) ) } else { Bytes2 :: new_unchecked ( self . 0 . slice ( start .. ) ) } } pub fn as_reader < 'r > ( & 'r self ) -> ChainReader < 'r > { ChainReader :: new_unchecked ( self . as_slice ( ) ) } } impl molecule :: prelude :: Entity for Chain { type Builder = ChainBuilder ; const NAME : & 'static str = "Chain" ; fn new_unchecked ( data : molecule :: bytes :: Bytes ) -> Self { Chain ( data ) } fn as_bytes ( & self ) -> molecule :: bytes :: Bytes { self . 0 . clone ( ) } fn as_slice ( & self ) -> & [ u8 ] { & self . 0 [ .. ] } fn from_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { ChainReader :: from_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn from_compatible_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { ChainReader :: from_compatible_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn new_builder ( ) -> Self :: Builder { :: core :: default :: Default :: default ( ) } fn as_builder ( self ) -> Self :: Builder { Self :: new_builder ( ) . main ( self . main ( ) ) . uncle ( self . uncle ( ) ) } } +# [ derive ( Clone , Copy ) ] pub struct ChainReader < 'r > ( & 'r [ u8 ] ) ; impl < 'r > :: core :: fmt :: LowerHex for ChainReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl < 'r > :: core :: fmt :: Debug for ChainReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl < 'r > :: core :: fmt :: Display for ChainReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{} {{ " , Self :: NAME ) ? ; write ! ( f , "{}: {}" , "main" , self . main ( ) ) ? ; write ! ( f , ", {}: {}" , "uncle" , self . uncle ( ) ) ? ; let extra_count = self . count_extra_fields ( ) ; if extra_count != 0 { write ! ( f , ", .. ({} fields)" , extra_count ) ? ; } write ! ( f , " }}" ) } } impl < 'r > ChainReader < 'r > { pub const FIELD_COUNT : usize = 2 ; pub fn total_size ( & self ) -> usize { molecule :: unpack_number ( self . as_slice ( ) ) as usize } pub fn field_count ( & self ) -> usize { if self . total_size ( ) == molecule :: NUMBER_SIZE { 0 } else { ( molecule :: unpack_number ( & self . as_slice ( ) [ molecule :: NUMBER_SIZE .. ] ) as usize / 4 ) - 1 } } pub fn count_extra_fields ( & self ) -> usize { self . field_count ( ) - Self :: FIELD_COUNT } pub fn has_extra_fields ( & self ) -> bool { Self :: FIELD_COUNT != self . field_count ( ) } pub fn main ( & self ) -> Bytes2Reader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 4 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; Bytes2Reader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn uncle ( & self ) -> Bytes2Reader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; if self . has_extra_fields ( ) { let end = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; Bytes2Reader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } else { Bytes2Reader :: new_unchecked ( & self . as_slice ( ) [ start .. ] ) } } } impl < 'r > molecule :: prelude :: Reader < 'r > for ChainReader < 'r > { type Entity = Chain ; const NAME : & 'static str = "ChainReader" ; fn to_entity ( & self ) -> Self :: Entity { Self :: Entity :: new_unchecked ( self . as_slice ( ) . to_owned ( ) . into ( ) ) } fn new_unchecked ( slice : & 'r [ u8 ] ) -> Self { ChainReader ( slice ) } fn as_slice ( & self ) -> & 'r [ u8 ] { self . 0 } fn verify ( slice : & [ u8 ] , compatible : bool ) -> molecule :: error :: VerificationResult < ( ) > { use molecule :: verification_error as ve ; let slice_len = slice . len ( ) ; if slice_len < molecule :: NUMBER_SIZE { return ve ! ( Self , HeaderIsBroken , molecule :: NUMBER_SIZE , slice_len ) ; } let total_size = molecule :: unpack_number ( slice ) as usize ; if slice_len != total_size { return ve ! ( Self , TotalSizeNotMatch , total_size , slice_len ) ; } if slice_len == molecule :: NUMBER_SIZE && Self :: FIELD_COUNT == 0 { return Ok ( ( ) ) ; } if slice_len < molecule :: NUMBER_SIZE * 2 { return ve ! ( Self , HeaderIsBroken , molecule :: NUMBER_SIZE * 2 , slice_len ) ; } let offset_first = molecule :: unpack_number ( & slice [ molecule :: NUMBER_SIZE .. ] ) as usize ; if offset_first % 4 != 0 || offset_first < molecule :: NUMBER_SIZE * 2 { return ve ! ( Self , OffsetsNotMatch ) ; } let field_count = offset_first / 4 - 1 ; if field_count < Self :: FIELD_COUNT { return ve ! ( Self , FieldCountNotMatch , Self :: FIELD_COUNT , field_count ) ; } else if ! compatible && field_count > Self :: FIELD_COUNT { return ve ! ( Self , FieldCountNotMatch , Self :: FIELD_COUNT , field_count ) ; } ; let header_size = molecule :: NUMBER_SIZE * ( field_count + 1 ) ; if slice_len < header_size { return ve ! ( Self , HeaderIsBroken , header_size , slice_len ) ; } let mut offsets : Vec < usize > = slice [ molecule :: NUMBER_SIZE .. ] . chunks ( molecule :: NUMBER_SIZE ) . take ( field_count ) . map ( | x | molecule :: unpack_number ( x ) as usize ) . collect ( ) ; offsets . push ( total_size ) ; if offsets . windows ( 2 ) . any ( | i | i [ 0 ] > i [ 1 ] ) { return ve ! ( Self , OffsetsNotMatch ) ; } Bytes2Reader :: verify ( & slice [ offsets [ 0 ] .. offsets [ 1 ] ] , compatible ) ? ; Bytes2Reader :: verify ( & slice [ offsets [ 1 ] .. offsets [ 2 ] ] , compatible ) ? ; Ok ( ( ) ) } } +# [ derive ( Debug , Default ) ] pub struct ChainBuilder { pub ( crate ) main : Bytes2 , pub ( crate ) uncle : Bytes2 , } impl ChainBuilder { pub const FIELD_COUNT : usize = 2 ; pub fn main ( mut self , v : Bytes2 ) -> Self { self . main = v ; self } pub fn uncle ( mut self , v : Bytes2 ) -> Self { self . uncle = v ; self } } impl molecule :: prelude :: Builder for ChainBuilder { type Entity = Chain ; const NAME : & 'static str = "ChainBuilder" ; fn expected_length ( & self ) -> usize { molecule :: NUMBER_SIZE * ( Self :: FIELD_COUNT + 1 ) + self . main . as_slice ( ) . len ( ) + self . uncle . as_slice ( ) . len ( ) } fn write < W : :: molecule :: io :: Write > ( & self , writer : & mut W ) -> :: molecule :: io :: Result < ( ) > { let mut total_size = molecule :: NUMBER_SIZE * ( Self :: FIELD_COUNT + 1 ) ; let mut offsets = Vec :: with_capacity ( Self :: FIELD_COUNT ) ; offsets . push ( total_size ) ; total_size += self . main . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . uncle . as_slice ( ) . len ( ) ; writer . write_all ( & molecule :: pack_number ( total_size as molecule :: Number ) ) ? ; for offset in offsets . into_iter ( ) { writer . write_all ( & molecule :: pack_number ( offset as molecule :: Number ) ) ? ; } writer . write_all ( self . main . as_slice ( ) ) ? ; writer . write_all ( self . uncle . as_slice ( ) ) ? ; Ok ( ( ) ) } fn build ( & self ) -> Self :: Entity { let mut inner = Vec :: with_capacity ( self . expected_length ( ) ) ; self . write ( & mut inner ) . unwrap_or_else ( | _ | panic ! ( "{} build should be ok" , Self :: NAME ) ) ; Chain :: new_unchecked ( inner . into ( ) ) } } +# [ derive ( Clone ) ] pub struct HeaderInfo ( molecule :: bytes :: Bytes ) ; impl :: core :: fmt :: LowerHex for HeaderInfo { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl :: core :: fmt :: Debug for HeaderInfo { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl :: core :: fmt :: Display for HeaderInfo { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{} {{ " , Self :: NAME ) ? ; write ! ( f , "{}: {}" , "header" , self . header ( ) ) ? ; write ! ( f , ", {}: {}" , "total_difficulty" , self . total_difficulty ( ) ) ? ; write ! ( f , ", {}: {}" , "hash" , self . hash ( ) ) ? ; let extra_count = self . count_extra_fields ( ) ; if extra_count != 0 { write ! ( f , ", .. ({} fields)" , extra_count ) ? ; } write ! ( f , " }}" ) } } impl :: core :: default :: Default for HeaderInfo { fn default ( ) -> Self { let v : Vec < u8 > = vec ! [ 60 , 0 , 0 , 0 , 16 , 0 , 0 , 0 , 20 , 0 , 0 , 0 , 28 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , ] ; HeaderInfo :: new_unchecked ( v . into ( ) ) } } impl HeaderInfo { pub const FIELD_COUNT : usize = 3 ; pub fn total_size ( & self ) -> usize { molecule :: unpack_number ( self . as_slice ( ) ) as usize } pub fn field_count ( & self ) -> usize { if self . total_size ( ) == molecule :: NUMBER_SIZE { 0 } else { ( molecule :: unpack_number ( & self . as_slice ( ) [ molecule :: NUMBER_SIZE .. ] ) as usize / 4 ) - 1 } } pub fn count_extra_fields ( & self ) -> usize { self . field_count ( ) - Self :: FIELD_COUNT } pub fn has_extra_fields ( & self ) -> bool { Self :: FIELD_COUNT != self . field_count ( ) } pub fn header ( & self ) -> Bytes { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 4 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; Bytes :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn total_difficulty ( & self ) -> Uint64 { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; Uint64 :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn hash ( & self ) -> Byte32 { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; if self . has_extra_fields ( ) { let end = molecule :: unpack_number ( & slice [ 16 .. ] ) as usize ; Byte32 :: new_unchecked ( self . 0 . slice ( start .. end ) ) } else { Byte32 :: new_unchecked ( self . 0 . slice ( start .. ) ) } } pub fn as_reader < 'r > ( & 'r self ) -> HeaderInfoReader < 'r > { HeaderInfoReader :: new_unchecked ( self . as_slice ( ) ) } } impl molecule :: prelude :: Entity for HeaderInfo { type Builder = HeaderInfoBuilder ; const NAME : & 'static str = "HeaderInfo" ; fn new_unchecked ( data : molecule :: bytes :: Bytes ) -> Self { HeaderInfo ( data ) } fn as_bytes ( & self ) -> molecule :: bytes :: Bytes { self . 0 . clone ( ) } fn as_slice ( & self ) -> & [ u8 ] { & self . 0 [ .. ] } fn from_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { HeaderInfoReader :: from_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn from_compatible_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { HeaderInfoReader :: from_compatible_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn new_builder ( ) -> Self :: Builder { :: core :: default :: Default :: default ( ) } fn as_builder ( self ) -> Self :: Builder { Self :: new_builder ( ) . header ( self . header ( ) ) . total_difficulty ( self . total_difficulty ( ) ) . hash ( self . hash ( ) ) } } +# [ derive ( Clone , Copy ) ] pub struct HeaderInfoReader < 'r > ( & 'r [ u8 ] ) ; impl < 'r > :: core :: fmt :: LowerHex for HeaderInfoReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl < 'r > :: core :: fmt :: Debug for HeaderInfoReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl < 'r > :: core :: fmt :: Display for HeaderInfoReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{} {{ " , Self :: NAME ) ? ; write ! ( f , "{}: {}" , "header" , self . header ( ) ) ? ; write ! ( f , ", {}: {}" , "total_difficulty" , self . total_difficulty ( ) ) ? ; write ! ( f , ", {}: {}" , "hash" , self . hash ( ) ) ? ; let extra_count = self . count_extra_fields ( ) ; if extra_count != 0 { write ! ( f , ", .. ({} fields)" , extra_count ) ? ; } write ! ( f , " }}" ) } } impl < 'r > HeaderInfoReader < 'r > { pub const FIELD_COUNT : usize = 3 ; pub fn total_size ( & self ) -> usize { molecule :: unpack_number ( self . as_slice ( ) ) as usize } pub fn field_count ( & self ) -> usize { if self . total_size ( ) == molecule :: NUMBER_SIZE { 0 } else { ( molecule :: unpack_number ( & self . as_slice ( ) [ molecule :: NUMBER_SIZE .. ] ) as usize / 4 ) - 1 } } pub fn count_extra_fields ( & self ) -> usize { self . field_count ( ) - Self :: FIELD_COUNT } pub fn has_extra_fields ( & self ) -> bool { Self :: FIELD_COUNT != self . field_count ( ) } pub fn header ( & self ) -> BytesReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 4 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; BytesReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn total_difficulty ( & self ) -> Uint64Reader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; Uint64Reader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn hash ( & self ) -> Byte32Reader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; if self . has_extra_fields ( ) { let end = molecule :: unpack_number ( & slice [ 16 .. ] ) as usize ; Byte32Reader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } else { Byte32Reader :: new_unchecked ( & self . as_slice ( ) [ start .. ] ) } } } impl < 'r > molecule :: prelude :: Reader < 'r > for HeaderInfoReader < 'r > { type Entity = HeaderInfo ; const NAME : & 'static str = "HeaderInfoReader" ; fn to_entity ( & self ) -> Self :: Entity { Self :: Entity :: new_unchecked ( self . as_slice ( ) . to_owned ( ) . into ( ) ) } fn new_unchecked ( slice : & 'r [ u8 ] ) -> Self { HeaderInfoReader ( slice ) } fn as_slice ( & self ) -> & 'r [ u8 ] { self . 0 } fn verify ( slice : & [ u8 ] , compatible : bool ) -> molecule :: error :: VerificationResult < ( ) > { use molecule :: verification_error as ve ; let slice_len = slice . len ( ) ; if slice_len < molecule :: NUMBER_SIZE { return ve ! ( Self , HeaderIsBroken , molecule :: NUMBER_SIZE , slice_len ) ; } let total_size = molecule :: unpack_number ( slice ) as usize ; if slice_len != total_size { return ve ! ( Self , TotalSizeNotMatch , total_size , slice_len ) ; } if slice_len == molecule :: NUMBER_SIZE && Self :: FIELD_COUNT == 0 { return Ok ( ( ) ) ; } if slice_len < molecule :: NUMBER_SIZE * 2 { return ve ! ( Self , HeaderIsBroken , molecule :: NUMBER_SIZE * 2 , slice_len ) ; } let offset_first = molecule :: unpack_number ( & slice [ molecule :: NUMBER_SIZE .. ] ) as usize ; if offset_first % 4 != 0 || offset_first < molecule :: NUMBER_SIZE * 2 { return ve ! ( Self , OffsetsNotMatch ) ; } let field_count = offset_first / 4 - 1 ; if field_count < Self :: FIELD_COUNT { return ve ! ( Self , FieldCountNotMatch , Self :: FIELD_COUNT , field_count ) ; } else if ! compatible && field_count > Self :: FIELD_COUNT { return ve ! ( Self , FieldCountNotMatch , Self :: FIELD_COUNT , field_count ) ; } ; let header_size = molecule :: NUMBER_SIZE * ( field_count + 1 ) ; if slice_len < header_size { return ve ! ( Self , HeaderIsBroken , header_size , slice_len ) ; } let mut offsets : Vec < usize > = slice [ molecule :: NUMBER_SIZE .. ] . chunks ( molecule :: NUMBER_SIZE ) . take ( field_count ) . map ( | x | molecule :: unpack_number ( x ) as usize ) . collect ( ) ; offsets . push ( total_size ) ; if offsets . windows ( 2 ) . any ( | i | i [ 0 ] > i [ 1 ] ) { return ve ! ( Self , OffsetsNotMatch ) ; } BytesReader :: verify ( & slice [ offsets [ 0 ] .. offsets [ 1 ] ] , compatible ) ? ; Uint64Reader :: verify ( & slice [ offsets [ 1 ] .. offsets [ 2 ] ] , compatible ) ? ; Byte32Reader :: verify ( & slice [ offsets [ 2 ] .. offsets [ 3 ] ] , compatible ) ? ; Ok ( ( ) ) } } +# [ derive ( Debug , Default ) ] pub struct HeaderInfoBuilder { pub ( crate ) header : Bytes , pub ( crate ) total_difficulty : Uint64 , pub ( crate ) hash : Byte32 , } impl HeaderInfoBuilder { pub const FIELD_COUNT : usize = 3 ; pub fn header ( mut self , v : Bytes ) -> Self { self . header = v ; self } pub fn total_difficulty ( mut self , v : Uint64 ) -> Self { self . total_difficulty = v ; self } pub fn hash ( mut self , v : Byte32 ) -> Self { self . hash = v ; self } } impl molecule :: prelude :: Builder for HeaderInfoBuilder { type Entity = HeaderInfo ; const NAME : & 'static str = "HeaderInfoBuilder" ; fn expected_length ( & self ) -> usize { molecule :: NUMBER_SIZE * ( Self :: FIELD_COUNT + 1 ) + self . header . as_slice ( ) . len ( ) + self . total_difficulty . as_slice ( ) . len ( ) + self . hash . as_slice ( ) . len ( ) } fn write < W : :: molecule :: io :: Write > ( & self , writer : & mut W ) -> :: molecule :: io :: Result < ( ) > { let mut total_size = molecule :: NUMBER_SIZE * ( Self :: FIELD_COUNT + 1 ) ; let mut offsets = Vec :: with_capacity ( Self :: FIELD_COUNT ) ; offsets . push ( total_size ) ; total_size += self . header . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . total_difficulty . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . hash . as_slice ( ) . len ( ) ; writer . write_all ( & molecule :: pack_number ( total_size as molecule :: Number ) ) ? ; for offset in offsets . into_iter ( ) { writer . write_all ( & molecule :: pack_number ( offset as molecule :: Number ) ) ? ; } writer . write_all ( self . header . as_slice ( ) ) ? ; writer . write_all ( self . total_difficulty . as_slice ( ) ) ? ; writer . write_all ( self . hash . as_slice ( ) ) ? ; Ok ( ( ) ) } fn build ( & self ) -> Self :: Entity { let mut inner = Vec :: with_capacity ( self . expected_length ( ) ) ; self . write ( & mut inner ) . unwrap_or_else ( | _ | panic ! ( "{} build should be ok" , Self :: NAME ) ) ; HeaderInfo :: new_unchecked ( inner . into ( ) ) } } diff --git a/types/src/generated/mod.rs b/types/src/generated/mod.rs index 45429d4..dd2ef0e 100644 --- a/types/src/generated/mod.rs +++ b/types/src/generated/mod.rs @@ -2,3 +2,4 @@ pub mod basic; pub mod btc_difficulty; pub mod mint_xt_witness; pub mod tockb_cell_data; +pub mod eth_header_cell_data; diff --git a/types/src/generated/tockb_cell_data.rs b/types/src/generated/tockb_cell_data.rs index ed41499..2392513 100644 --- a/types/src/generated/tockb_cell_data.rs +++ b/types/src/generated/tockb_cell_data.rs @@ -1380,799 +1380,3 @@ impl molecule::prelude::Builder for ToCKBTypeArgsBuilder { ToCKBTypeArgs::new_unchecked(inner.into()) } } -#[derive(Clone)] -pub struct EthCellData(molecule::bytes::Bytes); -impl ::core::fmt::LowerHex for EthCellData { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl ::core::fmt::Debug for EthCellData { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl ::core::fmt::Display for EthCellData { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{} {{ ", Self::NAME)?; - write!(f, "{}: {}", "headers", self.headers())?; - let extra_count = self.count_extra_fields(); - if extra_count != 0 { - write!(f, ", .. ({} fields)", extra_count)?; - } - write!(f, " }}") - } -} -impl ::core::default::Default for EthCellData { - fn default() -> Self { - let v: Vec = vec![ - 28, 0, 0, 0, 8, 0, 0, 0, 20, 0, 0, 0, 12, 0, 0, 0, 16, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, - ]; - EthCellData::new_unchecked(v.into()) - } -} -impl EthCellData { - pub const FIELD_COUNT: usize = 1; - pub fn total_size(&self) -> usize { - molecule::unpack_number(self.as_slice()) as usize - } - pub fn field_count(&self) -> usize { - if self.total_size() == molecule::NUMBER_SIZE { - 0 - } else { - (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 - } - } - pub fn count_extra_fields(&self) -> usize { - self.field_count() - Self::FIELD_COUNT - } - pub fn has_extra_fields(&self) -> bool { - Self::FIELD_COUNT != self.field_count() - } - pub fn headers(&self) -> Chain { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[4..]) as usize; - if self.has_extra_fields() { - let end = molecule::unpack_number(&slice[8..]) as usize; - Chain::new_unchecked(self.0.slice(start..end)) - } else { - Chain::new_unchecked(self.0.slice(start..)) - } - } - pub fn as_reader<'r>(&'r self) -> EthCellDataReader<'r> { - EthCellDataReader::new_unchecked(self.as_slice()) - } -} -impl molecule::prelude::Entity for EthCellData { - type Builder = EthCellDataBuilder; - const NAME: &'static str = "EthCellData"; - fn new_unchecked(data: molecule::bytes::Bytes) -> Self { - EthCellData(data) - } - fn as_bytes(&self) -> molecule::bytes::Bytes { - self.0.clone() - } - fn as_slice(&self) -> &[u8] { - &self.0[..] - } - fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { - EthCellDataReader::from_slice(slice).map(|reader| reader.to_entity()) - } - fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { - EthCellDataReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) - } - fn new_builder() -> Self::Builder { - ::core::default::Default::default() - } - fn as_builder(self) -> Self::Builder { - Self::new_builder().headers(self.headers()) - } -} -#[derive(Clone, Copy)] -pub struct EthCellDataReader<'r>(&'r [u8]); -impl<'r> ::core::fmt::LowerHex for EthCellDataReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl<'r> ::core::fmt::Debug for EthCellDataReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl<'r> ::core::fmt::Display for EthCellDataReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{} {{ ", Self::NAME)?; - write!(f, "{}: {}", "headers", self.headers())?; - let extra_count = self.count_extra_fields(); - if extra_count != 0 { - write!(f, ", .. ({} fields)", extra_count)?; - } - write!(f, " }}") - } -} -impl<'r> EthCellDataReader<'r> { - pub const FIELD_COUNT: usize = 1; - pub fn total_size(&self) -> usize { - molecule::unpack_number(self.as_slice()) as usize - } - pub fn field_count(&self) -> usize { - if self.total_size() == molecule::NUMBER_SIZE { - 0 - } else { - (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 - } - } - pub fn count_extra_fields(&self) -> usize { - self.field_count() - Self::FIELD_COUNT - } - pub fn has_extra_fields(&self) -> bool { - Self::FIELD_COUNT != self.field_count() - } - pub fn headers(&self) -> ChainReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[4..]) as usize; - if self.has_extra_fields() { - let end = molecule::unpack_number(&slice[8..]) as usize; - ChainReader::new_unchecked(&self.as_slice()[start..end]) - } else { - ChainReader::new_unchecked(&self.as_slice()[start..]) - } - } -} -impl<'r> molecule::prelude::Reader<'r> for EthCellDataReader<'r> { - type Entity = EthCellData; - const NAME: &'static str = "EthCellDataReader"; - fn to_entity(&self) -> Self::Entity { - Self::Entity::new_unchecked(self.as_slice().to_owned().into()) - } - fn new_unchecked(slice: &'r [u8]) -> Self { - EthCellDataReader(slice) - } - fn as_slice(&self) -> &'r [u8] { - self.0 - } - fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { - use molecule::verification_error as ve; - let slice_len = slice.len(); - if slice_len < molecule::NUMBER_SIZE { - return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); - } - let total_size = molecule::unpack_number(slice) as usize; - if slice_len != total_size { - return ve!(Self, TotalSizeNotMatch, total_size, slice_len); - } - if slice_len == molecule::NUMBER_SIZE && Self::FIELD_COUNT == 0 { - return Ok(()); - } - if slice_len < molecule::NUMBER_SIZE * 2 { - return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); - } - let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; - if offset_first % 4 != 0 || offset_first < molecule::NUMBER_SIZE * 2 { - return ve!(Self, OffsetsNotMatch); - } - let field_count = offset_first / 4 - 1; - if field_count < Self::FIELD_COUNT { - return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); - } else if !compatible && field_count > Self::FIELD_COUNT { - return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); - }; - let header_size = molecule::NUMBER_SIZE * (field_count + 1); - if slice_len < header_size { - return ve!(Self, HeaderIsBroken, header_size, slice_len); - } - let mut offsets: Vec = slice[molecule::NUMBER_SIZE..] - .chunks(molecule::NUMBER_SIZE) - .take(field_count) - .map(|x| molecule::unpack_number(x) as usize) - .collect(); - offsets.push(total_size); - if offsets.windows(2).any(|i| i[0] > i[1]) { - return ve!(Self, OffsetsNotMatch); - } - ChainReader::verify(&slice[offsets[0]..offsets[1]], compatible)?; - Ok(()) - } -} -#[derive(Debug, Default)] -pub struct EthCellDataBuilder { - pub(crate) headers: Chain, -} -impl EthCellDataBuilder { - pub const FIELD_COUNT: usize = 1; - pub fn headers(mut self, v: Chain) -> Self { - self.headers = v; - self - } -} -impl molecule::prelude::Builder for EthCellDataBuilder { - type Entity = EthCellData; - const NAME: &'static str = "EthCellDataBuilder"; - fn expected_length(&self) -> usize { - molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) + self.headers.as_slice().len() - } - fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { - let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); - let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); - offsets.push(total_size); - total_size += self.headers.as_slice().len(); - writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; - for offset in offsets.into_iter() { - writer.write_all(&molecule::pack_number(offset as molecule::Number))?; - } - writer.write_all(self.headers.as_slice())?; - Ok(()) - } - fn build(&self) -> Self::Entity { - let mut inner = Vec::with_capacity(self.expected_length()); - self.write(&mut inner) - .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); - EthCellData::new_unchecked(inner.into()) - } -} -#[derive(Clone)] -pub struct Chain(molecule::bytes::Bytes); -impl ::core::fmt::LowerHex for Chain { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl ::core::fmt::Debug for Chain { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl ::core::fmt::Display for Chain { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{} {{ ", Self::NAME)?; - write!(f, "{}: {}", "main", self.main())?; - write!(f, ", {}: {}", "uncle", self.uncle())?; - let extra_count = self.count_extra_fields(); - if extra_count != 0 { - write!(f, ", .. ({} fields)", extra_count)?; - } - write!(f, " }}") - } -} -impl ::core::default::Default for Chain { - fn default() -> Self { - let v: Vec = vec![ - 20, 0, 0, 0, 12, 0, 0, 0, 16, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, - ]; - Chain::new_unchecked(v.into()) - } -} -impl Chain { - pub const FIELD_COUNT: usize = 2; - pub fn total_size(&self) -> usize { - molecule::unpack_number(self.as_slice()) as usize - } - pub fn field_count(&self) -> usize { - if self.total_size() == molecule::NUMBER_SIZE { - 0 - } else { - (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 - } - } - pub fn count_extra_fields(&self) -> usize { - self.field_count() - Self::FIELD_COUNT - } - pub fn has_extra_fields(&self) -> bool { - Self::FIELD_COUNT != self.field_count() - } - pub fn main(&self) -> Bytes2 { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[4..]) as usize; - let end = molecule::unpack_number(&slice[8..]) as usize; - Bytes2::new_unchecked(self.0.slice(start..end)) - } - pub fn uncle(&self) -> Bytes2 { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[8..]) as usize; - if self.has_extra_fields() { - let end = molecule::unpack_number(&slice[12..]) as usize; - Bytes2::new_unchecked(self.0.slice(start..end)) - } else { - Bytes2::new_unchecked(self.0.slice(start..)) - } - } - pub fn as_reader<'r>(&'r self) -> ChainReader<'r> { - ChainReader::new_unchecked(self.as_slice()) - } -} -impl molecule::prelude::Entity for Chain { - type Builder = ChainBuilder; - const NAME: &'static str = "Chain"; - fn new_unchecked(data: molecule::bytes::Bytes) -> Self { - Chain(data) - } - fn as_bytes(&self) -> molecule::bytes::Bytes { - self.0.clone() - } - fn as_slice(&self) -> &[u8] { - &self.0[..] - } - fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { - ChainReader::from_slice(slice).map(|reader| reader.to_entity()) - } - fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { - ChainReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) - } - fn new_builder() -> Self::Builder { - ::core::default::Default::default() - } - fn as_builder(self) -> Self::Builder { - Self::new_builder().main(self.main()).uncle(self.uncle()) - } -} -#[derive(Clone, Copy)] -pub struct ChainReader<'r>(&'r [u8]); -impl<'r> ::core::fmt::LowerHex for ChainReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl<'r> ::core::fmt::Debug for ChainReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl<'r> ::core::fmt::Display for ChainReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{} {{ ", Self::NAME)?; - write!(f, "{}: {}", "main", self.main())?; - write!(f, ", {}: {}", "uncle", self.uncle())?; - let extra_count = self.count_extra_fields(); - if extra_count != 0 { - write!(f, ", .. ({} fields)", extra_count)?; - } - write!(f, " }}") - } -} -impl<'r> ChainReader<'r> { - pub const FIELD_COUNT: usize = 2; - pub fn total_size(&self) -> usize { - molecule::unpack_number(self.as_slice()) as usize - } - pub fn field_count(&self) -> usize { - if self.total_size() == molecule::NUMBER_SIZE { - 0 - } else { - (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 - } - } - pub fn count_extra_fields(&self) -> usize { - self.field_count() - Self::FIELD_COUNT - } - pub fn has_extra_fields(&self) -> bool { - Self::FIELD_COUNT != self.field_count() - } - pub fn main(&self) -> Bytes2Reader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[4..]) as usize; - let end = molecule::unpack_number(&slice[8..]) as usize; - Bytes2Reader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn uncle(&self) -> Bytes2Reader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[8..]) as usize; - if self.has_extra_fields() { - let end = molecule::unpack_number(&slice[12..]) as usize; - Bytes2Reader::new_unchecked(&self.as_slice()[start..end]) - } else { - Bytes2Reader::new_unchecked(&self.as_slice()[start..]) - } - } -} -impl<'r> molecule::prelude::Reader<'r> for ChainReader<'r> { - type Entity = Chain; - const NAME: &'static str = "ChainReader"; - fn to_entity(&self) -> Self::Entity { - Self::Entity::new_unchecked(self.as_slice().to_owned().into()) - } - fn new_unchecked(slice: &'r [u8]) -> Self { - ChainReader(slice) - } - fn as_slice(&self) -> &'r [u8] { - self.0 - } - fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { - use molecule::verification_error as ve; - let slice_len = slice.len(); - if slice_len < molecule::NUMBER_SIZE { - return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); - } - let total_size = molecule::unpack_number(slice) as usize; - if slice_len != total_size { - return ve!(Self, TotalSizeNotMatch, total_size, slice_len); - } - if slice_len == molecule::NUMBER_SIZE && Self::FIELD_COUNT == 0 { - return Ok(()); - } - if slice_len < molecule::NUMBER_SIZE * 2 { - return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); - } - let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; - if offset_first % 4 != 0 || offset_first < molecule::NUMBER_SIZE * 2 { - return ve!(Self, OffsetsNotMatch); - } - let field_count = offset_first / 4 - 1; - if field_count < Self::FIELD_COUNT { - return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); - } else if !compatible && field_count > Self::FIELD_COUNT { - return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); - }; - let header_size = molecule::NUMBER_SIZE * (field_count + 1); - if slice_len < header_size { - return ve!(Self, HeaderIsBroken, header_size, slice_len); - } - let mut offsets: Vec = slice[molecule::NUMBER_SIZE..] - .chunks(molecule::NUMBER_SIZE) - .take(field_count) - .map(|x| molecule::unpack_number(x) as usize) - .collect(); - offsets.push(total_size); - if offsets.windows(2).any(|i| i[0] > i[1]) { - return ve!(Self, OffsetsNotMatch); - } - Bytes2Reader::verify(&slice[offsets[0]..offsets[1]], compatible)?; - Bytes2Reader::verify(&slice[offsets[1]..offsets[2]], compatible)?; - Ok(()) - } -} -#[derive(Debug, Default)] -pub struct ChainBuilder { - pub(crate) main: Bytes2, - pub(crate) uncle: Bytes2, -} -impl ChainBuilder { - pub const FIELD_COUNT: usize = 2; - pub fn main(mut self, v: Bytes2) -> Self { - self.main = v; - self - } - pub fn uncle(mut self, v: Bytes2) -> Self { - self.uncle = v; - self - } -} -impl molecule::prelude::Builder for ChainBuilder { - type Entity = Chain; - const NAME: &'static str = "ChainBuilder"; - fn expected_length(&self) -> usize { - molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) - + self.main.as_slice().len() - + self.uncle.as_slice().len() - } - fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { - let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); - let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); - offsets.push(total_size); - total_size += self.main.as_slice().len(); - offsets.push(total_size); - total_size += self.uncle.as_slice().len(); - writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; - for offset in offsets.into_iter() { - writer.write_all(&molecule::pack_number(offset as molecule::Number))?; - } - writer.write_all(self.main.as_slice())?; - writer.write_all(self.uncle.as_slice())?; - Ok(()) - } - fn build(&self) -> Self::Entity { - let mut inner = Vec::with_capacity(self.expected_length()); - self.write(&mut inner) - .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); - Chain::new_unchecked(inner.into()) - } -} -#[derive(Clone)] -pub struct HeaderInfo(molecule::bytes::Bytes); -impl ::core::fmt::LowerHex for HeaderInfo { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl ::core::fmt::Debug for HeaderInfo { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl ::core::fmt::Display for HeaderInfo { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{} {{ ", Self::NAME)?; - write!(f, "{}: {}", "header", self.header())?; - write!(f, ", {}: {}", "total_difficulty", self.total_difficulty())?; - write!(f, ", {}: {}", "hash", self.hash())?; - let extra_count = self.count_extra_fields(); - if extra_count != 0 { - write!(f, ", .. ({} fields)", extra_count)?; - } - write!(f, " }}") - } -} -impl ::core::default::Default for HeaderInfo { - fn default() -> Self { - let v: Vec = vec![ - 60, 0, 0, 0, 16, 0, 0, 0, 20, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, - ]; - HeaderInfo::new_unchecked(v.into()) - } -} -impl HeaderInfo { - pub const FIELD_COUNT: usize = 3; - pub fn total_size(&self) -> usize { - molecule::unpack_number(self.as_slice()) as usize - } - pub fn field_count(&self) -> usize { - if self.total_size() == molecule::NUMBER_SIZE { - 0 - } else { - (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 - } - } - pub fn count_extra_fields(&self) -> usize { - self.field_count() - Self::FIELD_COUNT - } - pub fn has_extra_fields(&self) -> bool { - Self::FIELD_COUNT != self.field_count() - } - pub fn header(&self) -> Bytes { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[4..]) as usize; - let end = molecule::unpack_number(&slice[8..]) as usize; - Bytes::new_unchecked(self.0.slice(start..end)) - } - pub fn total_difficulty(&self) -> Uint64 { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[8..]) as usize; - let end = molecule::unpack_number(&slice[12..]) as usize; - Uint64::new_unchecked(self.0.slice(start..end)) - } - pub fn hash(&self) -> Byte32 { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[12..]) as usize; - if self.has_extra_fields() { - let end = molecule::unpack_number(&slice[16..]) as usize; - Byte32::new_unchecked(self.0.slice(start..end)) - } else { - Byte32::new_unchecked(self.0.slice(start..)) - } - } - pub fn as_reader<'r>(&'r self) -> HeaderInfoReader<'r> { - HeaderInfoReader::new_unchecked(self.as_slice()) - } -} -impl molecule::prelude::Entity for HeaderInfo { - type Builder = HeaderInfoBuilder; - const NAME: &'static str = "HeaderInfo"; - fn new_unchecked(data: molecule::bytes::Bytes) -> Self { - HeaderInfo(data) - } - fn as_bytes(&self) -> molecule::bytes::Bytes { - self.0.clone() - } - fn as_slice(&self) -> &[u8] { - &self.0[..] - } - fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { - HeaderInfoReader::from_slice(slice).map(|reader| reader.to_entity()) - } - fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { - HeaderInfoReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) - } - fn new_builder() -> Self::Builder { - ::core::default::Default::default() - } - fn as_builder(self) -> Self::Builder { - Self::new_builder() - .header(self.header()) - .total_difficulty(self.total_difficulty()) - .hash(self.hash()) - } -} -#[derive(Clone, Copy)] -pub struct HeaderInfoReader<'r>(&'r [u8]); -impl<'r> ::core::fmt::LowerHex for HeaderInfoReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl<'r> ::core::fmt::Debug for HeaderInfoReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl<'r> ::core::fmt::Display for HeaderInfoReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{} {{ ", Self::NAME)?; - write!(f, "{}: {}", "header", self.header())?; - write!(f, ", {}: {}", "total_difficulty", self.total_difficulty())?; - write!(f, ", {}: {}", "hash", self.hash())?; - let extra_count = self.count_extra_fields(); - if extra_count != 0 { - write!(f, ", .. ({} fields)", extra_count)?; - } - write!(f, " }}") - } -} -impl<'r> HeaderInfoReader<'r> { - pub const FIELD_COUNT: usize = 3; - pub fn total_size(&self) -> usize { - molecule::unpack_number(self.as_slice()) as usize - } - pub fn field_count(&self) -> usize { - if self.total_size() == molecule::NUMBER_SIZE { - 0 - } else { - (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 - } - } - pub fn count_extra_fields(&self) -> usize { - self.field_count() - Self::FIELD_COUNT - } - pub fn has_extra_fields(&self) -> bool { - Self::FIELD_COUNT != self.field_count() - } - pub fn header(&self) -> BytesReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[4..]) as usize; - let end = molecule::unpack_number(&slice[8..]) as usize; - BytesReader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn total_difficulty(&self) -> Uint64Reader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[8..]) as usize; - let end = molecule::unpack_number(&slice[12..]) as usize; - Uint64Reader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn hash(&self) -> Byte32Reader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[12..]) as usize; - if self.has_extra_fields() { - let end = molecule::unpack_number(&slice[16..]) as usize; - Byte32Reader::new_unchecked(&self.as_slice()[start..end]) - } else { - Byte32Reader::new_unchecked(&self.as_slice()[start..]) - } - } -} -impl<'r> molecule::prelude::Reader<'r> for HeaderInfoReader<'r> { - type Entity = HeaderInfo; - const NAME: &'static str = "HeaderInfoReader"; - fn to_entity(&self) -> Self::Entity { - Self::Entity::new_unchecked(self.as_slice().to_owned().into()) - } - fn new_unchecked(slice: &'r [u8]) -> Self { - HeaderInfoReader(slice) - } - fn as_slice(&self) -> &'r [u8] { - self.0 - } - fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { - use molecule::verification_error as ve; - let slice_len = slice.len(); - if slice_len < molecule::NUMBER_SIZE { - return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); - } - let total_size = molecule::unpack_number(slice) as usize; - if slice_len != total_size { - return ve!(Self, TotalSizeNotMatch, total_size, slice_len); - } - if slice_len == molecule::NUMBER_SIZE && Self::FIELD_COUNT == 0 { - return Ok(()); - } - if slice_len < molecule::NUMBER_SIZE * 2 { - return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); - } - let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; - if offset_first % 4 != 0 || offset_first < molecule::NUMBER_SIZE * 2 { - return ve!(Self, OffsetsNotMatch); - } - let field_count = offset_first / 4 - 1; - if field_count < Self::FIELD_COUNT { - return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); - } else if !compatible && field_count > Self::FIELD_COUNT { - return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); - }; - let header_size = molecule::NUMBER_SIZE * (field_count + 1); - if slice_len < header_size { - return ve!(Self, HeaderIsBroken, header_size, slice_len); - } - let mut offsets: Vec = slice[molecule::NUMBER_SIZE..] - .chunks(molecule::NUMBER_SIZE) - .take(field_count) - .map(|x| molecule::unpack_number(x) as usize) - .collect(); - offsets.push(total_size); - if offsets.windows(2).any(|i| i[0] > i[1]) { - return ve!(Self, OffsetsNotMatch); - } - BytesReader::verify(&slice[offsets[0]..offsets[1]], compatible)?; - Uint64Reader::verify(&slice[offsets[1]..offsets[2]], compatible)?; - Byte32Reader::verify(&slice[offsets[2]..offsets[3]], compatible)?; - Ok(()) - } -} -#[derive(Debug, Default)] -pub struct HeaderInfoBuilder { - pub(crate) header: Bytes, - pub(crate) total_difficulty: Uint64, - pub(crate) hash: Byte32, -} -impl HeaderInfoBuilder { - pub const FIELD_COUNT: usize = 3; - pub fn header(mut self, v: Bytes) -> Self { - self.header = v; - self - } - pub fn total_difficulty(mut self, v: Uint64) -> Self { - self.total_difficulty = v; - self - } - pub fn hash(mut self, v: Byte32) -> Self { - self.hash = v; - self - } -} -impl molecule::prelude::Builder for HeaderInfoBuilder { - type Entity = HeaderInfo; - const NAME: &'static str = "HeaderInfoBuilder"; - fn expected_length(&self) -> usize { - molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) - + self.header.as_slice().len() - + self.total_difficulty.as_slice().len() - + self.hash.as_slice().len() - } - fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { - let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); - let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); - offsets.push(total_size); - total_size += self.header.as_slice().len(); - offsets.push(total_size); - total_size += self.total_difficulty.as_slice().len(); - offsets.push(total_size); - total_size += self.hash.as_slice().len(); - writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; - for offset in offsets.into_iter() { - writer.write_all(&molecule::pack_number(offset as molecule::Number))?; - } - writer.write_all(self.header.as_slice())?; - writer.write_all(self.total_difficulty.as_slice())?; - writer.write_all(self.hash.as_slice())?; - Ok(()) - } - fn build(&self) -> Self::Entity { - let mut inner = Vec::with_capacity(self.expected_length()); - self.write(&mut inner) - .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); - HeaderInfo::new_unchecked(inner.into()) - } -} From 59df51edc5eaaa5d83282d0b6bffd3b58e402c42 Mon Sep 17 00:00:00 2001 From: LeonLi000 Date: Mon, 28 Sep 2020 19:47:59 +0800 Subject: [PATCH 44/45] fmt code --- contracts/toCKB-typescript/src/utils/tools.rs | 9 +- .../toCKB_typescript/utils/case_builder.rs | 15 +- types/src/generated/eth_header_cell_data.rs | 809 +++++++++++++++++- types/src/generated/mod.rs | 2 +- 4 files changed, 814 insertions(+), 21 deletions(-) diff --git a/contracts/toCKB-typescript/src/utils/tools.rs b/contracts/toCKB-typescript/src/utils/tools.rs index 26b9e6c..798f064 100644 --- a/contracts/toCKB-typescript/src/utils/tools.rs +++ b/contracts/toCKB-typescript/src/utils/tools.rs @@ -217,7 +217,8 @@ pub fn verify_eth_header_on_main_chain( } let tail_info_reader = HeaderInfoReader::new_unchecked(tail_raw); let tail_info_raw = tail_info_reader.header().raw_data(); - let tail: BlockHeader = rlp::decode(tail_info_raw.to_vec().as_slice()).expect("invalid tail info."); + let tail: BlockHeader = + rlp::decode(tail_info_raw.to_vec().as_slice()).expect("invalid tail info."); if header.number > tail.number { return Err(Error::HeaderIsNotOnMainChain); } @@ -283,9 +284,11 @@ pub fn verify_eth_witness( for i in 0..proof_reader.proof().len() { proof.push(proof_reader.proof().get_unchecked(i).raw_data().to_vec()); } - let log_entry: LogEntry = rlp::decode(log_entry_data.as_slice()).map_err(|_e| Error::LogEntryInvalid)?; + let log_entry: LogEntry = + rlp::decode(log_entry_data.as_slice()).map_err(|_e| Error::LogEntryInvalid)?; debug!("log_entry is {:?}", &log_entry); - let receipt: Receipt = rlp::decode(receipt_data.as_slice()).map_err(|_e| Error::ReceiptInvalid)?; + let receipt: Receipt = + rlp::decode(receipt_data.as_slice()).map_err(|_e| Error::ReceiptInvalid)?; debug!("receipt_data is {:?}", &receipt); let locker_address = (log_entry.address.clone().0).0; debug!( diff --git a/tests/src/toCKB_typescript/utils/case_builder.rs b/tests/src/toCKB_typescript/utils/case_builder.rs index 4b340a8..350315d 100644 --- a/tests/src/toCKB_typescript/utils/case_builder.rs +++ b/tests/src/toCKB_typescript/utils/case_builder.rs @@ -1,12 +1,10 @@ use crate::toCKB_typescript::utils::types::generated::{ basic, basic::Bytes2, - btc_difficulty, mint_xt_witness, - tockb_cell_data::{ - BtcExtra, EthExtra, ToCKBCellData, ToCKBTypeArgs, XExtra, - XExtraUnion, - }, + btc_difficulty, eth_header_cell_data::{Chain, EthCellData, HeaderInfo}, + mint_xt_witness, + tockb_cell_data::{BtcExtra, EthExtra, ToCKBCellData, ToCKBTypeArgs, XExtra, XExtraUnion}, }; use anyhow::Result; use ckb_testtool::context::Context; @@ -101,7 +99,12 @@ impl CellDepView { .into(), ) // .total_difficulty(header.difficulty.0.as_u64().into()) - .hash(basic::Byte32::from_slice(header.hash.expect("invalid hash.").0.as_bytes()).expect("invalid hash.")) + .hash( + basic::Byte32::from_slice( + header.hash.expect("invalid hash.").0.as_bytes(), + ) + .expect("invalid hash."), + ) .build(); headers.push(header_info.as_slice().to_vec().into()); } diff --git a/types/src/generated/eth_header_cell_data.rs b/types/src/generated/eth_header_cell_data.rs index cee51dd..ec1ef7b 100644 --- a/types/src/generated/eth_header_cell_data.rs +++ b/types/src/generated/eth_header_cell_data.rs @@ -1,13 +1,800 @@ // Generated by Molecule 0.6.1 -use molecule :: prelude :: * ; -use super :: basic :: * ; -# [ derive ( Clone ) ] pub struct EthCellData ( molecule :: bytes :: Bytes ) ; impl :: core :: fmt :: LowerHex for EthCellData { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl :: core :: fmt :: Debug for EthCellData { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl :: core :: fmt :: Display for EthCellData { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{} {{ " , Self :: NAME ) ? ; write ! ( f , "{}: {}" , "headers" , self . headers ( ) ) ? ; let extra_count = self . count_extra_fields ( ) ; if extra_count != 0 { write ! ( f , ", .. ({} fields)" , extra_count ) ? ; } write ! ( f , " }}" ) } } impl :: core :: default :: Default for EthCellData { fn default ( ) -> Self { let v : Vec < u8 > = vec ! [ 28 , 0 , 0 , 0 , 8 , 0 , 0 , 0 , 20 , 0 , 0 , 0 , 12 , 0 , 0 , 0 , 16 , 0 , 0 , 0 , 4 , 0 , 0 , 0 , 4 , 0 , 0 , 0 , ] ; EthCellData :: new_unchecked ( v . into ( ) ) } } impl EthCellData { pub const FIELD_COUNT : usize = 1 ; pub fn total_size ( & self ) -> usize { molecule :: unpack_number ( self . as_slice ( ) ) as usize } pub fn field_count ( & self ) -> usize { if self . total_size ( ) == molecule :: NUMBER_SIZE { 0 } else { ( molecule :: unpack_number ( & self . as_slice ( ) [ molecule :: NUMBER_SIZE .. ] ) as usize / 4 ) - 1 } } pub fn count_extra_fields ( & self ) -> usize { self . field_count ( ) - Self :: FIELD_COUNT } pub fn has_extra_fields ( & self ) -> bool { Self :: FIELD_COUNT != self . field_count ( ) } pub fn headers ( & self ) -> Chain { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 4 .. ] ) as usize ; if self . has_extra_fields ( ) { let end = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; Chain :: new_unchecked ( self . 0 . slice ( start .. end ) ) } else { Chain :: new_unchecked ( self . 0 . slice ( start .. ) ) } } pub fn as_reader < 'r > ( & 'r self ) -> EthCellDataReader < 'r > { EthCellDataReader :: new_unchecked ( self . as_slice ( ) ) } } impl molecule :: prelude :: Entity for EthCellData { type Builder = EthCellDataBuilder ; const NAME : & 'static str = "EthCellData" ; fn new_unchecked ( data : molecule :: bytes :: Bytes ) -> Self { EthCellData ( data ) } fn as_bytes ( & self ) -> molecule :: bytes :: Bytes { self . 0 . clone ( ) } fn as_slice ( & self ) -> & [ u8 ] { & self . 0 [ .. ] } fn from_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { EthCellDataReader :: from_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn from_compatible_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { EthCellDataReader :: from_compatible_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn new_builder ( ) -> Self :: Builder { :: core :: default :: Default :: default ( ) } fn as_builder ( self ) -> Self :: Builder { Self :: new_builder ( ) . headers ( self . headers ( ) ) } } -# [ derive ( Clone , Copy ) ] pub struct EthCellDataReader < 'r > ( & 'r [ u8 ] ) ; impl < 'r > :: core :: fmt :: LowerHex for EthCellDataReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl < 'r > :: core :: fmt :: Debug for EthCellDataReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl < 'r > :: core :: fmt :: Display for EthCellDataReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{} {{ " , Self :: NAME ) ? ; write ! ( f , "{}: {}" , "headers" , self . headers ( ) ) ? ; let extra_count = self . count_extra_fields ( ) ; if extra_count != 0 { write ! ( f , ", .. ({} fields)" , extra_count ) ? ; } write ! ( f , " }}" ) } } impl < 'r > EthCellDataReader < 'r > { pub const FIELD_COUNT : usize = 1 ; pub fn total_size ( & self ) -> usize { molecule :: unpack_number ( self . as_slice ( ) ) as usize } pub fn field_count ( & self ) -> usize { if self . total_size ( ) == molecule :: NUMBER_SIZE { 0 } else { ( molecule :: unpack_number ( & self . as_slice ( ) [ molecule :: NUMBER_SIZE .. ] ) as usize / 4 ) - 1 } } pub fn count_extra_fields ( & self ) -> usize { self . field_count ( ) - Self :: FIELD_COUNT } pub fn has_extra_fields ( & self ) -> bool { Self :: FIELD_COUNT != self . field_count ( ) } pub fn headers ( & self ) -> ChainReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 4 .. ] ) as usize ; if self . has_extra_fields ( ) { let end = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; ChainReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } else { ChainReader :: new_unchecked ( & self . as_slice ( ) [ start .. ] ) } } } impl < 'r > molecule :: prelude :: Reader < 'r > for EthCellDataReader < 'r > { type Entity = EthCellData ; const NAME : & 'static str = "EthCellDataReader" ; fn to_entity ( & self ) -> Self :: Entity { Self :: Entity :: new_unchecked ( self . as_slice ( ) . to_owned ( ) . into ( ) ) } fn new_unchecked ( slice : & 'r [ u8 ] ) -> Self { EthCellDataReader ( slice ) } fn as_slice ( & self ) -> & 'r [ u8 ] { self . 0 } fn verify ( slice : & [ u8 ] , compatible : bool ) -> molecule :: error :: VerificationResult < ( ) > { use molecule :: verification_error as ve ; let slice_len = slice . len ( ) ; if slice_len < molecule :: NUMBER_SIZE { return ve ! ( Self , HeaderIsBroken , molecule :: NUMBER_SIZE , slice_len ) ; } let total_size = molecule :: unpack_number ( slice ) as usize ; if slice_len != total_size { return ve ! ( Self , TotalSizeNotMatch , total_size , slice_len ) ; } if slice_len == molecule :: NUMBER_SIZE && Self :: FIELD_COUNT == 0 { return Ok ( ( ) ) ; } if slice_len < molecule :: NUMBER_SIZE * 2 { return ve ! ( Self , HeaderIsBroken , molecule :: NUMBER_SIZE * 2 , slice_len ) ; } let offset_first = molecule :: unpack_number ( & slice [ molecule :: NUMBER_SIZE .. ] ) as usize ; if offset_first % 4 != 0 || offset_first < molecule :: NUMBER_SIZE * 2 { return ve ! ( Self , OffsetsNotMatch ) ; } let field_count = offset_first / 4 - 1 ; if field_count < Self :: FIELD_COUNT { return ve ! ( Self , FieldCountNotMatch , Self :: FIELD_COUNT , field_count ) ; } else if ! compatible && field_count > Self :: FIELD_COUNT { return ve ! ( Self , FieldCountNotMatch , Self :: FIELD_COUNT , field_count ) ; } ; let header_size = molecule :: NUMBER_SIZE * ( field_count + 1 ) ; if slice_len < header_size { return ve ! ( Self , HeaderIsBroken , header_size , slice_len ) ; } let mut offsets : Vec < usize > = slice [ molecule :: NUMBER_SIZE .. ] . chunks ( molecule :: NUMBER_SIZE ) . take ( field_count ) . map ( | x | molecule :: unpack_number ( x ) as usize ) . collect ( ) ; offsets . push ( total_size ) ; if offsets . windows ( 2 ) . any ( | i | i [ 0 ] > i [ 1 ] ) { return ve ! ( Self , OffsetsNotMatch ) ; } ChainReader :: verify ( & slice [ offsets [ 0 ] .. offsets [ 1 ] ] , compatible ) ? ; Ok ( ( ) ) } } -# [ derive ( Debug , Default ) ] pub struct EthCellDataBuilder { pub ( crate ) headers : Chain , } impl EthCellDataBuilder { pub const FIELD_COUNT : usize = 1 ; pub fn headers ( mut self , v : Chain ) -> Self { self . headers = v ; self } } impl molecule :: prelude :: Builder for EthCellDataBuilder { type Entity = EthCellData ; const NAME : & 'static str = "EthCellDataBuilder" ; fn expected_length ( & self ) -> usize { molecule :: NUMBER_SIZE * ( Self :: FIELD_COUNT + 1 ) + self . headers . as_slice ( ) . len ( ) } fn write < W : :: molecule :: io :: Write > ( & self , writer : & mut W ) -> :: molecule :: io :: Result < ( ) > { let mut total_size = molecule :: NUMBER_SIZE * ( Self :: FIELD_COUNT + 1 ) ; let mut offsets = Vec :: with_capacity ( Self :: FIELD_COUNT ) ; offsets . push ( total_size ) ; total_size += self . headers . as_slice ( ) . len ( ) ; writer . write_all ( & molecule :: pack_number ( total_size as molecule :: Number ) ) ? ; for offset in offsets . into_iter ( ) { writer . write_all ( & molecule :: pack_number ( offset as molecule :: Number ) ) ? ; } writer . write_all ( self . headers . as_slice ( ) ) ? ; Ok ( ( ) ) } fn build ( & self ) -> Self :: Entity { let mut inner = Vec :: with_capacity ( self . expected_length ( ) ) ; self . write ( & mut inner ) . unwrap_or_else ( | _ | panic ! ( "{} build should be ok" , Self :: NAME ) ) ; EthCellData :: new_unchecked ( inner . into ( ) ) } } -# [ derive ( Clone ) ] pub struct Chain ( molecule :: bytes :: Bytes ) ; impl :: core :: fmt :: LowerHex for Chain { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl :: core :: fmt :: Debug for Chain { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl :: core :: fmt :: Display for Chain { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{} {{ " , Self :: NAME ) ? ; write ! ( f , "{}: {}" , "main" , self . main ( ) ) ? ; write ! ( f , ", {}: {}" , "uncle" , self . uncle ( ) ) ? ; let extra_count = self . count_extra_fields ( ) ; if extra_count != 0 { write ! ( f , ", .. ({} fields)" , extra_count ) ? ; } write ! ( f , " }}" ) } } impl :: core :: default :: Default for Chain { fn default ( ) -> Self { let v : Vec < u8 > = vec ! [ 20 , 0 , 0 , 0 , 12 , 0 , 0 , 0 , 16 , 0 , 0 , 0 , 4 , 0 , 0 , 0 , 4 , 0 , 0 , 0 , ] ; Chain :: new_unchecked ( v . into ( ) ) } } impl Chain { pub const FIELD_COUNT : usize = 2 ; pub fn total_size ( & self ) -> usize { molecule :: unpack_number ( self . as_slice ( ) ) as usize } pub fn field_count ( & self ) -> usize { if self . total_size ( ) == molecule :: NUMBER_SIZE { 0 } else { ( molecule :: unpack_number ( & self . as_slice ( ) [ molecule :: NUMBER_SIZE .. ] ) as usize / 4 ) - 1 } } pub fn count_extra_fields ( & self ) -> usize { self . field_count ( ) - Self :: FIELD_COUNT } pub fn has_extra_fields ( & self ) -> bool { Self :: FIELD_COUNT != self . field_count ( ) } pub fn main ( & self ) -> Bytes2 { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 4 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; Bytes2 :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn uncle ( & self ) -> Bytes2 { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; if self . has_extra_fields ( ) { let end = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; Bytes2 :: new_unchecked ( self . 0 . slice ( start .. end ) ) } else { Bytes2 :: new_unchecked ( self . 0 . slice ( start .. ) ) } } pub fn as_reader < 'r > ( & 'r self ) -> ChainReader < 'r > { ChainReader :: new_unchecked ( self . as_slice ( ) ) } } impl molecule :: prelude :: Entity for Chain { type Builder = ChainBuilder ; const NAME : & 'static str = "Chain" ; fn new_unchecked ( data : molecule :: bytes :: Bytes ) -> Self { Chain ( data ) } fn as_bytes ( & self ) -> molecule :: bytes :: Bytes { self . 0 . clone ( ) } fn as_slice ( & self ) -> & [ u8 ] { & self . 0 [ .. ] } fn from_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { ChainReader :: from_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn from_compatible_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { ChainReader :: from_compatible_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn new_builder ( ) -> Self :: Builder { :: core :: default :: Default :: default ( ) } fn as_builder ( self ) -> Self :: Builder { Self :: new_builder ( ) . main ( self . main ( ) ) . uncle ( self . uncle ( ) ) } } -# [ derive ( Clone , Copy ) ] pub struct ChainReader < 'r > ( & 'r [ u8 ] ) ; impl < 'r > :: core :: fmt :: LowerHex for ChainReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl < 'r > :: core :: fmt :: Debug for ChainReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl < 'r > :: core :: fmt :: Display for ChainReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{} {{ " , Self :: NAME ) ? ; write ! ( f , "{}: {}" , "main" , self . main ( ) ) ? ; write ! ( f , ", {}: {}" , "uncle" , self . uncle ( ) ) ? ; let extra_count = self . count_extra_fields ( ) ; if extra_count != 0 { write ! ( f , ", .. ({} fields)" , extra_count ) ? ; } write ! ( f , " }}" ) } } impl < 'r > ChainReader < 'r > { pub const FIELD_COUNT : usize = 2 ; pub fn total_size ( & self ) -> usize { molecule :: unpack_number ( self . as_slice ( ) ) as usize } pub fn field_count ( & self ) -> usize { if self . total_size ( ) == molecule :: NUMBER_SIZE { 0 } else { ( molecule :: unpack_number ( & self . as_slice ( ) [ molecule :: NUMBER_SIZE .. ] ) as usize / 4 ) - 1 } } pub fn count_extra_fields ( & self ) -> usize { self . field_count ( ) - Self :: FIELD_COUNT } pub fn has_extra_fields ( & self ) -> bool { Self :: FIELD_COUNT != self . field_count ( ) } pub fn main ( & self ) -> Bytes2Reader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 4 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; Bytes2Reader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn uncle ( & self ) -> Bytes2Reader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; if self . has_extra_fields ( ) { let end = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; Bytes2Reader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } else { Bytes2Reader :: new_unchecked ( & self . as_slice ( ) [ start .. ] ) } } } impl < 'r > molecule :: prelude :: Reader < 'r > for ChainReader < 'r > { type Entity = Chain ; const NAME : & 'static str = "ChainReader" ; fn to_entity ( & self ) -> Self :: Entity { Self :: Entity :: new_unchecked ( self . as_slice ( ) . to_owned ( ) . into ( ) ) } fn new_unchecked ( slice : & 'r [ u8 ] ) -> Self { ChainReader ( slice ) } fn as_slice ( & self ) -> & 'r [ u8 ] { self . 0 } fn verify ( slice : & [ u8 ] , compatible : bool ) -> molecule :: error :: VerificationResult < ( ) > { use molecule :: verification_error as ve ; let slice_len = slice . len ( ) ; if slice_len < molecule :: NUMBER_SIZE { return ve ! ( Self , HeaderIsBroken , molecule :: NUMBER_SIZE , slice_len ) ; } let total_size = molecule :: unpack_number ( slice ) as usize ; if slice_len != total_size { return ve ! ( Self , TotalSizeNotMatch , total_size , slice_len ) ; } if slice_len == molecule :: NUMBER_SIZE && Self :: FIELD_COUNT == 0 { return Ok ( ( ) ) ; } if slice_len < molecule :: NUMBER_SIZE * 2 { return ve ! ( Self , HeaderIsBroken , molecule :: NUMBER_SIZE * 2 , slice_len ) ; } let offset_first = molecule :: unpack_number ( & slice [ molecule :: NUMBER_SIZE .. ] ) as usize ; if offset_first % 4 != 0 || offset_first < molecule :: NUMBER_SIZE * 2 { return ve ! ( Self , OffsetsNotMatch ) ; } let field_count = offset_first / 4 - 1 ; if field_count < Self :: FIELD_COUNT { return ve ! ( Self , FieldCountNotMatch , Self :: FIELD_COUNT , field_count ) ; } else if ! compatible && field_count > Self :: FIELD_COUNT { return ve ! ( Self , FieldCountNotMatch , Self :: FIELD_COUNT , field_count ) ; } ; let header_size = molecule :: NUMBER_SIZE * ( field_count + 1 ) ; if slice_len < header_size { return ve ! ( Self , HeaderIsBroken , header_size , slice_len ) ; } let mut offsets : Vec < usize > = slice [ molecule :: NUMBER_SIZE .. ] . chunks ( molecule :: NUMBER_SIZE ) . take ( field_count ) . map ( | x | molecule :: unpack_number ( x ) as usize ) . collect ( ) ; offsets . push ( total_size ) ; if offsets . windows ( 2 ) . any ( | i | i [ 0 ] > i [ 1 ] ) { return ve ! ( Self , OffsetsNotMatch ) ; } Bytes2Reader :: verify ( & slice [ offsets [ 0 ] .. offsets [ 1 ] ] , compatible ) ? ; Bytes2Reader :: verify ( & slice [ offsets [ 1 ] .. offsets [ 2 ] ] , compatible ) ? ; Ok ( ( ) ) } } -# [ derive ( Debug , Default ) ] pub struct ChainBuilder { pub ( crate ) main : Bytes2 , pub ( crate ) uncle : Bytes2 , } impl ChainBuilder { pub const FIELD_COUNT : usize = 2 ; pub fn main ( mut self , v : Bytes2 ) -> Self { self . main = v ; self } pub fn uncle ( mut self , v : Bytes2 ) -> Self { self . uncle = v ; self } } impl molecule :: prelude :: Builder for ChainBuilder { type Entity = Chain ; const NAME : & 'static str = "ChainBuilder" ; fn expected_length ( & self ) -> usize { molecule :: NUMBER_SIZE * ( Self :: FIELD_COUNT + 1 ) + self . main . as_slice ( ) . len ( ) + self . uncle . as_slice ( ) . len ( ) } fn write < W : :: molecule :: io :: Write > ( & self , writer : & mut W ) -> :: molecule :: io :: Result < ( ) > { let mut total_size = molecule :: NUMBER_SIZE * ( Self :: FIELD_COUNT + 1 ) ; let mut offsets = Vec :: with_capacity ( Self :: FIELD_COUNT ) ; offsets . push ( total_size ) ; total_size += self . main . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . uncle . as_slice ( ) . len ( ) ; writer . write_all ( & molecule :: pack_number ( total_size as molecule :: Number ) ) ? ; for offset in offsets . into_iter ( ) { writer . write_all ( & molecule :: pack_number ( offset as molecule :: Number ) ) ? ; } writer . write_all ( self . main . as_slice ( ) ) ? ; writer . write_all ( self . uncle . as_slice ( ) ) ? ; Ok ( ( ) ) } fn build ( & self ) -> Self :: Entity { let mut inner = Vec :: with_capacity ( self . expected_length ( ) ) ; self . write ( & mut inner ) . unwrap_or_else ( | _ | panic ! ( "{} build should be ok" , Self :: NAME ) ) ; Chain :: new_unchecked ( inner . into ( ) ) } } -# [ derive ( Clone ) ] pub struct HeaderInfo ( molecule :: bytes :: Bytes ) ; impl :: core :: fmt :: LowerHex for HeaderInfo { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl :: core :: fmt :: Debug for HeaderInfo { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl :: core :: fmt :: Display for HeaderInfo { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{} {{ " , Self :: NAME ) ? ; write ! ( f , "{}: {}" , "header" , self . header ( ) ) ? ; write ! ( f , ", {}: {}" , "total_difficulty" , self . total_difficulty ( ) ) ? ; write ! ( f , ", {}: {}" , "hash" , self . hash ( ) ) ? ; let extra_count = self . count_extra_fields ( ) ; if extra_count != 0 { write ! ( f , ", .. ({} fields)" , extra_count ) ? ; } write ! ( f , " }}" ) } } impl :: core :: default :: Default for HeaderInfo { fn default ( ) -> Self { let v : Vec < u8 > = vec ! [ 60 , 0 , 0 , 0 , 16 , 0 , 0 , 0 , 20 , 0 , 0 , 0 , 28 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , ] ; HeaderInfo :: new_unchecked ( v . into ( ) ) } } impl HeaderInfo { pub const FIELD_COUNT : usize = 3 ; pub fn total_size ( & self ) -> usize { molecule :: unpack_number ( self . as_slice ( ) ) as usize } pub fn field_count ( & self ) -> usize { if self . total_size ( ) == molecule :: NUMBER_SIZE { 0 } else { ( molecule :: unpack_number ( & self . as_slice ( ) [ molecule :: NUMBER_SIZE .. ] ) as usize / 4 ) - 1 } } pub fn count_extra_fields ( & self ) -> usize { self . field_count ( ) - Self :: FIELD_COUNT } pub fn has_extra_fields ( & self ) -> bool { Self :: FIELD_COUNT != self . field_count ( ) } pub fn header ( & self ) -> Bytes { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 4 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; Bytes :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn total_difficulty ( & self ) -> Uint64 { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; Uint64 :: new_unchecked ( self . 0 . slice ( start .. end ) ) } pub fn hash ( & self ) -> Byte32 { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; if self . has_extra_fields ( ) { let end = molecule :: unpack_number ( & slice [ 16 .. ] ) as usize ; Byte32 :: new_unchecked ( self . 0 . slice ( start .. end ) ) } else { Byte32 :: new_unchecked ( self . 0 . slice ( start .. ) ) } } pub fn as_reader < 'r > ( & 'r self ) -> HeaderInfoReader < 'r > { HeaderInfoReader :: new_unchecked ( self . as_slice ( ) ) } } impl molecule :: prelude :: Entity for HeaderInfo { type Builder = HeaderInfoBuilder ; const NAME : & 'static str = "HeaderInfo" ; fn new_unchecked ( data : molecule :: bytes :: Bytes ) -> Self { HeaderInfo ( data ) } fn as_bytes ( & self ) -> molecule :: bytes :: Bytes { self . 0 . clone ( ) } fn as_slice ( & self ) -> & [ u8 ] { & self . 0 [ .. ] } fn from_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { HeaderInfoReader :: from_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn from_compatible_slice ( slice : & [ u8 ] ) -> molecule :: error :: VerificationResult < Self > { HeaderInfoReader :: from_compatible_slice ( slice ) . map ( | reader | reader . to_entity ( ) ) } fn new_builder ( ) -> Self :: Builder { :: core :: default :: Default :: default ( ) } fn as_builder ( self ) -> Self :: Builder { Self :: new_builder ( ) . header ( self . header ( ) ) . total_difficulty ( self . total_difficulty ( ) ) . hash ( self . hash ( ) ) } } -# [ derive ( Clone , Copy ) ] pub struct HeaderInfoReader < 'r > ( & 'r [ u8 ] ) ; impl < 'r > :: core :: fmt :: LowerHex for HeaderInfoReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { use molecule :: hex_string ; if f . alternate ( ) { write ! ( f , "0x" ) ? ; } write ! ( f , "{}" , hex_string ( self . as_slice ( ) ) ) } } impl < 'r > :: core :: fmt :: Debug for HeaderInfoReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{}({:#x})" , Self :: NAME , self ) } } impl < 'r > :: core :: fmt :: Display for HeaderInfoReader < 'r > { fn fmt ( & self , f : & mut :: core :: fmt :: Formatter ) -> :: core :: fmt :: Result { write ! ( f , "{} {{ " , Self :: NAME ) ? ; write ! ( f , "{}: {}" , "header" , self . header ( ) ) ? ; write ! ( f , ", {}: {}" , "total_difficulty" , self . total_difficulty ( ) ) ? ; write ! ( f , ", {}: {}" , "hash" , self . hash ( ) ) ? ; let extra_count = self . count_extra_fields ( ) ; if extra_count != 0 { write ! ( f , ", .. ({} fields)" , extra_count ) ? ; } write ! ( f , " }}" ) } } impl < 'r > HeaderInfoReader < 'r > { pub const FIELD_COUNT : usize = 3 ; pub fn total_size ( & self ) -> usize { molecule :: unpack_number ( self . as_slice ( ) ) as usize } pub fn field_count ( & self ) -> usize { if self . total_size ( ) == molecule :: NUMBER_SIZE { 0 } else { ( molecule :: unpack_number ( & self . as_slice ( ) [ molecule :: NUMBER_SIZE .. ] ) as usize / 4 ) - 1 } } pub fn count_extra_fields ( & self ) -> usize { self . field_count ( ) - Self :: FIELD_COUNT } pub fn has_extra_fields ( & self ) -> bool { Self :: FIELD_COUNT != self . field_count ( ) } pub fn header ( & self ) -> BytesReader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 4 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; BytesReader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn total_difficulty ( & self ) -> Uint64Reader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 8 .. ] ) as usize ; let end = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; Uint64Reader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } pub fn hash ( & self ) -> Byte32Reader < 'r > { let slice = self . as_slice ( ) ; let start = molecule :: unpack_number ( & slice [ 12 .. ] ) as usize ; if self . has_extra_fields ( ) { let end = molecule :: unpack_number ( & slice [ 16 .. ] ) as usize ; Byte32Reader :: new_unchecked ( & self . as_slice ( ) [ start .. end ] ) } else { Byte32Reader :: new_unchecked ( & self . as_slice ( ) [ start .. ] ) } } } impl < 'r > molecule :: prelude :: Reader < 'r > for HeaderInfoReader < 'r > { type Entity = HeaderInfo ; const NAME : & 'static str = "HeaderInfoReader" ; fn to_entity ( & self ) -> Self :: Entity { Self :: Entity :: new_unchecked ( self . as_slice ( ) . to_owned ( ) . into ( ) ) } fn new_unchecked ( slice : & 'r [ u8 ] ) -> Self { HeaderInfoReader ( slice ) } fn as_slice ( & self ) -> & 'r [ u8 ] { self . 0 } fn verify ( slice : & [ u8 ] , compatible : bool ) -> molecule :: error :: VerificationResult < ( ) > { use molecule :: verification_error as ve ; let slice_len = slice . len ( ) ; if slice_len < molecule :: NUMBER_SIZE { return ve ! ( Self , HeaderIsBroken , molecule :: NUMBER_SIZE , slice_len ) ; } let total_size = molecule :: unpack_number ( slice ) as usize ; if slice_len != total_size { return ve ! ( Self , TotalSizeNotMatch , total_size , slice_len ) ; } if slice_len == molecule :: NUMBER_SIZE && Self :: FIELD_COUNT == 0 { return Ok ( ( ) ) ; } if slice_len < molecule :: NUMBER_SIZE * 2 { return ve ! ( Self , HeaderIsBroken , molecule :: NUMBER_SIZE * 2 , slice_len ) ; } let offset_first = molecule :: unpack_number ( & slice [ molecule :: NUMBER_SIZE .. ] ) as usize ; if offset_first % 4 != 0 || offset_first < molecule :: NUMBER_SIZE * 2 { return ve ! ( Self , OffsetsNotMatch ) ; } let field_count = offset_first / 4 - 1 ; if field_count < Self :: FIELD_COUNT { return ve ! ( Self , FieldCountNotMatch , Self :: FIELD_COUNT , field_count ) ; } else if ! compatible && field_count > Self :: FIELD_COUNT { return ve ! ( Self , FieldCountNotMatch , Self :: FIELD_COUNT , field_count ) ; } ; let header_size = molecule :: NUMBER_SIZE * ( field_count + 1 ) ; if slice_len < header_size { return ve ! ( Self , HeaderIsBroken , header_size , slice_len ) ; } let mut offsets : Vec < usize > = slice [ molecule :: NUMBER_SIZE .. ] . chunks ( molecule :: NUMBER_SIZE ) . take ( field_count ) . map ( | x | molecule :: unpack_number ( x ) as usize ) . collect ( ) ; offsets . push ( total_size ) ; if offsets . windows ( 2 ) . any ( | i | i [ 0 ] > i [ 1 ] ) { return ve ! ( Self , OffsetsNotMatch ) ; } BytesReader :: verify ( & slice [ offsets [ 0 ] .. offsets [ 1 ] ] , compatible ) ? ; Uint64Reader :: verify ( & slice [ offsets [ 1 ] .. offsets [ 2 ] ] , compatible ) ? ; Byte32Reader :: verify ( & slice [ offsets [ 2 ] .. offsets [ 3 ] ] , compatible ) ? ; Ok ( ( ) ) } } -# [ derive ( Debug , Default ) ] pub struct HeaderInfoBuilder { pub ( crate ) header : Bytes , pub ( crate ) total_difficulty : Uint64 , pub ( crate ) hash : Byte32 , } impl HeaderInfoBuilder { pub const FIELD_COUNT : usize = 3 ; pub fn header ( mut self , v : Bytes ) -> Self { self . header = v ; self } pub fn total_difficulty ( mut self , v : Uint64 ) -> Self { self . total_difficulty = v ; self } pub fn hash ( mut self , v : Byte32 ) -> Self { self . hash = v ; self } } impl molecule :: prelude :: Builder for HeaderInfoBuilder { type Entity = HeaderInfo ; const NAME : & 'static str = "HeaderInfoBuilder" ; fn expected_length ( & self ) -> usize { molecule :: NUMBER_SIZE * ( Self :: FIELD_COUNT + 1 ) + self . header . as_slice ( ) . len ( ) + self . total_difficulty . as_slice ( ) . len ( ) + self . hash . as_slice ( ) . len ( ) } fn write < W : :: molecule :: io :: Write > ( & self , writer : & mut W ) -> :: molecule :: io :: Result < ( ) > { let mut total_size = molecule :: NUMBER_SIZE * ( Self :: FIELD_COUNT + 1 ) ; let mut offsets = Vec :: with_capacity ( Self :: FIELD_COUNT ) ; offsets . push ( total_size ) ; total_size += self . header . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . total_difficulty . as_slice ( ) . len ( ) ; offsets . push ( total_size ) ; total_size += self . hash . as_slice ( ) . len ( ) ; writer . write_all ( & molecule :: pack_number ( total_size as molecule :: Number ) ) ? ; for offset in offsets . into_iter ( ) { writer . write_all ( & molecule :: pack_number ( offset as molecule :: Number ) ) ? ; } writer . write_all ( self . header . as_slice ( ) ) ? ; writer . write_all ( self . total_difficulty . as_slice ( ) ) ? ; writer . write_all ( self . hash . as_slice ( ) ) ? ; Ok ( ( ) ) } fn build ( & self ) -> Self :: Entity { let mut inner = Vec :: with_capacity ( self . expected_length ( ) ) ; self . write ( & mut inner ) . unwrap_or_else ( | _ | panic ! ( "{} build should be ok" , Self :: NAME ) ) ; HeaderInfo :: new_unchecked ( inner . into ( ) ) } } +use super::basic::*; +use molecule::prelude::*; +#[derive(Clone)] +pub struct EthCellData(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for EthCellData { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for EthCellData { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for EthCellData { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "headers", self.headers())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl ::core::default::Default for EthCellData { + fn default() -> Self { + let v: Vec = vec![ + 28, 0, 0, 0, 8, 0, 0, 0, 20, 0, 0, 0, 12, 0, 0, 0, 16, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + ]; + EthCellData::new_unchecked(v.into()) + } +} +impl EthCellData { + pub const FIELD_COUNT: usize = 1; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn headers(&self) -> Chain { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[8..]) as usize; + Chain::new_unchecked(self.0.slice(start..end)) + } else { + Chain::new_unchecked(self.0.slice(start..)) + } + } + pub fn as_reader<'r>(&'r self) -> EthCellDataReader<'r> { + EthCellDataReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for EthCellData { + type Builder = EthCellDataBuilder; + const NAME: &'static str = "EthCellData"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + EthCellData(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + EthCellDataReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + EthCellDataReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder().headers(self.headers()) + } +} +#[derive(Clone, Copy)] +pub struct EthCellDataReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for EthCellDataReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for EthCellDataReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for EthCellDataReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "headers", self.headers())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl<'r> EthCellDataReader<'r> { + pub const FIELD_COUNT: usize = 1; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn headers(&self) -> ChainReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[8..]) as usize; + ChainReader::new_unchecked(&self.as_slice()[start..end]) + } else { + ChainReader::new_unchecked(&self.as_slice()[start..]) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for EthCellDataReader<'r> { + type Entity = EthCellData; + const NAME: &'static str = "EthCellDataReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + EthCellDataReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let total_size = molecule::unpack_number(slice) as usize; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + if slice_len == molecule::NUMBER_SIZE && Self::FIELD_COUNT == 0 { + return Ok(()); + } + if slice_len < molecule::NUMBER_SIZE * 2 { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); + } + let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; + if offset_first % 4 != 0 || offset_first < molecule::NUMBER_SIZE * 2 { + return ve!(Self, OffsetsNotMatch); + } + let field_count = offset_first / 4 - 1; + if field_count < Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + } else if !compatible && field_count > Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + }; + let header_size = molecule::NUMBER_SIZE * (field_count + 1); + if slice_len < header_size { + return ve!(Self, HeaderIsBroken, header_size, slice_len); + } + let mut offsets: Vec = slice[molecule::NUMBER_SIZE..] + .chunks(molecule::NUMBER_SIZE) + .take(field_count) + .map(|x| molecule::unpack_number(x) as usize) + .collect(); + offsets.push(total_size); + if offsets.windows(2).any(|i| i[0] > i[1]) { + return ve!(Self, OffsetsNotMatch); + } + ChainReader::verify(&slice[offsets[0]..offsets[1]], compatible)?; + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct EthCellDataBuilder { + pub(crate) headers: Chain, +} +impl EthCellDataBuilder { + pub const FIELD_COUNT: usize = 1; + pub fn headers(mut self, v: Chain) -> Self { + self.headers = v; + self + } +} +impl molecule::prelude::Builder for EthCellDataBuilder { + type Entity = EthCellData; + const NAME: &'static str = "EthCellDataBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) + self.headers.as_slice().len() + } + fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { + let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); + let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); + offsets.push(total_size); + total_size += self.headers.as_slice().len(); + writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; + for offset in offsets.into_iter() { + writer.write_all(&molecule::pack_number(offset as molecule::Number))?; + } + writer.write_all(self.headers.as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + EthCellData::new_unchecked(inner.into()) + } +} +#[derive(Clone)] +pub struct Chain(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for Chain { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for Chain { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for Chain { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "main", self.main())?; + write!(f, ", {}: {}", "uncle", self.uncle())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl ::core::default::Default for Chain { + fn default() -> Self { + let v: Vec = vec![ + 20, 0, 0, 0, 12, 0, 0, 0, 16, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + ]; + Chain::new_unchecked(v.into()) + } +} +impl Chain { + pub const FIELD_COUNT: usize = 2; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn main(&self) -> Bytes2 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + Bytes2::new_unchecked(self.0.slice(start..end)) + } + pub fn uncle(&self) -> Bytes2 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[12..]) as usize; + Bytes2::new_unchecked(self.0.slice(start..end)) + } else { + Bytes2::new_unchecked(self.0.slice(start..)) + } + } + pub fn as_reader<'r>(&'r self) -> ChainReader<'r> { + ChainReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for Chain { + type Builder = ChainBuilder; + const NAME: &'static str = "Chain"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + Chain(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + ChainReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + ChainReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder().main(self.main()).uncle(self.uncle()) + } +} +#[derive(Clone, Copy)] +pub struct ChainReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for ChainReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for ChainReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for ChainReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "main", self.main())?; + write!(f, ", {}: {}", "uncle", self.uncle())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl<'r> ChainReader<'r> { + pub const FIELD_COUNT: usize = 2; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn main(&self) -> Bytes2Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + Bytes2Reader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn uncle(&self) -> Bytes2Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[12..]) as usize; + Bytes2Reader::new_unchecked(&self.as_slice()[start..end]) + } else { + Bytes2Reader::new_unchecked(&self.as_slice()[start..]) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for ChainReader<'r> { + type Entity = Chain; + const NAME: &'static str = "ChainReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + ChainReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let total_size = molecule::unpack_number(slice) as usize; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + if slice_len == molecule::NUMBER_SIZE && Self::FIELD_COUNT == 0 { + return Ok(()); + } + if slice_len < molecule::NUMBER_SIZE * 2 { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); + } + let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; + if offset_first % 4 != 0 || offset_first < molecule::NUMBER_SIZE * 2 { + return ve!(Self, OffsetsNotMatch); + } + let field_count = offset_first / 4 - 1; + if field_count < Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + } else if !compatible && field_count > Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + }; + let header_size = molecule::NUMBER_SIZE * (field_count + 1); + if slice_len < header_size { + return ve!(Self, HeaderIsBroken, header_size, slice_len); + } + let mut offsets: Vec = slice[molecule::NUMBER_SIZE..] + .chunks(molecule::NUMBER_SIZE) + .take(field_count) + .map(|x| molecule::unpack_number(x) as usize) + .collect(); + offsets.push(total_size); + if offsets.windows(2).any(|i| i[0] > i[1]) { + return ve!(Self, OffsetsNotMatch); + } + Bytes2Reader::verify(&slice[offsets[0]..offsets[1]], compatible)?; + Bytes2Reader::verify(&slice[offsets[1]..offsets[2]], compatible)?; + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct ChainBuilder { + pub(crate) main: Bytes2, + pub(crate) uncle: Bytes2, +} +impl ChainBuilder { + pub const FIELD_COUNT: usize = 2; + pub fn main(mut self, v: Bytes2) -> Self { + self.main = v; + self + } + pub fn uncle(mut self, v: Bytes2) -> Self { + self.uncle = v; + self + } +} +impl molecule::prelude::Builder for ChainBuilder { + type Entity = Chain; + const NAME: &'static str = "ChainBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) + + self.main.as_slice().len() + + self.uncle.as_slice().len() + } + fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { + let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); + let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); + offsets.push(total_size); + total_size += self.main.as_slice().len(); + offsets.push(total_size); + total_size += self.uncle.as_slice().len(); + writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; + for offset in offsets.into_iter() { + writer.write_all(&molecule::pack_number(offset as molecule::Number))?; + } + writer.write_all(self.main.as_slice())?; + writer.write_all(self.uncle.as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + Chain::new_unchecked(inner.into()) + } +} +#[derive(Clone)] +pub struct HeaderInfo(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for HeaderInfo { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for HeaderInfo { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for HeaderInfo { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "header", self.header())?; + write!(f, ", {}: {}", "total_difficulty", self.total_difficulty())?; + write!(f, ", {}: {}", "hash", self.hash())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl ::core::default::Default for HeaderInfo { + fn default() -> Self { + let v: Vec = vec![ + 60, 0, 0, 0, 16, 0, 0, 0, 20, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, + ]; + HeaderInfo::new_unchecked(v.into()) + } +} +impl HeaderInfo { + pub const FIELD_COUNT: usize = 3; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn header(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } + pub fn total_difficulty(&self) -> Uint64 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + let end = molecule::unpack_number(&slice[12..]) as usize; + Uint64::new_unchecked(self.0.slice(start..end)) + } + pub fn hash(&self) -> Byte32 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[12..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[16..]) as usize; + Byte32::new_unchecked(self.0.slice(start..end)) + } else { + Byte32::new_unchecked(self.0.slice(start..)) + } + } + pub fn as_reader<'r>(&'r self) -> HeaderInfoReader<'r> { + HeaderInfoReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for HeaderInfo { + type Builder = HeaderInfoBuilder; + const NAME: &'static str = "HeaderInfo"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + HeaderInfo(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + HeaderInfoReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + HeaderInfoReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder() + .header(self.header()) + .total_difficulty(self.total_difficulty()) + .hash(self.hash()) + } +} +#[derive(Clone, Copy)] +pub struct HeaderInfoReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for HeaderInfoReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for HeaderInfoReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for HeaderInfoReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "header", self.header())?; + write!(f, ", {}: {}", "total_difficulty", self.total_difficulty())?; + write!(f, ", {}: {}", "hash", self.hash())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl<'r> HeaderInfoReader<'r> { + pub const FIELD_COUNT: usize = 3; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn header(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn total_difficulty(&self) -> Uint64Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + let end = molecule::unpack_number(&slice[12..]) as usize; + Uint64Reader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn hash(&self) -> Byte32Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[12..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[16..]) as usize; + Byte32Reader::new_unchecked(&self.as_slice()[start..end]) + } else { + Byte32Reader::new_unchecked(&self.as_slice()[start..]) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for HeaderInfoReader<'r> { + type Entity = HeaderInfo; + const NAME: &'static str = "HeaderInfoReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + HeaderInfoReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let total_size = molecule::unpack_number(slice) as usize; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + if slice_len == molecule::NUMBER_SIZE && Self::FIELD_COUNT == 0 { + return Ok(()); + } + if slice_len < molecule::NUMBER_SIZE * 2 { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); + } + let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; + if offset_first % 4 != 0 || offset_first < molecule::NUMBER_SIZE * 2 { + return ve!(Self, OffsetsNotMatch); + } + let field_count = offset_first / 4 - 1; + if field_count < Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + } else if !compatible && field_count > Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + }; + let header_size = molecule::NUMBER_SIZE * (field_count + 1); + if slice_len < header_size { + return ve!(Self, HeaderIsBroken, header_size, slice_len); + } + let mut offsets: Vec = slice[molecule::NUMBER_SIZE..] + .chunks(molecule::NUMBER_SIZE) + .take(field_count) + .map(|x| molecule::unpack_number(x) as usize) + .collect(); + offsets.push(total_size); + if offsets.windows(2).any(|i| i[0] > i[1]) { + return ve!(Self, OffsetsNotMatch); + } + BytesReader::verify(&slice[offsets[0]..offsets[1]], compatible)?; + Uint64Reader::verify(&slice[offsets[1]..offsets[2]], compatible)?; + Byte32Reader::verify(&slice[offsets[2]..offsets[3]], compatible)?; + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct HeaderInfoBuilder { + pub(crate) header: Bytes, + pub(crate) total_difficulty: Uint64, + pub(crate) hash: Byte32, +} +impl HeaderInfoBuilder { + pub const FIELD_COUNT: usize = 3; + pub fn header(mut self, v: Bytes) -> Self { + self.header = v; + self + } + pub fn total_difficulty(mut self, v: Uint64) -> Self { + self.total_difficulty = v; + self + } + pub fn hash(mut self, v: Byte32) -> Self { + self.hash = v; + self + } +} +impl molecule::prelude::Builder for HeaderInfoBuilder { + type Entity = HeaderInfo; + const NAME: &'static str = "HeaderInfoBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) + + self.header.as_slice().len() + + self.total_difficulty.as_slice().len() + + self.hash.as_slice().len() + } + fn write(&self, writer: &mut W) -> ::molecule::io::Result<()> { + let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); + let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); + offsets.push(total_size); + total_size += self.header.as_slice().len(); + offsets.push(total_size); + total_size += self.total_difficulty.as_slice().len(); + offsets.push(total_size); + total_size += self.hash.as_slice().len(); + writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; + for offset in offsets.into_iter() { + writer.write_all(&molecule::pack_number(offset as molecule::Number))?; + } + writer.write_all(self.header.as_slice())?; + writer.write_all(self.total_difficulty.as_slice())?; + writer.write_all(self.hash.as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + HeaderInfo::new_unchecked(inner.into()) + } +} diff --git a/types/src/generated/mod.rs b/types/src/generated/mod.rs index dd2ef0e..9cc430f 100644 --- a/types/src/generated/mod.rs +++ b/types/src/generated/mod.rs @@ -1,5 +1,5 @@ pub mod basic; pub mod btc_difficulty; +pub mod eth_header_cell_data; pub mod mint_xt_witness; pub mod tockb_cell_data; -pub mod eth_header_cell_data; From 4a157d2a408864c95709afe95283c524419a0864 Mon Sep 17 00:00:00 2001 From: LeonLi000 Date: Thu, 22 Oct 2020 15:16:31 +0800 Subject: [PATCH 45/45] add xt amount verify --- contracts/toCKB-typescript/Cargo.lock | 1 + contracts/toCKB-typescript/Cargo.toml | 2 ++ contracts/toCKB-typescript/src/utils/mod.rs | 1 + contracts/toCKB-typescript/src/utils/tools.rs | 27 +++++++++++++++++++ tests/src/toCKB_typescript/tests/mint_xt.rs | 11 ++++---- types/src/tockb_cell.rs | 2 +- 6 files changed, 38 insertions(+), 6 deletions(-) diff --git a/contracts/toCKB-typescript/Cargo.lock b/contracts/toCKB-typescript/Cargo.lock index c915e4b..dcf2f78 100644 --- a/contracts/toCKB-typescript/Cargo.lock +++ b/contracts/toCKB-typescript/Cargo.lock @@ -381,6 +381,7 @@ dependencies = [ "bitcoin-spv 5.0.0 (git+https://github.com/summa-tx/bitcoin-spv.git?branch=rust/dep-change)", "ckb-std 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "eth-spv-lib 0.1.0 (git+https://github.com/LeonLi000/eth-spv-lib.git)", + "ethereum-types 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "int-enum 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "molecule 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/contracts/toCKB-typescript/Cargo.toml b/contracts/toCKB-typescript/Cargo.toml index 626fce3..c449e96 100644 --- a/contracts/toCKB-typescript/Cargo.toml +++ b/contracts/toCKB-typescript/Cargo.toml @@ -16,6 +16,8 @@ hex = { version = "0.4", default-features = false } eth-spv-lib = { git = "https://github.com/LeonLi000/eth-spv-lib.git" } rlp = {version = "0.4.5", default-features = false } tockb-types = { path = "../../types", default-features = false, features = ["contract"] } +#ethabi = {version = "12.0.0", default-features = false} +ethereum-types = {version = "0.9.2", default-features = false } [profile.release] overflow-checks = true diff --git a/contracts/toCKB-typescript/src/utils/mod.rs b/contracts/toCKB-typescript/src/utils/mod.rs index 6c02e09..fc75b3b 100644 --- a/contracts/toCKB-typescript/src/utils/mod.rs +++ b/contracts/toCKB-typescript/src/utils/mod.rs @@ -1,3 +1,4 @@ pub mod tools; + pub use tockb_types as types; pub use tockb_types::config; diff --git a/contracts/toCKB-typescript/src/utils/tools.rs b/contracts/toCKB-typescript/src/utils/tools.rs index 798f064..f633565 100644 --- a/contracts/toCKB-typescript/src/utils/tools.rs +++ b/contracts/toCKB-typescript/src/utils/tools.rs @@ -261,6 +261,7 @@ pub fn verify_eth_witness( let proof_reader = ETHSPVProofReader::new_unchecked(proof); let header_data = proof_reader.header_data().raw_data().to_vec(); let header: BlockHeader = rlp::decode(header_data.as_slice()).expect("invalid header data"); + debug!("the witness header data: {:?}", header); //verify the header is on main chain. verify_eth_header_on_main_chain(&header, cell_dep_index_list)?; @@ -284,12 +285,21 @@ pub fn verify_eth_witness( for i in 0..proof_reader.proof().len() { proof.push(proof_reader.proof().get_unchecked(i).raw_data().to_vec()); } + debug!("proof: {:?}", hex::encode(proof[0].clone())); let log_entry: LogEntry = rlp::decode(log_entry_data.as_slice()).map_err(|_e| Error::LogEntryInvalid)?; debug!("log_entry is {:?}", &log_entry); let receipt: Receipt = rlp::decode(receipt_data.as_slice()).map_err(|_e| Error::ReceiptInvalid)?; debug!("receipt_data is {:?}", &receipt); + let log_data = log_entry.data.clone(); + let slices = slice_data(log_data.as_slice())?; + debug!("log data slice: {:?}", slices); + let xt_amount:U256 = U256::from(slices[0]); + debug!("log data xt_amount: {:?}", xt_amount); + let expect_value = data.get_eth_lot_size()?.get_sudt_amount(); + debug!("expect_value: {:?}", expect_value); + //FIXME: verify xt amount. let locker_address = (log_entry.address.clone().0).0; debug!( "addr: {:?}, x_lock_address: {}", @@ -315,6 +325,23 @@ pub fn verify_eth_witness( Ok(EthExtraView {}) } +/// Converts a vector of bytes with len equal n * 32, to a vector of slices. +pub fn slice_data(data: &[u8]) -> Result, Error> { + if data.len() % 32 != 0 { + return Err(Error::Encoding); + } + + let times = data.len() / 32; + let mut result = Vec::with_capacity(times); + for i in 0..times { + let mut slice = [0u8; 32]; + let offset = 32 * i; + slice.copy_from_slice(&data[offset..offset + 32]); + result.push(slice); + } + Ok(result) +} + pub fn verify_btc_faulty_witness( data: &ToCKBCellDataView, proof: &[u8], diff --git a/tests/src/toCKB_typescript/tests/mint_xt.rs b/tests/src/toCKB_typescript/tests/mint_xt.rs index b0e250c..aad2e08 100644 --- a/tests/src/toCKB_typescript/tests/mint_xt.rs +++ b/tests/src/toCKB_typescript/tests/mint_xt.rs @@ -256,7 +256,7 @@ fn get_correct_eth_case() -> TestCase { TestCase { cell_deps: vec![CellDepView::HeadersOracle(HeadersOracle { - headers: vec!["f9021aa0f779e50b45bc27e4ed236840e5dbcf7afab50beaf553be56bf76da977e10cc73a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479452bc44d5378309ee2abf1539bf71de1b7d7be3b5a014c996b6934d7991643669e145b8355c63aa02cbde63d390fcf4e6181d5eea45a079b7e79dc739c31662fe6f25f65bf5a5d14299c7a7aa42c3f75b9fb05474f54ca0e28dc05418692cb7baab7e7f85c1dedb8791c275b797ea3b1ffcaec5ef2aa271b9010000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000010000000000000000000000000000000000000000000000000000000408000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000010000000000000000000000000000000000000000000000000000000400000000000100000000000000000000000000080000000000000000000000000000000000000000000100002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000903234373439353837313930323034343383890fe68395ba8e82d0d9845dd84a079150505945206e616e6f706f6f6c2e6f7267a0a35425f443452cf94ba4b698b00fd7b3ff4fc671dea3d5cc2dcbedbc3766f45e88af7fec6031063a17".to_owned()] + headers: vec!["f90211a0f779e50b45bc27e4ed236840e5dbcf7afab50beaf553be56bf76da977e10cc73a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479452bc44d5378309ee2abf1539bf71de1b7d7be3b5a014c996b6934d7991643669e145b8355c63aa02cbde63d390fcf4e6181d5eea45a079b7e79dc739c31662fe6f25f65bf5a5d14299c7a7aa42c3f75b9fb05474f54ca0e28dc05418692cb7baab7e7f85c1dedb8791c275b797ea3b1ffcaec5ef2aa271b90100000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000100000000000000000000000000000000000000000000000000000004080000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000100000000000000000000000000000000000000000000000000000004000000000001000000000000000000000000000800000000000000000000000000000000000000000001000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000008708caf63b47ed9b83890fe68395ba8e82d0d9845dd84a079150505945206e616e6f706f6f6c2e6f7267a0a35425f443452cf94ba4b698b00fd7b3ff4fc671dea3d5cc2dcbedbc3766f45e88af7fec6031063a17".to_owned()] })], toCKB_cells: ToCKBCells { inputs: vec![ToCKBCell { @@ -305,14 +305,14 @@ fn get_correct_eth_case() -> TestCase { outputs: vec![ SudtCell { capacity: PLEDGE, - amount: 249500000000000000, + amount: 249500, lockscript: Default::default(), owner_script: Default::default(), index: 1, }, SudtCell { capacity: XT_CELL_CAPACITY, - amount: 500000000000000, + amount: 500, lockscript: Default::default(), owner_script: Default::default(), index: 2, @@ -326,8 +326,9 @@ fn get_correct_eth_case() -> TestCase { log_index: 0, log_entry_data:"f89b94dac17f958d2ee523a2206206994597c13d831ec7f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa00000000000000000000000006cc5f688a315f3dc28a7781717a9a798a59fda7ba00000000000000000000000007e7a32d9dc98c485c489be8e732f97b4ffe3a4cda000000000000000000000000000000000000000000000000000000001a13b8600".to_owned(), receipt_index: 0, + // "f901b2f901af822080b901a9f901a60182d0d9b9010000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000010000000000000000000000000000000000000000000000000000000408000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000010000000000000000000000000000000000000000000000000000000400000000000100000000000000000000000000080000000000000000000000000000000000000000000100002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000f89df89b94dac17f958d2ee523a2206206994597c13d831ec7f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa00000000000000000000000006cc5f688a315f3dc28a7781717a9a798a59fda7ba00000000000000000000000007e7a32d9dc98c485c489be8e732f97b4ffe3a4cda000000000000000000000000000000000000000000000000000000001a13b8600" receipt_data:"f901a60182d0d9b9010000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000010000000000000000000000000000000000000000000000000000000408000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000010000000000000000000000000000000000000000000000000000000400000000000100000000000000000000000000080000000000000000000000000000000000000000000100002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000f89df89b94dac17f958d2ee523a2206206994597c13d831ec7f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa00000000000000000000000006cc5f688a315f3dc28a7781717a9a798a59fda7ba00000000000000000000000007e7a32d9dc98c485c489be8e732f97b4ffe3a4cda000000000000000000000000000000000000000000000000000000001a13b8600".to_owned(), - header_data: "f9021aa0f779e50b45bc27e4ed236840e5dbcf7afab50beaf553be56bf76da977e10cc73a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479452bc44d5378309ee2abf1539bf71de1b7d7be3b5a014c996b6934d7991643669e145b8355c63aa02cbde63d390fcf4e6181d5eea45a079b7e79dc739c31662fe6f25f65bf5a5d14299c7a7aa42c3f75b9fb05474f54ca0e28dc05418692cb7baab7e7f85c1dedb8791c275b797ea3b1ffcaec5ef2aa271b9010000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000010000000000000000000000000000000000000000000000000000000408000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000010000000000000000000000000000000000000000000000000000000400000000000100000000000000000000000000080000000000000000000000000000000000000000000100002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000903234373439353837313930323034343383890fe68395ba8e82d0d9845dd84a079150505945206e616e6f706f6f6c2e6f7267a0a35425f443452cf94ba4b698b00fd7b3ff4fc671dea3d5cc2dcbedbc3766f45e88af7fec6031063a17".to_owned(), + header_data: "f90211a0f779e50b45bc27e4ed236840e5dbcf7afab50beaf553be56bf76da977e10cc73a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479452bc44d5378309ee2abf1539bf71de1b7d7be3b5a014c996b6934d7991643669e145b8355c63aa02cbde63d390fcf4e6181d5eea45a079b7e79dc739c31662fe6f25f65bf5a5d14299c7a7aa42c3f75b9fb05474f54ca0e28dc05418692cb7baab7e7f85c1dedb8791c275b797ea3b1ffcaec5ef2aa271b90100000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000100000000000000000000000000000000000000000000000000000004080000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000100000000000000000000000000000000000000000000000000000004000000000001000000000000000000000000000800000000000000000000000000000000000000000001000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000008708caf63b47ed9b83890fe68395ba8e82d0d9845dd84a079150505945206e616e6f706f6f6c2e6f7267a0a35425f443452cf94ba4b698b00fd7b3ff4fc671dea3d5cc2dcbedbc3766f45e88af7fec6031063a17".to_owned(), proof: vec![ vec![ Vec::from_hex("2080").unwrap(), @@ -337,7 +338,7 @@ fn get_correct_eth_case() -> TestCase { let mut stream = RlpStream::new(); stream.begin_list(node.len()); for item in node { - stream.append(item); + stream.append(item); } stream.out() }).collect(), diff --git a/types/src/tockb_cell.rs b/types/src/tockb_cell.rs index 6d4a047..be15e65 100644 --- a/types/src/tockb_cell.rs +++ b/types/src/tockb_cell.rs @@ -19,7 +19,7 @@ use molecule::{ }; pub const BTC_UNIT: u128 = 100_000_000; -pub const ETH_UNIT: u128 = 1_000_000_000_000_000_000; +pub const ETH_UNIT: u128 = 1_000_000; #[repr(u8)] #[derive(Debug, Clone, Copy, IntEnum)]