Skip to content

Commit

Permalink
Merge pull request #115 from AluVM/strict-encode
Browse files Browse the repository at this point in the history
Support library strict encoding. Use confined types
  • Loading branch information
dr-orlovsky authored Apr 18, 2024
2 parents 895e7ad + 4c9a1ce commit 7103495
Show file tree
Hide file tree
Showing 13 changed files with 225 additions and 333 deletions.
10 changes: 4 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ std = ["amplify/std"]
log = ["std"]
alloc = ["amplify/alloc"]
curve25519 = ["curve25519-dalek"]
serde = ["serde_crate", "amplify/serde", "std"]
serde = ["serde_crate", "amplify/serde", "std", "strict_encoding/serde"]

[target.'cfg(target_arch = "wasm32")'.dependencies]
wasm-bindgen = "0.2"
Expand All @@ -55,3 +55,8 @@ wasm-bindgen-test = "0.3"

[package.metadata.docs.rs]
features = ["all"]

[patch.crates-io]
strict_encoding_derive = { git = "https://github.com/strict-types/strict-encoding", branch = "rstring" }
strict_encoding = { git = "https://github.com/strict-types/strict-encoding", branch = "rstring" }
strict_types = { git = "https://github.com/strict-types/strict-types", branch = "rstring" }
75 changes: 3 additions & 72 deletions src/data/encoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,11 @@ use std::iter::FromIterator;
use std::marker::PhantomData;
use std::string::FromUtf8Error;

use amplify::{IoError, Wrapper};
use amplify::{confinement, IoError, Wrapper};

use crate::data::encoding::DecodeError::InvalidBool;
use crate::data::{ByteStr, FloatLayout, IntLayout, Layout, MaybeNumber, Number, NumberLayout};
use crate::library::{
IsaSeg, IsaSegError, Lib, LibId, LibSeg, LibSegOverflow, LibSite, SegmentError,
};
use crate::library::{IsaSegError, LibId, LibSite, SegmentError};

/// Trait for encodable container data structures used by AluVM and runtime environments
pub trait Encode {
Expand Down Expand Up @@ -126,7 +124,7 @@ pub enum DecodeError {
/// Library segment construction error
#[display(inner)]
#[from]
LibSeg(LibSegOverflow),
LibSeg(confinement::Error),

/// ISAE segment construction error
#[display(inner)]
Expand Down Expand Up @@ -616,46 +614,6 @@ impl Decode for LibId {
}
}

impl Encode for IsaSeg {
type Error = EncodeError;

fn encode(&self, writer: impl Write) -> Result<usize, Self::Error> {
self.to_string().encode(writer)
}
}

impl Decode for IsaSeg {
type Error = DecodeError;

fn decode(reader: impl Read) -> Result<Self, Self::Error>
where
Self: Sized,
{
let s = String::decode(reader)?;
IsaSeg::with(s).map_err(DecodeError::from)
}
}

impl Encode for LibSeg {
type Error = EncodeError;

fn encode(&self, writer: impl Write) -> Result<usize, Self::Error> {
MaxLenByte::new(self).encode(writer)
}
}

impl Decode for LibSeg {
type Error = DecodeError;

fn decode(reader: impl Read) -> Result<Self, Self::Error>
where
Self: Sized,
{
let seg: Vec<_> = MaxLenByte::decode(reader)?.release();
Ok(LibSeg::from_iter(seg)?)
}
}

impl Encode for LibSite {
type Error = io::Error;

Expand All @@ -676,30 +634,3 @@ impl Decode for LibSite {
Ok(LibSite::with(pos, id))
}
}

impl Encode for Lib {
type Error = EncodeError;

fn encode(&self, mut writer: impl Write) -> Result<usize, Self::Error> {
Ok(self.isae_segment().encode(&mut writer)?
+ self.code.encode(&mut writer)?
+ self.data.encode(&mut writer)?
+ self.libs.encode(&mut writer)?)
}
}

impl Decode for Lib {
type Error = DecodeError;

fn decode(mut reader: impl Read) -> Result<Self, Self::Error>
where
Self: Sized,
{
Ok(Lib::with(
String::decode(&mut reader)?.as_str(),
ByteStr::decode(&mut reader)?.to_vec(),
ByteStr::decode(&mut reader)?.to_vec(),
LibSeg::decode(&mut reader)?,
)?)
}
}
59 changes: 23 additions & 36 deletions src/isa/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ use super::{
};
use crate::data::{ByteStr, MaybeNumber, Number, NumberLayout};
use crate::isa::{ExtendFlag, FloatEqFlag, IntFlags, MergeFlag, NoneEqFlag, SignFlag};
use crate::library::{constants, LibSite};
use crate::library::{constants, IsaName, IsaSeg, LibSite};
use crate::reg::{CoreRegs, NumericRegister, Reg, Reg32, RegA, RegA2, RegAR, RegBlockAR, RegR};

/// Turing machine movement after instruction execution
Expand Down Expand Up @@ -67,13 +67,13 @@ pub trait InstructionSet: Bytecode + core::fmt::Display + core::fmt::Debug {
///
/// Each id must be up to 8 bytes and consist of upper case latin alphanumeric characters,
/// starting with non-number.
fn isa_ids() -> BTreeSet<&'static str>;
fn isa_ids() -> IsaSeg;

/// ISA Extension IDs represented as a standard string (space-separated)
///
/// Concatenated length of the ISA IDs joined via ' ' character must not exceed 128 bytes.
#[inline]
fn isa_string() -> String { Self::isa_ids().into_iter().collect::<Vec<_>>().join(" ") }
fn isa_string() -> String { Self::isa_ids().to_string() }

/// ISA Extension IDs encoded in a standard way (space-separated)
///
Expand All @@ -83,7 +83,7 @@ pub trait InstructionSet: Bytecode + core::fmt::Display + core::fmt::Debug {

/// Checks whether provided ISA extension ID is supported by the current instruction set
#[inline]
fn is_supported(id: &str) -> bool { Self::isa_ids().contains(id) }
fn is_supported(id: &IsaName) -> bool { Self::isa_ids().contains(id) }

/// Lists all registers which are used by the instruction.
fn regs(&self) -> BTreeSet<Reg> {
Expand Down Expand Up @@ -123,13 +123,12 @@ where
type Context<'ctx> = Extension::Context<'ctx>;

#[inline]
fn isa_ids() -> BTreeSet<&'static str> {
let mut set = BTreeSet::new();
set.insert(constants::ISA_ID_ALU);
set.extend(DigestOp::isa_ids());
set.extend(Secp256k1Op::isa_ids());
set.extend(Curve25519Op::isa_ids());
set.extend(Extension::isa_ids());
fn isa_ids() -> IsaSeg {
let mut set = IsaSeg::with(constants::ISA_ID_ALU);
set.extend(DigestOp::isa_ids()).expect("hardcoded");
set.extend(Secp256k1Op::isa_ids()).expect("hardcoded");
set.extend(Curve25519Op::isa_ids()).expect("hardcoded");
set.extend(Extension::isa_ids()).expect("hardcoded");
set
}

Expand Down Expand Up @@ -199,7 +198,7 @@ impl InstructionSet for ControlFlowOp {
type Context<'ctx> = ();

#[inline]
fn isa_ids() -> BTreeSet<&'static str> { BTreeSet::default() }
fn isa_ids() -> IsaSeg { IsaSeg::default() }

fn src_regs(&self) -> BTreeSet<Reg> { bset![] }

Expand Down Expand Up @@ -246,7 +245,7 @@ impl InstructionSet for PutOp {
type Context<'ctx> = ();

#[inline]
fn isa_ids() -> BTreeSet<&'static str> { BTreeSet::default() }
fn isa_ids() -> IsaSeg { IsaSeg::default() }

fn src_regs(&self) -> BTreeSet<Reg> { bset![] }

Expand Down Expand Up @@ -309,7 +308,7 @@ impl InstructionSet for MoveOp {
type Context<'ctx> = ();

#[inline]
fn isa_ids() -> BTreeSet<&'static str> { BTreeSet::default() }
fn isa_ids() -> IsaSeg { IsaSeg::default() }

fn src_regs(&self) -> BTreeSet<Reg> {
match self {
Expand Down Expand Up @@ -493,7 +492,7 @@ impl InstructionSet for CmpOp {
type Context<'ctx> = ();

#[inline]
fn isa_ids() -> BTreeSet<&'static str> { BTreeSet::default() }
fn isa_ids() -> IsaSeg { IsaSeg::default() }

fn src_regs(&self) -> BTreeSet<Reg> {
match self {
Expand Down Expand Up @@ -647,7 +646,7 @@ impl InstructionSet for ArithmeticOp {
type Context<'ctx> = ();

#[inline]
fn isa_ids() -> BTreeSet<&'static str> { BTreeSet::default() }
fn isa_ids() -> IsaSeg { IsaSeg::default() }

fn src_regs(&self) -> BTreeSet<Reg> {
match self {
Expand Down Expand Up @@ -812,7 +811,7 @@ impl InstructionSet for BitwiseOp {
type Context<'ctx> = ();

#[inline]
fn isa_ids() -> BTreeSet<&'static str> { BTreeSet::default() }
fn isa_ids() -> IsaSeg { IsaSeg::default() }

fn src_regs(&self) -> BTreeSet<Reg> {
match self {
Expand Down Expand Up @@ -1043,7 +1042,7 @@ impl InstructionSet for BytesOp {
type Context<'ctx> = ();

#[inline]
fn isa_ids() -> BTreeSet<&'static str> { BTreeSet::default() }
fn isa_ids() -> IsaSeg { IsaSeg::default() }

fn src_regs(&self) -> BTreeSet<Reg> {
match self {
Expand Down Expand Up @@ -1362,11 +1361,7 @@ impl InstructionSet for DigestOp {
type Context<'ctx> = ();

#[inline]
fn isa_ids() -> BTreeSet<&'static str> {
let mut set = BTreeSet::new();
set.insert(constants::ISA_ID_BPDIGEST);
set
}
fn isa_ids() -> IsaSeg { IsaSeg::with(constants::ISA_ID_BPDIGEST) }

fn src_regs(&self) -> BTreeSet<Reg> {
match self {
Expand Down Expand Up @@ -1434,15 +1429,11 @@ impl InstructionSet for Secp256k1Op {

#[cfg(not(feature = "secp256k1"))]
#[inline]
fn isa_ids() -> BTreeSet<&'static str> { BTreeSet::default() }
fn isa_ids() -> IsaSeg { IsaSeg::default() }

#[cfg(feature = "secp256k1")]
#[inline]
fn isa_ids() -> BTreeSet<&'static str> {
let mut set = BTreeSet::new();
set.insert(constants::ISA_ID_SECP256K);
set
}
fn isa_ids() -> IsaSeg { IsaSeg::with(constants::ISA_ID_SECP256K) }

fn src_regs(&self) -> BTreeSet<Reg> {
match self {
Expand Down Expand Up @@ -1581,15 +1572,11 @@ impl InstructionSet for Curve25519Op {

#[cfg(not(feature = "curve25519"))]
#[inline]
fn isa_ids() -> BTreeSet<&'static str> { BTreeSet::default() }
fn isa_ids() -> IsaSeg { IsaSeg::default() }

#[cfg(feature = "curve25519")]
#[inline]
fn isa_ids() -> BTreeSet<&'static str> {
let mut set = BTreeSet::new();
set.insert(constants::ISA_ID_ED25519);
set
}
fn isa_ids() -> IsaSeg { IsaSeg::with(constants::ISA_ID_ED25519) }

fn src_regs(&self) -> BTreeSet<Reg> {
match self {
Expand Down Expand Up @@ -1646,7 +1633,7 @@ impl InstructionSet for ReservedOp {
type Context<'ctx> = ();

#[inline]
fn isa_ids() -> BTreeSet<&'static str> { BTreeSet::default() }
fn isa_ids() -> IsaSeg { IsaSeg::default() }

fn src_regs(&self) -> BTreeSet<Reg> { bset![] }

Expand Down
19 changes: 4 additions & 15 deletions src/library/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,35 +25,24 @@

#![allow(missing_docs)]

pub const CODE_SEGMENT_MAX_LEN: usize = 1 << 16;
pub const CODE_SEGMENT_MAX_LEN: usize = 0xFFFF;

pub const DATA_SEGMENT_MAX_LEN: usize = 1 << 16;
pub const DATA_SEGMENT_MAX_LEN: usize = 0xFFFF;

/// Maximum number of libraries that may be referenced (used by) any other library; i.e. limit for
/// the number of records inside program segment.
pub const LIBS_SEGMENT_MAX_COUNT: usize = 1 << 8;
pub const LIBS_SEGMENT_MAX_COUNT: usize = 0xFF;

/// Maximum total number of libraries which may be used by a single program; i.e. maximal number of
/// nodes in a library dependency tree.
pub const LIBS_MAX_TOTAL: u16 = 1024;

pub const ISAE_SEGMENT_MAX_LEN: usize = 0xFF;

pub const ISAE_SEGMENT_MAX_COUNT: usize = 32;
pub const ISAE_SEGMENT_MAX_COUNT: usize = 64;

pub const ISA_ID_MIN_LEN: usize = 2;

pub const ISA_ID_MAX_LEN: usize = 8;

pub const ISA_ID_ALLOWED_CHARS: [char; 36] = [
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
];
pub const ISA_ID_ALLOWED_FIRST_CHAR: [char; 26] = [
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
];

pub const ISA_ID_ALU: &str = "ALU";
pub const ISA_ID_BPDIGEST: &str = "BPDIGEST";
pub const ISA_ID_SECP256K: &str = "SECP256K";
Expand Down
Loading

0 comments on commit 7103495

Please sign in to comment.