Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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