Skip to content
Open
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
32 changes: 28 additions & 4 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 @@ -20,6 +20,7 @@ rustler = { version = "0.36.2", optional = true }
bytemuck = { version = "1.12", features = ["derive"] }
alloy-primitives = "1.0.23"
alloy-sol-types = "1.0.23"
serde_bytes = "0.11.19"

[features]
default = ["transaction", "prove"]
Expand Down
1 change: 1 addition & 0 deletions arm/src/action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use crate::{
};

#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(feature = "nif", serde(rename = "Elixir.Anoma.Arm.Action"))]
pub struct Action {
pub compliance_units: Vec<ComplianceUnit>,
pub logic_verifier_inputs: Vec<LogicVerifierInputs>,
Expand Down
30 changes: 29 additions & 1 deletion arm/src/action_tree.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,42 @@
use crate::utils::{bytes_to_words, words_to_bytes};
use crate::{
merkle_path::{MerklePath, PADDING_LEAF},
utils::hash_two,
};
use risc0_zkvm::sha::Digest;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde_bytes::ByteBuf;

#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Deserialize, Clone, PartialEq, Eq, Serialize)]
#[cfg_attr(feature = "nif", serde(rename = "Elixir.Anoma.Arm.MerkleTree"))]
pub struct MerkleTree {
#[serde(
deserialize_with = "deserialize_leaves",
serialize_with = "serialize_leaves"
)]
pub leaves: Vec<Vec<u32>>,
}

pub fn serialize_leaves<S>(t: &[Vec<u32>], s: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
t.iter()
.map(|t| ByteBuf::from(words_to_bytes(t)))
.collect::<Vec<ByteBuf>>()
.serialize(s)
}

pub fn deserialize_leaves<'de, D>(deserializer: D) -> Result<Vec<Vec<u32>>, D::Error>
where
D: Deserializer<'de>,
{
Ok(Vec::<ByteBuf>::deserialize(deserializer)?
.into_iter()
.map(|t| bytes_to_words(&t.into_vec()))
.collect())
}

impl MerkleTree {
pub fn new(leaves: Vec<Digest>) -> Self {
let leaves = leaves
Expand Down
13 changes: 12 additions & 1 deletion arm/src/compliance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::{
merkle_path::MerklePath,
nullifier_key::NullifierKey,
resource::Resource,
utils::{bytes_to_words, words_to_bytes},
utils::{bytes_to_words, vec_u32, words_to_bytes},
};
use hex::FromHex;
use k256::{
Expand All @@ -21,29 +21,40 @@ lazy_static! {
}

#[derive(Clone, Debug, Default, serde::Serialize, serde::Deserialize)]
#[cfg_attr(feature = "nif", serde(rename = "Elixir.Anoma.Arm.ComplianceInstance"))]
pub struct ComplianceInstance {
#[serde(with = "vec_u32")]
pub consumed_nullifier: Vec<u32>,
#[serde(with = "vec_u32")]
pub consumed_logic_ref: Vec<u32>,
#[serde(with = "vec_u32")]
pub consumed_commitment_tree_root: Vec<u32>,
#[serde(with = "vec_u32")]
pub created_commitment: Vec<u32>,
#[serde(with = "vec_u32")]
pub created_logic_ref: Vec<u32>,
#[serde(with = "vec_u32")]
pub delta_x: Vec<u32>,
#[serde(with = "vec_u32")]
pub delta_y: Vec<u32>,
}

#[derive(Clone, serde::Serialize, serde::Deserialize)]
#[cfg_attr(feature = "nif", serde(rename = "Elixir.Anoma.Arm.ComplianceWitness"))]
pub struct ComplianceWitness {
/// The consumed resource
pub consumed_resource: Resource,
/// The path from the consumed commitment to the root in the commitment tree
pub merkle_path: MerklePath,
/// The existing root for the ephemeral resource
#[serde(with = "vec_u32")]
pub ephemeral_root: Vec<u32>,
/// Nullifier key of the consumed resource
pub nf_key: NullifierKey,
/// The created resource
pub created_resource: Resource,
/// Random scalar for delta commitment
#[serde(with = "serde_bytes")]
pub rcv: Vec<u8>,
// TODO: If we want to add function privacy, include:
// pub input_resource_logic_cm_r: [u8; DATA_BYTES],
Expand Down
3 changes: 3 additions & 0 deletions arm/src/compliance_unit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,12 @@ use serde::{Deserialize, Serialize};
use crate::{compliance::ComplianceWitness, constants::COMPLIANCE_PK, proving_system::prove};

#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(feature = "nif", serde(rename = "Elixir.Anoma.Arm.ComplianceUnit"))]
pub struct ComplianceUnit {
// vk is a constant in the compliance unit, so we don't place it here.
#[serde(with = "serde_bytes")]
pub proof: Vec<u8>,
#[serde(with = "serde_bytes")]
pub instance: Vec<u8>,
}

Expand Down
109 changes: 63 additions & 46 deletions arm/src/delta_proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,81 @@ use k256::ecdsa::{Error, RecoveryId, Signature, SigningKey, VerifyingKey};
use k256::{
elliptic_curve::PublicKey, elliptic_curve::ScalarPrimitive, ProjectivePoint, Scalar, SecretKey,
};
use serde::{Deserialize, Serialize};
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};

use serde_bytes::ByteArray;
use sha3::{Digest, Keccak256};

#[derive(Clone, Debug)]
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(feature = "nif", serde(rename = "Elixir.Anoma.Arm.DeltaProof"))]
pub struct DeltaProof {
#[serde(
deserialize_with = "deserialize_signature",
serialize_with = "serialize_signature"
)]
pub signature: Signature,
#[serde(
deserialize_with = "deserialize_recovery_id",
serialize_with = "serialize_recovery_id"
)]
pub recid: RecoveryId,
}

#[derive(Clone, Debug)]
fn serialize_signature<S>(t: &Signature, s: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
ByteArray::<64>::new(t.to_bytes().into()).serialize(s)
}

fn deserialize_signature<'de, D>(deserializer: D) -> Result<Signature, D::Error>
where
D: Deserializer<'de>,
{
let b: [u8; 64] = ByteArray::deserialize(deserializer)?.into_array();
Signature::from_bytes(&b.into()).map_err(de::Error::custom)
}

fn serialize_recovery_id<S>(t: &RecoveryId, s: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
s.serialize_u8(t.to_byte())
}

fn deserialize_recovery_id<'de, D>(d: D) -> Result<RecoveryId, D::Error>
where
D: Deserializer<'de>,
{
let s: u8 = de::Deserialize::deserialize(d)?;
RecoveryId::try_from(s).map_err(de::Error::custom)
}

#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(feature = "nif", serde(rename = "Elixir.Anoma.Arm.DeltaWitness"))]
pub struct DeltaWitness {
#[serde(
deserialize_with = "deserialize_signing_key",
serialize_with = "serialize_signing_key"
)]
pub signing_key: SigningKey,
}

fn serialize_signing_key<S>(t: &SigningKey, s: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
ByteArray::<32>::new(t.to_bytes().into()).serialize(s)
}

fn deserialize_signing_key<'de, D>(deserializer: D) -> Result<SigningKey, D::Error>
where
D: Deserializer<'de>,
{
let b: [u8; 32] = ByteArray::deserialize(deserializer)?.into_array();
SigningKey::from_bytes(&b.into()).map_err(de::Error::custom)
}

pub struct DeltaInstance {
pub verifying_key: VerifyingKey,
}
Expand Down Expand Up @@ -123,49 +183,6 @@ impl DeltaInstance {
}
}

impl Serialize for DeltaProof {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_bytes(&self.to_bytes())
}
}

impl<'de> Deserialize<'de> for DeltaProof {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let bytes: Vec<u8> = Vec::deserialize(deserializer)?;
if bytes.len() != 65 {
return Err(serde::de::Error::custom(
"Invalid byte length for DeltaProof",
));
}
Ok(DeltaProof::from_bytes(&bytes))
}
}

impl Serialize for DeltaWitness {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_bytes(&self.to_bytes())
}
}

impl<'de> Deserialize<'de> for DeltaWitness {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let bytes = <[u8; 32]>::deserialize(deserializer)?;
Ok(DeltaWitness::from_bytes(&bytes))
}
}

#[test]
fn test_delta_proof() {
use k256::elliptic_curve::rand_core::OsRng;
Expand Down
4 changes: 3 additions & 1 deletion arm/src/encryption.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ impl SecretKey {
}

#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct Ciphertext(Vec<u8>);
pub struct Ciphertext(#[serde(with = "serde_bytes")] Vec<u8>);

impl Ciphertext {
pub fn from_bytes(cipher: Vec<u8>) -> Self {
Expand Down Expand Up @@ -88,8 +88,10 @@ impl Ciphertext {
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
struct InnerCiphert {
// AES GCM encrypted message
#[serde(with = "serde_bytes")]
pub cipher: Vec<u8>,
// 96-bits; unique per message
#[serde(with = "serde_bytes")]
pub nonce: [u8; 12],
// Sender's public key
pub pk: AffinePoint,
Expand Down
2 changes: 0 additions & 2 deletions arm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ pub mod nullifier_key;
pub mod proving_system;
pub mod resource;
pub mod resource_logic;
#[cfg(feature = "nif")]
pub mod rustler_util;
#[cfg(feature = "transaction")]
pub mod test_logic;
#[cfg(feature = "transaction")]
Expand Down
11 changes: 7 additions & 4 deletions arm/src/logic_instance.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
#[cfg(feature = "nif")]
use rustler::NifStruct;
use crate::utils::vec_u32;
use serde::{Deserialize, Serialize};

#[derive(Clone, Debug, Default, Serialize, Deserialize)]
#[cfg_attr(feature = "nif", derive(NifStruct))]
#[cfg_attr(feature = "nif", module = "Anoma.Arm.LogicInstance")]
#[cfg_attr(feature = "nif", serde(rename = "Elixir.Anoma.Arm.LogicInstance"))]
pub struct LogicInstance {
#[serde(with = "vec_u32")]
pub tag: Vec<u32>,
pub is_consumed: bool,
#[serde(with = "vec_u32")]
pub root: Vec<u32>,
pub app_data: AppData,
}

#[derive(Clone, Debug, Default, Serialize, Deserialize)]
#[cfg_attr(feature = "nif", serde(rename = "Elixir.Anoma.Arm.AppData"))]
pub struct AppData {
pub resource_payload: Vec<ExpirableBlob>,
pub discovery_payload: Vec<ExpirableBlob>,
Expand All @@ -21,7 +22,9 @@ pub struct AppData {
}

#[derive(Clone, Debug, Default, Serialize, Deserialize)]
#[cfg_attr(feature = "nif", serde(rename = "Elixir.Anoma.Arm.ExpirableBlob"))]
pub struct ExpirableBlob {
#[serde(with = "vec_u32")]
pub blob: Vec<u32>,
pub deletion_criterion: u32,
}
Expand Down
Loading