Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RCP-240313B: Abstract script and type libraries out of consensus structures #221

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions src/schema/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@
use armor::StrictArmor;
use baid58::{Baid58ParseError, Chunking, FromBaid58, ToBaid58, CHUNKING_32};
use commit_verify::{CommitEncode, CommitEngine, CommitId, CommitmentId, DigestExt, Sha256};
use strict_encoding::{StrictDecode, StrictDeserialize, StrictEncode, StrictSerialize, StrictType};
use strict_encoding::{
StrictDecode, StrictDeserialize, StrictDumb, StrictEncode, StrictSerialize, StrictType,
};

use super::{
AssignmentType, ExtensionSchema, GenesisSchema, Script, StateSchema, TransitionSchema,
Expand Down Expand Up @@ -141,7 +143,7 @@
pub fn to_mnemonic(&self) -> String { self.to_baid58().mnemonic() }
}

pub trait SchemaRoot: Clone + Eq + StrictType + StrictEncode + StrictDecode + Default {
pub trait SchemaRoot: Clone + Eq + StrictType + StrictEncode + StrictDecode + StrictDumb {
fn schema_id(&self) -> SchemaId;
}
impl SchemaRoot for () {
Expand All @@ -153,8 +155,8 @@
pub type RootSchema = Schema<()>;
pub type SubSchema = Schema<RootSchema>;

#[derive(Clone, Eq, Default, Debug)]
#[derive(StrictType, StrictEncode, StrictDecode)]
#[derive(Clone, Eq, Debug)]

Check warning on line 158 in src/schema/schema.rs

View check run for this annotation

Codecov / codecov/patch

src/schema/schema.rs#L158

Added line #L158 was not covered by tests
#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
#[strict_type(lib = LIB_NAME_RGB)]
#[cfg_attr(
feature = "serde",
Expand Down Expand Up @@ -194,7 +196,7 @@
e.commit_to_map(&self.extensions);
e.commit_to_map(&self.transitions);

e.commit_to_serialized(&self.types.id());
e.commit_to_serialized(&*self.types);

Check warning on line 199 in src/schema/schema.rs

View check run for this annotation

Codecov / codecov/patch

src/schema/schema.rs#L199

Added line #L199 was not covered by tests
e.commit_to_serialized(&self.script);
}
}
Expand Down
56 changes: 12 additions & 44 deletions src/schema/script.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@

use std::ops::Deref;

use strict_types::TypeSystem;
use strict_types::TypeSysId;

use crate::vm::AluScript;
use crate::LIB_NAME_RGB;
Expand Down Expand Up @@ -83,16 +83,21 @@

/// Types used by a schema and virtual machine
#[derive(Clone, Eq, PartialEq, Debug, From)]
#[derive(StrictType, StrictEncode, StrictDecode)]
#[strict_type(lib = LIB_NAME_RGB, tags = custom)]
#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
#[strict_type(lib = LIB_NAME_RGB, tags = custom, dumb = Self::Strict(strict_dumb!()))]
#[cfg_attr(
feature = "serde",
derive(Serialize, Deserialize),

Check warning on line 90 in src/schema/script.rs

View check run for this annotation

Codecov / codecov/patch

src/schema/script.rs#L90

Added line #L90 was not covered by tests
serde(crate = "serde_crate", rename_all = "camelCase", tag = "type")
)]
pub enum Types {
#[from]
#[strict_type(tag = 0x01)]
Strict(TypeSystem),
Strict(TypeSysId),
}

impl Deref for Types {
type Target = TypeSystem;
type Target = TypeSysId;

fn deref(&self) -> &Self::Target {
match self {
Expand All @@ -101,47 +106,10 @@
}
}

impl Default for Types {
fn default() -> Self { Types::Strict(none!()) }
}

impl Types {
pub fn as_strict(&self) -> &TypeSystem {
pub fn as_strict(&self) -> &TypeSysId {

Check warning on line 110 in src/schema/script.rs

View check run for this annotation

Codecov / codecov/patch

src/schema/script.rs#L110

Added line #L110 was not covered by tests
match self {
Types::Strict(ts) => ts,
}
}
}

#[cfg(feature = "serde")]
mod _serde {
use armor::AsciiArmor;
use serde_crate::de::Error;
use serde_crate::{Deserialize, Deserializer, Serialize, Serializer};

use super::*;

impl Serialize for Types {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer {
if serializer.is_human_readable() {
serializer.serialize_str(&self.as_strict().to_ascii_armored_string())
} else {
self.as_strict().serialize(serializer)
}
}
}

impl<'de> Deserialize<'de> for Types {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'de> {
if deserializer.is_human_readable() {
let s = String::deserialize(deserializer)?;
let sys = TypeSystem::from_ascii_armored_str(&s).map_err(D::Error::custom)?;
Ok(Types::Strict(sys))
} else {
Ok(Types::Strict(TypeSystem::deserialize(deserializer)?))
}
Types::Strict(id) => id,

Check warning on line 112 in src/schema/script.rs

View check run for this annotation

Codecov / codecov/patch

src/schema/script.rs#L112

Added line #L112 was not covered by tests
}
}
}
2 changes: 1 addition & 1 deletion src/stl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ use crate::{

/// Strict types id for the library providing data types for RGB consensus.
pub const LIB_ID_RGB: &str =
"urn:ubideco:stl:6NAFZspAZ14Y1NynHeQBJVNqep4arKkKx8zchhHrESvr#airport-border-match";
"urn:ubideco:stl:2YLR1EqJCDGB97JAD22mTwNdg6Gpbzi8PwkGKE6UsDx8#hotel-comet-grand";

fn _rgb_core_stl() -> Result<TypeLib, CompileError> {
LibBuilder::new(libname!(LIB_NAME_RGB), tiny_bset! {
Expand Down
27 changes: 26 additions & 1 deletion src/validation/consignment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@
use std::collections::{BTreeMap, BTreeSet};
use std::rc::Rc;

use aluvm::isa::Instr;
use aluvm::library::LibId;
use aluvm::Program;
use strict_types::{TypeSysId, TypeSystem};

use crate::vm::RgbIsa;
use crate::{
AnchoredBundle, AssetTag, AssignmentType, BundleId, Genesis, OpId, OpRef, Operation,
SecretSeal, SubSchema, WitnessId, XChain,
Expand All @@ -40,6 +46,7 @@

impl<'consignment, C: ConsignmentApi> ConsignmentApi for CheckedConsignment<'consignment, C> {
type Iter<'placeholder> = C::Iter<'placeholder>;
type Program = C::Program;

fn schema(&self) -> &SubSchema { self.0.schema() }

Expand All @@ -62,6 +69,15 @@
}

fn op_witness_id(&self, opid: OpId) -> Option<WitnessId> { self.0.op_witness_id(opid) }

fn program<'a>(
&self,
libs: impl IntoIterator<Item = &'a LibId>,
) -> Result<&Self::Program, LibId> {
self.0.program(libs)
}

Check warning on line 78 in src/validation/consignment.rs

View check run for this annotation

Codecov / codecov/patch

src/validation/consignment.rs#L73-L78

Added lines #L73 - L78 were not covered by tests

fn type_system(&self, id: TypeSysId) -> Option<&TypeSystem> { self.0.type_system(id) }

Check warning on line 80 in src/validation/consignment.rs

View check run for this annotation

Codecov / codecov/patch

src/validation/consignment.rs#L80

Added line #L80 was not covered by tests
}

/// Trait defining common data access API for all storage-related RGB structures
Expand All @@ -75,13 +91,15 @@
/// Iterator for all bundle ids present in the consignment.
type Iter<'a>: Iterator<Item = BundleId>;

type Program: Program<Isa = Instr<RgbIsa>>;

/// Returns reference to the schema object used by the consignment.
fn schema(&self) -> &SubSchema;

/// Asset tags uses in the confidential asset validation.
fn asset_tags(&self) -> &BTreeMap<AssignmentType, AssetTag>;

/// Retrieves reference to a operation (genesis, state transition or state
/// Retrieves reference to an operation (genesis, state transition or state
/// extension) matching the provided id, or `None` otherwise
fn operation(&self, opid: OpId) -> Option<OpRef>;

Expand All @@ -107,4 +125,11 @@

/// Returns witness id for a given operation.
fn op_witness_id(&self, opid: OpId) -> Option<WitnessId>;

fn program<'a>(
&self,
libs: impl IntoIterator<Item = &'a LibId>,
) -> Result<&Self::Program, LibId>;

fn type_system(&self, id: TypeSysId) -> Option<&TypeSystem>;
}
51 changes: 29 additions & 22 deletions src/validation/logic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@

use amplify::confinement::{Confined, SmallBlob};
use amplify::Wrapper;
use strict_types::SemId;
use strict_types::{SemId, TypeSystem};

use crate::schema::{AssignmentsSchema, GlobalSchema, ValencySchema};
use crate::validation::{CheckedConsignment, ConsignmentApi, VirtualMachine};
use crate::validation::{CheckedConsignment, ConsignmentApi, Failure, VirtualMachine};
use crate::{
validation, AssetTag, AssignmentType, Assignments, AssignmentsRef, ContractId, ExposedSeal,
GlobalState, GlobalStateSchema, GlobalValues, GraphSeal, Inputs, OpFullType, OpId, OpRef,
Expand Down Expand Up @@ -135,10 +135,16 @@

let mut status = validation::Status::new();

let sys_id = *consignment.schema().types;
let Some(type_sys) = consignment.type_system(sys_id) else {
status.add_failure(Failure::TypesAbsent(sys_id));
return status;

Check warning on line 141 in src/validation/logic.rs

View check run for this annotation

Codecov / codecov/patch

src/validation/logic.rs#L138-L141

Added lines #L138 - L141 were not covered by tests
};

// Validate type system
status += self.validate_type_system();
status += self.validate_metadata(id, *metadata_schema, op.metadata());
status += self.validate_global_state(id, op.globals(), global_schema);
status += self.validate_metadata(id, type_sys, *metadata_schema, op.metadata());
status += self.validate_global_state(id, type_sys, op.globals(), global_schema);

Check warning on line 147 in src/validation/logic.rs

View check run for this annotation

Codecov / codecov/patch

src/validation/logic.rs#L146-L147

Added lines #L146 - L147 were not covered by tests
let prev_state = if let OpRef::Transition(transition) = op {
let prev_state = extract_prev_state(consignment, id, &transition.inputs, &mut status);
status += self.validate_prev_state(id, &prev_state, owned_schema);
Expand All @@ -155,10 +161,10 @@
}
status += match op.assignments() {
AssignmentsRef::Genesis(assignments) => {
self.validate_owned_state(id, assignments, assign_schema)
self.validate_owned_state(id, type_sys, assignments, assign_schema)

Check warning on line 164 in src/validation/logic.rs

View check run for this annotation

Codecov / codecov/patch

src/validation/logic.rs#L164

Added line #L164 was not covered by tests
}
AssignmentsRef::Graph(assignments) => {
self.validate_owned_state(id, assignments, assign_schema)
self.validate_owned_state(id, type_sys, assignments, assign_schema)

Check warning on line 167 in src/validation/logic.rs

View check run for this annotation

Codecov / codecov/patch

src/validation/logic.rs#L167

Added line #L167 was not covered by tests
}
};

Expand Down Expand Up @@ -196,13 +202,13 @@
fn validate_metadata(
&self,
opid: OpId,
type_sys: &TypeSystem,

Check warning on line 205 in src/validation/logic.rs

View check run for this annotation

Codecov / codecov/patch

src/validation/logic.rs#L205

Added line #L205 was not covered by tests
sem_id: SemId,
metadata: &SmallBlob,
) -> validation::Status {
let mut status = validation::Status::new();

if self
.types
if type_sys

Check warning on line 211 in src/validation/logic.rs

View check run for this annotation

Codecov / codecov/patch

src/validation/logic.rs#L211

Added line #L211 was not covered by tests
.strict_deserialize_type(sem_id, metadata.as_ref())
.is_err()
{
Expand All @@ -215,6 +221,7 @@
fn validate_global_state(
&self,
opid: OpId,
type_sys: &TypeSystem,

Check warning on line 224 in src/validation/logic.rs

View check run for this annotation

Codecov / codecov/patch

src/validation/logic.rs#L224

Added line #L224 was not covered by tests
global: &GlobalState,
global_schema: &GlobalSchema,
) -> validation::Status {
Expand Down Expand Up @@ -258,8 +265,7 @@

// Validating data types
for data in set {
if self
.types
if type_sys

Check warning on line 268 in src/validation/logic.rs

View check run for this annotation

Codecov / codecov/patch

src/validation/logic.rs#L268

Added line #L268 was not covered by tests
.strict_deserialize_type(*sem_id, data.value.as_ref())
.is_err()
{
Expand Down Expand Up @@ -334,6 +340,7 @@
fn validate_owned_state<Seal: ExposedSeal>(
&self,
id: OpId,
type_sys: &TypeSystem,

Check warning on line 343 in src/validation/logic.rs

View check run for this annotation

Codecov / codecov/patch

src/validation/logic.rs#L343

Added line #L343 was not covered by tests
owned_state: &Assignments<Seal>,
assign_schema: &AssignmentsSchema,
) -> validation::Status {
Expand Down Expand Up @@ -370,18 +377,18 @@

match owned_state.get(state_id) {
None => {}
Some(TypedAssigns::Declarative(set)) => set.iter().for_each(|data| {
status += assignment.validate(&self.types, &id, *state_id, data)
}),
Some(TypedAssigns::Fungible(set)) => set.iter().for_each(|data| {
status += assignment.validate(&self.types, &id, *state_id, data)
}),
Some(TypedAssigns::Structured(set)) => set.iter().for_each(|data| {
status += assignment.validate(&self.types, &id, *state_id, data)
}),
Some(TypedAssigns::Attachment(set)) => set.iter().for_each(|data| {
status += assignment.validate(&self.types, &id, *state_id, data)
}),
Some(TypedAssigns::Declarative(set)) => set
.iter()
.for_each(|data| status += assignment.validate(type_sys, &id, *state_id, data)),
Some(TypedAssigns::Fungible(set)) => set
.iter()
.for_each(|data| status += assignment.validate(type_sys, &id, *state_id, data)),
Some(TypedAssigns::Structured(set)) => set
.iter()
.for_each(|data| status += assignment.validate(type_sys, &id, *state_id, data)),
Some(TypedAssigns::Attachment(set)) => set
.iter()
.for_each(|data| status += assignment.validate(type_sys, &id, *state_id, data)),

Check warning on line 391 in src/validation/logic.rs

View check run for this annotation

Codecov / codecov/patch

src/validation/logic.rs#L380-L391

Added lines #L380 - L391 were not covered by tests
};
}

Expand Down
27 changes: 1 addition & 26 deletions src/validation/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
// limitations under the License.

use crate::validation::Status;
use crate::{validation, OpFullType, OpSchema, Schema, StateSchema, SubSchema, TransitionType};
use crate::{validation, OpFullType, OpSchema, Schema, SubSchema, TransitionType};

impl SubSchema {
pub fn verify(&self) -> validation::Status {
Expand Down Expand Up @@ -52,37 +52,12 @@ impl SubSchema {
status.add_failure(validation::Failure::SchemaBlankTransitionRedefined);
}

for (type_id, schema) in &self.global_types {
if !self.types.contains_key(&schema.sem_id) {
status.add_failure(validation::Failure::SchemaGlobalSemIdUnknown(
*type_id,
schema.sem_id,
));
}
}

for (type_id, schema) in &self.owned_types {
if let StateSchema::Structured(sem_id) = schema {
if !self.types.contains_key(sem_id) {
status.add_failure(validation::Failure::SchemaOwnedSemIdUnknown(
*type_id, *sem_id,
));
}
}
}

status
}

fn verify_operation(&self, op_type: OpFullType, schema: &impl OpSchema) -> Status {
let mut status = validation::Status::new();

if !self.types.contains_key(&schema.metadata()) {
status.add_failure(validation::Failure::SchemaOpMetaSemIdUnknown(
op_type,
schema.metadata(),
));
}
if matches!(schema.inputs(), Some(inputs) if inputs.is_empty()) {
status.add_failure(validation::Failure::SchemaOpEmptyInputs(op_type));
}
Expand Down
17 changes: 6 additions & 11 deletions src/validation/script.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use aluvm::isa::Instr;
use aluvm::Program;

use crate::validation;
use crate::validation::OpInfo;
use crate::vm::AluRuntime;
use crate::{validation, Script};
use crate::vm::{AluRuntime, RgbIsa};

/// Trait for concrete types wrapping virtual machines to be used from inside
/// RGB schema validation routines.
Expand All @@ -32,15 +35,7 @@ pub trait VirtualMachine {
fn validate(&self, info: OpInfo) -> Result<(), validation::Failure>;
}

impl VirtualMachine for Script {
fn validate(&self, info: OpInfo) -> Result<(), validation::Failure> {
match self {
Script::AluVM(script) => AluRuntime::new(script).validate(info),
}
}
}

impl<'script> VirtualMachine for AluRuntime<'script> {
impl<'consignment, P: Program<Isa = Instr<RgbIsa>>> VirtualMachine for AluRuntime<'consignment, P> {
fn validate(&self, info: OpInfo) -> Result<(), validation::Failure> {
let id = info.id;
self.run_validations(&info)
Expand Down
Loading
Loading