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
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.
39 changes: 17 additions & 22 deletions arm/src/action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::{
compliance::{ComplianceInstance, ComplianceWitness},
compliance_unit::ComplianceUnit,
delta_proof::DeltaWitness,
logic_proof::{LogicProof, LogicProver},
logic_proof::{LogicProver, LogicVerifier, LogicVerifierInputs},
merkle_path::COMMITMENT_TREE_DEPTH,
nullifier_key::NullifierKey,
resource::Resource,
Expand All @@ -19,29 +19,26 @@ use serde::{Deserialize, Serialize};
#[cfg_attr(feature = "nif", module = "Anoma.Arm.Action")]
pub struct Action {
pub compliance_units: Vec<ComplianceUnit>,
pub logic_verifier_inputs: Vec<LogicProof>,
pub logic_verifier_inputs: Vec<LogicVerifierInputs>,
}

impl Action {
pub fn new(
compliance_units: Vec<ComplianceUnit>,
logic_verifier_inputs: Vec<LogicProof>,
) -> Self {
pub fn new(compliance_units: Vec<ComplianceUnit>, logic_verifiers: Vec<LogicVerifier>) -> Self {
Action {
compliance_units,
logic_verifier_inputs,
logic_verifier_inputs: logic_verifiers.into_iter().map(|lv| lv.into()).collect(),
}
}

pub fn get_compliance_units(&self) -> &Vec<ComplianceUnit> {
&self.compliance_units
}

pub fn get_logic_verifier_inputs(&self) -> &Vec<LogicProof> {
pub fn get_logic_verifier_inputs(&self) -> &Vec<LogicVerifierInputs> {
&self.logic_verifier_inputs
}

pub fn verify(&self) -> bool {
pub fn verify(self) -> bool {
for unit in &self.compliance_units {
if !unit.verify() {
return false;
Expand Down Expand Up @@ -76,22 +73,20 @@ impl Action {
let action_tree = MerkleTree::from(tags.clone());
let root = action_tree.root();

for proof in &self.logic_verifier_inputs {
let instance = proof.get_instance();

if root != instance.root {
return false;
}
for input in self.logic_verifier_inputs {
if let Some(index) = tags.iter().position(|tag| *tag == input.tag) {
if input.verifying_key != logics[index] {
// The verifying_key doesn't match the resource logic
return false;
}

if let Some(index) = tags.iter().position(|tag| *tag == instance.tag) {
if proof.verifying_key != logics[index] {
let is_comsumed = index % 2 == 0;
let verifier = input.to_logic_verifier(is_comsumed, root.clone());
if !verifier.verify() {
return false;
}
} else {
return false;
}

if !proof.verify() {
// Tag not found
return false;
}
}
Expand Down Expand Up @@ -159,7 +154,7 @@ pub fn create_an_action(nonce: u8) -> (Action, DeltaWitness) {
let logic_verifier_inputs = vec![consumed_logic_proof, created_logic_proof];

let action = Action::new(compliance_units, logic_verifier_inputs);
assert!(action.verify());
assert!(action.clone().verify());

let delta_witness = DeltaWitness::from_bytes_vec(&[compliance_witness.rcv]);
(action, delta_witness)
Expand Down
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("e04fd74c5f4ed1fc3ccf4412c358927907eec18891c87f157a4b0eede2e01adc")
Digest::from_hex("2c10d71e919b8b6359bfc167294c9994c1699e3eeb851d4b7775edb67b54a327")
.unwrap();

// compliance verification key / compliance image id
pub static ref PADDING_LOGIC_VK: Digest =
Digest::from_hex("751068c8a7bf034fefac9ba4adb745ecb5a1345e40345b8f0a4bef380f06fbe2")
Digest::from_hex("f8047dc2cf6cbe45137a588a3f019814218e7d7199b1b86a57b51c310e04fae9")
.unwrap();
}
29 changes: 24 additions & 5 deletions arm/src/encryption.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::utils::{bytes_to_words, words_to_bytes};
use aes_gcm::{aead::Aead, Aes256Gcm, Key, KeyInit};
use k256::{
elliptic_curve::{group::GroupEncoding, Field},
Expand Down Expand Up @@ -28,12 +29,26 @@ impl SecretKey {
pub struct Ciphertext(Vec<u8>);

impl Ciphertext {
pub fn new(cipher: Vec<u8>) -> Self {
pub fn from_bytes(cipher: Vec<u8>) -> Self {
Ciphertext(cipher)
}

pub fn inner(&self) -> Vec<u8> {
self.0.clone()
pub fn from_words(words: &[u32]) -> Self {
Ciphertext(words_to_bytes(words).to_vec())
}

pub fn inner(&self) -> &[u8] {
&self.0
}

pub fn as_words(&self) -> Vec<u32> {
let mut padded = self.inner().to_vec();
let len = self.inner().len();
let rem = len % 4;
if rem != 0 {
padded.resize(len + (4 - rem), 0);
}
bytes_to_words(&padded)
}

pub fn encrypt(
Expand Down Expand Up @@ -63,7 +78,7 @@ impl Ciphertext {
return Err(aes_gcm::Error);
}
let cipher: InnerCiphert =
bincode::deserialize(&self.inner()).expect("deserialization failure");
bincode::deserialize(self.inner()).expect("deserialization failure");
// Generate the secret key using Diffie-Hellman exchange
let inner_secret_key = InnerSecretKey::from_dh_exchange(&cipher.pk, sk.inner());

Expand Down Expand Up @@ -131,6 +146,10 @@ fn test_encryption() {

// Decryption
let decryption = cipher.decrypt(&receiver_sk).unwrap();

assert_eq!(message, decryption);

let cipher_words = cipher.as_words();
let cipher_from_words = Ciphertext::from_words(&cipher_words);
let decrypted_from_words = cipher_from_words.decrypt(&receiver_sk).unwrap();
assert_eq!(message, decrypted_from_words);
}
44 changes: 40 additions & 4 deletions arm/src/logic_instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,50 @@ pub struct LogicInstance {
pub tag: Vec<u32>,
pub is_consumed: bool,
pub root: Vec<u32>,
pub cipher: Vec<u8>,
pub app_data: Vec<ExpirableBlob>,
pub app_data: AppData,
}

#[derive(Clone, Debug, Default, Serialize, Deserialize)]
#[cfg_attr(feature = "nif", derive(NifStruct))]
#[cfg_attr(feature = "nif", module = "Anoma.Arm.AppData")]
pub struct AppData {
pub resource_payload: Vec<ExpirableBlob>,
pub discovery_payload: Vec<ExpirableBlob>,
pub external_payload: Vec<ExpirableBlob>,
pub application_payload: Vec<ExpirableBlob>,
}

#[derive(Clone, Debug, Default, Serialize, Deserialize)]
#[cfg_attr(feature = "nif", derive(NifStruct))]
#[cfg_attr(feature = "nif", module = "Anoma.Arm.ExpirableBlob")]
pub struct ExpirableBlob {
pub blob: Vec<u8>,
pub deletion_criterion: u8,
pub blob: Vec<u32>,
pub deletion_criterion: u32,
}

impl AppData {
pub fn new() -> Self {
AppData {
resource_payload: Vec::new(),
discovery_payload: Vec::new(),
external_payload: Vec::new(),
application_payload: Vec::new(),
}
}

pub fn add_resource_payload(&mut self, blob: ExpirableBlob) {
self.resource_payload.push(blob);
}

pub fn add_discovery_payload(&mut self, blob: ExpirableBlob) {
self.discovery_payload.push(blob);
}

pub fn add_external_payload(&mut self, blob: ExpirableBlob) {
self.external_payload.push(blob);
}

pub fn add_application_payload(&mut self, blob: ExpirableBlob) {
self.application_payload.push(blob);
}
}
60 changes: 54 additions & 6 deletions arm/src/logic_proof.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
use crate::{
action_tree::ACTION_TREE_DEPTH,
constants::{PADDING_LOGIC_PK, PADDING_LOGIC_VK},
logic_instance::AppData,
logic_instance::LogicInstance,
merkle_path::MerklePath,
nullifier_key::{NullifierKey, NullifierKeyCommitment},
proving_system::{journal_to_instance, prove, verify as verify_proof},
resource::Resource,
resource_logic::TrivialLogicWitness,
utils::words_to_bytes,
};
use rand::Rng;
use risc0_zkvm::sha::{Digest, DIGEST_WORDS};
use risc0_zkvm::{
serde::to_vec,
sha::{Digest, DIGEST_WORDS},
};
#[cfg(feature = "nif")]
use rustler::NifStruct;
use serde::{Deserialize, Serialize};
Expand All @@ -27,9 +32,9 @@ pub trait LogicProver: Default + Clone + Serialize + for<'de> Deserialize<'de> {

fn witness(&self) -> &Self::Witness;

fn prove(&self) -> LogicProof {
fn prove(&self) -> LogicVerifier {
let (proof, instance) = prove(Self::proving_key(), self.witness());
LogicProof {
LogicVerifier {
// TODO: handle the unwrap properly
proof,
instance,
Expand All @@ -40,14 +45,24 @@ pub trait LogicProver: Default + Clone + Serialize + for<'de> Deserialize<'de> {

#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(feature = "nif", derive(NifStruct))]
#[cfg_attr(feature = "nif", module = "Anoma.Arm.LogicProof")]
pub struct LogicProof {
#[cfg_attr(feature = "nif", module = "Anoma.Arm.LogicVerifier")]
pub struct LogicVerifier {
pub proof: Vec<u8>,
pub instance: Vec<u8>,
pub verifying_key: Vec<u32>,
}

impl LogicProof {
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(feature = "nif", derive(NifStruct))]
#[cfg_attr(feature = "nif", module = "Anoma.Arm.LogicVerifierInputs")]
pub struct LogicVerifierInputs {
pub tag: Vec<u32>,
pub verifying_key: Vec<u32>,
pub app_data: AppData,
pub proof: Vec<u8>,
}

impl LogicVerifier {
pub fn verify(&self) -> bool {
let vk = if self.verifying_key.len() == DIGEST_WORDS {
let words: [u32; DIGEST_WORDS] = self.verifying_key.clone().try_into().unwrap();
Expand All @@ -64,6 +79,39 @@ impl LogicProof {
}
}

impl LogicVerifierInputs {
pub fn to_logic_verifier(self, is_consumed: bool, root: Vec<u32>) -> LogicVerifier {
let instance_words = to_vec(&self.to_instance(is_consumed, root))
.expect("Failed to serialize LogicInstance");
LogicVerifier {
proof: self.proof,
instance: words_to_bytes(&instance_words).to_vec(),
verifying_key: self.verifying_key,
}
}

fn to_instance(&self, is_consumed: bool, root: Vec<u32>) -> LogicInstance {
LogicInstance {
tag: self.tag.clone(),
is_consumed,
root,
app_data: self.app_data.clone(),
}
}
}

impl From<LogicVerifier> for LogicVerifierInputs {
fn from(logic_proof: LogicVerifier) -> Self {
let instance = logic_proof.get_instance();
LogicVerifierInputs {
tag: instance.tag,
verifying_key: logic_proof.verifying_key,
app_data: instance.app_data,
proof: logic_proof.proof,
}
}
}

#[derive(Clone, Deserialize, Serialize)]
pub struct PaddingResourceLogic {
witness: TrivialLogicWitness,
Expand Down
14 changes: 2 additions & 12 deletions arm/src/resource_logic.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{
action_tree::ACTION_TREE_DEPTH, logic_instance::ExpirableBlob, logic_instance::LogicInstance,
action_tree::ACTION_TREE_DEPTH, logic_instance::AppData, logic_instance::LogicInstance,
merkle_path::MerklePath, nullifier_key::NullifierKey, resource::Resource,
};
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -43,17 +43,7 @@ impl LogicCircuit for TrivialLogicWitness {
tag: tag.as_words().to_vec(),
is_consumed: self.is_consumed, // It can be either consumed or created to reduce padding resources
root,
cipher: vec![63, 127, 191, 255], // some dummy cipher for testing
app_data: vec![
ExpirableBlob {
blob: vec![31, 63, 95, 127],
deletion_criterion: 0,
},
ExpirableBlob {
blob: vec![159, 191, 223, 255],
deletion_criterion: 1,
},
], // some dummy app data for testing
app_data: AppData::default(), // No app data for trivial logic
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions arm/src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,15 @@ impl Transaction {
}
}

pub fn verify(&self) -> bool {
pub fn verify(self) -> bool {
match &self.delta_proof {
Delta::Proof(ref proof) => {
let msg = self.get_delta_msg();
let instance = self.delta();
if DeltaProof::verify(&msg, proof, instance).is_err() {
return false;
}
for action in &self.actions {
for action in self.actions {
if !action.verify() {
return false;
}
Expand Down Expand Up @@ -105,7 +105,7 @@ pub fn generate_test_transaction(n_actions: usize) -> Transaction {
let (actions, delta_witness) = create_multiple_actions(n_actions);
let mut tx = Transaction::create(actions, Delta::Witness(delta_witness));
tx.generate_delta_proof();
assert!(tx.verify());
assert!(tx.clone().verify());
tx
}

Expand Down
2 changes: 1 addition & 1 deletion arm/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use risc0_zkvm::sha::{Impl, Sha256, DIGEST_WORDS};

pub fn bytes_to_words(bytes: &[u8]) -> Vec<u32> {
let mut words = Vec::new();
for chunk in bytes.chunks(4) {
for chunk in bytes.chunks_exact(4) {
let mut word = 0u32;
for &byte in chunk {
word = (word << 8) | (byte as u32);
Expand Down
Binary file modified examples/kudo_application/app/elfs/kudo-main-guest.bin
Binary file not shown.
Binary file not shown.
Binary file modified examples/kudo_application/app/elfs/simple-kudo-receive-guest.bin
Binary file not shown.
2 changes: 1 addition & 1 deletion examples/kudo_application/app/src/kudo_main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use serde::{Deserialize, Serialize};
pub const KUDO_LOGIC_ELF: &[u8] = include_bytes!("../elfs/kudo-main-guest.bin");
lazy_static! {
pub static ref KUDO_LOGIC_ID: Digest =
Digest::from_hex("079b2a05c035c5eea13acf359515b690f31eb05a22ffde3be5cb87c4f24d284a")
Digest::from_hex("639d1ed04c420c224fe1f4d751b207fd6586ef36a673c220f62c23e47f95981e")
.unwrap();
}

Expand Down
2 changes: 1 addition & 1 deletion examples/kudo_application/app/src/simple_denomination.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use serde::{Deserialize, Serialize};
pub const DENOMINATION_ELF: &[u8] = include_bytes!("../elfs/simple-kudo-denomination-guest.bin");
lazy_static! {
pub static ref DENOMINATION_ID: Digest =
Digest::from_hex("e909276f48bc961f86e7c7739cce1ab46937d18c1438c4741a05f61f3547b62c")
Digest::from_hex("2074ae290e5ca64511ff2b329408e48cc4202b8e3538af9eb92155dd3779b8eb")
.unwrap();
}

Expand Down
Loading
Loading