Skip to content
Closed
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
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,9 @@ We have the following feature flags in arm lib:
| ------------------------ | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `logic_circuit` | | It provides logic-related traits and gadgets |
| `compliance_circuit` | | A specific feature for compliance circuit |
| `transaction (default)` | `logic_circuit`, `compliance_circuit`, `prove` | It provides full transaction processing capabilities and will be in the Anoma SDK and validator with a selected prover feature. Succinct prover is used by default. |
| `transaction (default)` | `logic_circuit`, `compliance_circuit`, `prove`, `bonsai` | It provides full transaction processing capabilities and will be in the Anoma SDK and validator with a selected prover feature. Succinct prover is used by default. |
| `prove` | | Enables RISC0 proving capabilities (required for actual proof generation) |
| `bonsai` | | Enables bonsai sdk |
| `fast_prover` | | Fastest option producing linear-size proofs, and does not support compression via recursion |
| `composite_prover` | | Fastest option producing linear-size proofs, and supports compression via recursion |
| `groth16_prover` | | Generates groth16 proofs(requires x86_64 machines) |
Expand Down
3 changes: 2 additions & 1 deletion arm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ rustler = { version = "0.36.2", optional = true }
[features]
default = ["transaction"]
prove = ["risc0-zkvm/prove"]
bonsai = ["risc0-zkvm/bonsai"]
nif = ["dep:rustler"]
transaction = ["logic_circuit", "compliance_circuit", "prove", "dep:sha3"]
transaction = ["logic_circuit", "compliance_circuit", "prove", "dep:sha3", "bonsai"]
logic_circuit = []
compliance_circuit = []
fast_prover = []
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.
25 changes: 8 additions & 17 deletions arm/src/action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ 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 risc0_zkvm::Digest;
use serde::{Deserialize, Serialize};
#[cfg(feature = "nif")]
use {
Expand Down Expand Up @@ -61,19 +61,14 @@ impl Action {
// Construct the action tree
let tags = compliance_intances
.iter()
.flat_map(|instance| {
vec![
instance.consumed_nullifier.clone().into(),
instance.created_commitment.clone().into(),
]
})
.collect::<Vec<Leaf>>();
.flat_map(|instance| vec![instance.consumed_nullifier, instance.created_commitment])
.collect::<Vec<Digest>>();
let logics = compliance_intances
.iter()
.flat_map(|instance| {
vec![
instance.consumed_logic_ref.clone(),
instance.created_logic_ref.clone(),
instance.consumed_logic_ref.as_bytes().to_vec(),
instance.created_logic_ref.as_bytes().to_vec(),
]
})
.collect::<Vec<_>>();
Expand All @@ -87,8 +82,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 +128,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 +138,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
39 changes: 16 additions & 23 deletions arm/src/action_tree.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::merkle_path::{Hashable, Leaf, MerklePath};
use crate::merkle_path::{Hashable, MerklePath};
use risc0_zkvm::sha::Digest;

#[cfg(feature = "nif")]
Expand All @@ -11,34 +11,32 @@ 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<Digest>,
}

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"
);
MerkleTree { leaves }
}

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

pub fn root(&self) -> Vec<u8> {
pub fn root(&self) -> Digest {
let mut cur_layer = self.leaves.clone();
cur_layer.resize(ACTION_TREE_MAX_NUM, Digest::blank().into());
cur_layer.resize(ACTION_TREE_MAX_NUM, Digest::blank());
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| Digest::combine(&pair[0], &pair[1]))
.collect();
}
cur_layer[0].inner().to_vec()
cur_layer[0]
}

// Generate the merkle path for the current leave
Expand All @@ -56,36 +54,31 @@ 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, Digest::blank());
if let Some(position) = cur_layer.iter().position(|v| v == cur_leave) {
let mut merkle_path = Vec::new();
fn build_merkle_path_inner(
cur_layer: Vec<Leaf>,
cur_layer: Vec<Digest>,
position: usize,
path: &mut Vec<(Leaf, bool)>,
path: &mut Vec<(Digest, bool)>,
) {
if cur_layer.len() > 1 {
let sibling = {
let is_sibling_left = position % 2 != 0;
let sibling_value = if is_sibling_left {
cur_layer[position - 1].clone()
cur_layer[position - 1]
} else {
cur_layer[position + 1].clone()
cur_layer[position + 1]
};
(sibling_value, is_sibling_left)
};
path.push(sibling);

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

build_merkle_path_inner(prev_layer, position / 2, path);
Expand Down
61 changes: 31 additions & 30 deletions arm/src/compliance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ lazy_static! {
#[cfg_attr(feature = "nif", derive(NifStruct))]
#[cfg_attr(feature = "nif", module = "Anoma.Arm.ComplianceInstance")]
pub struct ComplianceInstance {
pub consumed_nullifier: Vec<u8>,
pub consumed_logic_ref: Vec<u8>,
pub consumed_commitment_tree_root: Vec<u8>,
pub created_commitment: Vec<u8>,
pub created_logic_ref: Vec<u8>,
pub delta_x: Vec<u8>,
pub delta_y: Vec<u8>,
pub consumed_nullifier: Digest,
pub consumed_logic_ref: Digest,
pub consumed_commitment_tree_root: Digest,
pub created_commitment: Digest,
pub created_logic_ref: Digest,
pub delta_x: Digest,
pub delta_y: Digest,
}

#[derive(Clone, serde::Serialize, serde::Deserialize)]
Expand All @@ -39,7 +39,7 @@ pub struct ComplianceWitness<const COMMITMENT_TREE_DEPTH: usize> {
/// The path from the consumed commitment to the root in the commitment tree
pub merkle_path: MerklePath<COMMITMENT_TREE_DEPTH>,
/// The existing root for the ephemeral resource
pub ephemeral_root: Vec<u8>,
pub ephemeral_root: Digest,
/// Nullifier key of the consumed resource
pub nf_key: NullifierKey,
/// The created resource
Expand All @@ -64,7 +64,7 @@ impl<const COMMITMENT_TREE_DEPTH: usize> ComplianceWitness<COMMITMENT_TREE_DEPTH
merkle_path: MerklePath::<COMMITMENT_TREE_DEPTH>::default(),
rcv: Scalar::random(&mut rng).to_bytes().to_vec(),
nf_key,
ephemeral_root: INITIAL_ROOT.as_bytes().to_vec(),
ephemeral_root: *INITIAL_ROOT,
}
}

Expand All @@ -81,7 +81,7 @@ impl<const COMMITMENT_TREE_DEPTH: usize> ComplianceWitness<COMMITMENT_TREE_DEPTH
merkle_path,
rcv: Scalar::random(&mut rng).to_bytes().to_vec(),
nf_key,
ephemeral_root: vec![0; 32], // not used
ephemeral_root: *INITIAL_ROOT,
}
}

Expand All @@ -97,7 +97,7 @@ impl<const COMMITMENT_TREE_DEPTH: usize> ComplianceWitness<COMMITMENT_TREE_DEPTH
merkle_path: MerklePath::<COMMITMENT_TREE_DEPTH>::default(),
rcv: Scalar::ONE.to_bytes().to_vec(),
nf_key,
ephemeral_root: INITIAL_ROOT.as_bytes().to_vec(),
ephemeral_root: *INITIAL_ROOT,
}
}

Expand All @@ -112,7 +112,8 @@ impl<const COMMITMENT_TREE_DEPTH: usize> ComplianceWitness<COMMITMENT_TREE_DEPTH

// constrain created_resource.nonce and consumed_resource.nf
assert_eq!(
self.created_resource.nonce, consumed_nullifier,
self.created_resource.nonce,
consumed_nullifier.as_bytes(),
"Created resource nonce must match consumed nullifier"
);

Expand All @@ -129,37 +130,37 @@ impl<const COMMITMENT_TREE_DEPTH: usize> ComplianceWitness<COMMITMENT_TREE_DEPTH
}
}

pub fn consumed_resource_logic(&self) -> Vec<u8> {
self.consumed_resource.logic_ref.clone()
pub fn consumed_resource_logic(&self) -> Digest {
Digest::from_bytes(self.consumed_resource.logic_ref.clone().try_into().unwrap())
}

pub fn created_resource_logic(&self) -> Vec<u8> {
self.created_resource.logic_ref.clone()
pub fn created_resource_logic(&self) -> Digest {
Digest::from_bytes(self.created_resource.logic_ref.clone().try_into().unwrap())
}

pub fn consumed_commitment(&self) -> Vec<u8> {
pub fn consumed_commitment(&self) -> Digest {
self.consumed_resource.commitment()
}

pub fn created_commitment(&self) -> Vec<u8> {
pub fn created_commitment(&self) -> Digest {
self.created_resource.commitment()
}

pub fn consumed_nullifier(&self, cm: &[u8]) -> Vec<u8> {
pub fn consumed_nullifier(&self, cm: &Digest) -> Digest {
self.consumed_resource
.nullifier_from_commitment(&self.nf_key, cm)
.unwrap()
}

pub fn consumed_commitment_tree_root(&self, cm: &[u8]) -> Vec<u8> {
pub fn consumed_commitment_tree_root(&self, cm: &Digest) -> Digest {
if self.consumed_resource.is_ephemeral {
self.ephemeral_root.clone()
self.ephemeral_root
} else {
self.merkle_path.root(cm)
}
}

pub fn delta(&self) -> (Vec<u8>, Vec<u8>) {
pub fn delta(&self) -> (Digest, Digest) {
// Compute delta and make delta commitment public
let rcv_array: [u8; 32] = self
.rcv
Expand All @@ -173,8 +174,8 @@ impl<const COMMITMENT_TREE_DEPTH: usize> ComplianceWitness<COMMITMENT_TREE_DEPTH

let encoded_delta = delta.to_encoded_point(false);
(
encoded_delta.x().unwrap().to_vec(),
encoded_delta.y().unwrap().to_vec(),
Digest::try_from(&encoded_delta.x().unwrap()[..]).unwrap(),
Digest::try_from(&encoded_delta.y().unwrap()[..]).unwrap(),
)
}
}
Expand Down Expand Up @@ -202,7 +203,7 @@ impl<const COMMITMENT_TREE_DEPTH: usize> Default for ComplianceWitness<COMMITMEN
quantity: 1u128,
value_ref: vec![0; 32],
is_ephemeral: false,
nonce: nf,
nonce: nf.as_bytes().to_vec(),
nk_commitment: nf_key.commit(),
rand_seed: vec![0; 32],
};
Expand All @@ -214,7 +215,7 @@ impl<const COMMITMENT_TREE_DEPTH: usize> Default for ComplianceWitness<COMMITMEN
ComplianceWitness {
consumed_resource,
created_resource,
ephemeral_root: vec![0; 32],
ephemeral_root: *INITIAL_ROOT,
merkle_path,
rcv,
nf_key,
Expand All @@ -226,12 +227,12 @@ impl ComplianceInstance {
pub fn delta_projective(&self) -> ProjectivePoint {
let x: [u8; 32] = self
.delta_x
.clone()
.as_bytes()
.try_into()
.expect("delta_x must be 32 bytes");
let y: [u8; 32] = self
.delta_y
.clone()
.as_bytes()
.try_into()
.expect("delta_y must be 32 bytes");
let encoded_point = EncodedPoint::from_affine_coordinates(&x.into(), &y.into(), false);
Expand All @@ -240,8 +241,8 @@ impl ComplianceInstance {

pub fn delta_msg(&self) -> Vec<u8> {
let mut msg = Vec::new();
msg.extend_from_slice(&self.consumed_nullifier);
msg.extend_from_slice(&self.created_commitment);
msg.extend_from_slice(self.consumed_nullifier.as_bytes());
msg.extend_from_slice(self.created_commitment.as_bytes());
msg
}
}
4 changes: 2 additions & 2 deletions arm/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ pub const PADDING_LOGIC_PK: &[u8] = include_bytes!("../elfs/trivial-logic-guest.
lazy_static! {
// compliance verification key / compliance image id
pub static ref COMPLIANCE_VK: Digest =
Digest::from_hex("ab5a67860b67f0bc448c1ac55d71561e837601a85591581055cf80e216ddc216")
Digest::from_hex("72a846603a31c75771a7e63fd6849e2915a7e0d230f379e6832237281759b95b")
.unwrap();

// compliance verification key / compliance image id
pub static ref PADDING_LOGIC_VK: Digest =
Digest::from_hex("95c8992a13f68d6d969e4e1558c2aa2fdcbe05900a4f531b3b49b397e79b8a44")
Digest::from_hex("793d346e837569972ae098f9b506fc746651bb1b9e6a977c06017f9a9889992d")
.unwrap();
}
5 changes: 3 additions & 2 deletions arm/src/logic_instance.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use risc0_zkvm::Digest;
use serde::{Deserialize, Serialize};

#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct LogicInstance {
pub tag: Vec<u8>,
pub tag: Digest,
pub is_consumed: bool,
pub root: Vec<u8>,
pub root: Digest,
pub cipher: Vec<u8>,
pub app_data: Vec<ExpirableBlob>,
}
Expand Down
Loading
Loading