Skip to content
Merged
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
9 changes: 4 additions & 5 deletions src/contract/attachment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,14 @@

use std::str::FromStr;

use amplify::confinement::TinyString;
use amplify::{Bytes32, RawArray};
use baid58::{Baid58ParseError, FromBaid58, ToBaid58};
use bp::secp256k1::rand::{thread_rng, RngCore};
use commit_verify::{CommitStrategy, CommitVerify, Conceal, StrictEncodedProtocol};
use strict_encoding::StrictEncode;

use super::{ConfidentialState, ExposedState};
use crate::{StateCommitment, StateData, StateType, LIB_NAME_RGB};
use crate::{MediaType, StateCommitment, StateData, StateType, LIB_NAME_RGB};

/// Unique data attachment identifier
#[derive(Wrapper, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display, From)]
Expand Down Expand Up @@ -72,17 +71,17 @@ pub struct Revealed {
pub id: AttachId,
/// We do not enforce a MIME standard since non-standard types can be also
/// used
pub media_type: TinyString,
pub media_type: MediaType,
pub salt: u64,
}

impl Revealed {
/// Creates new revealed attachment for the attachment id and MIME type.
/// Uses `thread_rng` to initialize [`Revealed::salt`].
pub fn new(id: AttachId, media_type: impl Into<TinyString>) -> Self {
pub fn new(id: AttachId, media_type: MediaType) -> Self {
Self {
id,
media_type: media_type.into(),
media_type,
salt: thread_rng().next_u64(),
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/contract/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,13 @@ pub trait ExposedState:
}

/// Categories of the state
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)]
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display)]
#[cfg_attr(
feature = "serde",
derive(Serialize, Deserialize),
serde(crate = "serde_crate", rename_all = "camelCase")
)]
#[display(lowercase)]
pub enum StateType {
/// No state data
Void,
Expand Down
4 changes: 2 additions & 2 deletions src/schema/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub use operations::{
};
pub use schema::{
ExtensionType, GlobalStateType, RootSchema, Schema, SchemaId, SchemaRoot, SchemaTypeIndex,
SubSchema, TransitionType,
SubSchema, TransitionType, BLANK_TRANSITION_ID,
};
pub use script::{Script, VmType};
pub use state::{FungibleType, GlobalStateSchema, StateSchema};
pub use state::{FungibleType, GlobalStateSchema, MediaType, StateSchema};
2 changes: 1 addition & 1 deletion src/schema/occurrences.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ impl StrictDecode for Occurrences {

#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Display)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))]
#[display(Debug)]
#[display("expected from {min} to {max} elements, while {found} were provided")]
pub struct OccurrencesMismatch {
pub min: u16,
pub max: u16,
Expand Down
14 changes: 13 additions & 1 deletion src/schema/operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,23 @@ pub enum OpType {

/// Aggregated type used to supply full contract operation type and
/// transition/state extension type information
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)]
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display)]
#[cfg_attr(
feature = "serde",
derive(Serialize, Deserialize),
serde(crate = "serde_crate", rename_all = "camelCase")
)]
pub enum OpFullType {
/// Genesis operation (no subtypes)
#[display("genesis")]
Genesis,

/// State transition contract operation, subtyped by transition type
#[display("state transition #{0}")]
StateTransition(TransitionType),

/// State extension contract operation, subtyped by extension type
#[display("state extension #{0}")]
StateExtension(ExtensionType),
}

Expand All @@ -84,6 +92,10 @@ impl OpFullType {
OpFullType::StateExtension(ty) => ty,
}
}

pub fn is_transition(self) -> bool { matches!(self, Self::StateTransition(_)) }

pub fn is_extension(self) -> bool { matches!(self, Self::StateExtension(_)) }
}

/// Trait defining common API for all operation type schemata
Expand Down
12 changes: 11 additions & 1 deletion src/schema/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ use super::{
AssignmentType, ExtensionSchema, GenesisSchema, Script, StateSchema, TransitionSchema,
ValencyType,
};
use crate::{Ffv, GlobalStateSchema, LIB_NAME_RGB};
use crate::{Ffv, GlobalStateSchema, Occurrences, LIB_NAME_RGB};

pub trait SchemaTypeIndex:
Copy + Eq + Ord + Default + StrictType + StrictEncode + StrictDecode
Expand All @@ -45,6 +45,7 @@ impl SchemaTypeIndex for u16 {}
pub type GlobalStateType = u16;
pub type ExtensionType = u16;
pub type TransitionType = u16;
pub const BLANK_TRANSITION_ID: u16 = TransitionType::MAX;

/// Schema identifier.
///
Expand Down Expand Up @@ -134,6 +135,15 @@ impl<Root: SchemaRoot> StrictDeserialize for Schema<Root> {}
impl<Root: SchemaRoot> Schema<Root> {
#[inline]
pub fn schema_id(&self) -> SchemaId { self.commitment_id() }

pub fn blank_transition(&self) -> TransitionSchema {
let mut schema = TransitionSchema::default();
for id in self.owned_types.keys() {
schema.inputs.insert(*id, Occurrences::NoneOrMore).ok();
schema.assignments.insert(*id, Occurrences::NoneOrMore).ok();
}
schema
}
}

#[cfg(test)]
Expand Down
33 changes: 29 additions & 4 deletions src/schema/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,31 @@ use strict_types::SemId;

use crate::{StateType, LIB_NAME_RGB};

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Display)]
#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
#[strict_type(lib = LIB_NAME_RGB, tags = repr, into_u8, try_from_u8)]
#[cfg_attr(
feature = "serde",
derive(Serialize, Deserialize),
serde(crate = "serde_crate", rename_all = "camelCase")
)]
#[non_exhaustive]
#[repr(u8)]
pub enum MediaType {
#[display("*/*")]
#[strict_type(dumb)]
Any = 0xFF,
// TODO: Complete MIME type implementation
}

impl MediaType {
pub fn conforms(&self, other: &MediaType) -> bool {
match (self, other) {
(MediaType::Any, MediaType::Any) => true,
}
}
}

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
#[strict_type(lib = LIB_NAME_RGB, tags = order)]
Expand All @@ -38,8 +63,7 @@ pub enum StateSchema {
Declarative,
Fungible(FungibleType),
Structured(SemId),
// TODO: Add MIME type requirements
Attachment,
Attachment(MediaType),
}

impl StateSchema {
Expand All @@ -48,7 +72,7 @@ impl StateSchema {
StateSchema::Declarative => StateType::Void,
StateSchema::Fungible(_) => StateType::Fungible,
StateSchema::Structured(_) => StateType::Structured,
StateSchema::Attachment => StateType::Attachment,
StateSchema::Attachment(_) => StateType::Attachment,
}
}
}
Expand All @@ -60,7 +84,7 @@ impl StateSchema {
/// future we plan to support more types. We reserve this possibility by
/// internally encoding [`ConfidentialFormat`] with the same type specification
/// details as used for [`DateFormat`]
#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
#[derive(Copy, Clone, PartialEq, Eq, Debug, Default, Display)]
#[derive(StrictType, StrictEncode, StrictDecode)]
#[strict_type(lib = LIB_NAME_RGB, tags = repr, into_u8, try_from_u8)]
#[cfg_attr(
Expand All @@ -71,6 +95,7 @@ impl StateSchema {
#[repr(u8)]
pub enum FungibleType {
#[default]
#[display("64bit")]
Unsigned64Bit = U64.into_code(),
}

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

mod script;
mod subschema;
mod schema;
mod model;
mod state;
mod validator;
Expand Down
Loading