Skip to content

Commit

Permalink
Merge pull request #808 from 0xPolygonMiden/vlopes11-tsmt-masm
Browse files Browse the repository at this point in the history
feat: add stdlib smt collection
  • Loading branch information
vlopes11 authored Apr 14, 2023
2 parents b43e28d + 21b64be commit 5a5db0a
Show file tree
Hide file tree
Showing 23 changed files with 1,142 additions and 104 deletions.
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@
## 0.6.0 (TBD)

#### Assembly
- Added new instruction: `mtree_verify`.
- Added new instructions: `mtree_verify`, `adv.smtget`.
- [BREAKING] Refactored `adv.mem` decorator to use parameters from operand stack instead of immediate values.

#### Stdlib
- Added new module: `collections::smt` with `smt::get`.

## 0.5.0 (2023-03-29)

#### CLI
Expand Down
1 change: 1 addition & 0 deletions assembly/src/assembler/instruction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@ impl Assembler {
Instruction::AdvMem => adv_ops::adv_mem(span),
Instruction::AdvExt2Inv => span.add_decorator(Decorator::Advice(Ext2Inv)),
Instruction::AdvExt2INTT => span.add_decorator(Decorator::Advice(Ext2INTT)),
Instruction::AdvSmtGet => span.add_decorator(Decorator::Advice(SmtGet)),

// ----- cryptographic instructions ---------------------------------------------------
Instruction::Hash => crypto_ops::hash(span),
Expand Down
9 changes: 8 additions & 1 deletion assembly/src/parsers/adv_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ use super::{
// INSTRUCTION PARSERS
// ================================================================================================

/// Returns `AdvU64Div`, `AdvKeyval`, or `AdvMem` instruction node.
/// Returns `AdvU64Div`, `AdvKeyval`, `AdvMem`, `AdvExt2Inv`, `AdvExt2INTT`, or `AdvSmtGet`
/// instruction node.
///
/// # Errors
/// Returns an error if:
Expand Down Expand Up @@ -49,6 +50,12 @@ pub fn parse_adv_inject(op: &Token) -> Result<Node, ParsingError> {
}
Ok(Instruction(AdvExt2INTT))
}
"smtget" => {
if op.num_parts() > 2 {
return Err(ParsingError::extra_param(op));
}
Ok(Instruction(AdvSmtGet))
}
_ => Err(ParsingError::invalid_op(op)),
}
}
2 changes: 2 additions & 0 deletions assembly/src/parsers/nodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ pub enum Instruction {
AdvMem,
AdvExt2Inv,
AdvExt2INTT,
AdvSmtGet,

// ----- cryptographic operations -------------------------------------------------------------
Hash,
Expand Down Expand Up @@ -537,6 +538,7 @@ impl fmt::Display for Instruction {
Self::AdvMem => write!(f, "adv.mem"),
Self::AdvExt2Inv => write!(f, "adv.ext2inv"),
Self::AdvExt2INTT => write!(f, "adv.ext2intt"),
Self::AdvSmtGet => write!(f, "adv.smtget"),

// ----- cryptographic operations -----------------------------------------------------
Self::Hash => write!(f, "hash"),
Expand Down
1 change: 1 addition & 0 deletions assembly/src/parsers/serde/deserialization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,7 @@ impl Deserializable for Instruction {
OpCode::AdvLoadW => Ok(Instruction::AdvLoadW),
OpCode::AdvExt2Inv => Ok(Instruction::AdvExt2Inv),
OpCode::AdvExt2INTT => Ok(Instruction::AdvExt2INTT),
OpCode::AdvSmtGet => Ok(Instruction::AdvSmtGet),

// ----- cryptographic operations -----------------------------------------------------
OpCode::Hash => Ok(Instruction::Hash),
Expand Down
27 changes: 14 additions & 13 deletions assembly/src/parsers/serde/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,23 +257,24 @@ pub enum OpCode {
AdvMem = 227,
AdvExt2Inv = 228,
AdvExt2INTT = 229,
AdvSmtGet = 230,

// ----- cryptographic operations -------------------------------------------------------------
Hash = 230,
HMerge = 231,
HPerm = 232,
MTreeGet = 233,
MTreeSet = 234,
MTreeMerge = 235,
MTreeVerify = 236,
FriExt2Fold4 = 237,
Hash = 231,
HMerge = 232,
HPerm = 233,
MTreeGet = 234,
MTreeSet = 235,
MTreeMerge = 236,
MTreeVerify = 237,
FriExt2Fold4 = 238,

// ----- exec / call --------------------------------------------------------------------------
ExecLocal = 238,
ExecImported = 239,
CallLocal = 240,
CallImported = 241,
SysCall = 242,
ExecLocal = 239,
ExecImported = 240,
CallLocal = 241,
CallImported = 242,
SysCall = 243,

// ----- control flow -------------------------------------------------------------------------
IfElse = 253,
Expand Down
1 change: 1 addition & 0 deletions assembly/src/parsers/serde/serialization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,7 @@ impl Serializable for Instruction {
Self::AdvLoadW => OpCode::AdvLoadW.write_into(target),
Self::AdvExt2Inv => OpCode::AdvExt2Inv.write_into(target),
Self::AdvExt2INTT => OpCode::AdvExt2INTT.write_into(target),
Self::AdvSmtGet => OpCode::AdvSmtGet.write_into(target),

// ----- cryptographic operations -----------------------------------------------------
Self::Hash => OpCode::Hash.write_into(target),
Expand Down
3 changes: 2 additions & 1 deletion assembly/src/parsers/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,11 +184,12 @@ fn test_ast_parsing_adv_ops() {

#[test]
fn test_ast_parsing_adv_injection() {
let source = "begin adv.u64div adv.keyval adv.mem end";
let source = "begin adv.u64div adv.keyval adv.mem adv.smtget end";
let nodes: Vec<Node> = vec![
Node::Instruction(Instruction::AdvU64Div),
Node::Instruction(Instruction::AdvKeyval),
Node::Instruction(Instruction::AdvMem),
Node::Instruction(Instruction::AdvSmtGet),
];

assert_program_output(source, BTreeMap::new(), nodes);
Expand Down
3 changes: 2 additions & 1 deletion core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ pub use ::crypto::{Word, ONE, WORD_SIZE, ZERO};
pub mod crypto {
pub mod merkle {
pub use ::crypto::merkle::{
MerkleError, MerklePath, MerklePathSet, MerkleStore, MerkleTree, NodeIndex, SimpleSmt,
EmptySubtreeRoots, MerkleError, MerklePath, MerklePathSet, MerkleStore, MerkleTree,
NodeIndex, SimpleSmt,
};
}

Expand Down
19 changes: 19 additions & 0 deletions core/src/operations/decorators/advice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,24 @@ pub enum AdviceInjector {
/// routine interpolates ( using inverse NTT ) the evaluations into a polynomial in
/// coefficient form and pushes the result into the advice stack.
Ext2INTT,

/// Pushes the value and depth flags of a leaf indexed by `key` on a Sparse Merkle tree with
/// the provided `root`.
///
/// The Sparse Merkle tree is tiered, meaning it will have leaf depths in `{16, 32, 48, 64}`.
/// The depth flags define the tier on which the leaf is located.
///
/// The operand stack is expected to be arranged as follows (from the top):
/// - key, 4 elements.
/// - root of the Sparse Merkle tree, 4 elements.
///
/// After a successful operation, the advice stack will look as follows:
/// - boolean flag set to `1` if the depth is `16` or `48`.
/// - boolean flag set to `1` if the depth is `16` or `32`.
/// - remaining key word; will be zeroed if the tree don't contain a mapped value for the key.
/// - value word; will be zeroed if the tree don't contain a mapped value for the key.
/// - boolean flag set to `1` if a remaining key is not zero.
SmtGet,
}

impl fmt::Display for AdviceInjector {
Expand All @@ -62,6 +80,7 @@ impl fmt::Display for AdviceInjector {
Self::Memory => write!(f, "mem"),
Self::Ext2Inv => write!(f, "ext2_inv"),
Self::Ext2INTT => write!(f, "ext2_intt"),
Self::SmtGet => write!(f, "smt_get"),
}
}
}
1 change: 1 addition & 0 deletions processor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,6 @@ winter-prover = { package = "winter-prover", version = "0.6", default-features =
logtest = { version = "2.0", default-features = false }
miden-assembly = { package = "miden-assembly", path = "../assembly", version = "0.6", default-features = false }
rand-utils = { package = "winter-rand-utils", version = "0.6" }
test-utils = { package = "miden-test-utils", path = "../test-utils", version = "0.1" }
winter-fri = { package = "winter-fri", version = "0.6" }
winter-utils = { package = "winter-utils", version = "0.6" }
15 changes: 14 additions & 1 deletion processor/src/advice/mem_provider.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::{
AdviceInputs, AdviceProvider, AdviceSource, BTreeMap, ExecutionError, Felt, IntoBytes,
MerklePath, MerkleStore, NodeIndex, Vec, Word,
MerklePath, MerkleStore, NodeIndex, StarkField, Vec, Word,
};

// MEMORY ADVICE PROVIDER
Expand Down Expand Up @@ -120,6 +120,19 @@ impl AdviceProvider for MemAdviceProvider {
.map_err(ExecutionError::MerkleStoreLookupFailed)
}

fn get_leaf_depth(
&self,
root: Word,
tree_depth: &Felt,
index: &Felt,
) -> Result<u8, ExecutionError> {
let tree_depth = u8::try_from(tree_depth.as_int())
.map_err(|_| ExecutionError::InvalidTreeDepth { depth: *tree_depth })?;
self.store
.get_leaf_depth(root, tree_depth, index.as_int())
.map_err(ExecutionError::MerkleStoreLookupFailed)
}

fn update_merkle_node(
&mut self,
root: Word,
Expand Down
26 changes: 25 additions & 1 deletion processor/src/advice/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::{ExecutionError, Felt, InputError, Word};
use super::{ExecutionError, Felt, InputError, StarkField, Word};
use vm_core::{
crypto::merkle::{MerklePath, MerkleStore, NodeIndex},
utils::{
Expand Down Expand Up @@ -124,6 +124,21 @@ pub trait AdviceProvider {
index: &Felt,
) -> Result<MerklePath, ExecutionError>;

/// Reconstructs a path from the root until a leaf or empty node and returns its depth.
///
/// For more information, check [MerkleStore::get_leaf_depth].
///
/// # Errors
/// Will return an error if:
/// - The provided `tree_depth` doesn't fit `u8`.
/// - The conditions of [MerkleStore::get_leaf_depth] aren't met.
fn get_leaf_depth(
&self,
root: Word,
tree_depth: &Felt,
index: &Felt,
) -> Result<u8, ExecutionError>;

/// Updates a node at the specified depth and index in a Merkle tree with the specified root;
/// returns the Merkle path from the updated node to the new root.
///
Expand Down Expand Up @@ -211,6 +226,15 @@ where
T::get_merkle_path(self, root, depth, index)
}

fn get_leaf_depth(
&self,
root: Word,
tree_depth: &Felt,
index: &Felt,
) -> Result<u8, ExecutionError> {
T::get_leaf_depth(self, root, tree_depth, index)
}

fn update_merkle_node(
&mut self,
root: Word,
Expand Down
Loading

0 comments on commit 5a5db0a

Please sign in to comment.