Skip to content

Commit

Permalink
validation: check that seals and anchors use layer1 allowed in genesis
Browse files Browse the repository at this point in the history
  • Loading branch information
dr-orlovsky committed Oct 30, 2023
1 parent b6d754d commit c0be2d9
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 28 deletions.
10 changes: 10 additions & 0 deletions src/contract/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ pub use seal::{
};
pub use state::{ConfidentialState, ExposedState, StateCommitment, StateData, StateType};

use crate::Layer1;

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Display)]

Check warning on line 66 in src/contract/mod.rs

View check run for this annotation

Codecov / codecov/patch

src/contract/mod.rs#L66

Added line #L66 was not covered by tests
#[display(lowercase)]
#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
Expand All @@ -79,6 +81,14 @@ pub enum AltLayer1 {
// Prime = 0x11,
}

impl AltLayer1 {
pub fn layer1(&self) -> Layer1 {
match self {
AltLayer1::Liquid => Layer1::Liquid,
}
}

Check warning on line 89 in src/contract/mod.rs

View check run for this annotation

Codecov / codecov/patch

src/contract/mod.rs#L85-L89

Added lines #L85 - L89 were not covered by tests
}

#[derive(Wrapper, Clone, PartialEq, Eq, Hash, Debug, From)]

Check warning on line 92 in src/contract/mod.rs

View check run for this annotation

Codecov / codecov/patch

src/contract/mod.rs#L92

Added line #L92 was not covered by tests
#[wrapper(Deref)]
#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
Expand Down
7 changes: 6 additions & 1 deletion src/validation/status.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,15 @@ use core::ops::AddAssign;
use std::fmt::{self, Display, Formatter};

use bp::dbc::anchor;
use bp::seals::txout::blind::ChainBlindSeal;
use bp::{seals, Txid};
use strict_types::SemId;

use crate::contract::Opout;
use crate::schema::{self, SchemaId};
use crate::{
AssignmentType, BundleId, Layer1, OccurrencesMismatch, OpFullType, OpId, SecretSeal, StateType,
AssignmentType, BundleId, Layer1, OccurrencesMismatch, OpFullType, OpId, SealDefinition,
SecretSeal, StateType,
};

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Display)]
Expand Down Expand Up @@ -318,6 +320,9 @@ pub enum Failure {
SealNoWitnessTx(Txid),
/// 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
/// by the contract genesis.
SealInvalidLayer1(Layer1, SealDefinition<ChainBlindSeal>),
/// transition {0} doesn't close seal with the witness transaction {1}.
/// Details: {2}
SealInvalid(OpId, Txid, seals::txout::VerifyError),
Expand Down
60 changes: 33 additions & 27 deletions src/validation/validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ use super::status::{Failure, Warning};
use super::{ConsignmentApi, Status, Validity, VirtualMachine};
use crate::vm::AluRuntime;
use crate::{
Anchor, AnchoredBundle, BundleId, ContractId, GraphSeal, Layer1, OpId, OpRef, Operation, Opout,
Schema, SchemaId, SchemaRoot, Script, SealDefinition, SubSchema, Transition, TransitionBundle,
TypedAssigns,
AltLayer1, Anchor, AnchoredBundle, BundleId, ContractId, GraphSeal, Layer1, OpId, OpRef,
Operation, Opout, Schema, SchemaId, SchemaRoot, Script, SealDefinition, SubSchema, Transition,
TransitionBundle, TypedAssigns,
};

#[derive(Clone, Debug, Display, Error, From)]
Expand All @@ -57,6 +57,7 @@ pub struct Validator<'consignment, 'resolver, C: ConsignmentApi, R: ResolveTx> {
schema_id: SchemaId,
genesis_id: OpId,
contract_id: ContractId,
layers1: BTreeSet<Layer1>,
anchor_index: BTreeMap<OpId, &'consignment Anchor>,
end_transitions: Vec<(&'consignment Transition, BundleId)>,
validation_index: BTreeSet<OpId>,
Expand All @@ -75,9 +76,10 @@ impl<'consignment, 'resolver, C: ConsignmentApi, R: ResolveTx>
let mut status = Status::default();

// Frequently used computation-heavy data
let genesis_id = consignment.genesis().id();
let contract_id = consignment.genesis().contract_id();
let schema_id = consignment.genesis().schema_id;
let genesis = consignment.genesis();
let genesis_id = genesis.id();
let contract_id = genesis.contract_id();
let schema_id = genesis.schema_id;

Check warning on line 82 in src/validation/validator.rs

View check run for this annotation

Codecov / codecov/patch

src/validation/validator.rs#L79-L82

Added lines #L79 - L82 were not covered by tests

// Create indexes
let mut anchor_index = BTreeMap::<OpId, &Anchor>::new();

Check warning on line 85 in src/validation/validator.rs

View check run for this annotation

Codecov / codecov/patch

src/validation/validator.rs#L85

Added line #L85 was not covered by tests
Expand Down Expand Up @@ -132,6 +134,9 @@ impl<'consignment, 'resolver, C: ConsignmentApi, R: ResolveTx>
// Index used to avoid repeated validations of the same anchor+transition pairs
let anchor_validation_index = BTreeSet::<OpId>::new();

let mut layers1 = bset! { Layer1::Bitcoin };
layers1.extend(genesis.alt_layer1.iter().map(AltLayer1::layer1));

Check warning on line 139 in src/validation/validator.rs

View check run for this annotation

Codecov / codecov/patch

src/validation/validator.rs#L137-L139

Added lines #L137 - L139 were not covered by tests
let vm = match &consignment.schema().script {
Script::AluVM(lib) => {
Box::new(AluRuntime::new(lib)) as Box<dyn VirtualMachine + 'consignment>
Expand All @@ -144,6 +149,7 @@ impl<'consignment, 'resolver, C: ConsignmentApi, R: ResolveTx>
schema_id,
genesis_id,
contract_id,
layers1,

Check warning on line 152 in src/validation/validator.rs

View check run for this annotation

Codecov / codecov/patch

src/validation/validator.rs#L152

Added line #L152 was not covered by tests
anchor_index,
end_transitions,
validation_index,
Expand Down Expand Up @@ -424,56 +430,56 @@ impl<'consignment, 'resolver, C: ConsignmentApi, R: ResolveTx>
continue;
};

let seal = match (seal, self.anchor_index.get(&op)) {
let Some(anchor) = self.anchor_index.get(&op) else {
panic!("anchor for the operation {op} was not indexed by the validator");

Check warning on line 434 in src/validation/validator.rs

View check run for this annotation

Codecov / codecov/patch

src/validation/validator.rs#L433-L434

Added lines #L433 - L434 were not covered by tests
};
if seal.layer1() != anchor.layer1() {
self.status.add_failure(Failure::SealWitnessLayer1Mismatch {
seal: seal.layer1(),
anchor: anchor.layer1(),
});
continue;
}
if !self.layers1.contains(&seal.layer1()) {
self.status
.add_failure(Failure::SealInvalidLayer1(seal.layer1(), seal));
continue;
}

Check warning on line 447 in src/validation/validator.rs

View check run for this annotation

Codecov / codecov/patch

src/validation/validator.rs#L436-L447

Added lines #L436 - L447 were not covered by tests

let seal = match (seal, anchor) {

Check warning on line 449 in src/validation/validator.rs

View check run for this annotation

Codecov / codecov/patch

src/validation/validator.rs#L449

Added line #L449 was not covered by tests
(
SealDefinition::Bitcoin(
seal @ GraphSeal {

Check warning on line 452 in src/validation/validator.rs

View check run for this annotation

Codecov / codecov/patch

src/validation/validator.rs#L452

Added line #L452 was not covered by tests
txid: TxPtr::WitnessTx,
..
},
),
Some(Anchor::Bitcoin(anchor)),
) |
(
) |
SealDefinition::Liquid(
seal @ GraphSeal {

Check warning on line 458 in src/validation/validator.rs

View check run for this annotation

Codecov / codecov/patch

src/validation/validator.rs#L458

Added line #L458 was not covered by tests
txid: TxPtr::WitnessTx,
..
},
),
Some(Anchor::Liquid(anchor)),
Anchor::Bitcoin(anchor) | Anchor::Liquid(anchor),

Check warning on line 463 in src/validation/validator.rs

View check run for this annotation

Codecov / codecov/patch

src/validation/validator.rs#L463

Added line #L463 was not covered by tests
) => {
let prev_witness_txid = anchor.txid;
seal.resolve(prev_witness_txid)
}
(SealDefinition::Bitcoin(_) | SealDefinition::Liquid(_), None) => {
panic!("anchor for the operation {op} was not indexed by the validator");
}
(
SealDefinition::Bitcoin(
seal @ GraphSeal {
txid: TxPtr::Txid(txid),

Check warning on line 471 in src/validation/validator.rs

View check run for this annotation

Codecov / codecov/patch

src/validation/validator.rs#L470-L471

Added lines #L470 - L471 were not covered by tests
..
},
),
Some(Anchor::Bitcoin(_)),
) |
(
) |
SealDefinition::Liquid(
seal @ GraphSeal {
txid: TxPtr::Txid(txid),

Check warning on line 477 in src/validation/validator.rs

View check run for this annotation

Codecov / codecov/patch

src/validation/validator.rs#L476-L477

Added lines #L476 - L477 were not covered by tests
..
},
),
Some(Anchor::Liquid(_)),
Anchor::Bitcoin(_) | Anchor::Liquid(_),
) => seal.resolve(txid),

Check warning on line 482 in src/validation/validator.rs

View check run for this annotation

Codecov / codecov/patch

src/validation/validator.rs#L481-L482

Added lines #L481 - L482 were not covered by tests
(SealDefinition::Bitcoin(_) | SealDefinition::Liquid(_), Some(anchor)) => {
self.status.add_failure(Failure::SealWitnessLayer1Mismatch {
seal: seal.layer1(),
anchor: anchor.layer1(),
});
continue;
}
};
seals.push(seal);

Check warning on line 484 in src/validation/validator.rs

View check run for this annotation

Codecov / codecov/patch

src/validation/validator.rs#L484

Added line #L484 was not covered by tests
}
Expand Down

0 comments on commit c0be2d9

Please sign in to comment.