diff --git a/arm/src/logic_instance.rs b/arm/src/logic_instance.rs index 74fcced7..6dc88f86 100644 --- a/arm/src/logic_instance.rs +++ b/arm/src/logic_instance.rs @@ -1,11 +1,7 @@ use risc0_zkvm::Digest; -#[cfg(feature = "nif")] -use rustler::NifStruct; use serde::{Deserialize, Serialize}; #[derive(Clone, Debug, Default, Serialize, Deserialize)] -#[cfg_attr(feature = "nif", derive(NifStruct))] -#[cfg_attr(feature = "nif", module = "Anoma.Arm.LogicInstance")] pub struct LogicInstance { pub tag: Digest, pub is_consumed: bool, diff --git a/arm/src/rustler_util.rs b/arm/src/rustler_util.rs index b4027a05..a79a79dd 100644 --- a/arm/src/rustler_util.rs +++ b/arm/src/rustler_util.rs @@ -8,7 +8,7 @@ use crate::action_tree::MerkleTree; use crate::compliance::{ComplianceInstance, ComplianceWitness}; use crate::compliance_unit::ComplianceUnit; use crate::delta_proof::{DeltaProof, DeltaWitness}; -use crate::logic_instance::{AppData, ExpirableBlob}; +use crate::logic_instance::{AppData, ExpirableBlob, LogicInstance}; use crate::logic_proof::{LogicVerifier, LogicVerifierInputs}; use crate::merkle_path::MerklePath; use crate::nullifier_key::{NullifierKey, NullifierKeyCommitment}; @@ -18,6 +18,7 @@ use crate::utils::{bytes_to_words, words_to_bytes}; use bincode; use k256::ecdsa::{RecoveryId, Signature, SigningKey}; use k256::AffinePoint; +use risc0_zkvm::Digest; use rustler::types::map::map_new; use rustler::{atoms, Binary, Decoder, Encoder, NifResult}; use rustler::{Env, Error, OwnedBinary, Term}; @@ -40,6 +41,9 @@ atoms! { at_discovery_payload = "discovery_payload", at_external_payload = "external_payload", at_application_payload = "application_payload", + at_logic_instance = "Anoma.Arm.LogicInstance", + at_is_consumed = "is_consumed", + at_root = "root", at_logic_verifier_inputs = "Elixir.Anoma.Arm.LogicVerifierInputs", at_tag = "tag", at_verifying_key = "verifying_key", @@ -131,6 +135,19 @@ impl<'a> RustlerDecoder<'a> for Vec { } } +impl RustlerEncoder for Digest { + fn rustler_encode<'a>(&self, env: Env<'a>) -> Result, Error> { + self.as_words().to_vec().rustler_encode(env) + } +} + +impl<'a> RustlerDecoder<'a> for Digest { + fn rustler_decode(term: Term<'a>) -> NifResult { + let binary: Vec = term.decode()?; + binary.try_into().map_err(|_| Error::BadArg) + } +} + impl RustlerEncoder for AffinePoint { fn rustler_encode<'a>(&self, env: Env<'a>) -> Result, Error> { bincode::serialize(self) @@ -361,9 +378,9 @@ impl RustlerEncoder for LogicVerifierInputs { impl<'a> RustlerDecoder<'a> for LogicVerifierInputs { fn rustler_decode(term: Term<'a>) -> NifResult { let tag_term = term.map_get(at_tag().encode(term.get_env()))?; - let tag: Vec = RustlerDecoder::rustler_decode(tag_term)?; + let tag = RustlerDecoder::rustler_decode(tag_term)?; let verifying_key_term = term.map_get(at_verifying_key().encode(term.get_env()))?; - let verifying_key: Vec = RustlerDecoder::rustler_decode(verifying_key_term)?; + let verifying_key = RustlerDecoder::rustler_decode(verifying_key_term)?; let app_data_term = term.map_get(at_app_data_key().encode(term.get_env()))?; let app_data: AppData = app_data_term.decode()?; let proof_term = term.map_get(at_proof().encode(term.get_env()))?; @@ -378,6 +395,45 @@ impl<'a> RustlerDecoder<'a> for LogicVerifierInputs { } } +impl RustlerEncoder for LogicInstance { + fn rustler_encode<'a>(&self, env: Env<'a>) -> NifResult> { + map_new(env) + .map_put(at_struct().encode(env), at_logic_instance().encode(env))? + .map_put(at_tag().encode(env), self.tag.rustler_encode(env)?)? + .map_put(at_is_consumed().encode(env), self.is_consumed.encode(env))? + .map_put(at_root().encode(env), self.root.rustler_encode(env)?)? + .map_put( + at_app_data().encode(env), + self.app_data.rustler_encode(env)?, + ) + } +} + +impl<'a> RustlerDecoder<'a> for LogicInstance { + fn rustler_decode(term: Term<'a>) -> NifResult { + let env = term.get_env(); + + let tag_term = term.map_get(at_tag().encode(env))?; + let tag = RustlerDecoder::rustler_decode(tag_term)?; + + let is_consumed_term = term.map_get(at_is_consumed().encode(env))?; + let is_consumed: bool = is_consumed_term.decode()?; + + let root_term = term.map_get(at_root().encode(env))?; + let root = RustlerDecoder::rustler_decode(root_term)?; + + let app_data_term = term.map_get(at_app_data().encode(env))?; + let app_data = RustlerDecoder::rustler_decode(app_data_term)?; + + Ok(LogicInstance { + tag, + is_consumed, + root, + app_data, + }) + } +} + impl Encoder for LogicVerifierInputs { fn encode<'a>(&self, env: Env<'a>) -> Term<'a> { let encoded = self.rustler_encode(env); @@ -450,7 +506,7 @@ impl RustlerEncoder for MerkleTree { let encoded_vec: Term = self .leaves .iter() - .map(|leaf: &Vec| { + .map(|leaf| { leaf.rustler_encode(env) .expect("could not encode MerkleTree leaf") }) @@ -471,7 +527,7 @@ impl<'a> RustlerDecoder<'a> for MerkleTree { let leaves_terms = Vec::::decode(leaves_term).expect("failed to decode MerkleTree leaves"); - let leaves: Vec> = leaves_terms + let leaves: Vec = leaves_terms .iter() .map(|term| RustlerDecoder::rustler_decode(*term).expect("failed to decode leaf")) .collect(); @@ -518,11 +574,11 @@ impl<'a> RustlerDecoder<'a> for MerklePath { fn rustler_decode(term: Term<'a>) -> NifResult { let path_terms = Vec::::decode(term).expect("failed to decode MerklePath list"); - let path: Vec<(Vec, bool)> = path_terms + let path: Vec<(Digest, bool)> = path_terms .iter() .map(|term| { let tuple: (Term, Term) = term.decode().expect("failed to decode MerklePath tuple"); - let hash: Vec = RustlerDecoder::rustler_decode(tuple.0) + let hash: Digest = RustlerDecoder::rustler_decode(tuple.0) .expect("failed to decode MerklePath hash"); let is_right: bool = tuple .1 @@ -579,9 +635,14 @@ impl RustlerEncoder for ComplianceInstance { at_created_logic_ref().encode(env), self.created_logic_ref.rustler_encode(env)?, )? - .map_put(at_delta_x().encode(env), self.delta_x.rustler_encode(env)?)? - .map_put(at_delta_y().encode(env), self.delta_y.rustler_encode(env)?)?; - + .map_put( + at_delta_x().encode(env), + self.delta_x.to_vec().rustler_encode(env)?, + )? + .map_put( + at_delta_y().encode(env), + self.delta_y.to_vec().rustler_encode(env)?, + )?; Ok(map) } } @@ -590,38 +651,37 @@ impl<'a> RustlerDecoder<'a> for ComplianceInstance { fn rustler_decode(term: Term<'a>) -> NifResult { let consumed_nullifier_term = term.map_get(at_consumed_nullifier().encode(term.get_env()))?; - let consumed_nullifier: Vec = RustlerDecoder::rustler_decode(consumed_nullifier_term)?; + let consumed_nullifier = RustlerDecoder::rustler_decode(consumed_nullifier_term)?; let consumed_logic_ref_term = term.map_get(at_consumed_logic_ref().encode(term.get_env()))?; - let consumed_logic_ref: Vec = RustlerDecoder::rustler_decode(consumed_logic_ref_term)?; + let consumed_logic_ref = RustlerDecoder::rustler_decode(consumed_logic_ref_term)?; let consumed_commitment_tree_root_term = term.map_get(at_consumed_commitment_tree_root().encode(term.get_env()))?; - let consumed_commitment_tree_root: Vec = + let consumed_commitment_tree_root = RustlerDecoder::rustler_decode(consumed_commitment_tree_root_term)?; let created_commitment_term = term.map_get(at_created_commitment().encode(term.get_env()))?; - let created_commitment: Vec = RustlerDecoder::rustler_decode(created_commitment_term)?; + let created_commitment = RustlerDecoder::rustler_decode(created_commitment_term)?; let created_logic_ref_term = term.map_get(at_created_logic_ref().encode(term.get_env()))?; - let created_logic_ref: Vec = RustlerDecoder::rustler_decode(created_logic_ref_term)?; + let created_logic_ref = RustlerDecoder::rustler_decode(created_logic_ref_term)?; let delta_x_term = term.map_get(at_delta_x().encode(term.get_env()))?; let delta_x: Vec = RustlerDecoder::rustler_decode(delta_x_term)?; let delta_y_term = term.map_get(at_delta_y().encode(term.get_env()))?; let delta_y: Vec = RustlerDecoder::rustler_decode(delta_y_term)?; - Ok(ComplianceInstance { consumed_nullifier, consumed_logic_ref, consumed_commitment_tree_root, created_commitment, created_logic_ref, - delta_x, - delta_y, + delta_x: <[u32; 8]>::try_from(delta_x).map_err(|_e| Error::BadArg)?, + delta_y: <[u32; 8]>::try_from(delta_y).map_err(|_e| Error::BadArg)?, }) } } @@ -678,7 +738,7 @@ impl<'a> RustlerDecoder<'a> for ComplianceWitness { let merkle_path: MerklePath = RustlerDecoder::rustler_decode(merkle_path_term)?; let ephemeral_root_term = term.map_get(at_ephemeral_root().encode(term.get_env()))?; - let ephemeral_root: Vec = RustlerDecoder::rustler_decode(ephemeral_root_term)?; + let ephemeral_root = RustlerDecoder::rustler_decode(ephemeral_root_term)?; let nf_key_term = term.map_get(at_nf_key().encode(term.get_env()))?; let nf_key: NullifierKey = nf_key_term.decode()?; @@ -718,7 +778,7 @@ impl<'a> Decoder<'a> for ComplianceWitness { impl RustlerEncoder for NullifierKeyCommitment { fn rustler_encode<'a>(&self, env: Env<'a>) -> Result, Error> { - let inner_bytes = self.inner().to_vec(); + let inner_bytes = self.inner().as_words().to_vec(); inner_bytes.rustler_encode(env) } } @@ -726,7 +786,8 @@ impl RustlerEncoder for NullifierKeyCommitment { impl<'a> RustlerDecoder<'a> for NullifierKeyCommitment { fn rustler_decode(term: Term<'a>) -> NifResult { let bytes: Vec = RustlerDecoder::rustler_decode(term)?; - Ok(NullifierKeyCommitment::from_bytes(&bytes)) + Ok(NullifierKeyCommitment::from_bytes(&bytes) + .map_err(|e| Error::Term(Box::new(e.to_string())))?) } } @@ -794,14 +855,17 @@ impl RustlerEncoder for Resource { self.value_ref.rustler_encode(env)?, )? .map_put(at_is_ephemeral().encode(env), self.is_ephemeral.encode(env))? - .map_put(at_nonce().encode(env), self.nonce.rustler_encode(env)?)? + .map_put( + at_nonce().encode(env), + self.nonce.to_vec().rustler_encode(env)?, + )? .map_put( at_nk_commitment().encode(env), self.nk_commitment.rustler_encode(env)?, )? .map_put( at_rand_seed().encode(env), - self.rand_seed.rustler_encode(env)?, + self.rand_seed.to_vec().rustler_encode(env)?, )?; Ok(map) @@ -811,16 +875,16 @@ impl RustlerEncoder for Resource { impl<'a> RustlerDecoder<'a> for Resource { fn rustler_decode(term: Term<'a>) -> NifResult { let logic_ref_term = term.map_get(at_logic_ref().encode(term.get_env()))?; - let logic_ref: Vec = RustlerDecoder::rustler_decode(logic_ref_term)?; + let logic_ref = RustlerDecoder::rustler_decode(logic_ref_term)?; let label_ref_term = term.map_get(at_label_ref().encode(term.get_env()))?; - let label_ref: Vec = RustlerDecoder::rustler_decode(label_ref_term)?; + let label_ref = RustlerDecoder::rustler_decode(label_ref_term)?; let quantity_term = term.map_get(at_quantity().encode(term.get_env()))?; let quantity: u128 = quantity_term.decode()?; let value_ref_term = term.map_get(at_value_ref().encode(term.get_env()))?; - let value_ref: Vec = RustlerDecoder::rustler_decode(value_ref_term)?; + let value_ref = RustlerDecoder::rustler_decode(value_ref_term)?; let is_ephemeral_term = term.map_get(at_is_ephemeral().encode(term.get_env()))?; let is_ephemeral: bool = is_ephemeral_term.decode()?; @@ -841,9 +905,11 @@ impl<'a> RustlerDecoder<'a> for Resource { quantity, value_ref, is_ephemeral, - nonce, + nonce: <[u8; 32]>::try_from(nonce) + .map_err(|_e| Error::Term(Box::new("invalid_nonce")))?, nk_commitment, - rand_seed, + rand_seed: <[u8; 32]>::try_from(rand_seed) + .map_err(|_e| Error::Term(Box::new("invalid_nonce")))?, }) } } @@ -971,7 +1037,7 @@ impl<'a> RustlerDecoder<'a> for LogicVerifier { let instance: Vec = RustlerDecoder::rustler_decode(instance_term)?; let verifying_key_term = term.map_get(at_verifying_key().encode(term.get_env()))?; - let verifying_key: Vec = RustlerDecoder::rustler_decode(verifying_key_term)?; + let verifying_key = RustlerDecoder::rustler_decode(verifying_key_term)?; Ok(LogicVerifier { proof,