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
1 change: 1 addition & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions arm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ bincode = "1.3.3"
hex = "0.4"
lazy_static = "1.5.0"
rustler = { version = "0.36.2", optional = true }
bytemuck = { version = "1.12", features = ["derive"] }

[features]
default = ["transaction"]
Expand Down
Binary file modified arm/elfs/compliance-guest.bin
Binary file not shown.
Binary file modified arm/elfs/trivial-logic-guest.bin
Binary file not shown.
28 changes: 10 additions & 18 deletions arm/src/action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,15 @@ use crate::{
compliance_unit::ComplianceUnit,
delta_proof::DeltaWitness,
logic_proof::{LogicProof, LogicProver},
merkle_path::Leaf,
merkle_path::COMMITMENT_TREE_DEPTH,
nullifier_key::NullifierKey,
resource::Resource,
resource_logic::TrivialLogicWitness,
};
use k256::ProjectivePoint;
use serde::{Deserialize, Serialize};
#[cfg(feature = "nif")]
use {
rustler::types::map::map_new,
rustler::{Atom, Decoder, Encoder, Env, NifResult, NifStruct, Term},
};
use rustler::NifStruct;
use serde::{Deserialize, Serialize};

#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(feature = "nif", derive(NifStruct))]
Expand Down Expand Up @@ -59,15 +55,15 @@ impl Action {
.collect::<Vec<ComplianceInstance>>();

// Construct the action tree
let tags = compliance_intances
let tags: Vec<Vec<u32>> = compliance_intances
.iter()
.flat_map(|instance| {
vec![
instance.consumed_nullifier.clone().into(),
instance.created_commitment.clone().into(),
instance.consumed_nullifier.clone(),
instance.created_commitment.clone(),
]
})
.collect::<Vec<Leaf>>();
.collect();
let logics = compliance_intances
.iter()
.flat_map(|instance| {
Expand All @@ -77,7 +73,7 @@ impl Action {
]
})
.collect::<Vec<_>>();
let action_tree = MerkleTree::new(tags.clone());
let action_tree = MerkleTree::from(tags.clone());
let root = action_tree.root();

for proof in &self.logic_verifier_inputs {
Expand All @@ -87,8 +83,7 @@ impl Action {
return false;
}

let instance_tag: Leaf = instance.tag.clone().into();
if let Some(index) = tags.iter().position(|tag| tag == &instance_tag) {
if let Some(index) = tags.iter().position(|tag| *tag == instance.tag) {
if proof.verifying_key != logics[index] {
return false;
}
Expand Down Expand Up @@ -134,7 +129,7 @@ pub fn create_an_action(nonce: u8) -> (Action, DeltaWitness) {
let consumed_resource_nf = consumed_resource.nullifier(&nf_key).unwrap();

let mut created_resource = consumed_resource.clone();
created_resource.set_nonce(consumed_resource_nf.clone());
created_resource.set_nonce(consumed_resource_nf.as_bytes().to_vec());

let compliance_witness = ComplianceWitness::<COMMITMENT_TREE_DEPTH>::with_fixed_rcv(
consumed_resource.clone(),
Expand All @@ -144,10 +139,7 @@ pub fn create_an_action(nonce: u8) -> (Action, DeltaWitness) {
let compliance_receipt = ComplianceUnit::create(&compliance_witness);

let created_resource_cm = created_resource.commitment();
let action_tree = MerkleTree::new(vec![
consumed_resource_nf.clone().into(),
created_resource_cm.clone().into(),
]);
let action_tree = MerkleTree::new(vec![consumed_resource_nf, created_resource_cm]);
let consumed_resource_path = action_tree.generate_path(&consumed_resource_nf).unwrap();
let created_resource_path = action_tree.generate_path(&created_resource_cm).unwrap();

Expand Down
56 changes: 34 additions & 22 deletions arm/src/action_tree.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use crate::merkle_path::{Hashable, Leaf, MerklePath};
use crate::{
merkle_path::{MerklePath, PADDING_LEAF},
utils::hash_two,
};
use risc0_zkvm::sha::Digest;

#[cfg(feature = "nif")]
Expand All @@ -11,34 +14,36 @@ pub const ACTION_TREE_DEPTH: usize = 4;
#[cfg_attr(feature = "nif", derive(NifStruct))]
#[cfg_attr(feature = "nif", module = "Anoma.Arm.MerkleTree")]
pub struct MerkleTree {
leaves: Vec<Leaf>,
leaves: Vec<Vec<u32>>,
}

impl MerkleTree {
pub fn new(leaves: Vec<Leaf>) -> Self {
pub fn new(leaves: Vec<Digest>) -> Self {
assert!(
leaves.len() <= ACTION_TREE_MAX_NUM,
"The number of leaves exceeds the ACTION_TREE_MAX_NUM"
);
let leaves = leaves
.into_iter()
.map(|digest| digest.as_words().to_vec())
.collect();
MerkleTree { leaves }
}

pub fn insert(&mut self, value: Leaf) {
self.leaves.push(value)
pub fn insert(&mut self, value: Digest) {
self.leaves.push(value.as_words().to_vec())
}

pub fn root(&self) -> Vec<u8> {
pub fn root(&self) -> Vec<u32> {
let mut cur_layer = self.leaves.clone();
cur_layer.resize(ACTION_TREE_MAX_NUM, Digest::blank().into());
cur_layer.resize(ACTION_TREE_MAX_NUM, PADDING_LEAF.as_words().to_vec());
while cur_layer.len() > 1 {
cur_layer = cur_layer
.chunks(2)
.map(|pair| {
Digest::combine(&pair[0].clone().into(), &pair[1].clone().into()).into()
})
.map(|pair| hash_two(&pair[0], &pair[1]))
.collect();
}
cur_layer[0].inner().to_vec()
cur_layer[0].clone()
}

// Generate the merkle path for the current leave
Expand All @@ -56,18 +61,15 @@ impl MerkleTree {
/// - A `bool` indicating whether the sibling is on the left (`true`) or right (`false`).
///
/// Returns `None` if the leaf is not found in the tree.
pub fn generate_path(&self, cur_leave: &[u8]) -> Option<MerklePath<ACTION_TREE_DEPTH>> {
pub fn generate_path(&self, cur_leave: &Digest) -> Option<MerklePath<ACTION_TREE_DEPTH>> {
let mut cur_layer = self.leaves.clone();
cur_layer.resize(ACTION_TREE_MAX_NUM, Digest::blank().into());
if let Some(position) = cur_layer
.iter()
.position(|v| v == &cur_leave.to_vec().into())
{
cur_layer.resize(ACTION_TREE_MAX_NUM, PADDING_LEAF.as_words().to_vec());
if let Some(position) = cur_layer.iter().position(|v| v == cur_leave.as_words()) {
let mut merkle_path = Vec::new();
fn build_merkle_path_inner(
cur_layer: Vec<Leaf>,
cur_layer: Vec<Vec<u32>>,
position: usize,
path: &mut Vec<(Leaf, bool)>,
path: &mut Vec<(Vec<u32>, bool)>,
) {
if cur_layer.len() > 1 {
let sibling = {
Expand All @@ -83,9 +85,7 @@ impl MerkleTree {

let prev_layer = cur_layer
.chunks(2)
.map(|pair| {
Digest::combine(&pair[0].clone().into(), &pair[1].clone().into()).into()
})
.map(|pair| hash_two(&pair[0], &pair[1]))
.collect();

build_merkle_path_inner(prev_layer, position / 2, path);
Expand All @@ -103,3 +103,15 @@ impl MerkleTree {
}
}
}

impl From<Vec<Digest>> for MerkleTree {
fn from(leaves: Vec<Digest>) -> Self {
MerkleTree::new(leaves)
}
}

impl From<Vec<Vec<u32>>> for MerkleTree {
fn from(leaves: Vec<Vec<u32>>) -> Self {
MerkleTree { leaves }
}
}
Loading
Loading