From 4bc2d52efdcdb9a9407bc4482f810936c67dfeef Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Wed, 30 Sep 2020 03:22:31 +0200 Subject: [PATCH] RGB: consignment validation for extensions --- src/rgb/stash/consignment.rs | 23 +++++++++++++---------- src/rgb/validation.rs | 17 ++++++++++++----- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/src/rgb/stash/consignment.rs b/src/rgb/stash/consignment.rs index b238202e..5645c487 100644 --- a/src/rgb/stash/consignment.rs +++ b/src/rgb/stash/consignment.rs @@ -34,8 +34,8 @@ pub struct Consignment { version: u16, pub genesis: Genesis, pub endpoints: ConsignmentEndpoints, - pub data: OwnedData, - pub extensions: ExtensionData, + pub owned_data: OwnedData, + pub extension_data: ExtensionData, } impl Consignment { @@ -48,22 +48,25 @@ impl Consignment { Self { version: RGB_CONSIGNMENT_VERSION, genesis, - extensions, + extension_data: extensions, endpoints, - data, + owned_data: data, } } #[inline] pub fn txids(&self) -> BTreeSet { - self.data.iter().map(|(anchor, _)| anchor.txid).collect() + self.owned_data + .iter() + .map(|(anchor, _)| anchor.txid) + .collect() } #[inline] pub fn node_ids(&self) -> BTreeSet { let mut set = bset![self.genesis.node_id()]; - set.extend(self.data.iter().map(|(_, node)| node.node_id())); - set.extend(self.extensions.iter().map(Extension::node_id)); + set.extend(self.owned_data.iter().map(|(_, node)| node.node_id())); + set.extend(self.extension_data.iter().map(Extension::node_id)); set } @@ -79,7 +82,7 @@ impl Consignment { impl StrictEncode for Consignment { fn strict_encode(&self, mut e: E) -> Result { Ok( - strict_encode_list!(e; self.version, self.genesis, self.endpoints, self.data, self.extensions), + strict_encode_list!(e; self.version, self.genesis, self.endpoints, self.owned_data, self.extension_data), ) } } @@ -90,8 +93,8 @@ impl StrictDecode for Consignment { version: u16::strict_decode(&mut d)?, genesis: Genesis::strict_decode(&mut d)?, endpoints: ConsignmentEndpoints::strict_decode(&mut d)?, - data: OwnedData::strict_decode(&mut d)?, - extensions: ExtensionData::strict_decode(&mut d)?, + owned_data: OwnedData::strict_decode(&mut d)?, + extension_data: ExtensionData::strict_decode(&mut d)?, }) } } diff --git a/src/rgb/validation.rs b/src/rgb/validation.rs index 87ab0bcf..fb46680b 100644 --- a/src/rgb/validation.rs +++ b/src/rgb/validation.rs @@ -21,6 +21,7 @@ use super::schema::OccurrencesError; use super::{ schema, seal, Anchor, AnchorId, Consignment, ContractId, Node, NodeId, Schema, SchemaId, }; +use crate::rgb::schema::NodeType; use crate::rgb::AssignmentsVariant; #[derive(Clone, Copy, PartialEq, Eq, Debug, Display, Error)] @@ -245,12 +246,16 @@ impl<'validator, R: TxResolver> Validator<'validator, R> { // Create indexes let mut node_index = BTreeMap::::new(); let mut anchor_index = BTreeMap::::new(); - for (anchor, transition) in &consignment.data { + for (anchor, transition) in &consignment.owned_data { let node_id = transition.node_id(); node_index.insert(node_id, transition); anchor_index.insert(node_id, anchor); } node_index.insert(genesis_id, &consignment.genesis); + for extension in &consignment.extension_data { + let node_id = extension.node_id(); + node_index.insert(node_id, extension); + } // Collect all endpoint transitions // This is pretty simple operation; it takes a lot of code because @@ -382,6 +387,7 @@ impl<'validator, R: TxResolver> Validator<'validator, R> { queue.push_back(node); while let Some(node) = queue.pop_front() { let node_id = node.node_id(); + let node_type = node.node_type(); // [VALIDATION]: Verify node against the schema. Here we check // only a single node, not state evolution (it @@ -392,8 +398,8 @@ impl<'validator, R: TxResolver> Validator<'validator, R> { } // Making sure we do have a corresponding anchor; otherwise - // reporting failure (see below) - with the except of genesis - // node, which does not have a corresponding anchor + // reporting failure (see below) - with the except of genesis and + // extension nodes, which does not have a corresponding anchor if let Some(anchor) = self.anchor_index.get(&node_id).cloned() { // Ok, now we have the `node` and the `anchor`, let's do all // required checks @@ -409,9 +415,9 @@ impl<'validator, R: TxResolver> Validator<'validator, R> { self.validate_graph_node(node, anchor); // Ouch, we are out of that multi-level nested cycles :) - } else if node_id != self.genesis_id { + } else if node_type != NodeType::Genesis && node_type != NodeType::Extension { // This point is actually unreachable: b/c of the - // consignment structure, each node (other then genesis) + // consignment structure, each state transition // has a corresponding anchor. So if we've got here there // is something broken with LNP/BP core library. // TODO: Consider to remove this failure and replace it @@ -443,6 +449,7 @@ impl<'validator, R: TxResolver> Validator<'validator, R> { fn validate_graph_node(&mut self, node: &'validator dyn Node, anchor: &'validator Anchor) { let txid = anchor.txid; let node_id = node.node_id(); + let node_type = node.node_type(); // Check that the anchor is committed into a transaction spending all of // the transition inputs.