Merge branch 'main' into schouhy/add-clippy-to-ci

This commit is contained in:
Oleksandr Pravdyvyi 2025-07-23 17:41:40 +03:00
commit d9ced25e98
No known key found for this signature in database
GPG Key ID: 9F8955C63C443871
16 changed files with 594 additions and 436 deletions

12
Cargo.lock generated
View File

@ -996,6 +996,7 @@ dependencies = [
"anyhow", "anyhow",
"elliptic-curve", "elliptic-curve",
"hex", "hex",
"k256",
"log", "log",
"reqwest 0.11.27", "reqwest 0.11.27",
"risc0-zkvm", "risc0-zkvm",
@ -1246,6 +1247,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb"
dependencies = [ dependencies = [
"const-oid", "const-oid",
"pem-rfc7468",
"zeroize", "zeroize",
] ]
@ -1485,6 +1487,7 @@ dependencies = [
"ff", "ff",
"generic-array", "generic-array",
"group", "group",
"pem-rfc7468",
"pkcs8", "pkcs8",
"rand_core 0.6.4", "rand_core 0.6.4",
"sec1", "sec1",
@ -3195,6 +3198,15 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
[[package]]
name = "pem-rfc7468"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412"
dependencies = [
"base64ct",
]
[[package]] [[package]]
name = "percent-encoding" name = "percent-encoding"
version = "2.3.1" version = "2.3.1"

View File

@ -55,7 +55,7 @@ features = ["std", "std_rng", "getrandom"]
version = "0.8.5" version = "0.8.5"
[workspace.dependencies.k256] [workspace.dependencies.k256]
features = ["ecdsa-core", "arithmetic", "expose-field", "serde"] features = ["ecdsa-core", "arithmetic", "expose-field", "serde", "pem"]
version = "0.13.4" version = "0.13.4"
[workspace.dependencies.elliptic-curve] [workspace.dependencies.elliptic-curve]

View File

@ -2,12 +2,14 @@ use aes_gcm::{aead::Aead, Aes256Gcm, KeyInit};
use common::merkle_tree_public::TreeHashType; use common::merkle_tree_public::TreeHashType;
use constants_types::{CipherText, Nonce}; use constants_types::{CipherText, Nonce};
use elliptic_curve::point::AffineCoordinates; use elliptic_curve::point::AffineCoordinates;
use k256::AffinePoint; use k256::{ecdsa::SigningKey, AffinePoint, FieldBytes};
use log::info; use log::info;
use rand::{rngs::OsRng, RngCore};
use secret_holders::{SeedHolder, TopSecretKeyHolder, UTXOSecretKeyHolder}; use secret_holders::{SeedHolder, TopSecretKeyHolder, UTXOSecretKeyHolder};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::account_core::PublicKey; use crate::account_core::PublicKey;
pub type PublicAccountSigningKey = [u8; 32];
pub mod constants_types; pub mod constants_types;
pub mod ephemeral_key_holder; pub mod ephemeral_key_holder;
@ -20,6 +22,7 @@ pub struct AddressKeyHolder {
#[allow(dead_code)] #[allow(dead_code)]
top_secret_key_holder: TopSecretKeyHolder, top_secret_key_holder: TopSecretKeyHolder,
pub utxo_secret_key_holder: UTXOSecretKeyHolder, pub utxo_secret_key_holder: UTXOSecretKeyHolder,
pub_account_signing_key: PublicAccountSigningKey,
pub address: TreeHashType, pub address: TreeHashType,
pub nullifer_public_key: PublicKey, pub nullifer_public_key: PublicKey,
pub viewing_public_key: PublicKey, pub viewing_public_key: PublicKey,
@ -38,15 +41,29 @@ impl AddressKeyHolder {
let nullifer_public_key = utxo_secret_key_holder.generate_nullifier_public_key(); let nullifer_public_key = utxo_secret_key_holder.generate_nullifier_public_key();
let viewing_public_key = utxo_secret_key_holder.generate_viewing_public_key(); let viewing_public_key = utxo_secret_key_holder.generate_viewing_public_key();
let pub_account_signing_key = {
let mut bytes = [0; 32];
OsRng.fill_bytes(&mut bytes);
bytes
};
Self { Self {
top_secret_key_holder, top_secret_key_holder,
utxo_secret_key_holder, utxo_secret_key_holder,
address, address,
nullifer_public_key, nullifer_public_key,
viewing_public_key, viewing_public_key,
pub_account_signing_key,
} }
} }
/// Returns the signing key for public transaction signatures
pub fn get_pub_account_signing_key(&self) -> SigningKey {
let field_bytes = FieldBytes::from_slice(&self.pub_account_signing_key);
// TODO: remove unwrap
SigningKey::from_bytes(&field_bytes).unwrap()
}
pub fn calculate_shared_secret_receiver( pub fn calculate_shared_secret_receiver(
&self, &self,
ephemeral_public_key_sender: AffinePoint, ephemeral_public_key_sender: AffinePoint,
@ -305,6 +322,16 @@ mod tests {
assert_eq!(decrypted_data, plaintext); assert_eq!(decrypted_data, plaintext);
} }
#[test]
fn test_get_public_account_signing_key() {
let address_key_holder = AddressKeyHolder::new_os_random();
let signing_key = address_key_holder.get_pub_account_signing_key();
assert_eq!(
signing_key.to_bytes().as_slice(),
address_key_holder.pub_account_signing_key
);
}
#[test] #[test]
fn key_generation_test() { fn key_generation_test() {
let seed_holder = SeedHolder::new_os_random(); let seed_holder = SeedHolder::new_os_random();

View File

@ -10,6 +10,7 @@ serde_json.workspace = true
serde.workspace = true serde.workspace = true
reqwest.workspace = true reqwest.workspace = true
risc0-zkvm = { git = "https://github.com/risc0/risc0.git", branch = "release-2.3" } risc0-zkvm = { git = "https://github.com/risc0/risc0.git", branch = "release-2.3" }
k256.workspace = true
rs_merkle.workspace = true rs_merkle.workspace = true
sha2.workspace = true sha2.workspace = true

View File

@ -88,3 +88,9 @@ impl ExecutionFailureKind {
Self::DBError(err) Self::DBError(err)
} }
} }
#[derive(Debug, thiserror::Error)]
pub enum TransactionSignatureError {
#[error("invalid signature for transaction body")]
InvalidSignature,
}

View File

@ -140,7 +140,7 @@ impl<Leav: TreeLeavItem + Clone> HashStorageMerkleTree<Leav> {
} }
} }
pub fn add_tx(&mut self, tx: Leav) { pub fn add_tx(&mut self, tx: &Leav) {
let last = self.leaves.len(); let last = self.leaves.len();
self.leaves.insert(last, tx.clone()); self.leaves.insert(last, tx.clone());
@ -267,7 +267,7 @@ mod tests {
let mut tree = HashStorageMerkleTree::new(vec![tx1.clone()]); let mut tree = HashStorageMerkleTree::new(vec![tx1.clone()]);
tree.add_tx(tx2.clone()); tree.add_tx(&tx2);
assert_eq!(tree.leaves.len(), 2); assert_eq!(tree.leaves.len(), 2);
assert_eq!(tree.get_tx(tx2.hash()), Some(&tx2)); assert_eq!(tree.get_tx(tx2.hash()), Some(&tx2));
} }

View File

@ -8,7 +8,7 @@ pub trait TreeLeavItem {
impl TreeLeavItem for Transaction { impl TreeLeavItem for Transaction {
fn hash(&self) -> TreeHashType { fn hash(&self) -> TreeHashType {
self.hash() self.body().hash()
} }
} }

View File

@ -1,6 +1,11 @@
use k256::ecdsa::{
signature::{Signer, Verifier},
Signature, SigningKey, VerifyingKey,
};
use log::info; use log::info;
use secp256k1_zkp::{PedersenCommitment, Tweak}; use secp256k1_zkp::{PedersenCommitment, Tweak};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use sha2::{digest::FixedOutput, Digest}; use sha2::{digest::FixedOutput, Digest};
use crate::merkle_tree_public::TreeHashType; use crate::merkle_tree_public::TreeHashType;
@ -11,11 +16,13 @@ use elliptic_curve::{
}; };
use sha2::digest::typenum::{UInt, UTerm}; use sha2::digest::typenum::{UInt, UTerm};
use crate::TransactionSignatureError;
pub type CipherText = Vec<u8>; pub type CipherText = Vec<u8>;
pub type Nonce = GenericArray<u8, UInt<UInt<UInt<UInt<UTerm, B1>, B1>, B0>, B0>>; pub type Nonce = GenericArray<u8, UInt<UInt<UInt<UInt<UTerm, B1>, B1>, B0>, B0>>;
pub type Tag = u8; pub type Tag = u8;
#[derive(Debug, Serialize, Deserialize, Clone, Copy)] #[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
pub enum TxKind { pub enum TxKind {
Public, Public,
Private, Private,
@ -23,9 +30,9 @@ pub enum TxKind {
Deshielded, Deshielded,
} }
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
///General transaction object ///General transaction object
pub struct Transaction { pub struct TransactionBody {
pub tx_kind: TxKind, pub tx_kind: TxKind,
///Tx input data (public part) ///Tx input data (public part)
pub execution_input: Vec<u8>, pub execution_input: Vec<u8>,
@ -150,16 +157,20 @@ impl ActionData {
} }
} }
impl Transaction { impl TransactionBody {
/// Computes and returns the SHA-256 hash of the JSON-serialized representation of `self`. /// Computes and returns the SHA-256 hash of the JSON-serialized representation of `self`.
pub fn hash(&self) -> TreeHashType { pub fn hash(&self) -> TreeHashType {
let bytes_to_hash = self.to_bytes();
let mut hasher = sha2::Sha256::new();
hasher.update(&bytes_to_hash);
TreeHashType::from(hasher.finalize_fixed())
}
fn to_bytes(&self) -> Vec<u8> {
// TODO: Remove `unwrap` by implementing a `to_bytes` method // TODO: Remove `unwrap` by implementing a `to_bytes` method
// that deterministically encodes all transaction fields to bytes // that deterministically encodes all transaction fields to bytes
// and guarantees serialization will succeed. // and guarantees serialization will succeed.
let raw_data = serde_json::to_vec(&self).unwrap(); serde_json::to_vec(&self).unwrap()
let mut hasher = sha2::Sha256::new();
hasher.update(&raw_data);
TreeHashType::from(hasher.finalize_fixed())
} }
pub fn log(&self) { pub fn log(&self) {
@ -214,19 +225,89 @@ impl Transaction {
} }
} }
type TransactionHash = [u8; 32];
pub type TransactionSignature = Signature;
pub type SignaturePublicKey = VerifyingKey;
pub type SignaturePrivateKey = SigningKey;
/// A container for a transaction body with a signature.
/// Meant to be sent through the network to the sequencer
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
pub struct Transaction {
body: TransactionBody,
signature: TransactionSignature,
public_key: VerifyingKey,
}
impl Transaction {
/// Returns a new transaction signed with the provided `private_key`.
/// The signature is generated over the hash of the body as computed by `body.hash()`
pub fn new(body: TransactionBody, private_key: SigningKey) -> Transaction {
let signature: TransactionSignature = private_key.sign(&body.to_bytes());
let public_key = VerifyingKey::from(&private_key);
Self {
body,
signature,
public_key,
}
}
/// Converts the transaction into an `AuthenticatedTransaction` by verifying its signature.
/// Returns an error if the signature verification fails.
pub fn into_authenticated(self) -> Result<AuthenticatedTransaction, TransactionSignatureError> {
let hash = self.body.hash();
self.public_key
.verify(&self.body.to_bytes(), &self.signature)
.map_err(|_| TransactionSignatureError::InvalidSignature)?;
Ok(AuthenticatedTransaction {
hash,
transaction: self,
})
}
/// Returns the body of the transaction
pub fn body(&self) -> &TransactionBody {
&self.body
}
}
/// A transaction with a valid signature over the hash of its body.
/// Can only be constructed from an `Transaction`
/// if the signature is valid
#[derive(Debug, Clone)]
pub struct AuthenticatedTransaction {
hash: TransactionHash,
transaction: Transaction,
}
impl AuthenticatedTransaction {
/// Returns the underlying transaction
pub fn transaction(&self) -> &Transaction {
&self.transaction
}
/// Returns the precomputed hash over the body of the transaction
pub fn hash(&self) -> &TransactionHash {
&self.hash
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*;
use k256::{ecdsa::signature::Signer, FieldBytes};
use secp256k1_zkp::{constants::SECRET_KEY_SIZE, Tweak}; use secp256k1_zkp::{constants::SECRET_KEY_SIZE, Tweak};
use sha2::{digest::FixedOutput, Digest}; use sha2::{digest::FixedOutput, Digest};
use crate::{ use crate::{
merkle_tree_public::TreeHashType, merkle_tree_public::TreeHashType,
transaction::{Transaction, TxKind}, transaction::{Transaction, TransactionBody, TxKind},
}; };
#[test] fn test_transaction_body() -> TransactionBody {
fn test_transaction_hash_is_sha256_of_json_bytes() { TransactionBody {
let tx = Transaction {
tx_kind: TxKind::Public, tx_kind: TxKind::Public,
execution_input: vec![1, 2, 3, 4], execution_input: vec![1, 2, 3, 4],
execution_output: vec![5, 6, 7, 8], execution_output: vec![5, 6, 7, 8],
@ -241,16 +322,100 @@ mod tests {
secret_r: [8; 32], secret_r: [8; 32],
sc_addr: "someAddress".to_string(), sc_addr: "someAddress".to_string(),
state_changes: (serde_json::Value::Null, 10), state_changes: (serde_json::Value::Null, 10),
}; }
}
fn test_transaction() -> Transaction {
let body = test_transaction_body();
let key_bytes = FieldBytes::from_slice(&[37; 32]);
let private_key: SigningKey = SigningKey::from_bytes(key_bytes).unwrap();
Transaction::new(body, private_key)
}
#[test]
fn test_transaction_hash_is_sha256_of_json_bytes() {
let body = test_transaction_body();
let expected_hash = { let expected_hash = {
let data = serde_json::to_vec(&tx).unwrap(); let data = serde_json::to_vec(&body).unwrap();
let mut hasher = sha2::Sha256::new(); let mut hasher = sha2::Sha256::new();
hasher.update(&data); hasher.update(&data);
TreeHashType::from(hasher.finalize_fixed()) TreeHashType::from(hasher.finalize_fixed())
}; };
let hash = tx.hash(); let hash = body.hash();
assert_eq!(expected_hash, hash); assert_eq!(expected_hash, hash);
} }
#[test]
fn test_transaction_constructor() {
let body = test_transaction_body();
let key_bytes = FieldBytes::from_slice(&[37; 32]);
let private_key: SigningKey = SigningKey::from_bytes(key_bytes).unwrap();
let transaction = Transaction::new(body.clone(), private_key.clone());
assert_eq!(
transaction.public_key,
SignaturePublicKey::from(&private_key)
);
assert_eq!(transaction.body, body);
}
#[test]
fn test_transaction_body_getter() {
let body = test_transaction_body();
let key_bytes = FieldBytes::from_slice(&[37; 32]);
let private_key: SigningKey = SigningKey::from_bytes(key_bytes).unwrap();
let transaction = Transaction::new(body.clone(), private_key.clone());
assert_eq!(transaction.body(), &body);
}
#[test]
fn test_into_authenticated_succeeds_for_valid_signature() {
let transaction = test_transaction();
let authenticated_tx = transaction.clone().into_authenticated().unwrap();
let signature = authenticated_tx.transaction().signature;
let hash = authenticated_tx.hash();
assert_eq!(authenticated_tx.transaction(), &transaction);
assert_eq!(hash, &transaction.body.hash());
assert!(authenticated_tx
.transaction()
.public_key
.verify(&transaction.body.to_bytes(), &signature)
.is_ok());
}
#[test]
fn test_into_authenticated_fails_for_invalid_signature() {
let body = test_transaction_body();
let key_bytes = FieldBytes::from_slice(&[37; 32]);
let private_key: SigningKey = SigningKey::from_bytes(key_bytes).unwrap();
let transaction = {
let mut this = Transaction::new(body, private_key.clone());
// Modify the signature to make it invalid
// We do this by changing it to the signature of something else
this.signature = private_key.sign(b"deadbeef");
this
};
matches!(
transaction.into_authenticated(),
Err(TransactionSignatureError::InvalidSignature)
);
}
#[test]
fn test_authenticated_transaction_getter() {
let transaction = test_transaction();
let authenticated_tx = transaction.clone().into_authenticated().unwrap();
assert_eq!(authenticated_tx.transaction(), &transaction);
}
#[test]
fn test_authenticated_transaction_hash_getter() {
let transaction = test_transaction();
let authenticated_tx = transaction.clone().into_authenticated().unwrap();
assert_eq!(authenticated_tx.hash(), &transaction.body.hash());
}
} }

View File

@ -126,8 +126,9 @@ impl NodeChainStore {
let block_id = block.block_id; let block_id = block.block_id;
for tx in &block.transactions { for tx in &block.transactions {
if !tx.execution_input.is_empty() { if !tx.body().execution_input.is_empty() {
let public_action = serde_json::from_slice::<ActionData>(&tx.execution_input); let public_action =
serde_json::from_slice::<ActionData>(&tx.body().execution_input);
if let Ok(public_action) = public_action { if let Ok(public_action) = public_action {
match public_action { match public_action {
@ -161,24 +162,25 @@ impl NodeChainStore {
} }
self.utxo_commitments_store.add_tx_multiple( self.utxo_commitments_store.add_tx_multiple(
tx.utxo_commitments_created_hashes tx.body()
.utxo_commitments_created_hashes
.clone() .clone()
.into_iter() .into_iter()
.map(|hash| UTXOCommitment { hash }) .map(|hash| UTXOCommitment { hash })
.collect(), .collect(),
); );
for nullifier in tx.nullifier_created_hashes.iter() { for nullifier in tx.body().nullifier_created_hashes.iter() {
self.nullifier_store.insert(UTXONullifier { self.nullifier_store.insert(UTXONullifier {
utxo_hash: *nullifier, utxo_hash: *nullifier,
}); });
} }
if !tx.encoded_data.is_empty() { if !tx.body().encoded_data.is_empty() {
let ephemeral_public_key_sender = let ephemeral_public_key_sender =
serde_json::from_slice::<AffinePoint>(&tx.ephemeral_pub_key)?; serde_json::from_slice::<AffinePoint>(&tx.body().ephemeral_pub_key)?;
for (ciphertext, nonce, tag) in tx.encoded_data.clone() { for (ciphertext, nonce, tag) in tx.body().encoded_data.clone() {
let slice = nonce.as_slice(); let slice = nonce.as_slice();
let nonce = let nonce =
accounts::key_management::constants_types::Nonce::clone_from_slice(slice); accounts::key_management::constants_types::Nonce::clone_from_slice(slice);
@ -203,7 +205,7 @@ impl NodeChainStore {
} }
} }
self.pub_tx_store.add_tx(tx.clone()); self.pub_tx_store.add_tx(tx);
} }
self.block_store.put_block_at_id(block)?; self.block_store.put_block_at_id(block)?;
@ -282,7 +284,7 @@ mod tests {
use accounts::account_core::Account; use accounts::account_core::Account;
use common::block::{Block, Data}; use common::block::{Block, Data};
use common::merkle_tree_public::TreeHashType; use common::merkle_tree_public::TreeHashType;
use common::transaction::{Transaction, TxKind}; use common::transaction::{SignaturePrivateKey, Transaction, TransactionBody, TxKind};
use secp256k1_zkp::Tweak; use secp256k1_zkp::Tweak;
use std::path::PathBuf; use std::path::PathBuf;
use tempfile::tempdir; use tempfile::tempdir;
@ -299,14 +301,13 @@ mod tests {
} }
fn create_dummy_transaction( fn create_dummy_transaction(
// execution_input: Vec<u8>,
nullifier_created_hashes: Vec<[u8; 32]>, nullifier_created_hashes: Vec<[u8; 32]>,
utxo_commitments_spent_hashes: Vec<[u8; 32]>, utxo_commitments_spent_hashes: Vec<[u8; 32]>,
utxo_commitments_created_hashes: Vec<[u8; 32]>, utxo_commitments_created_hashes: Vec<[u8; 32]>,
) -> Transaction { ) -> Transaction {
let mut rng = rand::thread_rng(); let mut rng = rand::thread_rng();
Transaction { let body = TransactionBody {
tx_kind: TxKind::Private, tx_kind: TxKind::Private,
execution_input: vec![], execution_input: vec![],
execution_output: vec![], execution_output: vec![],
@ -321,7 +322,8 @@ mod tests {
secret_r: [0; 32], secret_r: [0; 32],
sc_addr: "sc_addr".to_string(), sc_addr: "sc_addr".to_string(),
state_changes: (serde_json::Value::Null, 0), state_changes: (serde_json::Value::Null, 0),
} };
Transaction::new(body, SignaturePrivateKey::random(&mut rng))
} }
fn create_sample_block(block_id: u64, prev_block_id: u64) -> Block { fn create_sample_block(block_id: u64, prev_block_id: u64) -> Block {
@ -417,7 +419,7 @@ mod tests {
store store
.utxo_commitments_store .utxo_commitments_store
.add_tx_multiple(vec![UTXOCommitment { hash: [3u8; 32] }]); .add_tx_multiple(vec![UTXOCommitment { hash: [3u8; 32] }]);
store.pub_tx_store.add_tx(create_dummy_transaction( store.pub_tx_store.add_tx(&create_dummy_transaction(
vec![[9; 32]], vec![[9; 32]],
vec![[7; 32]], vec![[7; 32]],
vec![[8; 32]], vec![[8; 32]],

View File

@ -3,7 +3,7 @@ use std::sync::{
Arc, Arc,
}; };
use common::ExecutionFailureKind; use common::{transaction::Transaction, ExecutionFailureKind};
use accounts::{ use accounts::{
account_core::{Account, AccountAddress}, account_core::{Account, AccountAddress},
@ -11,7 +11,7 @@ use accounts::{
}; };
use anyhow::Result; use anyhow::Result;
use chain_storage::NodeChainStore; use chain_storage::NodeChainStore;
use common::transaction::{Transaction, TxKind}; use common::transaction::{TransactionBody, TxKind};
use config::NodeConfig; use config::NodeConfig;
use log::info; use log::info;
use sc_core::proofs_circuits::{ use sc_core::proofs_circuits::{
@ -246,30 +246,30 @@ impl NodeCore {
let vec_public_info: Vec<u64> = vec_values_u64.into_iter().flatten().collect(); let vec_public_info: Vec<u64> = vec_values_u64.into_iter().flatten().collect();
let (tweak, secret_r, commitment) = pedersen_commitment_vec(vec_public_info); let (tweak, secret_r, commitment) = pedersen_commitment_vec(vec_public_info);
let transaction_body = TransactionBody {
tx_kind: TxKind::Private,
execution_input: vec![],
execution_output: vec![],
utxo_commitments_spent_hashes: vec![],
utxo_commitments_created_hashes: comm
.into_iter()
.map(|hash_data| hash_data.try_into().unwrap())
.collect(),
nullifier_created_hashes: vec![],
execution_proof_private: sc_core::transaction_payloads_tools::encode_receipt(receipt)
.unwrap(),
encoded_data: vec![(encoded_data.0, encoded_data.1.to_vec(), tag)],
ephemeral_pub_key: eph_pub_key.to_vec(),
commitment,
tweak,
secret_r,
sc_addr,
state_changes,
};
let key_to_sign_transaction = account.key_holder.get_pub_account_signing_key();
Ok(( Ok((
Transaction { Transaction::new(transaction_body, key_to_sign_transaction),
tx_kind: TxKind::Private,
execution_input: vec![],
execution_output: vec![],
utxo_commitments_spent_hashes: vec![],
utxo_commitments_created_hashes: comm
.into_iter()
.map(|hash_data| hash_data.try_into().unwrap())
.collect(),
nullifier_created_hashes: vec![],
execution_proof_private: sc_core::transaction_payloads_tools::encode_receipt(
receipt,
)
.unwrap(),
encoded_data: vec![(encoded_data.0, encoded_data.1.to_vec(), tag)],
ephemeral_pub_key: eph_pub_key.to_vec(),
commitment,
tweak,
secret_r,
sc_addr,
state_changes,
},
result_hash, result_hash,
)) ))
} }
@ -342,29 +342,30 @@ impl NodeCore {
let (tweak, secret_r, commitment) = pedersen_commitment_vec(vec_public_info); let (tweak, secret_r, commitment) = pedersen_commitment_vec(vec_public_info);
Ok(( let transaction_body = TransactionBody {
Transaction { tx_kind: TxKind::Private,
tx_kind: TxKind::Private, execution_input: vec![],
execution_input: vec![], execution_output: vec![],
execution_output: vec![], utxo_commitments_spent_hashes: vec![],
utxo_commitments_spent_hashes: vec![], utxo_commitments_created_hashes: comm
utxo_commitments_created_hashes: comm .into_iter()
.into_iter() .map(|hash_data| hash_data.try_into().unwrap())
.map(|hash_data| hash_data.try_into().unwrap()) .collect(),
.collect(), nullifier_created_hashes: vec![],
nullifier_created_hashes: vec![], execution_proof_private: sc_core::transaction_payloads_tools::encode_receipt(receipt)
execution_proof_private: sc_core::transaction_payloads_tools::encode_receipt(
receipt,
)
.unwrap(), .unwrap(),
encoded_data, encoded_data,
ephemeral_pub_key: eph_pub_key.to_vec(), ephemeral_pub_key: eph_pub_key.to_vec(),
commitment, commitment,
tweak, tweak,
secret_r, secret_r,
sc_addr, sc_addr,
state_changes, state_changes,
}, };
let key_to_sign_transaction = account.key_holder.get_pub_account_signing_key();
Ok((
Transaction::new(transaction_body, key_to_sign_transaction),
result_hashes, result_hashes,
)) ))
} }
@ -455,29 +456,31 @@ impl NodeCore {
let (tweak, secret_r, commitment) = pedersen_commitment_vec(vec_public_info); let (tweak, secret_r, commitment) = pedersen_commitment_vec(vec_public_info);
Ok(( let transaction_body = TransactionBody {
Transaction { tx_kind: TxKind::Private,
tx_kind: TxKind::Private, execution_input: vec![],
execution_input: vec![], execution_output: vec![],
execution_output: vec![], utxo_commitments_spent_hashes: vec![commitment_in],
utxo_commitments_spent_hashes: vec![commitment_in], utxo_commitments_created_hashes: commitments
utxo_commitments_created_hashes: commitments .into_iter()
.into_iter() .map(|hash_data| hash_data.try_into().unwrap())
.map(|hash_data| hash_data.try_into().unwrap()) .collect(),
.collect(), nullifier_created_hashes: vec![nullifier.try_into().unwrap()],
nullifier_created_hashes: vec![nullifier.try_into().unwrap()], execution_proof_private: sc_core::transaction_payloads_tools::encode_receipt(receipt)
execution_proof_private: sc_core::transaction_payloads_tools::encode_receipt(
receipt,
)
.unwrap(), .unwrap(),
encoded_data, encoded_data,
ephemeral_pub_key: eph_pub_key.to_vec(), ephemeral_pub_key: eph_pub_key.to_vec(),
commitment, commitment,
tweak, tweak,
secret_r, secret_r,
sc_addr, sc_addr,
state_changes, state_changes,
}, };
let key_to_sign_transaction = account.key_holder.get_pub_account_signing_key();
Ok((
Transaction::new(transaction_body, key_to_sign_transaction),
utxo_hashes, utxo_hashes,
)) ))
} }
@ -598,29 +601,31 @@ impl NodeCore {
let (tweak, secret_r, commitment) = pedersen_commitment_vec(vec_public_info); let (tweak, secret_r, commitment) = pedersen_commitment_vec(vec_public_info);
Ok(( let transaction_body = TransactionBody {
Transaction { tx_kind: TxKind::Private,
tx_kind: TxKind::Private, execution_input: vec![],
execution_input: vec![], execution_output: vec![],
execution_output: vec![], utxo_commitments_spent_hashes: commitments_in,
utxo_commitments_spent_hashes: commitments_in, utxo_commitments_created_hashes: commitments
utxo_commitments_created_hashes: commitments .into_iter()
.into_iter() .map(|hash_data| hash_data.try_into().unwrap())
.map(|hash_data| hash_data.try_into().unwrap()) .collect(),
.collect(), nullifier_created_hashes: nullifiers,
nullifier_created_hashes: nullifiers, execution_proof_private: sc_core::transaction_payloads_tools::encode_receipt(receipt)
execution_proof_private: sc_core::transaction_payloads_tools::encode_receipt(
receipt,
)
.unwrap(), .unwrap(),
encoded_data, encoded_data,
ephemeral_pub_key: eph_pub_key.to_vec(), ephemeral_pub_key: eph_pub_key.to_vec(),
commitment, commitment,
tweak, tweak,
secret_r, secret_r,
sc_addr, sc_addr,
state_changes, state_changes,
}, };
let key_to_sign_transaction = account.key_holder.get_pub_account_signing_key();
Ok((
Transaction::new(transaction_body, key_to_sign_transaction),
utxo_hashes_receiver, utxo_hashes_receiver,
utxo_hashes_not_spent, utxo_hashes_not_spent,
)) ))
@ -718,35 +723,37 @@ impl NodeCore {
let (tweak, secret_r, commitment) = pedersen_commitment_vec(vec_public_info); let (tweak, secret_r, commitment) = pedersen_commitment_vec(vec_public_info);
let transaction_body = TransactionBody {
tx_kind: TxKind::Shielded,
execution_input: serde_json::to_vec(&ActionData::SendMoneyShieldedTx(
SendMoneyShieldedTx {
acc_sender: acc,
amount: balance as u128,
},
))
.unwrap(),
execution_output: vec![],
utxo_commitments_spent_hashes: vec![],
utxo_commitments_created_hashes: commitments
.into_iter()
.map(|hash_data| hash_data.try_into().unwrap())
.collect(),
nullifier_created_hashes: vec![nullifier.try_into().unwrap()],
execution_proof_private: sc_core::transaction_payloads_tools::encode_receipt(receipt)
.unwrap(),
encoded_data,
ephemeral_pub_key: eph_pub_key.to_vec(),
commitment,
tweak,
secret_r,
sc_addr,
state_changes,
};
let key_to_sign_transaction = account.key_holder.get_pub_account_signing_key();
Ok(( Ok((
Transaction { Transaction::new(transaction_body, key_to_sign_transaction),
tx_kind: TxKind::Shielded,
execution_input: serde_json::to_vec(&ActionData::SendMoneyShieldedTx(
SendMoneyShieldedTx {
acc_sender: acc,
amount: balance as u128,
},
))
.unwrap(),
execution_output: vec![],
utxo_commitments_spent_hashes: vec![],
utxo_commitments_created_hashes: commitments
.into_iter()
.map(|hash_data| hash_data.try_into().unwrap())
.collect(),
nullifier_created_hashes: vec![nullifier.try_into().unwrap()],
execution_proof_private: sc_core::transaction_payloads_tools::encode_receipt(
receipt,
)
.unwrap(),
encoded_data,
ephemeral_pub_key: eph_pub_key.to_vec(),
commitment,
tweak,
secret_r,
sc_addr,
state_changes,
},
utxo_hashes, utxo_hashes,
)) ))
} }
@ -809,7 +816,7 @@ impl NodeCore {
let (tweak, secret_r, commitment) = pedersen_commitment_vec(vec_public_info); let (tweak, secret_r, commitment) = pedersen_commitment_vec(vec_public_info);
Ok(Transaction { let transaction_body = TransactionBody {
tx_kind: TxKind::Deshielded, tx_kind: TxKind::Deshielded,
execution_input: serde_json::to_vec(&ActionData::SendMoneyDeshieldedTx( execution_input: serde_json::to_vec(&ActionData::SendMoneyDeshieldedTx(
SendMoneyDeshieldedTx { SendMoneyDeshieldedTx {
@ -830,7 +837,11 @@ impl NodeCore {
secret_r, secret_r,
sc_addr, sc_addr,
state_changes, state_changes,
}) };
let key_to_sign_transaction = account.key_holder.get_pub_account_signing_key();
Ok(Transaction::new(transaction_body, key_to_sign_transaction))
} }
pub async fn send_private_mint_tx( pub async fn send_private_mint_tx(
@ -843,10 +854,10 @@ impl NodeCore {
let point_before_prove = std::time::Instant::now(); let point_before_prove = std::time::Instant::now();
let (tx, utxo_hash) = self.mint_utxo_private(acc, amount).await?; let (tx, utxo_hash) = self.mint_utxo_private(acc, amount).await?;
tx.log(); tx.body().log();
let point_after_prove = std::time::Instant::now(); let point_after_prove = std::time::Instant::now();
let commitment_generated_hash = tx.utxo_commitments_created_hashes[0]; let commitment_generated_hash = tx.body().utxo_commitments_created_hashes[0];
let timedelta = (point_after_prove - point_before_prove).as_millis(); let timedelta = (point_after_prove - point_before_prove).as_millis();
info!("Mint utxo proof spent {timedelta:?} milliseconds"); info!("Mint utxo proof spent {timedelta:?} milliseconds");
@ -871,10 +882,10 @@ impl NodeCore {
let (tx, utxo_hashes) = self let (tx, utxo_hashes) = self
.mint_utxo_multiple_assets_private(acc, amount, number_of_assets) .mint_utxo_multiple_assets_private(acc, amount, number_of_assets)
.await?; .await?;
tx.log(); tx.body().log();
let point_after_prove = std::time::Instant::now(); let point_after_prove = std::time::Instant::now();
let commitment_generated_hashes = tx.utxo_commitments_created_hashes.clone(); let commitment_generated_hashes = tx.body().utxo_commitments_created_hashes.clone();
let timedelta = (point_after_prove - point_before_prove).as_millis(); let timedelta = (point_after_prove - point_before_prove).as_millis();
info!("Mint utxo proof spent {timedelta:?} milliseconds"); info!("Mint utxo proof spent {timedelta:?} milliseconds");
@ -886,49 +897,50 @@ impl NodeCore {
)) ))
} }
pub async fn send_public_deposit( // pub async fn send_public_deposit(
&self, // &self,
acc: AccountAddress, // acc: AccountAddress,
amount: u128, // amount: u128,
) -> Result<SendTxResponse, ExecutionFailureKind> { // ) -> Result<SendTxResponse, ExecutionFailureKind> {
//Considering proof time, needs to be done before proof // //Considering proof time, needs to be done before proof
let tx_roots = self.get_roots().await; // let tx_roots = self.get_roots().await;
//
let public_context = { // let public_context = {
let read_guard = self.storage.read().await; // let read_guard = self.storage.read().await;
//
read_guard.produce_context(acc) // read_guard.produce_context(acc)
}; // };
//
let (tweak, secret_r, commitment) = pedersen_commitment_vec( // let (tweak, secret_r, commitment) = pedersen_commitment_vec(
//Will not panic, as public context is serializable // //Will not panic, as public context is serializable
public_context.produce_u64_list_from_context().unwrap(), // public_context.produce_u64_list_from_context().unwrap(),
); // );
//
let sc_addr = hex::encode([0; 32]); // let sc_addr = hex::encode([0; 32]);
//
//Sc does not change its state // //Sc does not change its state
let state_changes: Vec<DataBlobChangeVariant> = vec![]; // let state_changes: Vec<DataBlobChangeVariant> = vec![];
let new_len = 0; // let new_len = 0;
let state_changes = (serde_json::to_value(state_changes).unwrap(), new_len); // let state_changes = (serde_json::to_value(state_changes).unwrap(), new_len);
//
let tx: Transaction = // let tx: TransactionBody =
sc_core::transaction_payloads_tools::create_public_transaction_payload( // sc_core::transaction_payloads_tools::create_public_transaction_payload(
serde_json::to_vec(&ActionData::MintMoneyPublicTx(MintMoneyPublicTx { // serde_json::to_vec(&ActionData::MintMoneyPublicTx(MintMoneyPublicTx {
acc, // acc,
amount, // amount,
})) // }))
.unwrap(), // .unwrap(),
commitment, // commitment,
tweak, // tweak,
secret_r, // secret_r,
sc_addr, // sc_addr,
state_changes, // state_changes,
); // )
tx.log(); // .into();
// tx.log();
Ok(self.sequencer_client.send_tx(tx, tx_roots).await?) //
} // Ok(self.sequencer_client.send_tx(tx, tx_roots).await?)
// }
pub async fn send_private_send_tx( pub async fn send_private_send_tx(
&self, &self,
@ -943,7 +955,7 @@ impl NodeCore {
let (tx, utxo_hashes) = self let (tx, utxo_hashes) = self
.transfer_utxo_private(utxo, comm_hash, receivers) .transfer_utxo_private(utxo, comm_hash, receivers)
.await?; .await?;
tx.log(); tx.body().log();
let point_after_prove = std::time::Instant::now(); let point_after_prove = std::time::Instant::now();
let timedelta = (point_after_prove - point_before_prove).as_millis(); let timedelta = (point_after_prove - point_before_prove).as_millis();
@ -969,7 +981,7 @@ impl NodeCore {
let (tx, utxo_hashes_received, utxo_hashes_not_spent) = self let (tx, utxo_hashes_received, utxo_hashes_not_spent) = self
.transfer_utxo_multiple_assets_private(utxos, comm_hashes, number_to_send, receiver) .transfer_utxo_multiple_assets_private(utxos, comm_hashes, number_to_send, receiver)
.await?; .await?;
tx.log(); tx.body().log();
let point_after_prove = std::time::Instant::now(); let point_after_prove = std::time::Instant::now();
let timedelta = (point_after_prove - point_before_prove).as_millis(); let timedelta = (point_after_prove - point_before_prove).as_millis();
@ -995,7 +1007,7 @@ impl NodeCore {
let (tx, utxo_hashes) = self let (tx, utxo_hashes) = self
.transfer_balance_shielded(acc, amount, receivers) .transfer_balance_shielded(acc, amount, receivers)
.await?; .await?;
tx.log(); tx.body().log();
let point_after_prove = std::time::Instant::now(); let point_after_prove = std::time::Instant::now();
let timedelta = (point_after_prove - point_before_prove).as_millis(); let timedelta = (point_after_prove - point_before_prove).as_millis();
@ -1020,7 +1032,7 @@ impl NodeCore {
let tx = self let tx = self
.transfer_utxo_deshielded(utxo, comm_gen_hash, receivers) .transfer_utxo_deshielded(utxo, comm_gen_hash, receivers)
.await?; .await?;
tx.log(); tx.body().log();
let point_after_prove = std::time::Instant::now(); let point_after_prove = std::time::Instant::now();
let timedelta = (point_after_prove - point_before_prove).as_millis(); let timedelta = (point_after_prove - point_before_prove).as_millis();
@ -1154,46 +1166,46 @@ impl NodeCore {
Ok(()) Ok(())
} }
pub async fn operate_account_deposit_public( // pub async fn operate_account_deposit_public(
&mut self, // &mut self,
acc_addr: AccountAddress, // acc_addr: AccountAddress,
amount: u128, // amount: u128,
) -> Result<(), ExecutionFailureKind> { // ) -> Result<(), ExecutionFailureKind> {
let old_balance = { // let old_balance = {
let acc_map_read_guard = self.storage.read().await; // let acc_map_read_guard = self.storage.read().await;
//
let acc = acc_map_read_guard.acc_map.get(&acc_addr).unwrap(); // let acc = acc_map_read_guard.acc_map.get(&acc_addr).unwrap();
//
acc.balance // acc.balance
}; // };
//
info!( // info!(
"Balance of {:?} now is {old_balance:?}", // "Balance of {:?} now is {old_balance:?}",
hex::encode(acc_addr) // hex::encode(acc_addr)
); // );
//
let resp = self.send_public_deposit(acc_addr, amount).await?; // let resp = self.send_public_deposit(acc_addr, amount).await?;
info!("Response for public deposit is {resp:?}"); // info!("Response for public deposit is {resp:?}");
//
info!("Awaiting new blocks"); // info!("Awaiting new blocks");
tokio::time::sleep(std::time::Duration::from_secs(BLOCK_GEN_DELAY_SECS)).await; // tokio::time::sleep(std::time::Duration::from_secs(BLOCK_GEN_DELAY_SECS)).await;
//
let new_balance = { // let new_balance = {
let acc_map_read_guard = self.storage.read().await; // let acc_map_read_guard = self.storage.read().await;
//
let acc = acc_map_read_guard.acc_map.get(&acc_addr).unwrap(); // let acc = acc_map_read_guard.acc_map.get(&acc_addr).unwrap();
//
acc.balance // acc.balance
}; // };
//
info!( // info!(
"Balance of {:?} now is {new_balance:?}, delta is {:?}", // "Balance of {:?} now is {new_balance:?}, delta is {:?}",
hex::encode(acc_addr), // hex::encode(acc_addr),
new_balance - old_balance // new_balance - old_balance
); // );
//
Ok(()) // Ok(())
} // }
pub async fn operate_account_send_shielded_one_receiver( pub async fn operate_account_send_shielded_one_receiver(
&mut self, &mut self,
@ -1443,30 +1455,31 @@ impl NodeCore {
let (tweak, secret_r, commitment) = pedersen_commitment_vec(vec_public_info); let (tweak, secret_r, commitment) = pedersen_commitment_vec(vec_public_info);
Ok(( let transaction_body = TransactionBody {
Transaction { tx_kind: TxKind::Shielded,
tx_kind: TxKind::Shielded, execution_input: vec![],
execution_input: vec![], execution_output: serde_json::to_vec(&publication).unwrap(),
execution_output: serde_json::to_vec(&publication).unwrap(), utxo_commitments_spent_hashes: vec![commitment_in],
utxo_commitments_spent_hashes: vec![commitment_in], utxo_commitments_created_hashes: commitments
utxo_commitments_created_hashes: commitments .clone()
.clone() .into_iter()
.into_iter() .map(|hash_data| hash_data.try_into().unwrap())
.map(|hash_data| hash_data.try_into().unwrap()) .collect(),
.collect(), nullifier_created_hashes: vec![nullifier.try_into().unwrap()],
nullifier_created_hashes: vec![nullifier.try_into().unwrap()], execution_proof_private: sc_core::transaction_payloads_tools::encode_receipt(receipt)
execution_proof_private: sc_core::transaction_payloads_tools::encode_receipt(
receipt,
)
.unwrap(), .unwrap(),
encoded_data, encoded_data,
ephemeral_pub_key: eph_pub_key.to_vec(), ephemeral_pub_key: eph_pub_key.to_vec(),
commitment, commitment,
tweak, tweak,
secret_r, secret_r,
sc_addr, sc_addr,
state_changes, state_changes,
}, };
let key_to_sign_transaction = account.key_holder.get_pub_account_signing_key();
Ok((
Transaction::new(transaction_body, key_to_sign_transaction),
utxo_hashes, utxo_hashes,
)) ))
} }
@ -1486,13 +1499,13 @@ impl NodeCore {
let (tx, utxo_hashes) = self let (tx, utxo_hashes) = self
.split_utxo(utxo, comm_hash, receivers, visibility_list) .split_utxo(utxo, comm_hash, receivers, visibility_list)
.await?; .await?;
tx.log(); tx.body().log();
let point_after_prove = std::time::Instant::now(); let point_after_prove = std::time::Instant::now();
let timedelta = (point_after_prove - point_before_prove).as_millis(); let timedelta = (point_after_prove - point_before_prove).as_millis();
info!("Send private utxo proof spent {timedelta:?} milliseconds"); info!("Send private utxo proof spent {timedelta:?} milliseconds");
let commitments = tx.utxo_commitments_created_hashes.clone(); let commitments = tx.body().utxo_commitments_created_hashes.clone();
Ok(( Ok((
self.sequencer_client.send_tx(tx, tx_roots).await?, self.sequencer_client.send_tx(tx, tx_roots).await?,
@ -1563,20 +1576,8 @@ impl NodeCore {
Ok(()) Ok(())
} }
///Deposit balance, make it private
pub async fn subscenario_2(&mut self) -> Result<(), ExecutionFailureKind> {
let acc_addr = self.create_new_account().await;
self.operate_account_deposit_public(acc_addr, 100).await?;
self.operate_account_send_shielded_one_receiver(acc_addr, acc_addr, 100)
.await?;
Ok(())
}
///Mint utxo, privately send it to another user ///Mint utxo, privately send it to another user
pub async fn subscenario_3(&mut self) -> Result<(), ExecutionFailureKind> { pub async fn subscenario_2(&mut self) -> Result<(), ExecutionFailureKind> {
let acc_addr = self.create_new_account().await; let acc_addr = self.create_new_account().await;
let acc_addr_rec = self.create_new_account().await; let acc_addr_rec = self.create_new_account().await;
@ -1588,21 +1589,8 @@ impl NodeCore {
Ok(()) Ok(())
} }
///Deposit balance, shielded send it to another user
pub async fn subscenario_4(&mut self) -> Result<(), ExecutionFailureKind> {
let acc_addr = self.create_new_account().await;
let acc_addr_rec = self.create_new_account().await;
self.operate_account_deposit_public(acc_addr, 100).await?;
self.operate_account_send_shielded_one_receiver(acc_addr, acc_addr_rec, 100)
.await?;
Ok(())
}
///Mint utxo, deshielded send it to another user ///Mint utxo, deshielded send it to another user
pub async fn subscenario_5(&mut self) -> Result<(), ExecutionFailureKind> { pub async fn subscenario_3(&mut self) -> Result<(), ExecutionFailureKind> {
let acc_addr = self.create_new_account().await; let acc_addr = self.create_new_account().await;
let acc_addr_rec = self.create_new_account().await; let acc_addr_rec = self.create_new_account().await;

View File

@ -23,8 +23,7 @@ use crate::types::{
ExecuteScenarioSplitResponse, ExecuteSubscenarioRequest, ExecuteSubscenarioResponse, ExecuteScenarioSplitResponse, ExecuteSubscenarioRequest, ExecuteSubscenarioResponse,
ShowAccountPublicBalanceRequest, ShowAccountPublicBalanceResponse, ShowAccountUTXORequest, ShowAccountPublicBalanceRequest, ShowAccountPublicBalanceResponse, ShowAccountUTXORequest,
ShowAccountUTXOResponse, ShowTransactionRequest, ShowTransactionResponse, ShowAccountUTXOResponse, ShowTransactionRequest, ShowTransactionResponse,
UTXOShortEssentialStruct, WriteDepositPublicBalanceRequest, UTXOShortEssentialStruct, WriteMintPrivateUTXOMultipleAssetsRequest,
WriteDepositPublicBalanceResponse, WriteMintPrivateUTXOMultipleAssetsRequest,
WriteMintPrivateUTXOMultipleAssetsResponse, WriteMintPrivateUTXORequest, WriteMintPrivateUTXOMultipleAssetsResponse, WriteMintPrivateUTXORequest,
WriteMintPrivateUTXOResponse, WriteSendDeshieldedBalanceRequest, WriteMintPrivateUTXOResponse, WriteSendDeshieldedBalanceRequest,
WriteSendDeshieldedUTXOResponse, WriteSendPrivateUTXORequest, WriteSendPrivateUTXOResponse, WriteSendDeshieldedUTXOResponse, WriteSendPrivateUTXORequest, WriteSendPrivateUTXOResponse,
@ -42,7 +41,6 @@ pub const EXECUTE_SCENARIO_MULTIPLE_SEND: &str = "execute_scenario_multiple_send
pub const SHOW_ACCOUNT_PUBLIC_BALANCE: &str = "show_account_public_balance"; pub const SHOW_ACCOUNT_PUBLIC_BALANCE: &str = "show_account_public_balance";
pub const SHOW_ACCOUNT_UTXO: &str = "show_account_utxo"; pub const SHOW_ACCOUNT_UTXO: &str = "show_account_utxo";
pub const SHOW_TRANSACTION: &str = "show_transaction"; pub const SHOW_TRANSACTION: &str = "show_transaction";
pub const WRITE_DEPOSIT_PUBLIC_BALANCE: &str = "write_deposit_public_balance";
pub const WRITE_MINT_UTXO: &str = "write_mint_utxo"; pub const WRITE_MINT_UTXO: &str = "write_mint_utxo";
pub const WRITE_MINT_UTXO_MULTIPLE_ASSETS: &str = "write_mint_utxo_multiple_assets"; pub const WRITE_MINT_UTXO_MULTIPLE_ASSETS: &str = "write_mint_utxo_multiple_assets";
pub const WRITE_SEND_UTXO_PRIVATE: &str = "write_send_utxo_private"; pub const WRITE_SEND_UTXO_PRIVATE: &str = "write_send_utxo_private";
@ -92,14 +90,6 @@ impl JsonHandler {
.subscenario_3() .subscenario_3()
.await .await
.map_err(cast_common_execution_error_into_rpc_error)?, .map_err(cast_common_execution_error_into_rpc_error)?,
4 => store
.subscenario_4()
.await
.map_err(cast_common_execution_error_into_rpc_error)?,
5 => store
.subscenario_5()
.await
.map_err(cast_common_execution_error_into_rpc_error)?,
_ => return Err(RpcErr(RpcError::invalid_params("Scenario id not found"))), _ => return Err(RpcErr(RpcError::invalid_params("Scenario id not found"))),
} }
} }
@ -312,42 +302,46 @@ impl JsonHandler {
ShowTransactionResponse { ShowTransactionResponse {
hash: req.tx_hash, hash: req.tx_hash,
tx_kind: tx.tx_kind, tx_kind: tx.body().tx_kind,
public_input: if let Ok(action) = public_input: if let Ok(action) =
serde_json::from_slice::<ActionData>(&tx.execution_input) serde_json::from_slice::<ActionData>(&tx.body().execution_input)
{ {
action.into_hexed_print() action.into_hexed_print()
} else { } else {
"".to_string() "".to_string()
}, },
public_output: if let Ok(action) = public_output: if let Ok(action) =
serde_json::from_slice::<ActionData>(&tx.execution_output) serde_json::from_slice::<ActionData>(&tx.body().execution_output)
{ {
action.into_hexed_print() action.into_hexed_print()
} else { } else {
"".to_string() "".to_string()
}, },
utxo_commitments_created_hashes: tx utxo_commitments_created_hashes: tx
.body()
.utxo_commitments_created_hashes .utxo_commitments_created_hashes
.iter() .iter()
.map(hex::encode) .map(hex::encode)
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
utxo_commitments_spent_hashes: tx utxo_commitments_spent_hashes: tx
.body()
.utxo_commitments_spent_hashes .utxo_commitments_spent_hashes
.iter() .iter()
.map(hex::encode) .map(hex::encode)
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
utxo_nullifiers_created_hashes: tx utxo_nullifiers_created_hashes: tx
.body()
.nullifier_created_hashes .nullifier_created_hashes
.iter() .iter()
.map(hex::encode) .map(hex::encode)
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
encoded_data: tx encoded_data: tx
.body()
.encoded_data .encoded_data
.iter() .iter()
.map(|val| (hex::encode(val.0.clone()), hex::encode(val.1.clone()))) .map(|val| (hex::encode(val.0.clone()), hex::encode(val.1.clone())))
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
ephemeral_pub_key: hex::encode(tx.ephemeral_pub_key.clone()), ephemeral_pub_key: hex::encode(tx.body().ephemeral_pub_key.clone()),
} }
} }
}; };
@ -355,36 +349,6 @@ impl JsonHandler {
respond(helperstruct) respond(helperstruct)
} }
pub async fn process_write_deposit_public_balance(
&self,
request: Request,
) -> Result<Value, RpcErr> {
let req = WriteDepositPublicBalanceRequest::parse(Some(request.params))?;
let acc_addr_hex_dec = hex::decode(req.account_addr.clone()).map_err(|_| {
RpcError::parse_error("Failed to decode account address from hex string".to_string())
})?;
let acc_addr: [u8; 32] = acc_addr_hex_dec.try_into().map_err(|_| {
RpcError::parse_error("Failed to parse account address from bytes".to_string())
})?;
{
let mut cover_guard = self.node_chain_store.lock().await;
cover_guard
.operate_account_deposit_public(acc_addr, req.amount as u128)
.await
.map_err(cast_common_execution_error_into_rpc_error)?;
};
let helperstruct = WriteDepositPublicBalanceResponse {
status: SUCCESS.to_string(),
};
respond(helperstruct)
}
pub async fn process_write_mint_utxo(&self, request: Request) -> Result<Value, RpcErr> { pub async fn process_write_mint_utxo(&self, request: Request) -> Result<Value, RpcErr> {
let req = WriteMintPrivateUTXORequest::parse(Some(request.params))?; let req = WriteMintPrivateUTXORequest::parse(Some(request.params))?;
@ -777,9 +741,6 @@ impl JsonHandler {
SHOW_ACCOUNT_PUBLIC_BALANCE => self.process_show_account_public_balance(request).await, SHOW_ACCOUNT_PUBLIC_BALANCE => self.process_show_account_public_balance(request).await,
SHOW_ACCOUNT_UTXO => self.process_show_account_utxo_request(request).await, SHOW_ACCOUNT_UTXO => self.process_show_account_utxo_request(request).await,
SHOW_TRANSACTION => self.process_show_transaction(request).await, SHOW_TRANSACTION => self.process_show_transaction(request).await,
WRITE_DEPOSIT_PUBLIC_BALANCE => {
self.process_write_deposit_public_balance(request).await
}
WRITE_MINT_UTXO => self.process_write_mint_utxo(request).await, WRITE_MINT_UTXO => self.process_write_mint_utxo(request).await,
WRITE_MINT_UTXO_MULTIPLE_ASSETS => { WRITE_MINT_UTXO_MULTIPLE_ASSETS => {
self.process_write_mint_utxo_multiple_assets(request).await self.process_write_mint_utxo_multiple_assets(request).await

View File

@ -1,6 +1,6 @@
use accounts::{account_core::Account, key_management::ephemeral_key_holder::EphemeralKeyHolder}; use accounts::{account_core::Account, key_management::ephemeral_key_holder::EphemeralKeyHolder};
use anyhow::Result; use anyhow::Result;
use common::transaction::{Transaction, TxKind}; use common::transaction::{TransactionBody, TxKind};
use rand::thread_rng; use rand::thread_rng;
use risc0_zkvm::Receipt; use risc0_zkvm::Receipt;
use secp256k1_zkp::{CommitmentSecrets, PedersenCommitment, Tweak}; use secp256k1_zkp::{CommitmentSecrets, PedersenCommitment, Tweak};
@ -15,8 +15,8 @@ pub fn create_public_transaction_payload(
secret_r: [u8; 32], secret_r: [u8; 32],
sc_addr: String, sc_addr: String,
state_changes: (serde_json::Value, usize), state_changes: (serde_json::Value, usize),
) -> Transaction { ) -> TransactionBody {
Transaction { TransactionBody {
tx_kind: TxKind::Public, tx_kind: TxKind::Public,
execution_input, execution_input,
execution_output: vec![], execution_output: vec![],

View File

@ -6,22 +6,22 @@ use common::{
block::{Block, HashableBlockData}, block::{Block, HashableBlockData},
merkle_tree_public::TreeHashType, merkle_tree_public::TreeHashType,
nullifier::UTXONullifier, nullifier::UTXONullifier,
transaction::{Transaction, TxKind}, transaction::{AuthenticatedTransaction, Transaction, TransactionBody, TxKind},
utxo_commitment::UTXOCommitment, utxo_commitment::UTXOCommitment,
}; };
use config::SequencerConfig; use config::SequencerConfig;
use mempool::MemPool; use mempool::MemPool;
use mempool_transaction::MempoolTransaction;
use sequencer_store::SequecerChainStore; use sequencer_store::SequecerChainStore;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use transaction_mempool::TransactionMempool;
pub mod config; pub mod config;
pub mod mempool_transaction;
pub mod sequencer_store; pub mod sequencer_store;
pub mod transaction_mempool;
pub struct SequencerCore { pub struct SequencerCore {
pub store: SequecerChainStore, pub store: SequecerChainStore,
pub mempool: MemPool<TransactionMempool>, pub mempool: MemPool<MempoolTransaction>,
pub sequencer_config: SequencerConfig, pub sequencer_config: SequencerConfig,
pub chain_height: u64, pub chain_height: u64,
} }
@ -36,6 +36,7 @@ pub enum TransactionMalformationErrorKind {
MempoolFullForRound { tx: TreeHashType }, MempoolFullForRound { tx: TreeHashType },
ChainStateFurtherThanTransactionState { tx: TreeHashType }, ChainStateFurtherThanTransactionState { tx: TreeHashType },
FailedToInsert { tx: TreeHashType, details: String }, FailedToInsert { tx: TreeHashType, details: String },
InvalidSignature,
} }
impl Display for TransactionMalformationErrorKind { impl Display for TransactionMalformationErrorKind {
@ -55,7 +56,7 @@ impl SequencerCore {
config.is_genesis_random, config.is_genesis_random,
&config.initial_accounts, &config.initial_accounts,
), ),
mempool: MemPool::<TransactionMempool>::default(), mempool: MemPool::<MempoolTransaction>::default(),
chain_height: config.genesis_id, chain_height: config.genesis_id,
sequencer_config: config, sequencer_config: config,
} }
@ -73,24 +74,23 @@ impl SequencerCore {
pub fn transaction_pre_check( pub fn transaction_pre_check(
&mut self, &mut self,
tx: &Transaction, tx: Transaction,
tx_roots: [[u8; 32]; 2], tx_roots: [[u8; 32]; 2],
) -> Result<(), TransactionMalformationErrorKind> { ) -> Result<AuthenticatedTransaction, TransactionMalformationErrorKind> {
let Transaction { let tx = tx
.into_authenticated()
.map_err(|_| TransactionMalformationErrorKind::InvalidSignature)?;
let TransactionBody {
tx_kind, tx_kind,
ref execution_input, ref execution_input,
ref execution_output, ref execution_output,
ref utxo_commitments_created_hashes, ref utxo_commitments_created_hashes,
ref nullifier_created_hashes, ref nullifier_created_hashes,
.. ..
} = tx; } = tx.transaction().body();
let hash = tx.hash();
let mempool_size = self.mempool.len(); let tx_hash = *tx.hash();
if mempool_size >= self.sequencer_config.max_num_tx_in_block {
return Err(TransactionMalformationErrorKind::MempoolFullForRound { tx: hash });
}
let curr_sequencer_roots = self.get_tree_roots(); let curr_sequencer_roots = self.get_tree_roots();
@ -149,50 +149,61 @@ impl SequencerCore {
}); });
if tx_tree_check { if tx_tree_check {
return Err(TransactionMalformationErrorKind::TxHashAlreadyPresentInTree { tx: hash }); return Err(
TransactionMalformationErrorKind::TxHashAlreadyPresentInTree { tx: *tx.hash() },
);
} }
if nullifier_tree_check { if nullifier_tree_check {
return Err( return Err(
TransactionMalformationErrorKind::NullifierAlreadyPresentInTree { tx: hash }, TransactionMalformationErrorKind::NullifierAlreadyPresentInTree { tx: *tx.hash() },
); );
} }
if utxo_commitments_check { if utxo_commitments_check {
return Err( return Err(
TransactionMalformationErrorKind::UTXOCommitmentAlreadyPresentInTree { tx: hash }, TransactionMalformationErrorKind::UTXOCommitmentAlreadyPresentInTree {
tx: *tx.hash(),
},
); );
} }
Ok(()) Ok(tx)
} }
pub fn push_tx_into_mempool_pre_check( pub fn push_tx_into_mempool_pre_check(
&mut self, &mut self,
item: TransactionMempool, transaction: Transaction,
tx_roots: [[u8; 32]; 2], tx_roots: [[u8; 32]; 2],
) -> Result<(), TransactionMalformationErrorKind> { ) -> Result<(), TransactionMalformationErrorKind> {
self.transaction_pre_check(&item.tx, tx_roots)?; let mempool_size = self.mempool.len();
if mempool_size >= self.sequencer_config.max_num_tx_in_block {
return Err(TransactionMalformationErrorKind::MempoolFullForRound {
tx: transaction.body().hash(),
});
}
self.mempool.push_item(item); let authenticated_tx = self.transaction_pre_check(transaction, tx_roots)?;
self.mempool.push_item(authenticated_tx.into());
Ok(()) Ok(())
} }
fn execute_check_transaction_on_state( fn execute_check_transaction_on_state(
&mut self, &mut self,
tx: TransactionMempool, mempool_tx: &MempoolTransaction,
) -> Result<(), TransactionMalformationErrorKind> { ) -> Result<(), TransactionMalformationErrorKind> {
let Transaction { let TransactionBody {
ref utxo_commitments_created_hashes, ref utxo_commitments_created_hashes,
ref nullifier_created_hashes, ref nullifier_created_hashes,
.. ..
} = tx.tx; } = mempool_tx.auth_tx.transaction().body();
for utxo_comm in utxo_commitments_created_hashes { for utxo_comm in utxo_commitments_created_hashes {
self.store self.store
.utxo_commitments_store .utxo_commitments_store
.add_tx(UTXOCommitment { hash: *utxo_comm }); .add_tx(&UTXOCommitment { hash: *utxo_comm });
} }
for nullifier in nullifier_created_hashes.iter() { for nullifier in nullifier_created_hashes.iter() {
@ -201,7 +212,9 @@ impl SequencerCore {
}); });
} }
self.store.pub_tx_store.add_tx(tx.tx); self.store
.pub_tx_store
.add_tx(mempool_tx.auth_tx.transaction());
Ok(()) Ok(())
} }
@ -219,7 +232,7 @@ impl SequencerCore {
.pop_size(self.sequencer_config.max_num_tx_in_block); .pop_size(self.sequencer_config.max_num_tx_in_block);
for tx in &transactions { for tx in &transactions {
self.execute_check_transaction_on_state(tx.clone())?; self.execute_check_transaction_on_state(&tx)?;
} }
let prev_block_hash = self let prev_block_hash = self
@ -231,7 +244,10 @@ impl SequencerCore {
let hashable_data = HashableBlockData { let hashable_data = HashableBlockData {
block_id: new_block_height, block_id: new_block_height,
prev_block_id: self.chain_height, prev_block_id: self.chain_height,
transactions: transactions.into_iter().map(|tx_mem| tx_mem.tx).collect(), transactions: transactions
.into_iter()
.map(|tx_mem| tx_mem.auth_tx.transaction().clone())
.collect(),
data: vec![], data: vec![],
prev_block_hash, prev_block_hash,
}; };
@ -253,10 +269,10 @@ mod tests {
use super::*; use super::*;
use std::path::PathBuf; use std::path::PathBuf;
use common::transaction::{Transaction, TxKind}; use common::transaction::{SignaturePrivateKey, Transaction, TransactionBody, TxKind};
use mempool_transaction::MempoolTransaction;
use rand::Rng; use rand::Rng;
use secp256k1_zkp::Tweak; use secp256k1_zkp::Tweak;
use transaction_mempool::TransactionMempool;
fn setup_sequencer_config_variable_initial_accounts( fn setup_sequencer_config_variable_initial_accounts(
initial_accounts: Vec<AccountInitialData>, initial_accounts: Vec<AccountInitialData>,
@ -302,7 +318,7 @@ mod tests {
) -> Transaction { ) -> Transaction {
let mut rng = rand::thread_rng(); let mut rng = rand::thread_rng();
Transaction { let body = TransactionBody {
tx_kind: TxKind::Private, tx_kind: TxKind::Private,
execution_input: vec![], execution_input: vec![],
execution_output: vec![], execution_output: vec![],
@ -317,13 +333,16 @@ mod tests {
secret_r: [0; 32], secret_r: [0; 32],
sc_addr: "sc_addr".to_string(), sc_addr: "sc_addr".to_string(),
state_changes: (serde_json::Value::Null, 0), state_changes: (serde_json::Value::Null, 0),
} };
Transaction::new(body, SignaturePrivateKey::random(&mut rng))
} }
fn common_setup(sequencer: &mut SequencerCore) { fn common_setup(sequencer: &mut SequencerCore) {
let tx = create_dummy_transaction(vec![[9; 32]], vec![[7; 32]], vec![[8; 32]]); let tx = create_dummy_transaction(vec![[9; 32]], vec![[7; 32]], vec![[8; 32]]);
let tx_mempool = TransactionMempool { tx }; let mempool_tx = MempoolTransaction {
sequencer.mempool.push_item(tx_mempool); auth_tx: tx.into_authenticated().unwrap(),
};
sequencer.mempool.push_item(mempool_tx);
sequencer sequencer
.produce_new_block_with_mempool_transactions() .produce_new_block_with_mempool_transactions()
@ -445,13 +464,13 @@ mod tests {
let tx = create_dummy_transaction(vec![[91; 32]], vec![[71; 32]], vec![[81; 32]]); let tx = create_dummy_transaction(vec![[91; 32]], vec![[71; 32]], vec![[81; 32]]);
let tx_roots = sequencer.get_tree_roots(); let tx_roots = sequencer.get_tree_roots();
let result = sequencer.transaction_pre_check(&tx, tx_roots); let result = sequencer.transaction_pre_check(tx, tx_roots);
assert!(result.is_ok()); assert!(result.is_ok());
} }
#[test] #[test]
fn test_transaction_pre_check_fail_mempool_full() { fn test_push_tx_into_mempool_fails_mempool_full() {
let config = SequencerConfig { let config = SequencerConfig {
max_num_tx_in_block: 1, max_num_tx_in_block: 1,
..setup_sequencer_config() ..setup_sequencer_config()
@ -464,10 +483,12 @@ mod tests {
let tx_roots = sequencer.get_tree_roots(); let tx_roots = sequencer.get_tree_roots();
// Fill the mempool // Fill the mempool
let dummy_tx = TransactionMempool { tx: tx.clone() }; let dummy_tx = MempoolTransaction {
auth_tx: tx.clone().into_authenticated().unwrap(),
};
sequencer.mempool.push_item(dummy_tx); sequencer.mempool.push_item(dummy_tx);
let result = sequencer.transaction_pre_check(&tx, tx_roots); let result = sequencer.push_tx_into_mempool_pre_check(tx, tx_roots);
assert!(matches!( assert!(matches!(
result, result,
@ -484,9 +505,8 @@ mod tests {
let tx = create_dummy_transaction(vec![[93; 32]], vec![[73; 32]], vec![[83; 32]]); let tx = create_dummy_transaction(vec![[93; 32]], vec![[73; 32]], vec![[83; 32]]);
let tx_roots = sequencer.get_tree_roots(); let tx_roots = sequencer.get_tree_roots();
let tx_mempool = TransactionMempool { tx };
let result = sequencer.push_tx_into_mempool_pre_check(tx_mempool.clone(), tx_roots); let result = sequencer.push_tx_into_mempool_pre_check(tx, tx_roots);
assert!(result.is_ok()); assert!(result.is_ok());
assert_eq!(sequencer.mempool.len(), 1); assert_eq!(sequencer.mempool.len(), 1);
} }
@ -497,7 +517,9 @@ mod tests {
let mut sequencer = SequencerCore::start_from_config(config); let mut sequencer = SequencerCore::start_from_config(config);
let tx = create_dummy_transaction(vec![[94; 32]], vec![[7; 32]], vec![[8; 32]]); let tx = create_dummy_transaction(vec![[94; 32]], vec![[7; 32]], vec![[8; 32]]);
let tx_mempool = TransactionMempool { tx }; let tx_mempool = MempoolTransaction {
auth_tx: tx.into_authenticated().unwrap(),
};
sequencer.mempool.push_item(tx_mempool); sequencer.mempool.push_item(tx_mempool);
let block_id = sequencer.produce_new_block_with_mempool_transactions(); let block_id = sequencer.produce_new_block_with_mempool_transactions();

View File

@ -0,0 +1,20 @@
use common::{merkle_tree_public::TreeHashType, transaction::AuthenticatedTransaction};
use mempool::mempoolitem::MemPoolItem;
pub struct MempoolTransaction {
pub auth_tx: AuthenticatedTransaction,
}
impl From<AuthenticatedTransaction> for MempoolTransaction {
fn from(auth_tx: AuthenticatedTransaction) -> Self {
Self { auth_tx }
}
}
impl MemPoolItem for MempoolTransaction {
type Identifier = TreeHashType;
fn identifier(&self) -> Self::Identifier {
*self.auth_tx.hash()
}
}

View File

@ -1,43 +0,0 @@
use common::{merkle_tree_public::TreeHashType, transaction::Transaction};
use mempool::mempoolitem::MemPoolItem;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone)]
pub struct TransactionMempool {
pub tx: Transaction,
}
impl From<Transaction> for TransactionMempool {
fn from(value: Transaction) -> Self {
Self { tx: value }
}
}
impl Serialize for TransactionMempool {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.tx.serialize(serializer)
}
}
impl<'de> Deserialize<'de> for TransactionMempool {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
match Transaction::deserialize(deserializer) {
Ok(tx) => Ok(TransactionMempool { tx }),
Err(err) => Err(err),
}
}
}
impl MemPoolItem for TransactionMempool {
type Identifier = TreeHashType;
fn identifier(&self) -> Self::Identifier {
self.tx.hash()
}
}

View File

@ -76,10 +76,7 @@ impl JsonHandler {
{ {
let mut state = self.sequencer_state.lock().await; let mut state = self.sequencer_state.lock().await;
state.push_tx_into_mempool_pre_check( state.push_tx_into_mempool_pre_check(send_tx_req.transaction, send_tx_req.tx_roots)?;
send_tx_req.transaction.into(),
send_tx_req.tx_roots,
)?;
} }
let helperstruct = SendTxResponse { let helperstruct = SendTxResponse {