From 464ddf8ed395bbbf207523083aec026914b98eba Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 22 Jul 2024 23:25:13 +0200 Subject: [PATCH 1/2] validation: check that all actual witness ids match the expected value --- src/validation/status.rs | 3 ++- src/validation/validator.rs | 45 ++++++++++++++++++++++++++++++++----- 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/src/validation/status.rs b/src/validation/status.rs index 6f1f8254..0d0d974e 100644 --- a/src/validation/status.rs +++ b/src/validation/status.rs @@ -28,6 +28,7 @@ use strict_types::SemId; use crate::contract::Opout; use crate::schema::{self, SchemaId}; +use crate::validation::WitnessResolverError; use crate::{ AssignmentType, BundleId, ContractId, Layer1, OccurrencesMismatch, OpFullType, OpId, OpType, SecretSeal, StateType, Vin, XChain, XGraphSeal, XOutputSeal, XWitnessId, @@ -287,7 +288,7 @@ pub enum Failure { /// confidential and can't be validated. ConfidentialSeal(Opout), /// public witness {0} is not known to the resolver. - SealNoPubWitness(XWitnessId), + SealNoPubWitness(XWitnessId, WitnessResolverError), /// witness layer 1 {anchor} doesn't match seal definition {seal}. SealWitnessLayer1Mismatch { seal: Layer1, anchor: Layer1 }, /// seal {1} is defined on {0} which is not in the set of layers allowed diff --git a/src/validation/validator.rs b/src/validation/validator.rs index def5fc32..e3158498 100644 --- a/src/validation/validator.rs +++ b/src/validation/validator.rs @@ -37,9 +37,19 @@ use crate::{ XWitnessId, XWitnessTx, }; -#[derive(Clone, Debug, Display, Error, From)] +#[derive(Clone, PartialEq, Eq, Debug, Display, Error, From)] #[display(doc_comments)] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(crate = "serde_crate", rename_all = "camelCase") +)] pub enum WitnessResolverError { + /// actual witness id {actual} doesn't match extected if {expected}. + IdMismatch { + actual: XWitnessId, + expected: XWitnessId, + }, /// witness {0} does not exist. Unknown(XWitnessId), /// unable to retrieve witness {0}, {1} @@ -63,6 +73,31 @@ impl ResolveWitness for &T { } } +struct CheckedWitnessResolver { + inner: R, +} + +impl From for CheckedWitnessResolver { + fn from(inner: R) -> Self { Self { inner } } +} + +impl ResolveWitness for CheckedWitnessResolver { + fn resolve_pub_witness( + &self, + witness_id: XWitnessId, + ) -> Result { + let witness = self.inner.resolve_pub_witness(witness_id)?; + let actual_id = witness.witness_id(); + if actual_id != witness_id { + return Err(WitnessResolverError::IdMismatch { + actual: actual_id, + expected: witness_id, + }); + } + Ok(witness) + } +} + pub struct Validator<'consignment, 'resolver, C: ConsignmentApi, R: ResolveWitness> { consignment: CheckedConsignment<'consignment, C>, @@ -76,7 +111,7 @@ pub struct Validator<'consignment, 'resolver, C: ConsignmentApi, R: ResolveWitne validated_op_seals: RefCell>, validated_op_state: RefCell>, - resolver: &'resolver R, + resolver: CheckedWitnessResolver<&'resolver R>, } impl<'consignment, 'resolver, C: ConsignmentApi, R: ResolveWitness> @@ -136,7 +171,7 @@ impl<'consignment, 'resolver, C: ConsignmentApi, R: ResolveWitness> layers1, validated_op_state, validated_op_seals, - resolver, + resolver: CheckedWitnessResolver::from(resolver), } } @@ -417,7 +452,7 @@ impl<'consignment, 'resolver, C: ConsignmentApi, R: ResolveWitness> // Here the method can do SPV proof instead of querying the indexer. The SPV // proofs can be part of the consignments, but do not require . match self.resolver.resolve_pub_witness(witness_id) { - Err(_) => { + Err(err) => { // We wre unable to retrieve corresponding transaction, so can't check. // Reporting this incident and continuing further. Why this happens? No // connection to Bitcoin Core, Electrum or other backend etc. So this is not a @@ -429,7 +464,7 @@ impl<'consignment, 'resolver, C: ConsignmentApi, R: ResolveWitness> // failure!) self.status .borrow_mut() - .add_failure(Failure::SealNoPubWitness(witness_id)); + .add_failure(Failure::SealNoPubWitness(witness_id, err)); None } Ok(pub_witness) => { From 4ac2692b715015b91f025363c02e216078b76cff Mon Sep 17 00:00:00 2001 From: "Dr. Maxim Orlovsky" Date: Tue, 23 Jul 2024 16:34:09 +0200 Subject: [PATCH 2/2] validate: doc fix typo in witness resolver error Co-authored-by: Stefano Pellegrini <33753050+St333p@users.noreply.github.com> --- src/validation/validator.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/validation/validator.rs b/src/validation/validator.rs index e3158498..e24e5593 100644 --- a/src/validation/validator.rs +++ b/src/validation/validator.rs @@ -45,7 +45,7 @@ use crate::{ serde(crate = "serde_crate", rename_all = "camelCase") )] pub enum WitnessResolverError { - /// actual witness id {actual} doesn't match extected if {expected}. + /// actual witness id {actual} doesn't match expected id {expected}. IdMismatch { actual: XWitnessId, expected: XWitnessId,