diff --git a/Makefile b/Makefile index a9677e1..386eafe 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ CARGO := @cargo -MOLC := @moleculec +MOLC := moleculec MOLC_VERSION := 0.7.5 NEXTEST_RUN_ARGS := --no-fail-fast --success-output never --failure-output final diff --git a/prover/src/tests/service.rs b/prover/src/tests/service.rs index f697d9c..f6dbfab 100644 --- a/prover/src/tests/service.rs +++ b/prover/src/tests/service.rs @@ -85,7 +85,7 @@ fn test_spv_client( let new_client: packed::SpvClient = service.tip_client().pack(); old_client - .verify_new_client(&new_client, update) + .verify_new_client(&new_client, update, 0) .map_err(|err| err as i8) .unwrap(); old_client = new_client; diff --git a/verifier/schemas/types.mol b/verifier/schemas/types.mol index fe987da..671b7fc 100644 --- a/verifier/schemas/types.mol +++ b/verifier/schemas/types.mol @@ -53,6 +53,7 @@ struct SpvClient { struct SpvTypeArgs { type_id: Hash, clients_count: byte, + flags: byte, } // diff --git a/verifier/src/constants.rs b/verifier/src/constants.rs new file mode 100644 index 0000000..1b6d767 --- /dev/null +++ b/verifier/src/constants.rs @@ -0,0 +1,3 @@ +//! Constants. + +pub const FLAG_DISABLE_DIFFICULTY_CHECK: u8 = 0b1000_0000; diff --git a/verifier/src/lib.rs b/verifier/src/lib.rs index f98bed2..9e06865 100644 --- a/verifier/src/lib.rs +++ b/verifier/src/lib.rs @@ -11,6 +11,7 @@ extern crate core; #[macro_use] mod log; +pub mod constants; pub mod error; pub mod types; pub mod utilities; diff --git a/verifier/src/types/conversion/pack.rs b/verifier/src/types/conversion/pack.rs index c50cfc0..6a834c2 100644 --- a/verifier/src/types/conversion/pack.rs +++ b/verifier/src/types/conversion/pack.rs @@ -104,6 +104,7 @@ impl Pack for core::SpvTypeArgs { packed::SpvTypeArgs::new_builder() .type_id(self.type_id.pack()) .clients_count(self.clients_count.into()) + .flags(self.flags.into()) .build() } } diff --git a/verifier/src/types/conversion/unpack.rs b/verifier/src/types/conversion/unpack.rs index 5462119..ee55c49 100644 --- a/verifier/src/types/conversion/unpack.rs +++ b/verifier/src/types/conversion/unpack.rs @@ -104,6 +104,7 @@ impl<'r> Unpack for packed::SpvTypeArgsReader<'r> { core::SpvTypeArgs { type_id: self.type_id().unpack(), clients_count: self.clients_count().into(), + flags: self.flags().into(), } } } diff --git a/verifier/src/types/core.rs b/verifier/src/types/core.rs index a2cce11..e75c057 100644 --- a/verifier/src/types/core.rs +++ b/verifier/src/types/core.rs @@ -84,6 +84,12 @@ pub struct SpvTypeArgs { /// /// N.B. Exclude the SPV info cell. pub clients_count: u8, + /// Bit flags to control features. + /// + /// From high to low: + /// - Set 0-th bit to true, to disable difficulty checks. + /// - Other bits are reserved. + pub flags: u8, } #[cfg(feature = "std")] diff --git a/verifier/src/types/extension/packed.rs b/verifier/src/types/extension/packed.rs index 287c566..2050989 100644 --- a/verifier/src/types/extension/packed.rs +++ b/verifier/src/types/extension/packed.rs @@ -9,6 +9,7 @@ use bitcoin::{ use molecule::bytes::Bytes; use crate::{ + constants, core::result::Result, error::{BootstrapError, UpdateError, VerifyTxError}, types::{core, packed, prelude::*}, @@ -106,6 +107,7 @@ impl packed::SpvClient { &self, packed_new_client: &Self, update: packed::SpvUpdate, + flags: u8, ) -> Result<(), UpdateError> { let old_client = self.unpack(); let new_client = packed_new_client.unpack(); @@ -146,7 +148,9 @@ impl packed::SpvClient { expect {expected} but got {actual}" ); }); - return Err(UpdateError::Difficulty); + if flags & constants::FLAG_DISABLE_DIFFICULTY_CHECK == 0 { + return Err(UpdateError::Difficulty); + } } // Check POW. new_tip_block_hash = header diff --git a/verifier/src/types/generated/types.rs b/verifier/src/types/generated/types.rs index 2f15292..095af1e 100644 --- a/verifier/src/types/generated/types.rs +++ b/verifier/src/types/generated/types.rs @@ -3499,6 +3499,7 @@ impl ::core::fmt::Display for SpvTypeArgs { write!(f, "{} {{ ", Self::NAME)?; write!(f, "{}: {}", "type_id", self.type_id())?; write!(f, ", {}: {}", "clients_count", self.clients_count())?; + write!(f, ", {}: {}", "flags", self.flags())?; write!(f, " }}") } } @@ -3509,19 +3510,22 @@ impl ::core::default::Default for SpvTypeArgs { } } impl SpvTypeArgs { - const DEFAULT_VALUE: [u8; 33] = [ + const DEFAULT_VALUE: [u8; 34] = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, + 0, 0, 0, 0, ]; - pub const TOTAL_SIZE: usize = 33; - pub const FIELD_SIZES: [usize; 2] = [32, 1]; - pub const FIELD_COUNT: usize = 2; + pub const TOTAL_SIZE: usize = 34; + pub const FIELD_SIZES: [usize; 3] = [32, 1, 1]; + pub const FIELD_COUNT: usize = 3; pub fn type_id(&self) -> Hash { Hash::new_unchecked(self.0.slice(0..32)) } pub fn clients_count(&self) -> Byte { Byte::new_unchecked(self.0.slice(32..33)) } + pub fn flags(&self) -> Byte { + Byte::new_unchecked(self.0.slice(33..34)) + } pub fn as_reader<'r>(&'r self) -> SpvTypeArgsReader<'r> { SpvTypeArgsReader::new_unchecked(self.as_slice()) } @@ -3551,6 +3555,7 @@ impl molecule::prelude::Entity for SpvTypeArgs { Self::new_builder() .type_id(self.type_id()) .clients_count(self.clients_count()) + .flags(self.flags()) } } #[derive(Clone, Copy)] @@ -3574,19 +3579,23 @@ impl<'r> ::core::fmt::Display for SpvTypeArgsReader<'r> { write!(f, "{} {{ ", Self::NAME)?; write!(f, "{}: {}", "type_id", self.type_id())?; write!(f, ", {}: {}", "clients_count", self.clients_count())?; + write!(f, ", {}: {}", "flags", self.flags())?; write!(f, " }}") } } impl<'r> SpvTypeArgsReader<'r> { - pub const TOTAL_SIZE: usize = 33; - pub const FIELD_SIZES: [usize; 2] = [32, 1]; - pub const FIELD_COUNT: usize = 2; + pub const TOTAL_SIZE: usize = 34; + pub const FIELD_SIZES: [usize; 3] = [32, 1, 1]; + pub const FIELD_COUNT: usize = 3; pub fn type_id(&self) -> HashReader<'r> { HashReader::new_unchecked(&self.as_slice()[0..32]) } pub fn clients_count(&self) -> ByteReader<'r> { ByteReader::new_unchecked(&self.as_slice()[32..33]) } + pub fn flags(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[33..34]) + } } impl<'r> molecule::prelude::Reader<'r> for SpvTypeArgsReader<'r> { type Entity = SpvTypeArgs; @@ -3613,11 +3622,12 @@ impl<'r> molecule::prelude::Reader<'r> for SpvTypeArgsReader<'r> { pub struct SpvTypeArgsBuilder { pub(crate) type_id: Hash, pub(crate) clients_count: Byte, + pub(crate) flags: Byte, } impl SpvTypeArgsBuilder { - pub const TOTAL_SIZE: usize = 33; - pub const FIELD_SIZES: [usize; 2] = [32, 1]; - pub const FIELD_COUNT: usize = 2; + pub const TOTAL_SIZE: usize = 34; + pub const FIELD_SIZES: [usize; 3] = [32, 1, 1]; + pub const FIELD_COUNT: usize = 3; pub fn type_id(mut self, v: Hash) -> Self { self.type_id = v; self @@ -3626,6 +3636,10 @@ impl SpvTypeArgsBuilder { self.clients_count = v; self } + pub fn flags(mut self, v: Byte) -> Self { + self.flags = v; + self + } } impl molecule::prelude::Builder for SpvTypeArgsBuilder { type Entity = SpvTypeArgs; @@ -3636,6 +3650,7 @@ impl molecule::prelude::Builder for SpvTypeArgsBuilder { fn write(&self, writer: &mut W) -> molecule::io::Result<()> { writer.write_all(self.type_id.as_slice())?; writer.write_all(self.clients_count.as_slice())?; + writer.write_all(self.flags.as_slice())?; Ok(()) } fn build(&self) -> Self::Entity {