Skip to content

Commit

Permalink
validation: control matching operations with their ids
Browse files Browse the repository at this point in the history
Closes #254
  • Loading branch information
dr-orlovsky committed Jul 11, 2024
1 parent fe1d3b0 commit e737027
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 13 deletions.
8 changes: 7 additions & 1 deletion src/validation/status.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use strict_types::SemId;
use crate::contract::Opout;
use crate::schema::{self, SchemaId};
use crate::{
AssignmentType, BundleId, ContractId, Layer1, OccurrencesMismatch, OpFullType, OpId,
AssignmentType, BundleId, ContractId, Layer1, OccurrencesMismatch, OpFullType, OpId, OpType,
SecretSeal, StateType, Vin, XChain, XGraphSeal, XOutputSeal, XWitnessId,
};

Expand Down Expand Up @@ -237,6 +237,12 @@ pub enum Failure {
CyclicGraph(OpId),
/// operation {0} is absent from the consignment.
OperationAbsent(OpId),
/// {ty} data doesn't match operation id {expected} (actual id is {actual}).
OperationIdMismatch {
ty: OpType,
expected: OpId,
actual: OpId,
},
/// transition bundle {0} referenced in consignment terminals is absent from
/// the consignment.
TerminalBundleAbsent(BundleId),
Expand Down
39 changes: 27 additions & 12 deletions src/validation/validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,10 +230,13 @@ impl<'consignment, 'resolver, C: ConsignmentApi, R: ResolveWitness>
fn validate_logic_on_route(&self, opid: OpId) {
let schema = self.consignment.schema();
let Some(OpRef::Transition(transition)) = self.consignment.operation(opid) else {
panic!("provided {opid} is absent");
self.status
.borrow_mut()
.add_failure(Failure::OperationAbsent(opid));
return;
};

let mut queue: VecDeque<OpRef> = VecDeque::new();
let mut queue: VecDeque<(OpId, OpRef)> = VecDeque::new();

// Instead of constructing complex graph structures or using a recursions we
// utilize queue to keep the track of the upstream (ancestor) nodes and make
Expand All @@ -244,9 +247,18 @@ impl<'consignment, 'resolver, C: ConsignmentApi, R: ResolveWitness>
// change to a given operation is valid against the schema + committed
// into bitcoin transaction graph with proper anchor. That is what we are
// checking in the code below:
queue.push_back(OpRef::Transition(transition));
while let Some(operation) = queue.pop_front() {
let opid = operation.id();
queue.push_back((opid, OpRef::Transition(transition)));
while let Some((opid, operation)) = queue.pop_front() {
let actual_opid = operation.id();
if opid != actual_opid {
self.status
.borrow_mut()
.add_failure(Failure::OperationIdMismatch {
ty: operation.op_type(),
expected: opid,
actual: actual_opid,
});
}

if operation.contract_id() != self.contract_id {
self.status
Expand Down Expand Up @@ -274,12 +286,15 @@ impl<'consignment, 'resolver, C: ConsignmentApi, R: ResolveWitness>
OpRef::Transition(transition) => {
// Now, we must collect all parent nodes and add them to the verification queue
let parent_nodes = transition.inputs.iter().filter_map(|input| {
self.consignment.operation(input.prev_out.op).or_else(|| {
self.status
.borrow_mut()
.add_failure(Failure::OperationAbsent(input.prev_out.op));
None
})
self.consignment
.operation(input.prev_out.op)
.map(|op| (input.prev_out.op, op))
.or_else(|| {
self.status
.borrow_mut()
.add_failure(Failure::OperationAbsent(input.prev_out.op));
None
})
});

queue.extend(parent_nodes);
Expand Down Expand Up @@ -308,7 +323,7 @@ impl<'consignment, 'resolver, C: ConsignmentApi, R: ResolveWitness>
continue;
}

queue.push_back(prev_op);
queue.push_back((*prev_id, prev_op));
}
}
}
Expand Down

0 comments on commit e737027

Please sign in to comment.