Skip to content

Commit

Permalink
validation: move type system from schema to consignment
Browse files Browse the repository at this point in the history
  • Loading branch information
dr-orlovsky committed Mar 27, 2024
1 parent fbc979d commit 3b089b8
Show file tree
Hide file tree
Showing 9 changed files with 63 additions and 135 deletions.
7 changes: 2 additions & 5 deletions src/schema/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,6 @@ pub use operations::{
AssignmentType, AssignmentsSchema, ExtensionSchema, GenesisSchema, GlobalSchema, OpFullType,
OpSchema, OpType, TransitionSchema, ValencySchema, ValencyType,
};
pub use schema::{
ExtensionType, GlobalStateType, Schema, SchemaId,
TransitionType,
};
pub use script::{Script, Types, VmType};
pub use schema::{ExtensionType, GlobalStateType, Schema, SchemaId, TransitionType};
pub use script::{Script, VmType};
pub use state::{FungibleType, GlobalStateSchema, MediaType, StateSchema};
5 changes: 1 addition & 4 deletions src/schema/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ use super::{
AssignmentType, ExtensionSchema, GenesisSchema, Script, StateSchema, TransitionSchema,
ValencyType,
};
use crate::{Ffv, GlobalStateSchema, Occurrences, Types, LIB_NAME_RGB};
use crate::{Ffv, GlobalStateSchema, Occurrences, LIB_NAME_RGB};

#[derive(Wrapper, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From, Display)]
#[wrapper(FromStr, LowerHex, UpperHex)]
Expand Down Expand Up @@ -162,8 +162,6 @@ pub struct Schema {
pub extensions: TinyOrdMap<ExtensionType, ExtensionSchema>,
pub transitions: TinyOrdMap<TransitionType, TransitionSchema>,

/// Type system
pub types: Types,
/// Validation code.
pub script: Script,
}
Expand All @@ -182,7 +180,6 @@ impl CommitEncode for Schema {
e.commit_to_map(&self.extensions);
e.commit_to_map(&self.transitions);

e.commit_to_serialized(&self.types.id());
e.commit_to_serialized(&self.script);
}
}
Expand Down
83 changes: 0 additions & 83 deletions src/schema/script.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,6 @@
//! Components related to the scripting system used by schema or applied at the
//! specific contract operation level
use std::ops::{Deref, DerefMut};

use strict_types::TypeSystem;

use crate::vm::AluScript;
use crate::LIB_NAME_RGB;

Expand Down Expand Up @@ -80,82 +76,3 @@ impl Script {
alu
}
}

/// 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)]
pub enum Types {
#[from]
#[strict_type(tag = 0x01)]
Strict(TypeSystem),
}

impl Deref for Types {
type Target = TypeSystem;

fn deref(&self) -> &Self::Target {
match self {
Types::Strict(sys) => sys,
}
}
}

impl DerefMut for Types {
fn deref_mut(&mut self) -> &mut Self::Target {
match self {
Types::Strict(sys) => sys,
}
}
}

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

impl Types {
pub fn as_strict(&self) -> &TypeSystem {
match self {
Types::Strict(ts) => ts,
}
}

pub fn into_strict(self) -> TypeSystem {
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)?))
}
}
}
}
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:B5QUyVAAiot39pdJNqKAGy1vPaqpJYBK8eF1DUB5Q19w#aroma-spider-wave";
"urn:ubideco:stl:8c6sWAHuApYB1te5zqKLZK2JcqNHNdBn1p2VtvQBv4y8#suzuki-soda-talent";

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

use strict_types::TypeSystem;

use crate::{
AnchoredBundle, AssetTag, AssignmentType, BundleId, Genesis, OpId, OpRef, Operation,
SecretSeal, Schema, WitnessId, XChain,
AnchoredBundle, AssetTag, AssignmentType, BundleId, Genesis, OpId, OpRef, Operation, Schema,
SecretSeal, WitnessId, XChain,
};

pub struct CheckedConsignment<'consignment, C: ConsignmentApi>(&'consignment C);
Expand All @@ -43,6 +45,8 @@ impl<'consignment, C: ConsignmentApi> ConsignmentApi for CheckedConsignment<'con

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

fn types(&self) -> &TypeSystem { self.0.types() }

fn asset_tags(&self) -> &BTreeMap<AssignmentType, AssetTag> { self.0.asset_tags() }

fn operation(&self, opid: OpId) -> Option<OpRef> {
Expand Down Expand Up @@ -78,6 +82,9 @@ pub trait ConsignmentApi {
/// Returns reference to the schema object used by the consignment.
fn schema(&self) -> &Schema;

/// Returns reference to the type system.
fn types(&self) -> &TypeSystem;

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

Expand Down
43 changes: 22 additions & 21 deletions src/validation/logic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use std::collections::{BTreeMap, BTreeSet};

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};
Expand Down Expand Up @@ -137,8 +137,8 @@ impl Schema {

// 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, *metadata_schema, op.metadata(), consignment.types());
status += self.validate_global_state(id, op.globals(), global_schema, consignment.types());
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 +155,10 @@ impl Schema {
}
status += match op.assignments() {
AssignmentsRef::Genesis(assignments) => {
self.validate_owned_state(id, assignments, assign_schema)
self.validate_owned_state(id, assignments, assign_schema, consignment.types())
}
AssignmentsRef::Graph(assignments) => {
self.validate_owned_state(id, assignments, assign_schema)
self.validate_owned_state(id, assignments, assign_schema, consignment.types())
}
};

Expand Down Expand Up @@ -197,11 +197,11 @@ impl Schema {
opid: OpId,
sem_id: SemId,
metadata: &SmallBlob,
types: &TypeSystem,
) -> validation::Status {
let mut status = validation::Status::new();

if self
.types
if types
.strict_deserialize_type(sem_id, metadata.as_ref())
.is_err()
{
Expand All @@ -216,6 +216,7 @@ impl Schema {
opid: OpId,
global: &GlobalState,
global_schema: &GlobalSchema,
types: &TypeSystem,
) -> validation::Status {
let mut status = validation::Status::new();

Expand Down Expand Up @@ -257,8 +258,7 @@ impl Schema {

// Validating data types
for data in set {
if self
.types
if types
.strict_deserialize_type(*sem_id, data.value.as_ref())
.is_err()
{
Expand Down Expand Up @@ -335,6 +335,7 @@ impl Schema {
id: OpId,
owned_state: &Assignments<Seal>,
assign_schema: &AssignmentsSchema,
types: &TypeSystem,
) -> validation::Status {
let mut status = validation::Status::new();

Expand Down Expand Up @@ -369,18 +370,18 @@ impl Schema {

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(id, *state_id, data, types)),
Some(TypedAssigns::Fungible(set)) => set
.iter()
.for_each(|data| status += assignment.validate(id, *state_id, data, types)),
Some(TypedAssigns::Structured(set)) => set
.iter()
.for_each(|data| status += assignment.validate(id, *state_id, data, types)),
Some(TypedAssigns::Attachment(set)) => set
.iter()
.for_each(|data| status += assignment.validate(id, *state_id, data, types)),
};
}

Expand Down
23 changes: 15 additions & 8 deletions src/validation/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,26 +20,28 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use strict_types::TypeSystem;

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

impl Schema {
pub fn verify(&self) -> validation::Status {
pub fn verify(&self, types: &TypeSystem) -> validation::Status {
let mut status = validation::Status::new();

status += self.verify_operation(OpFullType::Genesis, &self.genesis);
status += self.verify_operation(OpFullType::Genesis, &self.genesis, types);
for (type_id, schema) in &self.transitions {
status += self.verify_operation(OpFullType::StateTransition(*type_id), schema);
status += self.verify_operation(OpFullType::StateTransition(*type_id), schema, types);
}
for (type_id, schema) in &self.extensions {
status += self.verify_operation(OpFullType::StateExtension(*type_id), schema);
status += self.verify_operation(OpFullType::StateExtension(*type_id), schema, types);
}
// Check that the schema doesn't contain reserved type ids
if self.transitions.contains_key(&TransitionType::BLANK) {
status.add_failure(validation::Failure::SchemaBlankTransitionRedefined);
}

for (type_id, schema) in &self.global_types {
if !self.types.contains_key(&schema.sem_id) {
if !types.contains_key(&schema.sem_id) {
status.add_failure(validation::Failure::SchemaGlobalSemIdUnknown(
*type_id,
schema.sem_id,
Expand All @@ -49,7 +51,7 @@ impl Schema {

for (type_id, schema) in &self.owned_types {
if let StateSchema::Structured(sem_id) = schema {
if !self.types.contains_key(sem_id) {
if !types.contains_key(sem_id) {
status.add_failure(validation::Failure::SchemaOwnedSemIdUnknown(
*type_id, *sem_id,
));
Expand All @@ -60,10 +62,15 @@ impl Schema {
status
}

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

if !self.types.contains_key(&schema.metadata()) {
if !types.contains_key(&schema.metadata()) {
status.add_failure(validation::Failure::SchemaOpMetaSemIdUnknown(
op_type,
schema.metadata(),
Expand Down
Loading

0 comments on commit 3b089b8

Please sign in to comment.