From f8c925c265cfc0b38be16b38005a362bc44a7e14 Mon Sep 17 00:00:00 2001 From: Sergio Chouhy Date: Sat, 17 May 2025 17:53:12 -0300 Subject: [PATCH 01/36] add clippy to CI --- ci_scripts/lint-ubuntu.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ci_scripts/lint-ubuntu.sh b/ci_scripts/lint-ubuntu.sh index d30ef67..7def8fa 100644 --- a/ci_scripts/lint-ubuntu.sh +++ b/ci_scripts/lint-ubuntu.sh @@ -6,4 +6,7 @@ source env.sh cargo install taplo-cli --locked cargo fmt -- --check -taplo fmt --check \ No newline at end of file +taplo fmt --check + +export RISC0_SKIP_BUILD=1 +cargo clippy --workspace --all-targets -- -D warnings \ No newline at end of file From cdd1bdbfbdb6531d6ee18a33c1fb856fda70194f Mon Sep 17 00:00:00 2001 From: Oleksandr Pravdyvyi Date: Wed, 18 Jun 2025 13:56:09 +0300 Subject: [PATCH 02/36] fix: lints fix --- accounts/src/key_management/mod.rs | 12 ++-- common/src/rpc_primitives/message.rs | 2 +- common/src/transaction.rs | 6 +- node_core/src/chain_storage/accounts_store.rs | 8 +-- node_core/src/chain_storage/block_store.rs | 6 +- node_core/src/chain_storage/mod.rs | 11 ++-- node_core/src/chain_storage/public_context.rs | 13 ++-- node_core/src/lib.rs | 60 +++++++------------ node_core/src/pre_start.rs | 12 ++-- node_rpc/src/process.rs | 10 ++-- sc_core/src/proofs_circuits.rs | 15 ++--- sc_core/src/transaction_payloads_tools.rs | 8 +-- sequencer_core/src/lib.rs | 6 +- storage/src/lib.rs | 10 ++-- storage/src/sc_db_utils.rs | 43 +++++++------ utxo/src/utxo_core.rs | 2 +- zkvm/src/lib.rs | 12 ++-- 17 files changed, 105 insertions(+), 131 deletions(-) diff --git a/accounts/src/key_management/mod.rs b/accounts/src/key_management/mod.rs index 69b8ce0..5862967 100644 --- a/accounts/src/key_management/mod.rs +++ b/accounts/src/key_management/mod.rs @@ -136,7 +136,7 @@ mod tests { // Generate a random ephemeral public key sender let scalar = Scalar::random(&mut OsRng); - let ephemeral_public_key_sender = (ProjectivePoint::generator() * scalar).to_affine(); + let ephemeral_public_key_sender = (ProjectivePoint::GENERATOR * scalar).to_affine(); // Calculate shared secret let shared_secret = @@ -170,7 +170,7 @@ mod tests { .decrypt_data( ephemeral_public_key_sender, CipherText::from(ciphertext), - nonce.clone(), + *nonce, ) .unwrap(); @@ -190,7 +190,7 @@ mod tests { assert!(!Into::::into( address_key_holder.viewing_public_key.is_identity() )); - assert!(address_key_holder.address.as_slice().len() > 0); // Assume TreeHashType has non-zero length for a valid address + assert!(!address_key_holder.address.as_slice().is_empty()); // Assume TreeHashType has non-zero length for a valid address } #[test] @@ -232,7 +232,7 @@ mod tests { .decrypt_data( ephemeral_public_key_sender, CipherText::from(ciphertext.clone()), - incorrect_nonce.clone(), + *incorrect_nonce, ) .unwrap(); @@ -268,7 +268,7 @@ mod tests { .decrypt_data( ephemeral_public_key_sender, CipherText::from(corrupted_ciphertext), - nonce.clone(), + *nonce, ) .unwrap(); @@ -301,7 +301,7 @@ mod tests { .decrypt_data( ephemeral_public_key_sender, CipherText::from(ciphertext), - nonce.clone(), + *nonce, ) .unwrap(); diff --git a/common/src/rpc_primitives/message.rs b/common/src/rpc_primitives/message.rs index 9378b60..c6bdc58 100644 --- a/common/src/rpc_primitives/message.rs +++ b/common/src/rpc_primitives/message.rs @@ -447,7 +447,7 @@ mod tests { /// A helper for the `broken` test. /// /// Check that the given JSON string parses, but is not recognized as a valid RPC message. - + /// /// Test things that are almost but not entirely JSONRPC are rejected /// /// The reject is done by returning it as Unmatched. diff --git a/common/src/transaction.rs b/common/src/transaction.rs index 1a95fe3..efd54f3 100644 --- a/common/src/transaction.rs +++ b/common/src/transaction.rs @@ -237,21 +237,21 @@ impl Transaction { "Transaction utxo_commitments_spent_hashes is {:?}", self.utxo_commitments_spent_hashes .iter() - .map(|val| hex::encode(val.clone())) + .map(|val| hex::encode(*val)) .collect::>() ); info!( "Transaction utxo_commitments_created_hashes is {:?}", self.utxo_commitments_created_hashes .iter() - .map(|val| hex::encode(val.clone())) + .map(|val| hex::encode(*val)) .collect::>() ); info!( "Transaction nullifier_created_hashes is {:?}", self.nullifier_created_hashes .iter() - .map(|val| hex::encode(val.clone())) + .map(|val| hex::encode(*val)) .collect::>() ); info!( diff --git a/node_core/src/chain_storage/accounts_store.rs b/node_core/src/chain_storage/accounts_store.rs index 6cdb100..1bd6dfc 100644 --- a/node_core/src/chain_storage/accounts_store.rs +++ b/node_core/src/chain_storage/accounts_store.rs @@ -54,7 +54,7 @@ mod tests { let mut store = NodeAccountsStore::new(); let account = create_sample_account(100); - let account_addr = account.address.clone(); + let account_addr = account.address; store.register_account(account); @@ -68,7 +68,7 @@ mod tests { let mut store = NodeAccountsStore::new(); let account = create_sample_account(100); - let account_addr = account.address.clone(); + let account_addr = account.address; store.register_account(account); assert_eq!(store.accounts.len(), 1); @@ -94,8 +94,8 @@ mod tests { let account1 = create_sample_account(100); let account2 = create_sample_account(200); - let address_1 = account1.address.clone(); - let address_2 = account2.address.clone(); + let address_1 = account1.address; + let address_2 = account2.address; store.register_account(account1); store.register_account(account2); diff --git a/node_core/src/chain_storage/block_store.rs b/node_core/src/chain_storage/block_store.rs index 677f426..ba97c3c 100644 --- a/node_core/src/chain_storage/block_store.rs +++ b/node_core/src/chain_storage/block_store.rs @@ -145,8 +145,8 @@ mod tests { fn create_sample_block(block_id: u64, prev_block_id: u64) -> Block { Block { - block_id: block_id, - prev_block_id: prev_block_id, + block_id, + prev_block_id, prev_block_hash: [0; 32], hash: [1; 32], transactions: vec![], @@ -211,7 +211,7 @@ mod tests { // The genesis block should be available on reload let result = node_store.get_block_at_id(0); - assert!(!result.is_err()); + assert!(result.is_ok()); } #[test] diff --git a/node_core/src/chain_storage/mod.rs b/node_core/src/chain_storage/mod.rs index f6b1343..2467a6b 100644 --- a/node_core/src/chain_storage/mod.rs +++ b/node_core/src/chain_storage/mod.rs @@ -80,7 +80,7 @@ impl NodeChainStore { Ok(( Self { - acc_map: From::from(acc_map), + acc_map, block_store, nullifier_store, utxo_commitments_store, @@ -324,8 +324,8 @@ mod tests { fn create_sample_block(block_id: u64, prev_block_id: u64) -> Block { Block { - block_id: block_id, - prev_block_id: prev_block_id, + block_id, + prev_block_id, prev_block_hash: [0; 32], hash: [1; 32], transactions: vec![], @@ -434,9 +434,6 @@ mod tests { assert_eq!(block_id, 1); assert_eq!(recovered_store.acc_map.len(), 1); - assert_eq!( - recovered_store.utxo_commitments_store.get_root().is_some(), - true - ); + assert!(recovered_store.utxo_commitments_store.get_root().is_some()); } } diff --git a/node_core/src/chain_storage/public_context.rs b/node_core/src/chain_storage/public_context.rs index 438fa50..87ae86e 100644 --- a/node_core/src/chain_storage/public_context.rs +++ b/node_core/src/chain_storage/public_context.rs @@ -71,16 +71,11 @@ impl PublicSCContext { //`ToDo` Replace with `next_chunk` usage, when feature stabilizes in Rust for i in 0..=(ser_data.len() / 8) { - let next_chunk: Vec; - - if (i + 1) * 8 < ser_data.len() { - next_chunk = ser_data[(i * 8)..((i + 1) * 8)].iter().cloned().collect(); + let next_chunk: Vec = if (i + 1) * 8 < ser_data.len() { + ser_data[(i * 8)..((i + 1) * 8)].to_vec() } else { - next_chunk = ser_data[(i * 8)..(ser_data.len())] - .iter() - .cloned() - .collect(); - } + ser_data[(i * 8)..(ser_data.len())].to_vec() + }; u64_list.push(PublicSCContext::produce_u64_from_fit_vec(next_chunk)); } diff --git a/node_core/src/lib.rs b/node_core/src/lib.rs index 49f1285..09c6299 100644 --- a/node_core/src/lib.rs +++ b/node_core/src/lib.rs @@ -204,19 +204,18 @@ impl NodeCore { serde_json::to_vec(&ephm_key_holder.generate_ephemeral_public_key()).unwrap(); let encoded_data = Account::encrypt_data( - &ephm_key_holder, + ephm_key_holder, account.key_holder.viewing_public_key, &serde_json::to_vec(&utxo).unwrap(), ); let tag = account.make_tag(); - let comm = generate_commitments(&vec![utxo]); + let comm = generate_commitments(&[utxo]); let mint_utxo_addr_bytes: Vec = zkvm::test_methods::MINT_UTXO_ID .iter() - .map(|num| num.to_le_bytes()) - .flatten() + .flat_map(|num| num.to_le_bytes()) .collect(); let sc_addr = hex::encode(mint_utxo_addr_bytes); @@ -297,7 +296,7 @@ impl NodeCore { .map(|utxo| { ( Account::encrypt_data( - &ephm_key_holder, + ephm_key_holder, account.key_holder.viewing_public_key, &serde_json::to_vec(&utxo).unwrap(), ), @@ -312,8 +311,7 @@ impl NodeCore { let mint_multiple_utxo_addr_bytes: Vec = zkvm::test_methods::MINT_UTXO_MULTIPLE_ASSETS_ID .iter() - .map(|num| num.to_le_bytes()) - .flatten() + .flat_map(|num| num.to_le_bytes()) .collect(); let sc_addr = hex::encode(mint_multiple_utxo_addr_bytes); @@ -386,14 +384,13 @@ impl NodeCore { .key_holder .utxo_secret_key_holder .nullifier_secret_key - .to_bytes() - .to_vec(), + .to_bytes(), ); let (resulting_utxos, receipt) = prove_send_utxo(utxo, receivers)?; let utxo_hashes = resulting_utxos .iter() - .map(|(utxo, addr)| (addr.clone(), utxo.hash)) + .map(|(utxo, addr)| (*addr, utxo.hash)) .collect(); let utxos: Vec = resulting_utxos @@ -413,7 +410,7 @@ impl NodeCore { let accout_enc = acc_map_read_guard.acc_map.get(&utxo_enc.owner).unwrap(); let (ciphertext, nonce) = Account::encrypt_data( - &ephm_key_holder, + ephm_key_holder, accout_enc.key_holder.viewing_public_key, &serde_json::to_vec(&utxo_enc).unwrap(), ); @@ -428,8 +425,7 @@ impl NodeCore { let send_utxo_addr_bytes: Vec = zkvm::test_methods::SEND_UTXO_ID .iter() - .map(|num| num.to_le_bytes()) - .flatten() + .flat_map(|num| num.to_le_bytes()) .collect(); let sc_addr = hex::encode(send_utxo_addr_bytes); @@ -535,7 +531,7 @@ impl NodeCore { let accout_enc = acc_map_read_guard.acc_map.get(&utxo_enc.owner).unwrap(); let (ciphertext, nonce) = Account::encrypt_data( - &ephm_key_holder, + ephm_key_holder, accout_enc.key_holder.viewing_public_key, &serde_json::to_vec(&utxo_enc).unwrap(), ); @@ -552,7 +548,7 @@ impl NodeCore { let accout_enc = acc_map_read_guard.acc_map.get(&utxo_enc.owner).unwrap(); let (ciphertext, nonce) = Account::encrypt_data( - &ephm_key_holder, + ephm_key_holder, accout_enc.key_holder.viewing_public_key, &serde_json::to_vec(&utxo_enc).unwrap(), ); @@ -573,8 +569,7 @@ impl NodeCore { let send_multiple_utxo_addr_bytes: Vec = zkvm::test_methods::SEND_UTXO_MULTIPLE_ASSETS_ID .iter() - .map(|num| num.to_le_bytes()) - .flatten() + .flat_map(|num| num.to_le_bytes()) .collect(); let sc_addr = hex::encode(send_multiple_utxo_addr_bytes); @@ -654,14 +649,13 @@ impl NodeCore { .key_holder .utxo_secret_key_holder .nullifier_secret_key - .to_bytes() - .to_vec(), + .to_bytes(), ); let (resulting_utxos, receipt) = prove_send_utxo_shielded(acc, balance as u128, receivers)?; let utxo_hashes = resulting_utxos .iter() - .map(|(utxo, addr)| (addr.clone(), utxo.hash)) + .map(|(utxo, addr)| (*addr, utxo.hash)) .collect(); let utxos: Vec = resulting_utxos @@ -681,7 +675,7 @@ impl NodeCore { let accout_enc = acc_map_read_guard.acc_map.get(&utxo_enc.owner).unwrap(); let (ciphertext, nonce) = Account::encrypt_data( - &ephm_key_holder, + ephm_key_holder, accout_enc.key_holder.viewing_public_key, &serde_json::to_vec(&utxo_enc).unwrap(), ); @@ -696,8 +690,7 @@ impl NodeCore { let mint_utxo_addr_bytes: Vec = zkvm::test_methods::SEND_UTXO_ID .iter() - .map(|num| num.to_le_bytes()) - .flatten() + .flat_map(|num| num.to_le_bytes()) .collect(); let sc_addr = hex::encode(mint_utxo_addr_bytes); @@ -782,16 +775,14 @@ impl NodeCore { .key_holder .utxo_secret_key_holder .nullifier_secret_key - .to_bytes() - .to_vec(), + .to_bytes(), ); let (resulting_balances, receipt) = prove_send_utxo_deshielded(utxo, receivers)?; let send_utxo_addr_bytes: Vec = zkvm::test_methods::SEND_UTXO_ID .iter() - .map(|num| num.to_le_bytes()) - .flatten() + .flat_map(|num| num.to_le_bytes()) .collect(); let sc_addr = hex::encode(send_utxo_addr_bytes); @@ -1372,14 +1363,13 @@ impl NodeCore { .key_holder .utxo_secret_key_holder .nullifier_secret_key - .to_bytes() - .to_vec(), + .to_bytes(), ); let (resulting_utxos, receipt) = prove_send_utxo(utxo, receivers)?; let utxo_hashes = resulting_utxos .iter() - .map(|(utxo, addr)| (addr.clone(), utxo.hash)) + .map(|(utxo, addr)| (*addr, utxo.hash)) .collect(); let utxos: Vec = resulting_utxos @@ -1399,7 +1389,7 @@ impl NodeCore { let accout_enc = acc_map_read_guard.acc_map.get(&utxo_enc.owner).unwrap(); let (ciphertext, nonce) = Account::encrypt_data( - &ephm_key_holder, + ephm_key_holder, accout_enc.key_holder.viewing_public_key, &serde_json::to_vec(&utxo_enc).unwrap(), ); @@ -1428,8 +1418,7 @@ impl NodeCore { let send_utxo_addr_bytes: Vec = zkvm::test_methods::SEND_UTXO_ID .iter() - .map(|num| num.to_le_bytes()) - .flatten() + .flat_map(|num| num.to_le_bytes()) .collect(); let sc_addr = hex::encode(send_utxo_addr_bytes); @@ -1528,10 +1517,7 @@ impl NodeCore { .send_split_tx( utxo.clone(), comm_gen_hash, - addrs_receivers - .clone() - .map(|addr| (utxo.amount / 3, addr)) - .to_vec(), + addrs_receivers.map(|addr| (utxo.amount / 3, addr)).to_vec(), visibility_list, ) .await?; diff --git a/node_core/src/pre_start.rs b/node_core/src/pre_start.rs index fe21e2b..e79dafc 100644 --- a/node_core/src/pre_start.rs +++ b/node_core/src/pre_start.rs @@ -22,8 +22,7 @@ pub async fn setup_empty_sc_states(node: &NodeChainStore) -> Result<()> { let mint_utxo_addr_bytes: Vec = zkvm::test_methods::MINT_UTXO_ID .iter() - .map(|num| num.to_le_bytes()) - .flatten() + .flat_map(|num| num.to_le_bytes()) .collect(); let mint_utxo_addr = hex::encode(mint_utxo_addr_bytes); node.block_store @@ -32,8 +31,7 @@ pub async fn setup_empty_sc_states(node: &NodeChainStore) -> Result<()> { let single_utxo_transfer_addr_bytes: Vec = zkvm::test_methods::SEND_UTXO_ID .iter() - .map(|num| num.to_le_bytes()) - .flatten() + .flat_map(|num| num.to_le_bytes()) .collect(); let single_utxo_transfer_addr = hex::encode(single_utxo_transfer_addr_bytes); node.block_store.put_sc_sc_state( @@ -46,8 +44,7 @@ pub async fn setup_empty_sc_states(node: &NodeChainStore) -> Result<()> { let mint_utxo_multiple_assets_addr_bytes: Vec = zkvm::test_methods::MINT_UTXO_MULTIPLE_ASSETS_ID .iter() - .map(|num| num.to_le_bytes()) - .flatten() + .flat_map(|num| num.to_le_bytes()) .collect(); let mint_utxo_multiple_assets_addr = hex::encode(mint_utxo_multiple_assets_addr_bytes); node.block_store.put_sc_sc_state( @@ -60,8 +57,7 @@ pub async fn setup_empty_sc_states(node: &NodeChainStore) -> Result<()> { let multiple_assets_utxo_transfer_addr_bytes: Vec = zkvm::test_methods::SEND_UTXO_MULTIPLE_ASSETS_ID .iter() - .map(|num| num.to_le_bytes()) - .flatten() + .flat_map(|num| num.to_le_bytes()) .collect(); let multiple_assets_utxo_transfer_addr = hex::encode(multiple_assets_utxo_transfer_addr_bytes); node.block_store.put_sc_sc_state( diff --git a/node_rpc/src/process.rs b/node_rpc/src/process.rs index f4937e9..bbfb281 100644 --- a/node_rpc/src/process.rs +++ b/node_rpc/src/process.rs @@ -330,17 +330,17 @@ impl JsonHandler { utxo_commitments_created_hashes: tx .utxo_commitments_created_hashes .iter() - .map(|val| hex::encode(val.clone())) + .map(hex::encode) .collect::>(), utxo_commitments_spent_hashes: tx .utxo_commitments_spent_hashes .iter() - .map(|val| hex::encode(val.clone())) + .map(hex::encode) .collect::>(), utxo_nullifiers_created_hashes: tx .nullifier_created_hashes .iter() - .map(|val| hex::encode(val.clone())) + .map(hex::encode) .collect::>(), encoded_data: tx .encoded_data @@ -529,7 +529,7 @@ impl JsonHandler { utxo_result: UTXOShortEssentialStruct { hash: hex::encode(new_utxo_rec.hash), asset: new_utxo_rec.asset.clone(), - commitment_hash: hex::encode(generate_commitments_helper(&vec![new_utxo_rec])[0]), + commitment_hash: hex::encode(generate_commitments_helper(&[new_utxo_rec])[0]), }, }; @@ -582,7 +582,7 @@ impl JsonHandler { utxo_result: UTXOShortEssentialStruct { hash: hex::encode(new_utxo_rec.hash), asset: new_utxo_rec.asset.clone(), - commitment_hash: hex::encode(generate_commitments_helper(&vec![new_utxo_rec])[0]), + commitment_hash: hex::encode(generate_commitments_helper(&[new_utxo_rec])[0]), }, }; diff --git a/sc_core/src/proofs_circuits.rs b/sc_core/src/proofs_circuits.rs index cbebe3e..caaa402 100644 --- a/sc_core/src/proofs_circuits.rs +++ b/sc_core/src/proofs_circuits.rs @@ -38,7 +38,7 @@ pub fn generate_commitments(input_utxos: &[UTXO]) -> Vec> { // takes the in_commitments[i] as a leaf, the root hash root_commitment and the path in_commitments_proofs[i][], // returns True if the in_commitments[i] is in the tree with root hash root_commitment otherwise returns False, as membership proof. pub fn validate_in_commitments_proof( - _in_commitment: &Vec, + _in_commitment: &[u8], _root_commitment: Vec, _in_commitments_proof: &[Vec], ) -> bool { @@ -65,11 +65,11 @@ fn private_kernel( nullifier_secret_key: Scalar, ) -> (Vec, Vec>) { let nullifiers: Vec<_> = input_utxos - .into_iter() - .map(|utxo| generate_nullifiers(&utxo, &nullifier_secret_key.to_bytes())) + .iter() + .map(|utxo| generate_nullifiers(utxo, &nullifier_secret_key.to_bytes())) .collect(); - let in_commitments = generate_commitments(&input_utxos); + let in_commitments = generate_commitments(input_utxos); for in_commitment in in_commitments { validate_in_commitments_proof( @@ -183,11 +183,11 @@ fn de_kernel( check_balances(public_info as u128, input_utxos); let nullifiers: Vec<_> = input_utxos - .into_iter() - .map(|utxo| generate_nullifiers(&utxo, &nullifier_secret_key.to_bytes())) + .iter() + .map(|utxo| generate_nullifiers(utxo, &nullifier_secret_key.to_bytes())) .collect(); - let in_commitments = generate_commitments(&input_utxos); + let in_commitments = generate_commitments(input_utxos); for in_commitment in in_commitments { validate_in_commitments_proof( @@ -235,6 +235,7 @@ pub fn generate_nullifiers_se(pedersen_commitment: &PedersenCommitment, nsk: &[u } #[allow(unused)] +#[allow(clippy::too_many_arguments)] fn se_kernel( root_commitment: &[u8], root_nullifier: [u8; 32], diff --git a/sc_core/src/transaction_payloads_tools.rs b/sc_core/src/transaction_payloads_tools.rs index 24ad8f2..9af9bfa 100644 --- a/sc_core/src/transaction_payloads_tools.rs +++ b/sc_core/src/transaction_payloads_tools.rs @@ -43,7 +43,7 @@ pub fn encode_utxos_to_receivers( let ephm_key_holder = &receiver.produce_ephemeral_key_holder(); let encoded_data = Account::encrypt_data( - &ephm_key_holder, + ephm_key_holder, receiver.key_holder.viewing_public_key, &serde_json::to_vec(&utxo).unwrap(), ); @@ -66,8 +66,7 @@ pub fn generate_nullifiers_spent_utxos(utxos_spent: Vec<(UTXO, &Account)>) -> Ve .key_holder .utxo_secret_key_holder .nullifier_secret_key - .to_bytes() - .to_vec(), + .to_bytes(), ); all_nullifiers.push(nullifier); @@ -91,8 +90,7 @@ pub fn generate_secret_random_commitment( .key_holder .utxo_secret_key_holder .viewing_secret_key - .to_bytes() - .to_vec(), + .to_bytes(), )?, generator_blinding_factor: Tweak::new(&mut thread_rng()), }; diff --git a/sequencer_core/src/lib.rs b/sequencer_core/src/lib.rs index 7a083f1..16b6ae7 100644 --- a/sequencer_core/src/lib.rs +++ b/sequencer_core/src/lib.rs @@ -306,12 +306,14 @@ mod tests { } } - fn common_setup(mut sequencer: &mut SequencerCore) { + fn common_setup(sequencer: &mut SequencerCore) { let tx = create_dummy_transaction([12; 32], vec![[9; 32]], vec![[7; 32]], vec![[8; 32]]); let tx_mempool = TransactionMempool { tx }; sequencer.mempool.push_item(tx_mempool); - sequencer.produce_new_block_with_mempool_transactions(); + sequencer + .produce_new_block_with_mempool_transactions() + .unwrap(); } #[test] diff --git a/storage/src/lib.rs b/storage/src/lib.rs index 7616842..ac54406 100644 --- a/storage/src/lib.rs +++ b/storage/src/lib.rs @@ -316,7 +316,7 @@ impl RocksDBIO { let cf_sc = self.sc_column(); let sc_addr_loc = format!("{sc_addr:?}{SC_LEN_SUFFIX}"); - let sc_len_addr = sc_addr_loc.as_str().as_bytes(); + let sc_len_addr = sc_addr_loc.as_bytes(); self.db .put_cf(&cf_sc, sc_len_addr, length.to_be_bytes()) @@ -360,7 +360,7 @@ impl RocksDBIO { let cf_sc = self.sc_column(); let sc_addr_loc = format!("{sc_addr:?}{SC_LEN_SUFFIX}"); - let sc_len_addr = sc_addr_loc.as_str().as_bytes(); + let sc_len_addr = sc_addr_loc.as_bytes(); let sc_len = self .db @@ -379,11 +379,11 @@ impl RocksDBIO { ///Get full sc state from DB pub fn get_sc_sc_state(&self, sc_addr: &str) -> DbResult> { let cf_sc = self.sc_column(); - let sc_len = self.get_sc_sc_state_len(&sc_addr)?; + let sc_len = self.get_sc_sc_state_len(sc_addr)?; let mut data_blob_list = vec![]; for id in 0..sc_len { - let blob_addr = produce_address_for_data_blob_at_id(&sc_addr, id); + let blob_addr = produce_address_for_data_blob_at_id(sc_addr, id); let blob = self .db @@ -541,7 +541,7 @@ impl RocksDBIO { ///Creates address for sc data blob at corresponding id fn produce_address_for_data_blob_at_id(sc_addr: &str, id: usize) -> Vec { - let mut prefix_bytes: Vec = sc_addr.as_bytes().iter().cloned().collect(); + let mut prefix_bytes: Vec = sc_addr.as_bytes().to_vec(); let id_bytes = id.to_be_bytes(); diff --git a/storage/src/sc_db_utils.rs b/storage/src/sc_db_utils.rs index b059de7..577ceb6 100644 --- a/storage/src/sc_db_utils.rs +++ b/storage/src/sc_db_utils.rs @@ -1,3 +1,5 @@ +use std::cmp::Ordering; + use serde::{de::Error, Deserialize, Serialize}; use crate::SC_DATA_BLOB_SIZE; @@ -49,6 +51,7 @@ impl DataBlob { } } +#[allow(clippy::large_enum_variant)] #[derive(Debug, Clone, Copy, Serialize, Deserialize)] pub enum DataBlobChangeVariant { Created { @@ -95,19 +98,11 @@ pub fn produce_blob_list_from_sc_public_state( //`ToDo` Replace with `next_chunk` usage, when feature stabilizes in Rust for i in 0..=(ser_data.len() / SC_DATA_BLOB_SIZE) { - let next_chunk: Vec; - - if (i + 1) * SC_DATA_BLOB_SIZE < ser_data.len() { - next_chunk = ser_data[(i * SC_DATA_BLOB_SIZE)..((i + 1) * SC_DATA_BLOB_SIZE)] - .iter() - .cloned() - .collect(); + let next_chunk: Vec = if (i + 1) * SC_DATA_BLOB_SIZE < ser_data.len() { + ser_data[(i * SC_DATA_BLOB_SIZE)..((i + 1) * SC_DATA_BLOB_SIZE)].to_vec() } else { - next_chunk = ser_data[(i * SC_DATA_BLOB_SIZE)..(ser_data.len())] - .iter() - .cloned() - .collect(); - } + ser_data[(i * SC_DATA_BLOB_SIZE)..(ser_data.len())].to_vec() + }; blob_list.push(produce_blob_from_fit_vec(next_chunk)); } @@ -126,17 +121,21 @@ pub fn compare_blob_lists( let old_len = blob_list_old.len(); let new_len = blob_list_new.len(); - if old_len > new_len { - for id in new_len..old_len { - changed_ids.push(DataBlobChangeVariant::Deleted { id }); + match old_len.cmp(&new_len) { + Ordering::Greater => { + for id in new_len..old_len { + changed_ids.push(DataBlobChangeVariant::Deleted { id }); + } } - } else if new_len > old_len { - for id in old_len..new_len { - changed_ids.push(DataBlobChangeVariant::Created { - id, - blob: blob_list_new[id], - }); + Ordering::Less => { + for (id, blob_item) in blob_list_new.iter().enumerate().take(new_len).skip(old_len) { + changed_ids.push(DataBlobChangeVariant::Created { + id, + blob: *blob_item, + }); + } } + Ordering::Equal => {} } loop { @@ -172,7 +171,7 @@ mod tests { #[test] fn test_produce_blob_from_fit_vec() { - let data = (0..0 + 255).collect(); + let data = (0..255).collect(); let blob = produce_blob_from_fit_vec(data); assert_eq!(blob.0[..4], [0, 1, 2, 3]); } diff --git a/utxo/src/utxo_core.rs b/utxo/src/utxo_core.rs index 4e40ce3..07a8830 100644 --- a/utxo/src/utxo_core.rs +++ b/utxo/src/utxo_core.rs @@ -58,7 +58,7 @@ impl UTXO { } pub fn create_utxo_from_payload(payload_with_asset: UTXOPayload) -> Self { let mut hasher = sha2::Sha256::new(); - hasher.update(&payload_with_asset.to_bytes()); + hasher.update(payload_with_asset.to_bytes()); let hash = ::from(hasher.finalize_fixed()); Self { diff --git a/zkvm/src/lib.rs b/zkvm/src/lib.rs index 7ab1225..cf3620b 100644 --- a/zkvm/src/lib.rs +++ b/zkvm/src/lib.rs @@ -160,12 +160,12 @@ pub fn prove_send_utxo_multiple_assets_one_receiver( digest .0 .into_iter() - .map(|payload| UTXO::create_utxo_from_payload(payload)) + .map(UTXO::create_utxo_from_payload) .collect(), digest .1 .into_iter() - .map(|payload| UTXO::create_utxo_from_payload(payload)) + .map(UTXO::create_utxo_from_payload) .collect(), receipt, )) @@ -432,7 +432,7 @@ mod tests { let (digest, receipt) = prove(vec![message, message_2], SUMMATION_ELF).unwrap(); - verify(receipt, SUMMATION_ID); + let _ = verify(receipt, SUMMATION_ID); assert_eq!(digest, message + message_2); } @@ -443,7 +443,7 @@ mod tests { let (digest, receipt) = prove(vec![message, message_2], SUMMATION_ELF).unwrap(); - verify(receipt, SUMMATION_ID); + let _ = verify(receipt, SUMMATION_ID); assert_eq!(digest, message + message_2); } @@ -454,7 +454,7 @@ mod tests { let (digest, receipt) = prove(vec![message, message_2], MULTIPLICATION_ELF).unwrap(); - verify(receipt, MULTIPLICATION_ID); + let _ = verify(receipt, MULTIPLICATION_ID); assert_eq!(digest, message * message_2); } @@ -465,7 +465,7 @@ mod tests { let (digest, receipt) = prove(vec![message, message_2], MULTIPLICATION_ELF).unwrap(); - verify(receipt, MULTIPLICATION_ID); + let _ = verify(receipt, MULTIPLICATION_ID); assert_eq!(digest, message * message_2); } From f4912661059f20a5f47a6a93dd57559086228912 Mon Sep 17 00:00:00 2001 From: Oleksandr Pravdyvyi Date: Wed, 18 Jun 2025 14:32:30 +0300 Subject: [PATCH 03/36] fix: lint fix 2 --- common/src/transaction.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/transaction.rs b/common/src/transaction.rs index efd54f3..bc25abf 100644 --- a/common/src/transaction.rs +++ b/common/src/transaction.rs @@ -209,7 +209,7 @@ impl ActionData { .into_iter() .map(|owned_utxo| owned_utxo.into()) .collect(); - format!("Published utxos {:?}", pub_own_utxo) + format!("Published utxos {pub_own_utxo:?}") } } } From f9eee73ef4a85c89513d636900f2f3d7a8e6820c Mon Sep 17 00:00:00 2001 From: Oleksandr Pravdyvyi Date: Wed, 18 Jun 2025 14:52:02 +0300 Subject: [PATCH 04/36] fix: lint fix 3 --- zkvm/src/lib.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/zkvm/src/lib.rs b/zkvm/src/lib.rs index cf3620b..2ad2f14 100644 --- a/zkvm/src/lib.rs +++ b/zkvm/src/lib.rs @@ -9,6 +9,7 @@ pub mod gas_calculator; pub use test_methods; +#[allow(clippy::result_large_err)] pub fn gas_limits_check( input_buffer: INP, elf: &[u8], @@ -31,6 +32,7 @@ pub fn gas_limits_check( Ok(()) } +#[allow(clippy::result_large_err)] pub fn prove_mint_utxo( amount_to_mint: u128, owner: AccountAddress, @@ -66,6 +68,7 @@ pub fn prove_mint_utxo( Ok((UTXO::create_utxo_from_payload(digest), receipt)) } +#[allow(clippy::result_large_err)] pub fn prove_send_utxo( spent_utxo: UTXO, owners_parts: Vec<(u128, AccountAddress)>, @@ -118,6 +121,7 @@ pub fn prove_send_utxo( )) } +#[allow(clippy::result_large_err)] pub fn prove_send_utxo_multiple_assets_one_receiver( spent_utxos: Vec, number_to_send: usize, @@ -171,6 +175,7 @@ pub fn prove_send_utxo_multiple_assets_one_receiver( )) } +#[allow(clippy::result_large_err)] pub fn prove_send_utxo_shielded( owner: AccountAddress, amount: u128, @@ -226,6 +231,7 @@ pub fn prove_send_utxo_shielded( )) } +#[allow(clippy::result_large_err)] pub fn prove_send_utxo_deshielded( spent_utxo: UTXO, owners_parts: Vec<(u128, AccountAddress)>, @@ -278,6 +284,7 @@ pub fn prove_send_utxo_deshielded( )) } +#[allow(clippy::result_large_err)] pub fn prove_mint_utxo_multiple_assets( amount_to_mint: u128, number_of_assets: usize, From 48a43eb268e478525fa939596ec1774a1604773d Mon Sep 17 00:00:00 2001 From: Oleksandr Pravdyvyi Date: Wed, 18 Jun 2025 15:58:15 +0300 Subject: [PATCH 05/36] fix: lint fix 4 --- node_core/src/chain_storage/mod.rs | 3 +-- sequencer_core/src/lib.rs | 29 +++++++++++++---------------- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/node_core/src/chain_storage/mod.rs b/node_core/src/chain_storage/mod.rs index 2467a6b..aaeef44 100644 --- a/node_core/src/chain_storage/mod.rs +++ b/node_core/src/chain_storage/mod.rs @@ -242,8 +242,7 @@ impl NodeChainStore { ); info!( - "Snapshot executed at {:?} with results {snapshot_trace:#?}", - block_id + "Snapshot executed at {block_id:?} with results {snapshot_trace:#?}" ); } } diff --git a/sequencer_core/src/lib.rs b/sequencer_core/src/lib.rs index 16b6ae7..301c74c 100644 --- a/sequencer_core/src/lib.rs +++ b/sequencer_core/src/lib.rs @@ -131,23 +131,20 @@ impl SequencerCore { //Tree checks let tx_tree_check = self.store.pub_tx_store.get_tx(*hash).is_some(); - let nullifier_tree_check = nullifier_created_hashes - .iter() - .map(|nullifier_hash| { - self.store.nullifier_store.contains(&UTXONullifier { - utxo_hash: *nullifier_hash, - }) + let nullifier_tree_check = nullifier_created_hashes.iter().any(|nullifier_hash| { + self.store.nullifier_store.contains(&UTXONullifier { + utxo_hash: *nullifier_hash, }) - .any(|check| check); - let utxo_commitments_check = utxo_commitments_created_hashes - .iter() - .map(|utxo_commitment_hash| { - self.store - .utxo_commitments_store - .get_tx(*utxo_commitment_hash) - .is_some() - }) - .any(|check| check); + }); + let utxo_commitments_check = + utxo_commitments_created_hashes + .iter() + .any(|utxo_commitment_hash| { + self.store + .utxo_commitments_store + .get_tx(*utxo_commitment_hash) + .is_some() + }); if tx_tree_check { return Err(TransactionMalformationErrorKind::TxHashAlreadyPresentInTree { tx: *hash }); From ac697c0bd88ab8f1bf281504d9f76ebc5eb40e38 Mon Sep 17 00:00:00 2001 From: Oleksandr Pravdyvyi Date: Wed, 18 Jun 2025 16:59:29 +0300 Subject: [PATCH 06/36] fix: lint fix 5 --- node_rpc/src/net_utils.rs | 2 +- sequencer_rpc/src/net_utils.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/node_rpc/src/net_utils.rs b/node_rpc/src/net_utils.rs index 6d68b26..215106c 100644 --- a/node_rpc/src/net_utils.rs +++ b/node_rpc/src/net_utils.rs @@ -53,7 +53,7 @@ pub fn new_http_server( polling_config, limits_config, } = config; - info!(target:"network", "Starting http server at {}", addr); + info!(target:"network", "Starting http server at {addr}"); let handler = web::Data::new(JsonHandler { polling_config, node_core_config: node_config, diff --git a/sequencer_rpc/src/net_utils.rs b/sequencer_rpc/src/net_utils.rs index 351d09b..b719a8c 100644 --- a/sequencer_rpc/src/net_utils.rs +++ b/sequencer_rpc/src/net_utils.rs @@ -53,7 +53,7 @@ pub fn new_http_server( polling_config, limits_config, } = config; - info!(target:NETWORK, "Starting http server at {}", addr); + info!(target:NETWORK, "Starting http server at {addr}"); let handler = web::Data::new(JsonHandler { polling_config, sequencer_state: seuquencer_core.clone(), From 3f9d671fb1f48d679a0c5c2d11d1ab1ecfa57024 Mon Sep 17 00:00:00 2001 From: Oleksandr Pravdyvyi Date: Wed, 18 Jun 2025 17:26:57 +0300 Subject: [PATCH 07/36] fix: lint fix probably latest --- sequencer_core/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sequencer_core/src/lib.rs b/sequencer_core/src/lib.rs index 301c74c..9b84982 100644 --- a/sequencer_core/src/lib.rs +++ b/sequencer_core/src/lib.rs @@ -263,7 +263,7 @@ mod tests { let mut rng = rand::thread_rng(); let random_u8: u8 = rng.gen(); - let path_str = format!("/tmp/sequencer_{:?}", random_u8); + let path_str = format!("/tmp/sequencer_{random_u8:?}"); SequencerConfig { home: PathBuf::from(path_str), From a174eb4b85c95a744c1bb72c30fa74174c0bb1b0 Mon Sep 17 00:00:00 2001 From: Sergio Chouhy Date: Thu, 10 Jul 2025 14:53:25 -0300 Subject: [PATCH 08/36] add un/verified signed transaction structs --- common/src/transaction.rs | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/common/src/transaction.rs b/common/src/transaction.rs index 3f2dcb2..9509a7c 100644 --- a/common/src/transaction.rs +++ b/common/src/transaction.rs @@ -1,5 +1,5 @@ use log::info; -use secp256k1_zkp::{PedersenCommitment, Tweak}; +use secp256k1_zkp::{PedersenCommitment, PublicKey, Scalar, Tweak}; use serde::{Deserialize, Serialize}; use sha2::{digest::FixedOutput, Digest}; @@ -57,6 +57,25 @@ pub struct Transaction { pub state_changes: (serde_json::Value, usize), } +#[derive(Serialize, Deserialize)] +struct TransactionSignature {} + +/// A transaction with a signature. +/// Meant to be sent through the network to the sequencer +#[derive(Serialize, Deserialize)] +pub struct UnverifiedSignedTransaction { + transaction: Transaction, + signature: TransactionSignature +} + +/// A transaction with a valid signature over its hash. +/// Can only be constructed from an `UnverifiedSignedTransaction` +/// if the signature is valid +pub struct VerifiedSignedTransaction { + transaction: Transaction, + signature: TransactionSignature +} + #[derive(Debug, Serialize, Deserialize)] pub struct MintMoneyPublicTx { pub acc: [u8; 32], @@ -150,6 +169,9 @@ impl ActionData { } } +type SignaturePrivateKey = Scalar; +type SignaturePublicKey = PublicKey; + impl Transaction { /// Computes and returns the SHA-256 hash of the JSON-serialized representation of `self`. pub fn hash(&self) -> TreeHashType { @@ -162,6 +184,13 @@ impl Transaction { TreeHashType::from(hasher.finalize_fixed()) } + pub fn sign(self, _private_key: SignaturePrivateKey) -> UnverifiedSignedTransaction { + let _hash = self.hash(); + // Implement actual signature over `hash` + let signature = TransactionSignature {}; + UnverifiedSignedTransaction { transaction: self, signature } + } + pub fn log(&self) { info!("Transaction hash is {:?}", hex::encode(self.hash())); info!("Transaction tx_kind is {:?}", self.tx_kind); @@ -214,6 +243,14 @@ impl Transaction { } } +impl UnverifiedSignedTransaction { + pub fn into_verified(self) -> VerifiedSignedTransaction { + let hash = self.transaction.hash(); + // Check signature over hash + todo!() + } +} + #[cfg(test)] mod tests { use secp256k1_zkp::{constants::SECRET_KEY_SIZE, Tweak}; From f02c97e622289312d615a26c4adb3ef4a0f125c5 Mon Sep 17 00:00:00 2001 From: Sergio Chouhy Date: Mon, 14 Jul 2025 08:45:38 -0300 Subject: [PATCH 09/36] rename structs. Implement serde for AuthenticatedTransaction --- common/src/block.rs | 6 +- common/src/merkle_tree_public/merkle_tree.rs | 4 +- .../src/merkle_tree_public/tree_leav_item.rs | 4 +- common/src/rpc_primitives/requests.rs | 4 +- common/src/transaction.rs | 67 ++++++++++++++----- node_core/src/chain_storage/block_store.rs | 4 +- node_core/src/chain_storage/mod.rs | 6 +- node_core/src/lib.rs | 32 ++++----- node_core/src/sequencer_client/json.rs | 4 +- node_core/src/sequencer_client/mod.rs | 4 +- sc_core/src/transaction_payloads_tools.rs | 6 +- sequencer_core/src/lib.rs | 14 ++-- sequencer_core/src/transaction_mempool.rs | 10 +-- 13 files changed, 99 insertions(+), 66 deletions(-) diff --git a/common/src/block.rs b/common/src/block.rs index 7757667..ae8765e 100644 --- a/common/src/block.rs +++ b/common/src/block.rs @@ -1,7 +1,7 @@ use rs_merkle::Hasher; use serde::{Deserialize, Serialize}; -use crate::{merkle_tree_public::hasher::OwnHasher, transaction::Transaction}; +use crate::{merkle_tree_public::hasher::OwnHasher, transaction::TransactionBody}; pub type BlockHash = [u8; 32]; pub type Data = Vec; @@ -13,7 +13,7 @@ pub struct Block { pub prev_block_id: BlockId, pub prev_block_hash: BlockHash, pub hash: BlockHash, - pub transactions: Vec, + pub transactions: Vec, pub data: Data, } @@ -22,7 +22,7 @@ pub struct HashableBlockData { pub block_id: BlockId, pub prev_block_id: BlockId, pub prev_block_hash: BlockHash, - pub transactions: Vec, + pub transactions: Vec, pub data: Data, } diff --git a/common/src/merkle_tree_public/merkle_tree.rs b/common/src/merkle_tree_public/merkle_tree.rs index 3540b06..d8229af 100644 --- a/common/src/merkle_tree_public/merkle_tree.rs +++ b/common/src/merkle_tree_public/merkle_tree.rs @@ -7,7 +7,7 @@ use serde::{ Deserialize, Deserializer, Serialize, }; -use crate::{transaction::Transaction, utxo_commitment::UTXOCommitment}; +use crate::{transaction::TransactionBody, utxo_commitment::UTXOCommitment}; use super::{hasher::OwnHasher, tree_leav_item::TreeLeavItem, TreeHashType}; @@ -81,7 +81,7 @@ impl<'de, Leav: TreeLeavItem + Clone + Deserialize<'de>> serde::Deserialize<'de> } } -pub type PublicTransactionMerkleTree = HashStorageMerkleTree; +pub type PublicTransactionMerkleTree = HashStorageMerkleTree; pub type UTXOCommitmentsMerkleTree = HashStorageMerkleTree; diff --git a/common/src/merkle_tree_public/tree_leav_item.rs b/common/src/merkle_tree_public/tree_leav_item.rs index 1fbbb1a..52bb8ef 100644 --- a/common/src/merkle_tree_public/tree_leav_item.rs +++ b/common/src/merkle_tree_public/tree_leav_item.rs @@ -1,4 +1,4 @@ -use crate::{transaction::Transaction, utxo_commitment::UTXOCommitment}; +use crate::{transaction::TransactionBody, utxo_commitment::UTXOCommitment}; use super::TreeHashType; @@ -6,7 +6,7 @@ pub trait TreeLeavItem { fn hash(&self) -> TreeHashType; } -impl TreeLeavItem for Transaction { +impl TreeLeavItem for TransactionBody { fn hash(&self) -> TreeHashType { self.hash() } diff --git a/common/src/rpc_primitives/requests.rs b/common/src/rpc_primitives/requests.rs index 6cad01d..7508ce9 100644 --- a/common/src/rpc_primitives/requests.rs +++ b/common/src/rpc_primitives/requests.rs @@ -1,6 +1,6 @@ use crate::block::Block; use crate::parse_request; -use crate::transaction::Transaction; +use crate::transaction::TransactionBody; use super::errors::RpcParseError; use super::parser::parse_params; @@ -20,7 +20,7 @@ pub struct RegisterAccountRequest { #[derive(Serialize, Deserialize, Debug)] pub struct SendTxRequest { - pub transaction: Transaction, + pub transaction: TransactionBody, ///UTXO Commitment Root, Pub Tx Root pub tx_roots: [[u8; 32]; 2], } diff --git a/common/src/transaction.rs b/common/src/transaction.rs index 9509a7c..fd0b4c3 100644 --- a/common/src/transaction.rs +++ b/common/src/transaction.rs @@ -25,7 +25,7 @@ pub enum TxKind { #[derive(Debug, Serialize, Deserialize, Clone)] ///General transaction object -pub struct Transaction { +pub struct TransactionBody { pub tx_kind: TxKind, ///Tx input data (public part) pub execution_input: Vec, @@ -58,22 +58,25 @@ pub struct Transaction { } #[derive(Serialize, Deserialize)] -struct TransactionSignature {} +struct TransactionSignature; + +#[derive(Serialize, Deserialize)] +struct TransactionHash; /// A transaction with a signature. /// Meant to be sent through the network to the sequencer #[derive(Serialize, Deserialize)] -pub struct UnverifiedSignedTransaction { - transaction: Transaction, - signature: TransactionSignature +pub struct SignedTransaction { + body: TransactionBody, + signature: TransactionSignature, } /// A transaction with a valid signature over its hash. /// Can only be constructed from an `UnverifiedSignedTransaction` /// if the signature is valid -pub struct VerifiedSignedTransaction { - transaction: Transaction, - signature: TransactionSignature +pub struct AuthenticatedTransaction { + hash: TransactionHash, + signed_tx: SignedTransaction } #[derive(Debug, Serialize, Deserialize)] @@ -172,7 +175,7 @@ impl ActionData { type SignaturePrivateKey = Scalar; type SignaturePublicKey = PublicKey; -impl Transaction { +impl TransactionBody { /// Computes and returns the SHA-256 hash of the JSON-serialized representation of `self`. pub fn hash(&self) -> TreeHashType { // TODO: Remove `unwrap` by implementing a `to_bytes` method @@ -184,11 +187,14 @@ impl Transaction { TreeHashType::from(hasher.finalize_fixed()) } - pub fn sign(self, _private_key: SignaturePrivateKey) -> UnverifiedSignedTransaction { + pub fn sign(self, _private_key: SignaturePrivateKey) -> SignedTransaction { let _hash = self.hash(); // Implement actual signature over `hash` let signature = TransactionSignature {}; - UnverifiedSignedTransaction { transaction: self, signature } + SignedTransaction { + body: self, + signature, + } } pub fn log(&self) { @@ -243,11 +249,38 @@ impl Transaction { } } -impl UnverifiedSignedTransaction { - pub fn into_verified(self) -> VerifiedSignedTransaction { - let hash = self.transaction.hash(); +impl SignedTransaction { + pub fn into_authenticated(self) -> AuthenticatedTransaction { + let hash = TransactionHash; // self.body.hash(); // Check signature over hash - todo!() + AuthenticatedTransaction { + hash, + signed_tx: self + } + } +} + +impl AuthenticatedTransaction { + pub fn as_signed(&self) -> &SignedTransaction { + &self.signed_tx + } +} + +impl Serialize for AuthenticatedTransaction { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + self.as_signed().serialize(serializer) + } +} + +impl<'de> Deserialize<'de> for AuthenticatedTransaction { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + SignedTransaction::deserialize(deserializer).map(|signed_tx| signed_tx.into_authenticated()) } } @@ -258,12 +291,12 @@ mod tests { use crate::{ merkle_tree_public::TreeHashType, - transaction::{Transaction, TxKind}, + transaction::{TransactionBody, TxKind}, }; #[test] fn test_transaction_hash_is_sha256_of_json_bytes() { - let tx = Transaction { + let tx = TransactionBody { tx_kind: TxKind::Public, execution_input: vec![1, 2, 3, 4], execution_output: vec![5, 6, 7, 8], diff --git a/node_core/src/chain_storage/block_store.rs b/node_core/src/chain_storage/block_store.rs index 677f426..ba5b24b 100644 --- a/node_core/src/chain_storage/block_store.rs +++ b/node_core/src/chain_storage/block_store.rs @@ -6,7 +6,7 @@ use anyhow::{anyhow, Result}; use common::block::Block; use common::merkle_tree_public::merkle_tree::HashStorageMerkleTree; use common::nullifier::UTXONullifier; -use common::transaction::Transaction; +use common::transaction::TransactionBody; use common::utxo_commitment::UTXOCommitment; use log::error; use storage::sc_db_utils::{DataBlob, DataBlobChangeVariant}; @@ -87,7 +87,7 @@ impl NodeBlockStore { )?) } - pub fn get_snapshot_transaction(&self) -> Result> { + pub fn get_snapshot_transaction(&self) -> Result> { Ok(serde_json::from_slice( &self.dbio.get_snapshot_transaction()?, )?) diff --git a/node_core/src/chain_storage/mod.rs b/node_core/src/chain_storage/mod.rs index 3f61393..c875bbd 100644 --- a/node_core/src/chain_storage/mod.rs +++ b/node_core/src/chain_storage/mod.rs @@ -278,7 +278,7 @@ mod tests { use accounts::account_core::Account; use common::block::{Block, Data}; use common::merkle_tree_public::TreeHashType; - use common::transaction::{Transaction, TxKind}; + use common::transaction::{TransactionBody, TxKind}; use secp256k1_zkp::Tweak; use std::path::PathBuf; use tempfile::tempdir; @@ -300,10 +300,10 @@ mod tests { nullifier_created_hashes: Vec<[u8; 32]>, utxo_commitments_spent_hashes: Vec<[u8; 32]>, utxo_commitments_created_hashes: Vec<[u8; 32]>, - ) -> Transaction { + ) -> TransactionBody { let mut rng = rand::thread_rng(); - Transaction { + TransactionBody { tx_kind: TxKind::Private, execution_input: vec![], execution_output: vec![], diff --git a/node_core/src/lib.rs b/node_core/src/lib.rs index 73775eb..fa49001 100644 --- a/node_core/src/lib.rs +++ b/node_core/src/lib.rs @@ -8,7 +8,7 @@ use common::ExecutionFailureKind; use accounts::account_core::{Account, AccountAddress}; use anyhow::Result; use chain_storage::NodeChainStore; -use common::transaction::{Transaction, TxKind}; +use common::transaction::{TransactionBody, TxKind}; use config::NodeConfig; use log::info; use sc_core::proofs_circuits::{ @@ -189,7 +189,7 @@ impl NodeCore { &self, acc: AccountAddress, amount: u128, - ) -> Result<(Transaction, [u8; 32]), ExecutionFailureKind> { + ) -> Result<(TransactionBody, [u8; 32]), ExecutionFailureKind> { let (utxo, receipt) = prove_mint_utxo(amount, acc)?; let result_hash = utxo.hash; @@ -246,7 +246,7 @@ impl NodeCore { let (tweak, secret_r, commitment) = pedersen_commitment_vec(vec_public_info); Ok(( - Transaction { + TransactionBody { tx_kind: TxKind::Private, execution_input: vec![], execution_output: vec![], @@ -278,7 +278,7 @@ impl NodeCore { acc: AccountAddress, amount: u128, number_of_assets: usize, - ) -> Result<(Transaction, Vec<[u8; 32]>), ExecutionFailureKind> { + ) -> Result<(TransactionBody, Vec<[u8; 32]>), ExecutionFailureKind> { let (utxos, receipt) = prove_mint_utxo_multiple_assets(amount, number_of_assets, acc)?; let result_hashes = utxos.iter().map(|utxo| utxo.hash).collect(); @@ -343,7 +343,7 @@ impl NodeCore { let (tweak, secret_r, commitment) = pedersen_commitment_vec(vec_public_info); Ok(( - Transaction { + TransactionBody { tx_kind: TxKind::Private, execution_input: vec![], execution_output: vec![], @@ -375,7 +375,7 @@ impl NodeCore { utxo: UTXO, commitment_in: [u8; 32], receivers: Vec<(u128, AccountAddress)>, - ) -> Result<(Transaction, Vec<(AccountAddress, [u8; 32])>), ExecutionFailureKind> { + ) -> Result<(TransactionBody, Vec<(AccountAddress, [u8; 32])>), ExecutionFailureKind> { let acc_map_read_guard = self.storage.read().await; let account = acc_map_read_guard.acc_map.get(&utxo.owner).unwrap(); @@ -459,7 +459,7 @@ impl NodeCore { let (tweak, secret_r, commitment) = pedersen_commitment_vec(vec_public_info); Ok(( - Transaction { + TransactionBody { tx_kind: TxKind::Private, execution_input: vec![], execution_output: vec![], @@ -492,7 +492,7 @@ impl NodeCore { commitments_in: Vec<[u8; 32]>, number_to_send: usize, receiver: AccountAddress, - ) -> Result<(Transaction, Vec<[u8; 32]>, Vec<[u8; 32]>), ExecutionFailureKind> { + ) -> Result<(TransactionBody, Vec<[u8; 32]>, Vec<[u8; 32]>), ExecutionFailureKind> { let acc_map_read_guard = self.storage.read().await; let account = acc_map_read_guard.acc_map.get(&utxos[0].owner).unwrap(); @@ -604,7 +604,7 @@ impl NodeCore { let (tweak, secret_r, commitment) = pedersen_commitment_vec(vec_public_info); Ok(( - Transaction { + TransactionBody { tx_kind: TxKind::Private, execution_input: vec![], execution_output: vec![], @@ -637,7 +637,7 @@ impl NodeCore { acc: AccountAddress, balance: u64, receivers: Vec<(u128, AccountAddress)>, - ) -> Result<(Transaction, Vec<(AccountAddress, [u8; 32])>), ExecutionFailureKind> { + ) -> Result<(TransactionBody, Vec<(AccountAddress, [u8; 32])>), ExecutionFailureKind> { let acc_map_read_guard = self.storage.read().await; let account = acc_map_read_guard.acc_map.get(&acc).unwrap(); @@ -727,7 +727,7 @@ impl NodeCore { let (tweak, secret_r, commitment) = pedersen_commitment_vec(vec_public_info); Ok(( - Transaction { + TransactionBody { tx_kind: TxKind::Shielded, execution_input: serde_json::to_vec(&ActionData::SendMoneyShieldedTx( SendMoneyShieldedTx { @@ -765,7 +765,7 @@ impl NodeCore { utxo: UTXO, comm_gen_hash: [u8; 32], receivers: Vec<(u128, AccountAddress)>, - ) -> Result { + ) -> Result { let acc_map_read_guard = self.storage.read().await; let commitment_in = acc_map_read_guard @@ -820,7 +820,7 @@ impl NodeCore { let (tweak, secret_r, commitment) = pedersen_commitment_vec(vec_public_info); - Ok(Transaction { + Ok(TransactionBody { tx_kind: TxKind::Deshielded, execution_input: serde_json::to_vec(&ActionData::SendMoneyDeshieldedTx( SendMoneyDeshieldedTx { @@ -924,7 +924,7 @@ impl NodeCore { let new_len = 0; 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( serde_json::to_vec(&ActionData::MintMoneyPublicTx(MintMoneyPublicTx { acc, @@ -1361,7 +1361,7 @@ impl NodeCore { commitment_in: [u8; 32], receivers: Vec<(u128, AccountAddress)>, visibility_list: [bool; 3], - ) -> Result<(Transaction, Vec<(AccountAddress, [u8; 32])>), ExecutionFailureKind> { + ) -> Result<(TransactionBody, Vec<(AccountAddress, [u8; 32])>), ExecutionFailureKind> { let acc_map_read_guard = self.storage.read().await; let account = acc_map_read_guard.acc_map.get(&utxo.owner).unwrap(); @@ -1459,7 +1459,7 @@ impl NodeCore { let (tweak, secret_r, commitment) = pedersen_commitment_vec(vec_public_info); Ok(( - Transaction { + TransactionBody { tx_kind: TxKind::Shielded, execution_input: vec![], execution_output: serde_json::to_vec(&publication).unwrap(), diff --git a/node_core/src/sequencer_client/json.rs b/node_core/src/sequencer_client/json.rs index df94ca2..b3ada03 100644 --- a/node_core/src/sequencer_client/json.rs +++ b/node_core/src/sequencer_client/json.rs @@ -1,11 +1,11 @@ -use common::transaction::Transaction; +use common::transaction::TransactionBody; use serde::{Deserialize, Serialize}; //Requests #[derive(Serialize, Deserialize, Debug)] pub struct SendTxRequest { - pub transaction: Transaction, + pub transaction: TransactionBody, ///UTXO Commitment Root, Pub Tx Root pub tx_roots: [[u8; 32]; 2], } diff --git a/node_core/src/sequencer_client/mod.rs b/node_core/src/sequencer_client/mod.rs index 7accd5f..3c96a85 100644 --- a/node_core/src/sequencer_client/mod.rs +++ b/node_core/src/sequencer_client/mod.rs @@ -4,7 +4,7 @@ use common::rpc_primitives::requests::{ GetBlockDataRequest, GetBlockDataResponse, GetGenesisIdRequest, GetGenesisIdResponse, RegisterAccountRequest, RegisterAccountResponse, }; -use common::transaction::Transaction; +use common::transaction::TransactionBody; use common::{SequencerClientError, SequencerRpcError}; use json::{SendTxRequest, SendTxResponse, SequencerRpcRequest, SequencerRpcResponse}; use k256::elliptic_curve::group::GroupEncoding; @@ -72,7 +72,7 @@ impl SequencerClient { pub async fn send_tx( &self, - transaction: Transaction, + transaction: TransactionBody, tx_roots: [[u8; 32]; 2], ) -> Result { let tx_req = SendTxRequest { diff --git a/sc_core/src/transaction_payloads_tools.rs b/sc_core/src/transaction_payloads_tools.rs index 4846be1..f8d3e3e 100644 --- a/sc_core/src/transaction_payloads_tools.rs +++ b/sc_core/src/transaction_payloads_tools.rs @@ -1,6 +1,6 @@ use accounts::account_core::Account; use anyhow::Result; -use common::transaction::{Transaction, TxKind}; +use common::transaction::{TransactionBody, TxKind}; use rand::thread_rng; use risc0_zkvm::Receipt; use secp256k1_zkp::{CommitmentSecrets, PedersenCommitment, Tweak}; @@ -15,8 +15,8 @@ pub fn create_public_transaction_payload( secret_r: [u8; 32], sc_addr: String, state_changes: (serde_json::Value, usize), -) -> Transaction { - Transaction { +) -> TransactionBody { + TransactionBody { tx_kind: TxKind::Public, execution_input, execution_output: vec![], diff --git a/sequencer_core/src/lib.rs b/sequencer_core/src/lib.rs index f2890ed..bec16b0 100644 --- a/sequencer_core/src/lib.rs +++ b/sequencer_core/src/lib.rs @@ -5,7 +5,7 @@ use common::{ block::{Block, HashableBlockData}, merkle_tree_public::TreeHashType, nullifier::UTXONullifier, - transaction::{Transaction, TxKind}, + transaction::{TransactionBody, TxKind}, utxo_commitment::UTXOCommitment, }; use config::SequencerConfig; @@ -71,10 +71,10 @@ impl SequencerCore { pub fn transaction_pre_check( &mut self, - tx: &Transaction, + tx: &TransactionBody, tx_roots: [[u8; 32]; 2], ) -> Result<(), TransactionMalformationErrorKind> { - let Transaction { + let TransactionBody { tx_kind, ref execution_input, ref execution_output, @@ -188,7 +188,7 @@ impl SequencerCore { &mut self, tx: TransactionMempool, ) -> Result<(), TransactionMalformationErrorKind> { - let Transaction { + let TransactionBody { ref utxo_commitments_created_hashes, ref nullifier_created_hashes, .. @@ -259,7 +259,7 @@ mod tests { use super::*; use std::path::PathBuf; - use common::transaction::{Transaction, TxKind}; + use common::transaction::{TransactionBody, TxKind}; use rand::Rng; use secp256k1_zkp::Tweak; use transaction_mempool::TransactionMempool; @@ -285,10 +285,10 @@ mod tests { nullifier_created_hashes: Vec<[u8; 32]>, utxo_commitments_spent_hashes: Vec<[u8; 32]>, utxo_commitments_created_hashes: Vec<[u8; 32]>, - ) -> Transaction { + ) -> TransactionBody { let mut rng = rand::thread_rng(); - Transaction { + TransactionBody { tx_kind: TxKind::Private, execution_input: vec![], execution_output: vec![], diff --git a/sequencer_core/src/transaction_mempool.rs b/sequencer_core/src/transaction_mempool.rs index d932b24..d6d81f2 100644 --- a/sequencer_core/src/transaction_mempool.rs +++ b/sequencer_core/src/transaction_mempool.rs @@ -1,14 +1,14 @@ -use common::{merkle_tree_public::TreeHashType, transaction::Transaction}; +use common::{merkle_tree_public::TreeHashType, transaction::TransactionBody}; use mempool::mempoolitem::MemPoolItem; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone)] pub struct TransactionMempool { - pub tx: Transaction, + pub tx: TransactionBody, } -impl From for TransactionMempool { - fn from(value: Transaction) -> Self { +impl From for TransactionMempool { + fn from(value: TransactionBody) -> Self { Self { tx: value } } } @@ -27,7 +27,7 @@ impl<'de> Deserialize<'de> for TransactionMempool { where D: serde::Deserializer<'de>, { - match Transaction::deserialize(deserializer) { + match TransactionBody::deserialize(deserializer) { Ok(tx) => Ok(TransactionMempool { tx }), Err(err) => Err(err), } From 6e48bcfd9e58b1d4eb5bb99e2305b7ed84ef2f91 Mon Sep 17 00:00:00 2001 From: Sergio Chouhy Date: Mon, 14 Jul 2025 09:37:00 -0300 Subject: [PATCH 10/36] sign transactions from node's end --- Cargo.lock | 1 + common/Cargo.toml | 1 + common/src/lib.rs | 6 + common/src/transaction.rs | 106 +++-- node_core/src/lib.rs | 582 +++++++++++++------------ node_core/src/sequencer_client/json.rs | 4 +- node_core/src/sequencer_client/mod.rs | 4 +- node_rpc/src/process.rs | 82 ++-- 8 files changed, 411 insertions(+), 375 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0200d46..c19ab6f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -996,6 +996,7 @@ dependencies = [ "anyhow", "elliptic-curve", "hex", + "k256", "log", "reqwest 0.11.27", "risc0-zkvm", diff --git a/common/Cargo.toml b/common/Cargo.toml index b1988ad..e00bf4d 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -10,6 +10,7 @@ serde_json.workspace = true serde.workspace = true reqwest.workspace = true risc0-zkvm = { git = "https://github.com/risc0/risc0.git", branch = "release-2.2" } +k256.workspace = true rs_merkle.workspace = true sha2.workspace = true diff --git a/common/src/lib.rs b/common/src/lib.rs index 46868d9..96a7b55 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -88,3 +88,9 @@ impl ExecutionFailureKind { Self::DBError(err) } } + +#[derive(Debug, thiserror::Error)] +pub enum TransactionSignatureError { + #[error("invalid signature for transaction body")] + InvalidSignature, +} diff --git a/common/src/transaction.rs b/common/src/transaction.rs index fd0b4c3..6e6f651 100644 --- a/common/src/transaction.rs +++ b/common/src/transaction.rs @@ -1,5 +1,6 @@ +use k256::Scalar; use log::info; -use secp256k1_zkp::{PedersenCommitment, PublicKey, Scalar, Tweak}; +use secp256k1_zkp::{PedersenCommitment, Tweak}; use serde::{Deserialize, Serialize}; use sha2::{digest::FixedOutput, Digest}; @@ -11,6 +12,8 @@ use elliptic_curve::{ }; use sha2::digest::typenum::{UInt, UTerm}; +use crate::TransactionSignatureError; + pub type CipherText = Vec; pub type Nonce = GenericArray, B1>, B0>, B0>>; pub type Tag = u8; @@ -57,28 +60,6 @@ pub struct TransactionBody { pub state_changes: (serde_json::Value, usize), } -#[derive(Serialize, Deserialize)] -struct TransactionSignature; - -#[derive(Serialize, Deserialize)] -struct TransactionHash; - -/// A transaction with a signature. -/// Meant to be sent through the network to the sequencer -#[derive(Serialize, Deserialize)] -pub struct SignedTransaction { - body: TransactionBody, - signature: TransactionSignature, -} - -/// A transaction with a valid signature over its hash. -/// Can only be constructed from an `UnverifiedSignedTransaction` -/// if the signature is valid -pub struct AuthenticatedTransaction { - hash: TransactionHash, - signed_tx: SignedTransaction -} - #[derive(Debug, Serialize, Deserialize)] pub struct MintMoneyPublicTx { pub acc: [u8; 32], @@ -172,9 +153,6 @@ impl ActionData { } } -type SignaturePrivateKey = Scalar; -type SignaturePublicKey = PublicKey; - impl TransactionBody { /// Computes and returns the SHA-256 hash of the JSON-serialized representation of `self`. pub fn hash(&self) -> TreeHashType { @@ -187,16 +165,6 @@ impl TransactionBody { TreeHashType::from(hasher.finalize_fixed()) } - pub fn sign(self, _private_key: SignaturePrivateKey) -> SignedTransaction { - let _hash = self.hash(); - // Implement actual signature over `hash` - let signature = TransactionSignature {}; - SignedTransaction { - body: self, - signature, - } - } - pub fn log(&self) { info!("Transaction hash is {:?}", hex::encode(self.hash())); info!("Transaction tx_kind is {:?}", self.tx_kind); @@ -249,38 +217,62 @@ impl TransactionBody { } } +type SignaturePrivateKey = Scalar; + +#[derive(Debug, Serialize, Deserialize)] +struct TransactionSignature; + +type TransactionHash = TreeHashType; + +/// A transaction with a signature. +/// Meant to be sent through the network to the sequencer +#[derive(Debug, Serialize, Deserialize)] +pub struct SignedTransaction { + pub body: TransactionBody, + signature: TransactionSignature, +} + impl SignedTransaction { - pub fn into_authenticated(self) -> AuthenticatedTransaction { - let hash = TransactionHash; // self.body.hash(); - // Check signature over hash - AuthenticatedTransaction { - hash, - signed_tx: self - } + pub fn from_transaction_body( + body: TransactionBody, + _private_key: SignaturePrivateKey, + ) -> SignedTransaction { + let _hash = body.hash(); + // TODO: Implement actual signature over `hash` + let signature = TransactionSignature {}; + Self { body, signature } } + + pub fn into_authenticated(self) -> Result { + let hash = self.body.hash(); + // TODO: Check signature over hash + Err(TransactionSignatureError::InvalidSignature) + } +} + +/// A transaction with a valid signature over the hash of its body. +/// Can only be constructed from an `SignedTransaction` +/// if the signature is valid +pub struct AuthenticatedTransaction { + hash: TransactionHash, + signed_tx: SignedTransaction, } impl AuthenticatedTransaction { pub fn as_signed(&self) -> &SignedTransaction { &self.signed_tx } -} -impl Serialize for AuthenticatedTransaction { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - self.as_signed().serialize(serializer) + pub fn body(&self) -> &TransactionBody { + &self.signed_tx.body } -} -impl<'de> Deserialize<'de> for AuthenticatedTransaction { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - SignedTransaction::deserialize(deserializer).map(|signed_tx| signed_tx.into_authenticated()) + pub fn signature(&self) -> &TransactionSignature { + &self.signed_tx.signature + } + + pub fn hash(&self) -> &TransactionHash { + &self.hash } } diff --git a/node_core/src/lib.rs b/node_core/src/lib.rs index fa49001..04aa467 100644 --- a/node_core/src/lib.rs +++ b/node_core/src/lib.rs @@ -3,7 +3,7 @@ use std::sync::{ Arc, }; -use common::ExecutionFailureKind; +use common::{transaction::SignedTransaction, ExecutionFailureKind}; use accounts::account_core::{Account, AccountAddress}; use anyhow::Result; @@ -189,7 +189,7 @@ impl NodeCore { &self, acc: AccountAddress, amount: u128, - ) -> Result<(TransactionBody, [u8; 32]), ExecutionFailureKind> { + ) -> Result<(SignedTransaction, [u8; 32]), ExecutionFailureKind> { let (utxo, receipt) = prove_mint_utxo(amount, acc)?; let result_hash = utxo.hash; @@ -244,31 +244,34 @@ impl NodeCore { let vec_public_info: Vec = vec_values_u64.into_iter().flatten().collect(); 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, + }; + // TODO: Change to the correct key once established. + let key_to_sign_transaction = account + .key_holder + .utxo_secret_key_holder + .nullifier_secret_key; Ok(( - 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, - } - .into(), + SignedTransaction::from_transaction_body(transaction_body, key_to_sign_transaction), result_hash, )) } @@ -278,7 +281,7 @@ impl NodeCore { acc: AccountAddress, amount: u128, number_of_assets: usize, - ) -> Result<(TransactionBody, Vec<[u8; 32]>), ExecutionFailureKind> { + ) -> Result<(SignedTransaction, Vec<[u8; 32]>), ExecutionFailureKind> { let (utxos, receipt) = prove_mint_utxo_multiple_assets(amount, number_of_assets, acc)?; let result_hashes = utxos.iter().map(|utxo| utxo.hash).collect(); @@ -342,30 +345,34 @@ impl NodeCore { let (tweak, secret_r, commitment) = pedersen_commitment_vec(vec_public_info); - Ok(( - 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, - ) + 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, - ephemeral_pub_key: eph_pub_key.to_vec(), - commitment, - tweak, - secret_r, - sc_addr, - state_changes, - } - .into(), + encoded_data, + ephemeral_pub_key: eph_pub_key.to_vec(), + commitment, + tweak, + secret_r, + sc_addr, + state_changes, + }; + // TODO: Change to the correct key once established. + let key_to_sign_transaction = account + .key_holder + .utxo_secret_key_holder + .nullifier_secret_key; + + Ok(( + SignedTransaction::from_transaction_body(transaction_body, key_to_sign_transaction), result_hashes, )) } @@ -375,7 +382,7 @@ impl NodeCore { utxo: UTXO, commitment_in: [u8; 32], receivers: Vec<(u128, AccountAddress)>, - ) -> Result<(TransactionBody, Vec<(AccountAddress, [u8; 32])>), ExecutionFailureKind> { + ) -> Result<(SignedTransaction, Vec<(AccountAddress, [u8; 32])>), ExecutionFailureKind> { let acc_map_read_guard = self.storage.read().await; let account = acc_map_read_guard.acc_map.get(&utxo.owner).unwrap(); @@ -458,30 +465,35 @@ impl NodeCore { let (tweak, secret_r, commitment) = pedersen_commitment_vec(vec_public_info); - Ok(( - TransactionBody { - tx_kind: TxKind::Private, - execution_input: vec![], - execution_output: vec![], - utxo_commitments_spent_hashes: vec![commitment_in], - 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, - ) + let transaction_body = TransactionBody { + tx_kind: TxKind::Private, + execution_input: vec![], + execution_output: vec![], + utxo_commitments_spent_hashes: vec![commitment_in], + 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, - } - .into(), + encoded_data, + ephemeral_pub_key: eph_pub_key.to_vec(), + commitment, + tweak, + secret_r, + sc_addr, + state_changes, + }; + + // TODO: Change to the correct key once established. + let key_to_sign_transaction = account + .key_holder + .utxo_secret_key_holder + .nullifier_secret_key; + + Ok(( + SignedTransaction::from_transaction_body(transaction_body, key_to_sign_transaction), utxo_hashes, )) } @@ -492,7 +504,7 @@ impl NodeCore { commitments_in: Vec<[u8; 32]>, number_to_send: usize, receiver: AccountAddress, - ) -> Result<(TransactionBody, Vec<[u8; 32]>, Vec<[u8; 32]>), ExecutionFailureKind> { + ) -> Result<(SignedTransaction, Vec<[u8; 32]>, Vec<[u8; 32]>), ExecutionFailureKind> { let acc_map_read_guard = self.storage.read().await; let account = acc_map_read_guard.acc_map.get(&utxos[0].owner).unwrap(); @@ -603,30 +615,35 @@ impl NodeCore { let (tweak, secret_r, commitment) = pedersen_commitment_vec(vec_public_info); - Ok(( - TransactionBody { - tx_kind: TxKind::Private, - execution_input: vec![], - execution_output: vec![], - utxo_commitments_spent_hashes: commitments_in, - utxo_commitments_created_hashes: commitments - .into_iter() - .map(|hash_data| hash_data.try_into().unwrap()) - .collect(), - nullifier_created_hashes: nullifiers, - execution_proof_private: sc_core::transaction_payloads_tools::encode_receipt( - receipt, - ) + let transaction_body = TransactionBody { + tx_kind: TxKind::Private, + execution_input: vec![], + execution_output: vec![], + utxo_commitments_spent_hashes: commitments_in, + utxo_commitments_created_hashes: commitments + .into_iter() + .map(|hash_data| hash_data.try_into().unwrap()) + .collect(), + nullifier_created_hashes: nullifiers, + 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, - } - .into(), + encoded_data, + ephemeral_pub_key: eph_pub_key.to_vec(), + commitment, + tweak, + secret_r, + sc_addr, + state_changes, + }; + + // TODO: Change to the correct key once established. + let key_to_sign_transaction = account + .key_holder + .utxo_secret_key_holder + .nullifier_secret_key; + + Ok(( + SignedTransaction::from_transaction_body(transaction_body, key_to_sign_transaction), utxo_hashes_receiver, utxo_hashes_not_spent, )) @@ -637,7 +654,7 @@ impl NodeCore { acc: AccountAddress, balance: u64, receivers: Vec<(u128, AccountAddress)>, - ) -> Result<(TransactionBody, Vec<(AccountAddress, [u8; 32])>), ExecutionFailureKind> { + ) -> Result<(SignedTransaction, Vec<(AccountAddress, [u8; 32])>), ExecutionFailureKind> { let acc_map_read_guard = self.storage.read().await; let account = acc_map_read_guard.acc_map.get(&acc).unwrap(); @@ -726,36 +743,41 @@ impl NodeCore { 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, + }; + + // TODO: Change to the correct key once established. + let key_to_sign_transaction = account + .key_holder + .utxo_secret_key_holder + .nullifier_secret_key; + Ok(( - 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, - } - .into(), + SignedTransaction::from_transaction_body(transaction_body, key_to_sign_transaction), utxo_hashes, )) } @@ -765,7 +787,7 @@ impl NodeCore { utxo: UTXO, comm_gen_hash: [u8; 32], receivers: Vec<(u128, AccountAddress)>, - ) -> Result { + ) -> Result { let acc_map_read_guard = self.storage.read().await; let commitment_in = acc_map_read_guard @@ -820,7 +842,7 @@ impl NodeCore { let (tweak, secret_r, commitment) = pedersen_commitment_vec(vec_public_info); - Ok(TransactionBody { + let transaction_body = TransactionBody { tx_kind: TxKind::Deshielded, execution_input: serde_json::to_vec(&ActionData::SendMoneyDeshieldedTx( SendMoneyDeshieldedTx { @@ -841,8 +863,18 @@ impl NodeCore { secret_r, sc_addr, state_changes, - } - .into()) + }; + + // TODO: Change to the correct key once established. + let key_to_sign_transaction = account + .key_holder + .utxo_secret_key_holder + .nullifier_secret_key; + + Ok(SignedTransaction::from_transaction_body( + transaction_body, + key_to_sign_transaction, + )) } pub async fn send_private_mint_tx( @@ -855,10 +887,10 @@ impl NodeCore { let point_before_prove = std::time::Instant::now(); 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 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(); info!("Mint utxo proof spent {timedelta:?} milliseconds"); @@ -883,10 +915,10 @@ impl NodeCore { let (tx, utxo_hashes) = self .mint_utxo_multiple_assets_private(acc, amount, number_of_assets) .await?; - tx.log(); + tx.body.log(); 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(); info!("Mint utxo proof spent {timedelta:?} milliseconds"); @@ -898,50 +930,50 @@ impl NodeCore { )) } - pub async fn send_public_deposit( - &self, - acc: AccountAddress, - amount: u128, - ) -> Result { - //Considering proof time, needs to be done before proof - let tx_roots = self.get_roots().await; - - let public_context = { - let read_guard = self.storage.read().await; - - read_guard.produce_context(acc) - }; - - let (tweak, secret_r, commitment) = pedersen_commitment_vec( - //Will not panic, as public context is serializable - public_context.produce_u64_list_from_context().unwrap(), - ); - - let sc_addr = hex::encode([0; 32]); - - //Sc does not change its state - let state_changes: Vec = vec![]; - let new_len = 0; - let state_changes = (serde_json::to_value(state_changes).unwrap(), new_len); - - let tx: TransactionBody = - sc_core::transaction_payloads_tools::create_public_transaction_payload( - serde_json::to_vec(&ActionData::MintMoneyPublicTx(MintMoneyPublicTx { - acc, - amount, - })) - .unwrap(), - commitment, - tweak, - secret_r, - sc_addr, - state_changes, - ) - .into(); - tx.log(); - - Ok(self.sequencer_client.send_tx(tx, tx_roots).await?) - } + // pub async fn send_public_deposit( + // &self, + // acc: AccountAddress, + // amount: u128, + // ) -> Result { + // //Considering proof time, needs to be done before proof + // let tx_roots = self.get_roots().await; + // + // let public_context = { + // let read_guard = self.storage.read().await; + // + // read_guard.produce_context(acc) + // }; + // + // let (tweak, secret_r, commitment) = pedersen_commitment_vec( + // //Will not panic, as public context is serializable + // public_context.produce_u64_list_from_context().unwrap(), + // ); + // + // let sc_addr = hex::encode([0; 32]); + // + // //Sc does not change its state + // let state_changes: Vec = vec![]; + // let new_len = 0; + // let state_changes = (serde_json::to_value(state_changes).unwrap(), new_len); + // + // let tx: TransactionBody = + // sc_core::transaction_payloads_tools::create_public_transaction_payload( + // serde_json::to_vec(&ActionData::MintMoneyPublicTx(MintMoneyPublicTx { + // acc, + // amount, + // })) + // .unwrap(), + // commitment, + // tweak, + // secret_r, + // sc_addr, + // state_changes, + // ) + // .into(); + // tx.log(); + // + // Ok(self.sequencer_client.send_tx(tx, tx_roots).await?) + // } pub async fn send_private_send_tx( &self, @@ -956,7 +988,7 @@ impl NodeCore { let (tx, utxo_hashes) = self .transfer_utxo_private(utxo, comm_hash, receivers) .await?; - tx.log(); + tx.body.log(); let point_after_prove = std::time::Instant::now(); let timedelta = (point_after_prove - point_before_prove).as_millis(); @@ -982,7 +1014,7 @@ impl NodeCore { let (tx, utxo_hashes_received, utxo_hashes_not_spent) = self .transfer_utxo_multiple_assets_private(utxos, comm_hashes, number_to_send, receiver) .await?; - tx.log(); + tx.body.log(); let point_after_prove = std::time::Instant::now(); let timedelta = (point_after_prove - point_before_prove).as_millis(); @@ -1008,7 +1040,7 @@ impl NodeCore { let (tx, utxo_hashes) = self .transfer_balance_shielded(acc, amount, receivers) .await?; - tx.log(); + tx.body.log(); let point_after_prove = std::time::Instant::now(); let timedelta = (point_after_prove - point_before_prove).as_millis(); @@ -1033,7 +1065,7 @@ impl NodeCore { let tx = self .transfer_utxo_deshielded(utxo, comm_gen_hash, receivers) .await?; - tx.log(); + tx.body.log(); let point_after_prove = std::time::Instant::now(); let timedelta = (point_after_prove - point_before_prove).as_millis(); @@ -1167,46 +1199,46 @@ impl NodeCore { Ok(()) } - pub async fn operate_account_deposit_public( - &mut self, - acc_addr: AccountAddress, - amount: u128, - ) -> Result<(), ExecutionFailureKind> { - let old_balance = { - let acc_map_read_guard = self.storage.read().await; - - let acc = acc_map_read_guard.acc_map.get(&acc_addr).unwrap(); - - acc.balance - }; - - info!( - "Balance of {:?} now is {old_balance:?}", - hex::encode(acc_addr) - ); - - let resp = self.send_public_deposit(acc_addr, amount).await?; - info!("Response for public deposit is {resp:?}"); - - info!("Awaiting new blocks"); - tokio::time::sleep(std::time::Duration::from_secs(BLOCK_GEN_DELAY_SECS)).await; - - let new_balance = { - let acc_map_read_guard = self.storage.read().await; - - let acc = acc_map_read_guard.acc_map.get(&acc_addr).unwrap(); - - acc.balance - }; - - info!( - "Balance of {:?} now is {new_balance:?}, delta is {:?}", - hex::encode(acc_addr), - new_balance - old_balance - ); - - Ok(()) - } + // pub async fn operate_account_deposit_public( + // &mut self, + // acc_addr: AccountAddress, + // amount: u128, + // ) -> Result<(), ExecutionFailureKind> { + // let old_balance = { + // let acc_map_read_guard = self.storage.read().await; + // + // let acc = acc_map_read_guard.acc_map.get(&acc_addr).unwrap(); + // + // acc.balance + // }; + // + // info!( + // "Balance of {:?} now is {old_balance:?}", + // hex::encode(acc_addr) + // ); + // + // let resp = self.send_public_deposit(acc_addr, amount).await?; + // info!("Response for public deposit is {resp:?}"); + // + // info!("Awaiting new blocks"); + // tokio::time::sleep(std::time::Duration::from_secs(BLOCK_GEN_DELAY_SECS)).await; + // + // let new_balance = { + // let acc_map_read_guard = self.storage.read().await; + // + // let acc = acc_map_read_guard.acc_map.get(&acc_addr).unwrap(); + // + // acc.balance + // }; + // + // info!( + // "Balance of {:?} now is {new_balance:?}, delta is {:?}", + // hex::encode(acc_addr), + // new_balance - old_balance + // ); + // + // Ok(()) + // } pub async fn operate_account_send_shielded_one_receiver( &mut self, @@ -1361,7 +1393,7 @@ impl NodeCore { commitment_in: [u8; 32], receivers: Vec<(u128, AccountAddress)>, visibility_list: [bool; 3], - ) -> Result<(TransactionBody, Vec<(AccountAddress, [u8; 32])>), ExecutionFailureKind> { + ) -> Result<(SignedTransaction, Vec<(AccountAddress, [u8; 32])>), ExecutionFailureKind> { let acc_map_read_guard = self.storage.read().await; let account = acc_map_read_guard.acc_map.get(&utxo.owner).unwrap(); @@ -1458,31 +1490,35 @@ impl NodeCore { let (tweak, secret_r, commitment) = pedersen_commitment_vec(vec_public_info); - Ok(( - TransactionBody { - tx_kind: TxKind::Shielded, - execution_input: vec![], - execution_output: serde_json::to_vec(&publication).unwrap(), - utxo_commitments_spent_hashes: vec![commitment_in], - utxo_commitments_created_hashes: commitments - .clone() - .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, - ) + let transaction_body = TransactionBody { + tx_kind: TxKind::Shielded, + execution_input: vec![], + execution_output: serde_json::to_vec(&publication).unwrap(), + utxo_commitments_spent_hashes: vec![commitment_in], + utxo_commitments_created_hashes: commitments + .clone() + .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, - } - .into(), + encoded_data, + ephemeral_pub_key: eph_pub_key.to_vec(), + commitment, + tweak, + secret_r, + sc_addr, + state_changes, + }; + // TODO: Change to the correct key once established. + let key_to_sign_transaction = account + .key_holder + .utxo_secret_key_holder + .nullifier_secret_key; + + Ok(( + SignedTransaction::from_transaction_body(transaction_body, key_to_sign_transaction), utxo_hashes, )) } @@ -1502,13 +1538,13 @@ impl NodeCore { let (tx, utxo_hashes) = self .split_utxo(utxo, comm_hash, receivers, visibility_list) .await?; - tx.log(); + tx.body.log(); let point_after_prove = std::time::Instant::now(); let timedelta = (point_after_prove - point_before_prove).as_millis(); 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(( self.sequencer_client.send_tx(tx, tx_roots).await?, @@ -1582,17 +1618,17 @@ impl NodeCore { 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(()) - } + // ///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 pub async fn subscenario_3(&mut self) -> Result<(), ExecutionFailureKind> { @@ -1607,18 +1643,18 @@ impl NodeCore { 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(()) - } + // ///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 pub async fn subscenario_5(&mut self) -> Result<(), ExecutionFailureKind> { diff --git a/node_core/src/sequencer_client/json.rs b/node_core/src/sequencer_client/json.rs index b3ada03..9275ca5 100644 --- a/node_core/src/sequencer_client/json.rs +++ b/node_core/src/sequencer_client/json.rs @@ -1,11 +1,11 @@ -use common::transaction::TransactionBody; +use common::transaction::SignedTransaction; use serde::{Deserialize, Serialize}; //Requests #[derive(Serialize, Deserialize, Debug)] pub struct SendTxRequest { - pub transaction: TransactionBody, + pub transaction: SignedTransaction, ///UTXO Commitment Root, Pub Tx Root pub tx_roots: [[u8; 32]; 2], } diff --git a/node_core/src/sequencer_client/mod.rs b/node_core/src/sequencer_client/mod.rs index 3c96a85..95a3378 100644 --- a/node_core/src/sequencer_client/mod.rs +++ b/node_core/src/sequencer_client/mod.rs @@ -4,7 +4,7 @@ use common::rpc_primitives::requests::{ GetBlockDataRequest, GetBlockDataResponse, GetGenesisIdRequest, GetGenesisIdResponse, RegisterAccountRequest, RegisterAccountResponse, }; -use common::transaction::TransactionBody; +use common::transaction::SignedTransaction; use common::{SequencerClientError, SequencerRpcError}; use json::{SendTxRequest, SendTxResponse, SequencerRpcRequest, SequencerRpcResponse}; use k256::elliptic_curve::group::GroupEncoding; @@ -72,7 +72,7 @@ impl SequencerClient { pub async fn send_tx( &self, - transaction: TransactionBody, + transaction: SignedTransaction, tx_roots: [[u8; 32]; 2], ) -> Result { let tx_req = SendTxRequest { diff --git a/node_rpc/src/process.rs b/node_rpc/src/process.rs index f4937e9..a188ec8 100644 --- a/node_rpc/src/process.rs +++ b/node_rpc/src/process.rs @@ -42,7 +42,7 @@ 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_UTXO: &str = "show_account_utxo"; pub const SHOW_TRANSACTION: &str = "show_transaction"; -pub const WRITE_DEPOSIT_PUBLIC_BALANCE: &str = "write_deposit_public_balance"; +// 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_MULTIPLE_ASSETS: &str = "write_mint_utxo_multiple_assets"; pub const WRITE_SEND_UTXO_PRIVATE: &str = "write_send_utxo_private"; @@ -84,18 +84,18 @@ impl JsonHandler { .subscenario_1() .await .map_err(cast_common_execution_error_into_rpc_error)?, - 2 => store - .subscenario_2() - .await - .map_err(cast_common_execution_error_into_rpc_error)?, + // 2 => store + // .subscenario_2() + // .await + // .map_err(cast_common_execution_error_into_rpc_error)?, 3 => store .subscenario_3() .await .map_err(cast_common_execution_error_into_rpc_error)?, - 4 => store - .subscenario_4() - .await - .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 @@ -355,35 +355,35 @@ impl JsonHandler { respond(helperstruct) } - pub async fn process_write_deposit_public_balance( - &self, - request: Request, - ) -> Result { - 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_deposit_public_balance( + // &self, + // request: Request, + // ) -> Result { + // 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 { let req = WriteMintPrivateUTXORequest::parse(Some(request.params))?; @@ -777,9 +777,9 @@ impl JsonHandler { SHOW_ACCOUNT_PUBLIC_BALANCE => self.process_show_account_public_balance(request).await, SHOW_ACCOUNT_UTXO => self.process_show_account_utxo_request(request).await, SHOW_TRANSACTION => self.process_show_transaction(request).await, - WRITE_DEPOSIT_PUBLIC_BALANCE => { - self.process_write_deposit_public_balance(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_MULTIPLE_ASSETS => { self.process_write_mint_utxo_multiple_assets(request).await From e7b727c0bac035fc9b93ff283a3a4253d4939766 Mon Sep 17 00:00:00 2001 From: Sergio Chouhy Date: Mon, 14 Jul 2025 15:45:20 -0300 Subject: [PATCH 11/36] make sequencer validate transaction signatures before adding transactions to blocks --- common/src/block.rs | 6 +- common/src/merkle_tree_public/merkle_tree.rs | 11 ++- .../src/merkle_tree_public/tree_leav_item.rs | 6 +- common/src/rpc_primitives/requests.rs | 3 +- common/src/transaction.rs | 7 +- node_core/src/chain_storage/block_store.rs | 4 +- node_core/src/chain_storage/mod.rs | 28 ++++--- node_rpc/src/process.rs | 12 ++- sequencer_core/src/lib.rs | 79 +++++++++++-------- sequencer_core/src/transaction_mempool.rs | 55 +++++++------ sequencer_rpc/src/process.rs | 5 +- 11 files changed, 118 insertions(+), 98 deletions(-) diff --git a/common/src/block.rs b/common/src/block.rs index ae8765e..4553245 100644 --- a/common/src/block.rs +++ b/common/src/block.rs @@ -1,7 +1,7 @@ use rs_merkle::Hasher; use serde::{Deserialize, Serialize}; -use crate::{merkle_tree_public::hasher::OwnHasher, transaction::TransactionBody}; +use crate::{merkle_tree_public::hasher::OwnHasher, transaction::SignedTransaction}; pub type BlockHash = [u8; 32]; pub type Data = Vec; @@ -13,7 +13,7 @@ pub struct Block { pub prev_block_id: BlockId, pub prev_block_hash: BlockHash, pub hash: BlockHash, - pub transactions: Vec, + pub transactions: Vec, pub data: Data, } @@ -22,7 +22,7 @@ pub struct HashableBlockData { pub block_id: BlockId, pub prev_block_id: BlockId, pub prev_block_hash: BlockHash, - pub transactions: Vec, + pub transactions: Vec, pub data: Data, } diff --git a/common/src/merkle_tree_public/merkle_tree.rs b/common/src/merkle_tree_public/merkle_tree.rs index d8229af..8886745 100644 --- a/common/src/merkle_tree_public/merkle_tree.rs +++ b/common/src/merkle_tree_public/merkle_tree.rs @@ -7,7 +7,10 @@ use serde::{ Deserialize, Deserializer, Serialize, }; -use crate::{transaction::TransactionBody, utxo_commitment::UTXOCommitment}; +use crate::{ + transaction::{AuthenticatedTransaction, SignedTransaction, TransactionBody}, + utxo_commitment::UTXOCommitment, +}; use super::{hasher::OwnHasher, tree_leav_item::TreeLeavItem, TreeHashType}; @@ -81,7 +84,7 @@ impl<'de, Leav: TreeLeavItem + Clone + Deserialize<'de>> serde::Deserialize<'de> } } -pub type PublicTransactionMerkleTree = HashStorageMerkleTree; +pub type PublicTransactionMerkleTree = HashStorageMerkleTree; pub type UTXOCommitmentsMerkleTree = HashStorageMerkleTree; @@ -139,7 +142,7 @@ impl HashStorageMerkleTree { } } - pub fn add_tx(&mut self, tx: Leav) { + pub fn add_tx(&mut self, tx: &Leav) { let last = self.leaves.len(); self.leaves.insert(last, tx.clone()); @@ -266,7 +269,7 @@ mod tests { 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.get_tx(tx2.hash()), Some(&tx2)); } diff --git a/common/src/merkle_tree_public/tree_leav_item.rs b/common/src/merkle_tree_public/tree_leav_item.rs index 52bb8ef..5599172 100644 --- a/common/src/merkle_tree_public/tree_leav_item.rs +++ b/common/src/merkle_tree_public/tree_leav_item.rs @@ -1,4 +1,4 @@ -use crate::{transaction::TransactionBody, utxo_commitment::UTXOCommitment}; +use crate::{transaction::SignedTransaction, utxo_commitment::UTXOCommitment}; use super::TreeHashType; @@ -6,9 +6,9 @@ pub trait TreeLeavItem { fn hash(&self) -> TreeHashType; } -impl TreeLeavItem for TransactionBody { +impl TreeLeavItem for SignedTransaction { fn hash(&self) -> TreeHashType { - self.hash() + self.body.hash() } } diff --git a/common/src/rpc_primitives/requests.rs b/common/src/rpc_primitives/requests.rs index 7508ce9..95b004f 100644 --- a/common/src/rpc_primitives/requests.rs +++ b/common/src/rpc_primitives/requests.rs @@ -1,5 +1,6 @@ use crate::block::Block; use crate::parse_request; +use crate::transaction::SignedTransaction; use crate::transaction::TransactionBody; use super::errors::RpcParseError; @@ -20,7 +21,7 @@ pub struct RegisterAccountRequest { #[derive(Serialize, Deserialize, Debug)] pub struct SendTxRequest { - pub transaction: TransactionBody, + pub transaction: SignedTransaction, ///UTXO Commitment Root, Pub Tx Root pub tx_roots: [[u8; 32]; 2], } diff --git a/common/src/transaction.rs b/common/src/transaction.rs index 6e6f651..1544d67 100644 --- a/common/src/transaction.rs +++ b/common/src/transaction.rs @@ -217,16 +217,16 @@ impl TransactionBody { } } -type SignaturePrivateKey = Scalar; +pub type SignaturePrivateKey = Scalar; -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Serialize, Deserialize, Clone)] struct TransactionSignature; type TransactionHash = TreeHashType; /// A transaction with a signature. /// Meant to be sent through the network to the sequencer -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Serialize, Deserialize, Clone)] pub struct SignedTransaction { pub body: TransactionBody, signature: TransactionSignature, @@ -253,6 +253,7 @@ impl SignedTransaction { /// A transaction with a valid signature over the hash of its body. /// Can only be constructed from an `SignedTransaction` /// if the signature is valid +#[derive(Clone)] pub struct AuthenticatedTransaction { hash: TransactionHash, signed_tx: SignedTransaction, diff --git a/node_core/src/chain_storage/block_store.rs b/node_core/src/chain_storage/block_store.rs index ba5b24b..c6bc386 100644 --- a/node_core/src/chain_storage/block_store.rs +++ b/node_core/src/chain_storage/block_store.rs @@ -6,7 +6,7 @@ use anyhow::{anyhow, Result}; use common::block::Block; use common::merkle_tree_public::merkle_tree::HashStorageMerkleTree; use common::nullifier::UTXONullifier; -use common::transaction::TransactionBody; +use common::transaction::{AuthenticatedTransaction, SignedTransaction, TransactionBody}; use common::utxo_commitment::UTXOCommitment; use log::error; use storage::sc_db_utils::{DataBlob, DataBlobChangeVariant}; @@ -87,7 +87,7 @@ impl NodeBlockStore { )?) } - pub fn get_snapshot_transaction(&self) -> Result> { + pub fn get_snapshot_transaction(&self) -> Result> { Ok(serde_json::from_slice( &self.dbio.get_snapshot_transaction()?, )?) diff --git a/node_core/src/chain_storage/mod.rs b/node_core/src/chain_storage/mod.rs index c875bbd..04ba03a 100644 --- a/node_core/src/chain_storage/mod.rs +++ b/node_core/src/chain_storage/mod.rs @@ -127,8 +127,8 @@ impl NodeChainStore { let block_id = block.block_id; for tx in &block.transactions { - if !tx.execution_input.is_empty() { - let public_action = serde_json::from_slice::(&tx.execution_input); + if !tx.body.execution_input.is_empty() { + let public_action = serde_json::from_slice::(&tx.body.execution_input); if let Ok(public_action) = public_action { match public_action { @@ -162,24 +162,25 @@ impl NodeChainStore { } self.utxo_commitments_store.add_tx_multiple( - tx.utxo_commitments_created_hashes + tx.body + .utxo_commitments_created_hashes .clone() .into_iter() .map(|hash| UTXOCommitment { hash }) .collect(), ); - for nullifier in tx.nullifier_created_hashes.iter() { + for nullifier in tx.body.nullifier_created_hashes.iter() { self.nullifier_store.insert(UTXONullifier { utxo_hash: *nullifier, }); } - if !tx.encoded_data.is_empty() { + if !tx.body.encoded_data.is_empty() { let ephemeral_public_key_sender = - serde_json::from_slice::(&tx.ephemeral_pub_key)?; + serde_json::from_slice::(&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 nonce = accounts::key_management::constants_types::Nonce::clone_from_slice(slice); @@ -204,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)?; @@ -278,7 +279,7 @@ mod tests { use accounts::account_core::Account; use common::block::{Block, Data}; use common::merkle_tree_public::TreeHashType; - use common::transaction::{TransactionBody, TxKind}; + use common::transaction::{SignaturePrivateKey, SignedTransaction, TransactionBody, TxKind}; use secp256k1_zkp::Tweak; use std::path::PathBuf; use tempfile::tempdir; @@ -300,10 +301,10 @@ mod tests { nullifier_created_hashes: Vec<[u8; 32]>, utxo_commitments_spent_hashes: Vec<[u8; 32]>, utxo_commitments_created_hashes: Vec<[u8; 32]>, - ) -> TransactionBody { + ) -> SignedTransaction { let mut rng = rand::thread_rng(); - TransactionBody { + let body = TransactionBody { tx_kind: TxKind::Private, execution_input: vec![], execution_output: vec![], @@ -318,7 +319,8 @@ mod tests { secret_r: [0; 32], sc_addr: "sc_addr".to_string(), state_changes: (serde_json::Value::Null, 0), - } + }; + SignedTransaction::from_transaction_body(body, SignaturePrivateKey::ONE) } fn create_sample_block(block_id: u64, prev_block_id: u64) -> Block { @@ -414,7 +416,7 @@ mod tests { store .utxo_commitments_store .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( [12; 32], vec![[9; 32]], vec![[7; 32]], diff --git a/node_rpc/src/process.rs b/node_rpc/src/process.rs index a188ec8..149121a 100644 --- a/node_rpc/src/process.rs +++ b/node_rpc/src/process.rs @@ -312,42 +312,46 @@ impl JsonHandler { ShowTransactionResponse { hash: req.tx_hash, - tx_kind: tx.tx_kind, + tx_kind: tx.body.tx_kind, public_input: if let Ok(action) = - serde_json::from_slice::(&tx.execution_input) + serde_json::from_slice::(&tx.body.execution_input) { action.into_hexed_print() } else { "".to_string() }, public_output: if let Ok(action) = - serde_json::from_slice::(&tx.execution_output) + serde_json::from_slice::(&tx.body.execution_output) { action.into_hexed_print() } else { "".to_string() }, utxo_commitments_created_hashes: tx + .body .utxo_commitments_created_hashes .iter() .map(|val| hex::encode(val.clone())) .collect::>(), utxo_commitments_spent_hashes: tx + .body .utxo_commitments_spent_hashes .iter() .map(|val| hex::encode(val.clone())) .collect::>(), utxo_nullifiers_created_hashes: tx + .body .nullifier_created_hashes .iter() .map(|val| hex::encode(val.clone())) .collect::>(), encoded_data: tx + .body .encoded_data .iter() .map(|val| (hex::encode(val.0.clone()), hex::encode(val.1.clone()))) .collect::>(), - ephemeral_pub_key: hex::encode(tx.ephemeral_pub_key.clone()), + ephemeral_pub_key: hex::encode(tx.body.ephemeral_pub_key.clone()), } } }; diff --git a/sequencer_core/src/lib.rs b/sequencer_core/src/lib.rs index bec16b0..d480670 100644 --- a/sequencer_core/src/lib.rs +++ b/sequencer_core/src/lib.rs @@ -5,14 +5,14 @@ use common::{ block::{Block, HashableBlockData}, merkle_tree_public::TreeHashType, nullifier::UTXONullifier, - transaction::{TransactionBody, TxKind}, + transaction::{AuthenticatedTransaction, SignedTransaction, TransactionBody, TxKind}, utxo_commitment::UTXOCommitment, }; use config::SequencerConfig; use mempool::MemPool; use sequencer_store::{accounts_store::AccountPublicData, SequecerChainStore}; use serde::{Deserialize, Serialize}; -use transaction_mempool::TransactionMempool; +use transaction_mempool::MempoolTransaction; pub mod config; pub mod sequencer_store; @@ -20,7 +20,7 @@ pub mod transaction_mempool; pub struct SequencerCore { pub store: SequecerChainStore, - pub mempool: MemPool, + pub mempool: MemPool, pub sequencer_config: SequencerConfig, pub chain_height: u64, } @@ -35,6 +35,7 @@ pub enum TransactionMalformationErrorKind { MempoolFullForRound { tx: TreeHashType }, ChainStateFurtherThanTransactionState { tx: TreeHashType }, FailedToInsert { tx: TreeHashType, details: String }, + InvalidSignature, } impl Display for TransactionMalformationErrorKind { @@ -53,7 +54,7 @@ impl SequencerCore { config.genesis_id, config.is_genesis_random, ), - mempool: MemPool::::default(), + mempool: MemPool::::default(), chain_height: config.genesis_id, sequencer_config: config, } @@ -71,9 +72,12 @@ impl SequencerCore { pub fn transaction_pre_check( &mut self, - tx: &TransactionBody, + tx: SignedTransaction, tx_roots: [[u8; 32]; 2], - ) -> Result<(), TransactionMalformationErrorKind> { + ) -> Result { + let tx = tx + .into_authenticated() + .map_err(|_| TransactionMalformationErrorKind::InvalidSignature)?; let TransactionBody { tx_kind, ref execution_input, @@ -81,10 +85,10 @@ impl SequencerCore { ref utxo_commitments_created_hashes, ref nullifier_created_hashes, .. - } = tx; - let tx_hash = tx.hash(); + } = tx.body(); 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: tx_hash }); @@ -151,53 +155,53 @@ impl SequencerCore { if tx_tree_check { return Err( - TransactionMalformationErrorKind::TxHashAlreadyPresentInTree { tx: tx.hash() }, + TransactionMalformationErrorKind::TxHashAlreadyPresentInTree { tx: *tx.hash() }, ); } if nullifier_tree_check { return Err( - TransactionMalformationErrorKind::NullifierAlreadyPresentInTree { tx: tx.hash() }, + TransactionMalformationErrorKind::NullifierAlreadyPresentInTree { tx: *tx.hash() }, ); } if utxo_commitments_check { return Err( TransactionMalformationErrorKind::UTXOCommitmentAlreadyPresentInTree { - tx: tx.hash(), + tx: *tx.hash(), }, ); } - Ok(()) + Ok(tx) } pub fn push_tx_into_mempool_pre_check( &mut self, - item: TransactionMempool, + item: SignedTransaction, tx_roots: [[u8; 32]; 2], ) -> Result<(), TransactionMalformationErrorKind> { - self.transaction_pre_check(&item.tx, tx_roots)?; + let item = self.transaction_pre_check(item, tx_roots)?; - self.mempool.push_item(item); + self.mempool.push_item(item.into()); Ok(()) } fn execute_check_transaction_on_state( &mut self, - tx: TransactionMempool, + tx: &MempoolTransaction, ) -> Result<(), TransactionMalformationErrorKind> { let TransactionBody { ref utxo_commitments_created_hashes, ref nullifier_created_hashes, .. - } = tx.tx; + } = tx.tx.body(); for utxo_comm in utxo_commitments_created_hashes { self.store .utxo_commitments_store - .add_tx(UTXOCommitment { hash: *utxo_comm }); + .add_tx(&UTXOCommitment { hash: *utxo_comm }); } for nullifier in nullifier_created_hashes.iter() { @@ -206,7 +210,7 @@ impl SequencerCore { }); } - self.store.pub_tx_store.add_tx(tx.tx); + self.store.pub_tx_store.add_tx(tx.tx.as_signed()); Ok(()) } @@ -227,7 +231,7 @@ impl SequencerCore { .pop_size(self.sequencer_config.max_num_tx_in_block); for tx in &transactions { - self.execute_check_transaction_on_state(tx.clone())?; + self.execute_check_transaction_on_state(&tx)?; } let prev_block_hash = self @@ -239,7 +243,10 @@ impl SequencerCore { let hashable_data = HashableBlockData { block_id: new_block_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.tx.as_signed().clone()) + .collect(), data: vec![], prev_block_hash, }; @@ -259,10 +266,10 @@ mod tests { use super::*; use std::path::PathBuf; - use common::transaction::{TransactionBody, TxKind}; + use common::transaction::{SignaturePrivateKey, SignedTransaction, TransactionBody, TxKind}; use rand::Rng; use secp256k1_zkp::Tweak; - use transaction_mempool::TransactionMempool; + use transaction_mempool::MempoolTransaction; fn setup_sequencer_config() -> SequencerConfig { let mut rng = rand::thread_rng(); @@ -285,10 +292,10 @@ mod tests { nullifier_created_hashes: Vec<[u8; 32]>, utxo_commitments_spent_hashes: Vec<[u8; 32]>, utxo_commitments_created_hashes: Vec<[u8; 32]>, - ) -> TransactionBody { + ) -> SignedTransaction { let mut rng = rand::thread_rng(); - TransactionBody { + let body = TransactionBody { tx_kind: TxKind::Private, execution_input: vec![], execution_output: vec![], @@ -303,12 +310,15 @@ mod tests { secret_r: [0; 32], sc_addr: "sc_addr".to_string(), state_changes: (serde_json::Value::Null, 0), - } + }; + SignedTransaction::from_transaction_body(body, SignaturePrivateKey::ONE) } fn common_setup(sequencer: &mut SequencerCore) { let tx = create_dummy_transaction(vec![[9; 32]], vec![[7; 32]], vec![[8; 32]]); - let tx_mempool = TransactionMempool { tx }; + let tx_mempool = MempoolTransaction { + tx: tx.into_authenticated().unwrap(), + }; sequencer.mempool.push_item(tx_mempool); sequencer.produce_new_block_with_mempool_transactions(); @@ -344,7 +354,7 @@ mod tests { let tx = create_dummy_transaction(vec![[91; 32]], vec![[71; 32]], vec![[81; 32]]); 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()); } @@ -363,10 +373,12 @@ mod tests { let tx_roots = sequencer.get_tree_roots(); // Fill the mempool - let dummy_tx = TransactionMempool { tx: tx.clone() }; + let dummy_tx = MempoolTransaction { + tx: tx.clone().into_authenticated().unwrap(), + }; sequencer.mempool.push_item(dummy_tx); - let result = sequencer.transaction_pre_check(&tx, tx_roots); + let result = sequencer.transaction_pre_check(tx, tx_roots); assert!(matches!( result, @@ -383,9 +395,8 @@ mod tests { let tx = create_dummy_transaction(vec![[93; 32]], vec![[73; 32]], vec![[83; 32]]); 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_eq!(sequencer.mempool.len(), 1); } @@ -396,7 +407,9 @@ mod tests { let mut sequencer = SequencerCore::start_from_config(config); let tx = create_dummy_transaction(vec![[94; 32]], vec![[7; 32]], vec![[8; 32]]); - let tx_mempool = TransactionMempool { tx }; + let tx_mempool = MempoolTransaction { + tx: tx.into_authenticated().unwrap(), + }; sequencer.mempool.push_item(tx_mempool); let block_id = sequencer.produce_new_block_with_mempool_transactions(); diff --git a/sequencer_core/src/transaction_mempool.rs b/sequencer_core/src/transaction_mempool.rs index d6d81f2..cb40ad5 100644 --- a/sequencer_core/src/transaction_mempool.rs +++ b/sequencer_core/src/transaction_mempool.rs @@ -1,43 +1,42 @@ -use common::{merkle_tree_public::TreeHashType, transaction::TransactionBody}; +use common::{merkle_tree_public::TreeHashType, transaction::AuthenticatedTransaction}; use mempool::mempoolitem::MemPoolItem; use serde::{Deserialize, Serialize}; -#[derive(Debug, Clone)] -pub struct TransactionMempool { - pub tx: TransactionBody, +pub struct MempoolTransaction { + pub tx: AuthenticatedTransaction, } -impl From for TransactionMempool { - fn from(value: TransactionBody) -> Self { +impl From for MempoolTransaction { + fn from(value: AuthenticatedTransaction) -> Self { Self { tx: value } } } -impl Serialize for TransactionMempool { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - self.tx.serialize(serializer) - } -} +// impl Serialize for TransactionMempool { +// fn serialize(&self, serializer: S) -> Result +// where +// S: serde::Serializer, +// { +// self.tx.serialize(serializer) +// } +// } +// +// impl<'de> Deserialize<'de> for TransactionMempool { +// fn deserialize(deserializer: D) -> Result +// where +// D: serde::Deserializer<'de>, +// { +// match TransactionBody::deserialize(deserializer) { +// Ok(tx) => Ok(TransactionMempool { tx }), +// Err(err) => Err(err), +// } +// } +// } -impl<'de> Deserialize<'de> for TransactionMempool { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - match TransactionBody::deserialize(deserializer) { - Ok(tx) => Ok(TransactionMempool { tx }), - Err(err) => Err(err), - } - } -} - -impl MemPoolItem for TransactionMempool { +impl MemPoolItem for MempoolTransaction { type Identifier = TreeHashType; fn identifier(&self) -> Self::Identifier { - self.tx.hash() + *self.tx.hash() } } diff --git a/sequencer_rpc/src/process.rs b/sequencer_rpc/src/process.rs index 5bac835..102da72 100644 --- a/sequencer_rpc/src/process.rs +++ b/sequencer_rpc/src/process.rs @@ -81,10 +81,7 @@ impl JsonHandler { { let mut state = self.sequencer_state.lock().await; - state.push_tx_into_mempool_pre_check( - send_tx_req.transaction.into(), - send_tx_req.tx_roots, - )?; + state.push_tx_into_mempool_pre_check(send_tx_req.transaction, send_tx_req.tx_roots)?; } let helperstruct = SendTxResponse { From 1ef7be0af6ee410d7456a036fd9df396cf681b48 Mon Sep 17 00:00:00 2001 From: Sergio Chouhy Date: Tue, 15 Jul 2025 15:48:59 -0300 Subject: [PATCH 12/36] add pem feature to k256 and remove manual impls of Serialize and Deserialize --- Cargo.lock | 11 +++++++ Cargo.toml | 2 +- accounts/src/key_management/mod.rs | 18 ++++++++++- common/src/transaction.rs | 48 +++++++++++++++++++++--------- node_core/src/chain_storage/mod.rs | 2 +- node_core/src/lib.rs | 35 +++++----------------- sequencer_core/src/lib.rs | 2 +- 7 files changed, 72 insertions(+), 46 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c19ab6f..554d101 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1247,6 +1247,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" dependencies = [ "const-oid", + "pem-rfc7468", "zeroize", ] @@ -1486,6 +1487,7 @@ dependencies = [ "ff", "generic-array", "group", + "pem-rfc7468", "pkcs8", "rand_core 0.6.4", "sec1", @@ -3196,6 +3198,15 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" 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]] name = "percent-encoding" version = "2.3.1" diff --git a/Cargo.toml b/Cargo.toml index 7af2e24..0419f1c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,7 +55,7 @@ features = ["std", "std_rng", "getrandom"] version = "0.8.5" [workspace.dependencies.k256] -features = ["ecdsa-core", "arithmetic", "expose-field", "serde"] +features = ["ecdsa-core", "arithmetic", "expose-field", "serde", "pem"] version = "0.13.4" [workspace.dependencies.elliptic-curve] diff --git a/accounts/src/key_management/mod.rs b/accounts/src/key_management/mod.rs index 69b8ce0..2598294 100644 --- a/accounts/src/key_management/mod.rs +++ b/accounts/src/key_management/mod.rs @@ -3,12 +3,14 @@ use common::merkle_tree_public::TreeHashType; use constants_types::{CipherText, Nonce}; use elliptic_curve::point::AffineCoordinates; use ephemeral_key_holder::EphemeralKeyHolder; -use k256::AffinePoint; +use k256::{ecdsa::SigningKey, AffinePoint, FieldBytes}; use log::info; +use rand::{rngs::OsRng, RngCore}; use secret_holders::{SeedHolder, TopSecretKeyHolder, UTXOSecretKeyHolder}; use serde::{Deserialize, Serialize}; use crate::account_core::PublicKey; +pub type PublicAccountSecretKey = [u8; 32]; pub mod constants_types; pub mod ephemeral_key_holder; @@ -21,6 +23,7 @@ pub struct AddressKeyHolder { #[allow(dead_code)] top_secret_key_holder: TopSecretKeyHolder, pub utxo_secret_key_holder: UTXOSecretKeyHolder, + pub pub_account_secret_key: PublicAccountSecretKey, pub address: TreeHashType, pub nullifer_public_key: PublicKey, pub viewing_public_key: PublicKey, @@ -39,15 +42,28 @@ impl AddressKeyHolder { 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 pub_account_secret_key = { + let mut bytes = [0; 32]; + OsRng.fill_bytes(&mut bytes); + bytes + }; + Self { top_secret_key_holder, utxo_secret_key_holder, address, nullifer_public_key, viewing_public_key, + pub_account_secret_key, } } + pub fn pub_account_secret_key(&self) -> SigningKey { + let field_bytes = FieldBytes::from_slice(&self.pub_account_secret_key); + // TODO: remove unwrap + SigningKey::from_bytes(&field_bytes).unwrap() + } + pub fn calculate_shared_secret_receiver( &self, ephemeral_public_key_sender: AffinePoint, diff --git a/common/src/transaction.rs b/common/src/transaction.rs index 1544d67..ee832c7 100644 --- a/common/src/transaction.rs +++ b/common/src/transaction.rs @@ -1,8 +1,17 @@ -use k256::Scalar; +use k256::{ + ecdsa::{ + signature::{Signer, Verifier}, + Signature, SigningKey, VerifyingKey, + }, + EncodedPoint, Scalar, +}; use log::info; use secp256k1_zkp::{PedersenCommitment, Tweak}; -use serde::{Deserialize, Serialize}; +use serde::de::{Error as DeError, Visitor}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + use sha2::{digest::FixedOutput, Digest}; +use std::fmt; use crate::merkle_tree_public::TreeHashType; @@ -217,10 +226,9 @@ impl TransactionBody { } } -pub type SignaturePrivateKey = Scalar; - -#[derive(Debug, Serialize, Deserialize, Clone)] -struct TransactionSignature; +pub type SignaturePrivateKey = SigningKey; +pub type SignaturePublicKey = VerifyingKey; +pub type TransactionSignature = Signature; type TransactionHash = TreeHashType; @@ -229,24 +237,36 @@ type TransactionHash = TreeHashType; #[derive(Debug, Serialize, Deserialize, Clone)] pub struct SignedTransaction { pub body: TransactionBody, - signature: TransactionSignature, + signature: (TransactionSignature, SignaturePublicKey), } impl SignedTransaction { pub fn from_transaction_body( body: TransactionBody, - _private_key: SignaturePrivateKey, + private_key: SignaturePrivateKey, ) -> SignedTransaction { - let _hash = body.hash(); + let hash = body.hash(); + let signature: Signature = private_key.sign(&hash); // TODO: Implement actual signature over `hash` - let signature = TransactionSignature {}; - Self { body, signature } + let public_key = VerifyingKey::from(&private_key); + Self { + body, + signature: (signature, public_key), + } } pub fn into_authenticated(self) -> Result { let hash = self.body.hash(); - // TODO: Check signature over hash - Err(TransactionSignatureError::InvalidSignature) + let (signature, public_key) = &self.signature; + + public_key + .verify(&hash, signature) + .map_err(|_| TransactionSignatureError::InvalidSignature)?; + + Ok(AuthenticatedTransaction { + hash, + signed_tx: self, + }) } } @@ -269,7 +289,7 @@ impl AuthenticatedTransaction { } pub fn signature(&self) -> &TransactionSignature { - &self.signed_tx.signature + &self.signed_tx.signature.0 } pub fn hash(&self) -> &TransactionHash { diff --git a/node_core/src/chain_storage/mod.rs b/node_core/src/chain_storage/mod.rs index 04ba03a..bb8641a 100644 --- a/node_core/src/chain_storage/mod.rs +++ b/node_core/src/chain_storage/mod.rs @@ -320,7 +320,7 @@ mod tests { sc_addr: "sc_addr".to_string(), state_changes: (serde_json::Value::Null, 0), }; - SignedTransaction::from_transaction_body(body, SignaturePrivateKey::ONE) + SignedTransaction::from_transaction_body(body, SignaturePrivateKey::random(&mut rng)) } fn create_sample_block(block_id: u64, prev_block_id: u64) -> Block { diff --git a/node_core/src/lib.rs b/node_core/src/lib.rs index 04aa467..7812614 100644 --- a/node_core/src/lib.rs +++ b/node_core/src/lib.rs @@ -265,10 +265,7 @@ impl NodeCore { state_changes, }; // TODO: Change to the correct key once established. - let key_to_sign_transaction = account - .key_holder - .utxo_secret_key_holder - .nullifier_secret_key; + let key_to_sign_transaction = account.key_holder.pub_account_secret_key(); Ok(( SignedTransaction::from_transaction_body(transaction_body, key_to_sign_transaction), @@ -366,10 +363,7 @@ impl NodeCore { state_changes, }; // TODO: Change to the correct key once established. - let key_to_sign_transaction = account - .key_holder - .utxo_secret_key_holder - .nullifier_secret_key; + let key_to_sign_transaction = account.key_holder.pub_account_secret_key(); Ok(( SignedTransaction::from_transaction_body(transaction_body, key_to_sign_transaction), @@ -487,10 +481,7 @@ impl NodeCore { }; // TODO: Change to the correct key once established. - let key_to_sign_transaction = account - .key_holder - .utxo_secret_key_holder - .nullifier_secret_key; + let key_to_sign_transaction = account.key_holder.pub_account_secret_key(); Ok(( SignedTransaction::from_transaction_body(transaction_body, key_to_sign_transaction), @@ -637,10 +628,7 @@ impl NodeCore { }; // TODO: Change to the correct key once established. - let key_to_sign_transaction = account - .key_holder - .utxo_secret_key_holder - .nullifier_secret_key; + let key_to_sign_transaction = account.key_holder.pub_account_secret_key(); Ok(( SignedTransaction::from_transaction_body(transaction_body, key_to_sign_transaction), @@ -771,10 +759,7 @@ impl NodeCore { }; // TODO: Change to the correct key once established. - let key_to_sign_transaction = account - .key_holder - .utxo_secret_key_holder - .nullifier_secret_key; + let key_to_sign_transaction = account.key_holder.pub_account_secret_key(); Ok(( SignedTransaction::from_transaction_body(transaction_body, key_to_sign_transaction), @@ -866,10 +851,7 @@ impl NodeCore { }; // TODO: Change to the correct key once established. - let key_to_sign_transaction = account - .key_holder - .utxo_secret_key_holder - .nullifier_secret_key; + let key_to_sign_transaction = account.key_holder.pub_account_secret_key(); Ok(SignedTransaction::from_transaction_body( transaction_body, @@ -1512,10 +1494,7 @@ impl NodeCore { state_changes, }; // TODO: Change to the correct key once established. - let key_to_sign_transaction = account - .key_holder - .utxo_secret_key_holder - .nullifier_secret_key; + let key_to_sign_transaction = account.key_holder.pub_account_secret_key(); Ok(( SignedTransaction::from_transaction_body(transaction_body, key_to_sign_transaction), diff --git a/sequencer_core/src/lib.rs b/sequencer_core/src/lib.rs index d480670..f812ea0 100644 --- a/sequencer_core/src/lib.rs +++ b/sequencer_core/src/lib.rs @@ -311,7 +311,7 @@ mod tests { sc_addr: "sc_addr".to_string(), state_changes: (serde_json::Value::Null, 0), }; - SignedTransaction::from_transaction_body(body, SignaturePrivateKey::ONE) + SignedTransaction::from_transaction_body(body, SignaturePrivateKey::random(&mut rng)) } fn common_setup(sequencer: &mut SequencerCore) { From b1724ec235465e9f685b8efe7baae8b6f53ebd22 Mon Sep 17 00:00:00 2001 From: Sergio Chouhy Date: Wed, 16 Jul 2025 08:43:05 -0300 Subject: [PATCH 13/36] move mempool checks outside transaction check function --- common/src/transaction.rs | 1 - sequencer_core/src/lib.rs | 19 +++++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/common/src/transaction.rs b/common/src/transaction.rs index ee832c7..d02ed41 100644 --- a/common/src/transaction.rs +++ b/common/src/transaction.rs @@ -247,7 +247,6 @@ impl SignedTransaction { ) -> SignedTransaction { let hash = body.hash(); let signature: Signature = private_key.sign(&hash); - // TODO: Implement actual signature over `hash` let public_key = VerifyingKey::from(&private_key); Self { body, diff --git a/sequencer_core/src/lib.rs b/sequencer_core/src/lib.rs index f812ea0..188394d 100644 --- a/sequencer_core/src/lib.rs +++ b/sequencer_core/src/lib.rs @@ -78,6 +78,7 @@ impl SequencerCore { let tx = tx .into_authenticated() .map_err(|_| TransactionMalformationErrorKind::InvalidSignature)?; + let TransactionBody { tx_kind, ref execution_input, @@ -87,13 +88,8 @@ impl SequencerCore { .. } = tx.body(); - 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: tx_hash }); - } - let curr_sequencer_roots = self.get_tree_roots(); if tx_roots != curr_sequencer_roots { @@ -178,12 +174,19 @@ impl SequencerCore { pub fn push_tx_into_mempool_pre_check( &mut self, - item: SignedTransaction, + signed_tx: SignedTransaction, tx_roots: [[u8; 32]; 2], ) -> Result<(), TransactionMalformationErrorKind> { - let item = self.transaction_pre_check(item, tx_roots)?; + let mempool_size = self.mempool.len(); + if mempool_size >= self.sequencer_config.max_num_tx_in_block { + return Err(TransactionMalformationErrorKind::MempoolFullForRound { + tx: signed_tx.body.hash(), + }); + } - self.mempool.push_item(item.into()); + let authenticated_tx = self.transaction_pre_check(signed_tx, tx_roots)?; + + self.mempool.push_item(authenticated_tx.into()); Ok(()) } From 8b1d3b478c8a1875927610f8b22df307ef73b1a9 Mon Sep 17 00:00:00 2001 From: Sergio Chouhy Date: Wed, 16 Jul 2025 10:04:23 -0300 Subject: [PATCH 14/36] minor refactor --- accounts/src/account_core/mod.rs | 2 +- accounts/src/key_management/mod.rs | 10 +++--- common/src/transaction.rs | 26 ++++++-------- node_core/src/lib.rs | 21 ++++-------- node_rpc/src/process.rs | 42 ----------------------- sequencer_core/src/lib.rs | 4 +-- sequencer_core/src/transaction_mempool.rs | 21 ------------ 7 files changed, 26 insertions(+), 100 deletions(-) diff --git a/accounts/src/account_core/mod.rs b/accounts/src/account_core/mod.rs index 192c158..66d143e 100644 --- a/accounts/src/account_core/mod.rs +++ b/accounts/src/account_core/mod.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use anyhow::Result; use common::{merkle_tree_public::TreeHashType, transaction::Tag}; -use k256::AffinePoint; +use k256::{ecdsa::VerifyingKey, AffinePoint}; use log::info; use serde::{Deserialize, Serialize}; use utxo::utxo_core::UTXO; diff --git a/accounts/src/key_management/mod.rs b/accounts/src/key_management/mod.rs index 2598294..e871a0f 100644 --- a/accounts/src/key_management/mod.rs +++ b/accounts/src/key_management/mod.rs @@ -10,7 +10,7 @@ use secret_holders::{SeedHolder, TopSecretKeyHolder, UTXOSecretKeyHolder}; use serde::{Deserialize, Serialize}; use crate::account_core::PublicKey; -pub type PublicAccountSecretKey = [u8; 32]; +pub type PublicAccountSigningKey = [u8; 32]; pub mod constants_types; pub mod ephemeral_key_holder; @@ -23,7 +23,7 @@ pub struct AddressKeyHolder { #[allow(dead_code)] top_secret_key_holder: TopSecretKeyHolder, pub utxo_secret_key_holder: UTXOSecretKeyHolder, - pub pub_account_secret_key: PublicAccountSecretKey, + pub_account_signing_key: PublicAccountSigningKey, pub address: TreeHashType, pub nullifer_public_key: PublicKey, pub viewing_public_key: PublicKey, @@ -54,12 +54,12 @@ impl AddressKeyHolder { address, nullifer_public_key, viewing_public_key, - pub_account_secret_key, + pub_account_signing_key: pub_account_secret_key, } } - pub fn pub_account_secret_key(&self) -> SigningKey { - let field_bytes = FieldBytes::from_slice(&self.pub_account_secret_key); + 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() } diff --git a/common/src/transaction.rs b/common/src/transaction.rs index d02ed41..68bf640 100644 --- a/common/src/transaction.rs +++ b/common/src/transaction.rs @@ -226,40 +226,40 @@ impl TransactionBody { } } -pub type SignaturePrivateKey = SigningKey; -pub type SignaturePublicKey = VerifyingKey; +type TransactionHash = [u8; 32]; pub type TransactionSignature = Signature; - -type TransactionHash = TreeHashType; +pub type SignaturePublicKey = VerifyingKey; +pub type SignaturePrivateKey = SigningKey; /// A transaction with a signature. /// Meant to be sent through the network to the sequencer #[derive(Debug, Serialize, Deserialize, Clone)] pub struct SignedTransaction { pub body: TransactionBody, - signature: (TransactionSignature, SignaturePublicKey), + signature: TransactionSignature, + public_key: VerifyingKey, } impl SignedTransaction { pub fn from_transaction_body( body: TransactionBody, - private_key: SignaturePrivateKey, + private_key: SigningKey, ) -> SignedTransaction { let hash = body.hash(); - let signature: Signature = private_key.sign(&hash); + let signature: TransactionSignature = private_key.sign(&hash); let public_key = VerifyingKey::from(&private_key); Self { body, - signature: (signature, public_key), + signature, + public_key, } } pub fn into_authenticated(self) -> Result { let hash = self.body.hash(); - let (signature, public_key) = &self.signature; - public_key - .verify(&hash, signature) + self.public_key + .verify(&hash, &self.signature) .map_err(|_| TransactionSignatureError::InvalidSignature)?; Ok(AuthenticatedTransaction { @@ -287,10 +287,6 @@ impl AuthenticatedTransaction { &self.signed_tx.body } - pub fn signature(&self) -> &TransactionSignature { - &self.signed_tx.signature.0 - } - pub fn hash(&self) -> &TransactionHash { &self.hash } diff --git a/node_core/src/lib.rs b/node_core/src/lib.rs index 7812614..5bed54a 100644 --- a/node_core/src/lib.rs +++ b/node_core/src/lib.rs @@ -264,8 +264,7 @@ impl NodeCore { sc_addr, state_changes, }; - // TODO: Change to the correct key once established. - let key_to_sign_transaction = account.key_holder.pub_account_secret_key(); + let key_to_sign_transaction = account.key_holder.get_pub_account_signing_key(); Ok(( SignedTransaction::from_transaction_body(transaction_body, key_to_sign_transaction), @@ -362,8 +361,7 @@ impl NodeCore { sc_addr, state_changes, }; - // TODO: Change to the correct key once established. - let key_to_sign_transaction = account.key_holder.pub_account_secret_key(); + let key_to_sign_transaction = account.key_holder.get_pub_account_signing_key(); Ok(( SignedTransaction::from_transaction_body(transaction_body, key_to_sign_transaction), @@ -480,8 +478,7 @@ impl NodeCore { state_changes, }; - // TODO: Change to the correct key once established. - let key_to_sign_transaction = account.key_holder.pub_account_secret_key(); + let key_to_sign_transaction = account.key_holder.get_pub_account_signing_key(); Ok(( SignedTransaction::from_transaction_body(transaction_body, key_to_sign_transaction), @@ -627,8 +624,7 @@ impl NodeCore { state_changes, }; - // TODO: Change to the correct key once established. - let key_to_sign_transaction = account.key_holder.pub_account_secret_key(); + let key_to_sign_transaction = account.key_holder.get_pub_account_signing_key(); Ok(( SignedTransaction::from_transaction_body(transaction_body, key_to_sign_transaction), @@ -758,8 +754,7 @@ impl NodeCore { state_changes, }; - // TODO: Change to the correct key once established. - let key_to_sign_transaction = account.key_holder.pub_account_secret_key(); + let key_to_sign_transaction = account.key_holder.get_pub_account_signing_key(); Ok(( SignedTransaction::from_transaction_body(transaction_body, key_to_sign_transaction), @@ -850,8 +845,7 @@ impl NodeCore { state_changes, }; - // TODO: Change to the correct key once established. - let key_to_sign_transaction = account.key_holder.pub_account_secret_key(); + let key_to_sign_transaction = account.key_holder.get_pub_account_signing_key(); Ok(SignedTransaction::from_transaction_body( transaction_body, @@ -1493,8 +1487,7 @@ impl NodeCore { sc_addr, state_changes, }; - // TODO: Change to the correct key once established. - let key_to_sign_transaction = account.key_holder.pub_account_secret_key(); + let key_to_sign_transaction = account.key_holder.get_pub_account_signing_key(); Ok(( SignedTransaction::from_transaction_body(transaction_body, key_to_sign_transaction), diff --git a/node_rpc/src/process.rs b/node_rpc/src/process.rs index 149121a..9f45b98 100644 --- a/node_rpc/src/process.rs +++ b/node_rpc/src/process.rs @@ -42,7 +42,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_UTXO: &str = "show_account_utxo"; 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_MULTIPLE_ASSETS: &str = "write_mint_utxo_multiple_assets"; pub const WRITE_SEND_UTXO_PRIVATE: &str = "write_send_utxo_private"; @@ -84,18 +83,10 @@ impl JsonHandler { .subscenario_1() .await .map_err(cast_common_execution_error_into_rpc_error)?, - // 2 => store - // .subscenario_2() - // .await - // .map_err(cast_common_execution_error_into_rpc_error)?, 3 => store .subscenario_3() .await .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 @@ -359,36 +350,6 @@ impl JsonHandler { respond(helperstruct) } - // pub async fn process_write_deposit_public_balance( - // &self, - // request: Request, - // ) -> Result { - // 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 { let req = WriteMintPrivateUTXORequest::parse(Some(request.params))?; @@ -781,9 +742,6 @@ impl JsonHandler { SHOW_ACCOUNT_PUBLIC_BALANCE => self.process_show_account_public_balance(request).await, SHOW_ACCOUNT_UTXO => self.process_show_account_utxo_request(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_MULTIPLE_ASSETS => { self.process_write_mint_utxo_multiple_assets(request).await diff --git a/sequencer_core/src/lib.rs b/sequencer_core/src/lib.rs index 188394d..174763e 100644 --- a/sequencer_core/src/lib.rs +++ b/sequencer_core/src/lib.rs @@ -363,7 +363,7 @@ mod tests { } #[test] - fn test_transaction_pre_check_fail_mempool_full() { + fn test_push_tx_into_mempool_fails_mempool_full() { let config = SequencerConfig { max_num_tx_in_block: 1, ..setup_sequencer_config() @@ -381,7 +381,7 @@ mod tests { }; 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!( result, diff --git a/sequencer_core/src/transaction_mempool.rs b/sequencer_core/src/transaction_mempool.rs index cb40ad5..fc73fc9 100644 --- a/sequencer_core/src/transaction_mempool.rs +++ b/sequencer_core/src/transaction_mempool.rs @@ -12,27 +12,6 @@ impl From for MempoolTransaction { } } -// impl Serialize for TransactionMempool { -// fn serialize(&self, serializer: S) -> Result -// where -// S: serde::Serializer, -// { -// self.tx.serialize(serializer) -// } -// } -// -// impl<'de> Deserialize<'de> for TransactionMempool { -// fn deserialize(deserializer: D) -> Result -// where -// D: serde::Deserializer<'de>, -// { -// match TransactionBody::deserialize(deserializer) { -// Ok(tx) => Ok(TransactionMempool { tx }), -// Err(err) => Err(err), -// } -// } -// } - impl MemPoolItem for MempoolTransaction { type Identifier = TreeHashType; From ab06501e040d9c08a7157ce0fb86365a6fe8c629 Mon Sep 17 00:00:00 2001 From: Sergio Chouhy Date: Wed, 16 Jul 2025 10:06:06 -0300 Subject: [PATCH 15/36] rename scenarios --- node_core/src/lib.rs | 29 ++--------------------------- node_rpc/src/process.rs | 8 ++++---- 2 files changed, 6 insertions(+), 31 deletions(-) diff --git a/node_core/src/lib.rs b/node_core/src/lib.rs index 5bed54a..0c10578 100644 --- a/node_core/src/lib.rs +++ b/node_core/src/lib.rs @@ -1590,20 +1590,8 @@ impl NodeCore { 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 - 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_rec = self.create_new_account().await; @@ -1615,21 +1603,8 @@ impl NodeCore { 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 - 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_rec = self.create_new_account().await; diff --git a/node_rpc/src/process.rs b/node_rpc/src/process.rs index 9f45b98..a3acd3e 100644 --- a/node_rpc/src/process.rs +++ b/node_rpc/src/process.rs @@ -83,12 +83,12 @@ impl JsonHandler { .subscenario_1() .await .map_err(cast_common_execution_error_into_rpc_error)?, - 3 => store - .subscenario_3() + 2 => store + .subscenario_2() .await .map_err(cast_common_execution_error_into_rpc_error)?, - 5 => store - .subscenario_5() + 3 => store + .subscenario_3() .await .map_err(cast_common_execution_error_into_rpc_error)?, _ => return Err(RpcErr(RpcError::invalid_params("Scenario id not found"))), From b6ea00daa43be0508b41a98e8d5270088ad76447 Mon Sep 17 00:00:00 2001 From: Sergio Chouhy Date: Wed, 16 Jul 2025 11:36:20 -0300 Subject: [PATCH 16/36] add transactions tests --- common/src/block.rs | 6 +- common/src/merkle_tree_public/merkle_tree.rs | 4 +- .../src/merkle_tree_public/tree_leav_item.rs | 4 +- common/src/rpc_primitives/requests.rs | 4 +- common/src/transaction.rs | 100 ++++++++++++++---- node_core/src/chain_storage/block_store.rs | 4 +- node_core/src/chain_storage/mod.rs | 6 +- node_core/src/lib.rs | 33 +++--- node_core/src/sequencer_client/json.rs | 4 +- node_core/src/sequencer_client/mod.rs | 4 +- sequencer_core/src/lib.rs | 20 ++-- 11 files changed, 120 insertions(+), 69 deletions(-) diff --git a/common/src/block.rs b/common/src/block.rs index 4553245..7757667 100644 --- a/common/src/block.rs +++ b/common/src/block.rs @@ -1,7 +1,7 @@ use rs_merkle::Hasher; use serde::{Deserialize, Serialize}; -use crate::{merkle_tree_public::hasher::OwnHasher, transaction::SignedTransaction}; +use crate::{merkle_tree_public::hasher::OwnHasher, transaction::Transaction}; pub type BlockHash = [u8; 32]; pub type Data = Vec; @@ -13,7 +13,7 @@ pub struct Block { pub prev_block_id: BlockId, pub prev_block_hash: BlockHash, pub hash: BlockHash, - pub transactions: Vec, + pub transactions: Vec, pub data: Data, } @@ -22,7 +22,7 @@ pub struct HashableBlockData { pub block_id: BlockId, pub prev_block_id: BlockId, pub prev_block_hash: BlockHash, - pub transactions: Vec, + pub transactions: Vec, pub data: Data, } diff --git a/common/src/merkle_tree_public/merkle_tree.rs b/common/src/merkle_tree_public/merkle_tree.rs index 8886745..bf98eb6 100644 --- a/common/src/merkle_tree_public/merkle_tree.rs +++ b/common/src/merkle_tree_public/merkle_tree.rs @@ -8,7 +8,7 @@ use serde::{ }; use crate::{ - transaction::{AuthenticatedTransaction, SignedTransaction, TransactionBody}, + transaction::{AuthenticatedTransaction, Transaction, TransactionBody}, utxo_commitment::UTXOCommitment, }; @@ -84,7 +84,7 @@ impl<'de, Leav: TreeLeavItem + Clone + Deserialize<'de>> serde::Deserialize<'de> } } -pub type PublicTransactionMerkleTree = HashStorageMerkleTree; +pub type PublicTransactionMerkleTree = HashStorageMerkleTree; pub type UTXOCommitmentsMerkleTree = HashStorageMerkleTree; diff --git a/common/src/merkle_tree_public/tree_leav_item.rs b/common/src/merkle_tree_public/tree_leav_item.rs index 5599172..fadc4c8 100644 --- a/common/src/merkle_tree_public/tree_leav_item.rs +++ b/common/src/merkle_tree_public/tree_leav_item.rs @@ -1,4 +1,4 @@ -use crate::{transaction::SignedTransaction, utxo_commitment::UTXOCommitment}; +use crate::{transaction::Transaction, utxo_commitment::UTXOCommitment}; use super::TreeHashType; @@ -6,7 +6,7 @@ pub trait TreeLeavItem { fn hash(&self) -> TreeHashType; } -impl TreeLeavItem for SignedTransaction { +impl TreeLeavItem for Transaction { fn hash(&self) -> TreeHashType { self.body.hash() } diff --git a/common/src/rpc_primitives/requests.rs b/common/src/rpc_primitives/requests.rs index 95b004f..532cfb7 100644 --- a/common/src/rpc_primitives/requests.rs +++ b/common/src/rpc_primitives/requests.rs @@ -1,6 +1,6 @@ use crate::block::Block; use crate::parse_request; -use crate::transaction::SignedTransaction; +use crate::transaction::Transaction; use crate::transaction::TransactionBody; use super::errors::RpcParseError; @@ -21,7 +21,7 @@ pub struct RegisterAccountRequest { #[derive(Serialize, Deserialize, Debug)] pub struct SendTxRequest { - pub transaction: SignedTransaction, + pub transaction: Transaction, ///UTXO Commitment Root, Pub Tx Root pub tx_roots: [[u8; 32]; 2], } diff --git a/common/src/transaction.rs b/common/src/transaction.rs index 68bf640..d79c832 100644 --- a/common/src/transaction.rs +++ b/common/src/transaction.rs @@ -27,7 +27,7 @@ pub type CipherText = Vec; pub type Nonce = GenericArray, B1>, B0>, B0>>; pub type Tag = u8; -#[derive(Debug, Serialize, Deserialize, Clone, Copy)] +#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)] pub enum TxKind { Public, Private, @@ -35,7 +35,7 @@ pub enum TxKind { Deshielded, } -#[derive(Debug, Serialize, Deserialize, Clone)] +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] ///General transaction object pub struct TransactionBody { pub tx_kind: TxKind, @@ -233,18 +233,15 @@ pub type SignaturePrivateKey = SigningKey; /// A transaction with a signature. /// Meant to be sent through the network to the sequencer -#[derive(Debug, Serialize, Deserialize, Clone)] -pub struct SignedTransaction { +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] +pub struct Transaction { pub body: TransactionBody, signature: TransactionSignature, public_key: VerifyingKey, } -impl SignedTransaction { - pub fn from_transaction_body( - body: TransactionBody, - private_key: SigningKey, - ) -> SignedTransaction { +impl Transaction { + pub fn new(body: TransactionBody, private_key: SigningKey) -> Transaction { let hash = body.hash(); let signature: TransactionSignature = private_key.sign(&hash); let public_key = VerifyingKey::from(&private_key); @@ -264,27 +261,27 @@ impl SignedTransaction { Ok(AuthenticatedTransaction { hash, - signed_tx: self, + transaction: self, }) } } /// A transaction with a valid signature over the hash of its body. -/// Can only be constructed from an `SignedTransaction` +/// Can only be constructed from an `Transaction` /// if the signature is valid -#[derive(Clone)] +#[derive(Debug, Clone)] pub struct AuthenticatedTransaction { hash: TransactionHash, - signed_tx: SignedTransaction, + transaction: Transaction, } impl AuthenticatedTransaction { - pub fn as_signed(&self) -> &SignedTransaction { - &self.signed_tx + pub fn as_transaction(&self) -> &Transaction { + &self.transaction } pub fn body(&self) -> &TransactionBody { - &self.signed_tx.body + &self.transaction.body } pub fn hash(&self) -> &TransactionHash { @@ -294,17 +291,18 @@ impl AuthenticatedTransaction { #[cfg(test)] mod tests { + use super::*; + use k256::FieldBytes; use secp256k1_zkp::{constants::SECRET_KEY_SIZE, Tweak}; use sha2::{digest::FixedOutput, Digest}; use crate::{ merkle_tree_public::TreeHashType, - transaction::{TransactionBody, TxKind}, + transaction::{Transaction, TransactionBody, TxKind}, }; - #[test] - fn test_transaction_hash_is_sha256_of_json_bytes() { - let tx = TransactionBody { + fn test_transaction_body() -> TransactionBody { + TransactionBody { tx_kind: TxKind::Public, execution_input: vec![1, 2, 3, 4], execution_output: vec![5, 6, 7, 8], @@ -319,16 +317,72 @@ mod tests { secret_r: [8; 32], sc_addr: "someAddress".to_string(), state_changes: (serde_json::Value::Null, 10), - }; + } + } + + #[test] + fn test_transaction_hash_is_sha256_of_json_bytes() { + let body = test_transaction_body(); 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(); hasher.update(&data); TreeHashType::from(hasher.finalize_fixed()) }; - let hash = tx.hash(); + let hash = body.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_into_authenticated_succeeds_for_valid_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 = Transaction::new(body, private_key.clone()); + let authenticated_tx = transaction.clone().into_authenticated().unwrap(); + + let signature = authenticated_tx.as_transaction().signature; + let hash = authenticated_tx.hash(); + assert_eq!(authenticated_tx.as_transaction(), &transaction); + assert_eq!(hash, &transaction.body.hash()); + + assert!(authenticated_tx + .as_transaction() + .public_key + .verify(hash, &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) + ); + } } diff --git a/node_core/src/chain_storage/block_store.rs b/node_core/src/chain_storage/block_store.rs index c6bc386..bcb988b 100644 --- a/node_core/src/chain_storage/block_store.rs +++ b/node_core/src/chain_storage/block_store.rs @@ -6,7 +6,7 @@ use anyhow::{anyhow, Result}; use common::block::Block; use common::merkle_tree_public::merkle_tree::HashStorageMerkleTree; use common::nullifier::UTXONullifier; -use common::transaction::{AuthenticatedTransaction, SignedTransaction, TransactionBody}; +use common::transaction::{AuthenticatedTransaction, Transaction, TransactionBody}; use common::utxo_commitment::UTXOCommitment; use log::error; use storage::sc_db_utils::{DataBlob, DataBlobChangeVariant}; @@ -87,7 +87,7 @@ impl NodeBlockStore { )?) } - pub fn get_snapshot_transaction(&self) -> Result> { + pub fn get_snapshot_transaction(&self) -> Result> { Ok(serde_json::from_slice( &self.dbio.get_snapshot_transaction()?, )?) diff --git a/node_core/src/chain_storage/mod.rs b/node_core/src/chain_storage/mod.rs index bb8641a..32a2eea 100644 --- a/node_core/src/chain_storage/mod.rs +++ b/node_core/src/chain_storage/mod.rs @@ -279,7 +279,7 @@ mod tests { use accounts::account_core::Account; use common::block::{Block, Data}; use common::merkle_tree_public::TreeHashType; - use common::transaction::{SignaturePrivateKey, SignedTransaction, TransactionBody, TxKind}; + use common::transaction::{SignaturePrivateKey, Transaction, TransactionBody, TxKind}; use secp256k1_zkp::Tweak; use std::path::PathBuf; use tempfile::tempdir; @@ -301,7 +301,7 @@ mod tests { nullifier_created_hashes: Vec<[u8; 32]>, utxo_commitments_spent_hashes: Vec<[u8; 32]>, utxo_commitments_created_hashes: Vec<[u8; 32]>, - ) -> SignedTransaction { + ) -> Transaction { let mut rng = rand::thread_rng(); let body = TransactionBody { @@ -320,7 +320,7 @@ mod tests { sc_addr: "sc_addr".to_string(), state_changes: (serde_json::Value::Null, 0), }; - SignedTransaction::from_transaction_body(body, SignaturePrivateKey::random(&mut rng)) + Transaction::new(body, SignaturePrivateKey::random(&mut rng)) } fn create_sample_block(block_id: u64, prev_block_id: u64) -> Block { diff --git a/node_core/src/lib.rs b/node_core/src/lib.rs index 0c10578..45b0988 100644 --- a/node_core/src/lib.rs +++ b/node_core/src/lib.rs @@ -3,7 +3,7 @@ use std::sync::{ Arc, }; -use common::{transaction::SignedTransaction, ExecutionFailureKind}; +use common::{transaction::Transaction, ExecutionFailureKind}; use accounts::account_core::{Account, AccountAddress}; use anyhow::Result; @@ -189,7 +189,7 @@ impl NodeCore { &self, acc: AccountAddress, amount: u128, - ) -> Result<(SignedTransaction, [u8; 32]), ExecutionFailureKind> { + ) -> Result<(Transaction, [u8; 32]), ExecutionFailureKind> { let (utxo, receipt) = prove_mint_utxo(amount, acc)?; let result_hash = utxo.hash; @@ -267,7 +267,7 @@ impl NodeCore { let key_to_sign_transaction = account.key_holder.get_pub_account_signing_key(); Ok(( - SignedTransaction::from_transaction_body(transaction_body, key_to_sign_transaction), + Transaction::new(transaction_body, key_to_sign_transaction), result_hash, )) } @@ -277,7 +277,7 @@ impl NodeCore { acc: AccountAddress, amount: u128, number_of_assets: usize, - ) -> Result<(SignedTransaction, Vec<[u8; 32]>), ExecutionFailureKind> { + ) -> Result<(Transaction, Vec<[u8; 32]>), ExecutionFailureKind> { let (utxos, receipt) = prove_mint_utxo_multiple_assets(amount, number_of_assets, acc)?; let result_hashes = utxos.iter().map(|utxo| utxo.hash).collect(); @@ -364,7 +364,7 @@ impl NodeCore { let key_to_sign_transaction = account.key_holder.get_pub_account_signing_key(); Ok(( - SignedTransaction::from_transaction_body(transaction_body, key_to_sign_transaction), + Transaction::new(transaction_body, key_to_sign_transaction), result_hashes, )) } @@ -374,7 +374,7 @@ impl NodeCore { utxo: UTXO, commitment_in: [u8; 32], receivers: Vec<(u128, AccountAddress)>, - ) -> Result<(SignedTransaction, Vec<(AccountAddress, [u8; 32])>), ExecutionFailureKind> { + ) -> Result<(Transaction, Vec<(AccountAddress, [u8; 32])>), ExecutionFailureKind> { let acc_map_read_guard = self.storage.read().await; let account = acc_map_read_guard.acc_map.get(&utxo.owner).unwrap(); @@ -481,7 +481,7 @@ impl NodeCore { let key_to_sign_transaction = account.key_holder.get_pub_account_signing_key(); Ok(( - SignedTransaction::from_transaction_body(transaction_body, key_to_sign_transaction), + Transaction::new(transaction_body, key_to_sign_transaction), utxo_hashes, )) } @@ -492,7 +492,7 @@ impl NodeCore { commitments_in: Vec<[u8; 32]>, number_to_send: usize, receiver: AccountAddress, - ) -> Result<(SignedTransaction, Vec<[u8; 32]>, Vec<[u8; 32]>), ExecutionFailureKind> { + ) -> Result<(Transaction, Vec<[u8; 32]>, Vec<[u8; 32]>), ExecutionFailureKind> { let acc_map_read_guard = self.storage.read().await; let account = acc_map_read_guard.acc_map.get(&utxos[0].owner).unwrap(); @@ -627,7 +627,7 @@ impl NodeCore { let key_to_sign_transaction = account.key_holder.get_pub_account_signing_key(); Ok(( - SignedTransaction::from_transaction_body(transaction_body, key_to_sign_transaction), + Transaction::new(transaction_body, key_to_sign_transaction), utxo_hashes_receiver, utxo_hashes_not_spent, )) @@ -638,7 +638,7 @@ impl NodeCore { acc: AccountAddress, balance: u64, receivers: Vec<(u128, AccountAddress)>, - ) -> Result<(SignedTransaction, Vec<(AccountAddress, [u8; 32])>), ExecutionFailureKind> { + ) -> Result<(Transaction, Vec<(AccountAddress, [u8; 32])>), ExecutionFailureKind> { let acc_map_read_guard = self.storage.read().await; let account = acc_map_read_guard.acc_map.get(&acc).unwrap(); @@ -757,7 +757,7 @@ impl NodeCore { let key_to_sign_transaction = account.key_holder.get_pub_account_signing_key(); Ok(( - SignedTransaction::from_transaction_body(transaction_body, key_to_sign_transaction), + Transaction::new(transaction_body, key_to_sign_transaction), utxo_hashes, )) } @@ -767,7 +767,7 @@ impl NodeCore { utxo: UTXO, comm_gen_hash: [u8; 32], receivers: Vec<(u128, AccountAddress)>, - ) -> Result { + ) -> Result { let acc_map_read_guard = self.storage.read().await; let commitment_in = acc_map_read_guard @@ -847,10 +847,7 @@ impl NodeCore { let key_to_sign_transaction = account.key_holder.get_pub_account_signing_key(); - Ok(SignedTransaction::from_transaction_body( - transaction_body, - key_to_sign_transaction, - )) + Ok(Transaction::new(transaction_body, key_to_sign_transaction)) } pub async fn send_private_mint_tx( @@ -1369,7 +1366,7 @@ impl NodeCore { commitment_in: [u8; 32], receivers: Vec<(u128, AccountAddress)>, visibility_list: [bool; 3], - ) -> Result<(SignedTransaction, Vec<(AccountAddress, [u8; 32])>), ExecutionFailureKind> { + ) -> Result<(Transaction, Vec<(AccountAddress, [u8; 32])>), ExecutionFailureKind> { let acc_map_read_guard = self.storage.read().await; let account = acc_map_read_guard.acc_map.get(&utxo.owner).unwrap(); @@ -1490,7 +1487,7 @@ impl NodeCore { let key_to_sign_transaction = account.key_holder.get_pub_account_signing_key(); Ok(( - SignedTransaction::from_transaction_body(transaction_body, key_to_sign_transaction), + Transaction::new(transaction_body, key_to_sign_transaction), utxo_hashes, )) } diff --git a/node_core/src/sequencer_client/json.rs b/node_core/src/sequencer_client/json.rs index 9275ca5..df94ca2 100644 --- a/node_core/src/sequencer_client/json.rs +++ b/node_core/src/sequencer_client/json.rs @@ -1,11 +1,11 @@ -use common::transaction::SignedTransaction; +use common::transaction::Transaction; use serde::{Deserialize, Serialize}; //Requests #[derive(Serialize, Deserialize, Debug)] pub struct SendTxRequest { - pub transaction: SignedTransaction, + pub transaction: Transaction, ///UTXO Commitment Root, Pub Tx Root pub tx_roots: [[u8; 32]; 2], } diff --git a/node_core/src/sequencer_client/mod.rs b/node_core/src/sequencer_client/mod.rs index 95a3378..7accd5f 100644 --- a/node_core/src/sequencer_client/mod.rs +++ b/node_core/src/sequencer_client/mod.rs @@ -4,7 +4,7 @@ use common::rpc_primitives::requests::{ GetBlockDataRequest, GetBlockDataResponse, GetGenesisIdRequest, GetGenesisIdResponse, RegisterAccountRequest, RegisterAccountResponse, }; -use common::transaction::SignedTransaction; +use common::transaction::Transaction; use common::{SequencerClientError, SequencerRpcError}; use json::{SendTxRequest, SendTxResponse, SequencerRpcRequest, SequencerRpcResponse}; use k256::elliptic_curve::group::GroupEncoding; @@ -72,7 +72,7 @@ impl SequencerClient { pub async fn send_tx( &self, - transaction: SignedTransaction, + transaction: Transaction, tx_roots: [[u8; 32]; 2], ) -> Result { let tx_req = SendTxRequest { diff --git a/sequencer_core/src/lib.rs b/sequencer_core/src/lib.rs index 174763e..3a74119 100644 --- a/sequencer_core/src/lib.rs +++ b/sequencer_core/src/lib.rs @@ -5,7 +5,7 @@ use common::{ block::{Block, HashableBlockData}, merkle_tree_public::TreeHashType, nullifier::UTXONullifier, - transaction::{AuthenticatedTransaction, SignedTransaction, TransactionBody, TxKind}, + transaction::{AuthenticatedTransaction, Transaction, TransactionBody, TxKind}, utxo_commitment::UTXOCommitment, }; use config::SequencerConfig; @@ -72,7 +72,7 @@ impl SequencerCore { pub fn transaction_pre_check( &mut self, - tx: SignedTransaction, + tx: Transaction, tx_roots: [[u8; 32]; 2], ) -> Result { let tx = tx @@ -174,17 +174,17 @@ impl SequencerCore { pub fn push_tx_into_mempool_pre_check( &mut self, - signed_tx: SignedTransaction, + transaction: Transaction, tx_roots: [[u8; 32]; 2], ) -> Result<(), TransactionMalformationErrorKind> { let mempool_size = self.mempool.len(); if mempool_size >= self.sequencer_config.max_num_tx_in_block { return Err(TransactionMalformationErrorKind::MempoolFullForRound { - tx: signed_tx.body.hash(), + tx: transaction.body.hash(), }); } - let authenticated_tx = self.transaction_pre_check(signed_tx, tx_roots)?; + let authenticated_tx = self.transaction_pre_check(transaction, tx_roots)?; self.mempool.push_item(authenticated_tx.into()); @@ -213,7 +213,7 @@ impl SequencerCore { }); } - self.store.pub_tx_store.add_tx(tx.tx.as_signed()); + self.store.pub_tx_store.add_tx(tx.tx.as_transaction()); Ok(()) } @@ -248,7 +248,7 @@ impl SequencerCore { prev_block_id: self.chain_height, transactions: transactions .into_iter() - .map(|tx_mem| tx_mem.tx.as_signed().clone()) + .map(|tx_mem| tx_mem.tx.as_transaction().clone()) .collect(), data: vec![], prev_block_hash, @@ -269,7 +269,7 @@ mod tests { use super::*; use std::path::PathBuf; - use common::transaction::{SignaturePrivateKey, SignedTransaction, TransactionBody, TxKind}; + use common::transaction::{SignaturePrivateKey, Transaction, TransactionBody, TxKind}; use rand::Rng; use secp256k1_zkp::Tweak; use transaction_mempool::MempoolTransaction; @@ -295,7 +295,7 @@ mod tests { nullifier_created_hashes: Vec<[u8; 32]>, utxo_commitments_spent_hashes: Vec<[u8; 32]>, utxo_commitments_created_hashes: Vec<[u8; 32]>, - ) -> SignedTransaction { + ) -> Transaction { let mut rng = rand::thread_rng(); let body = TransactionBody { @@ -314,7 +314,7 @@ mod tests { sc_addr: "sc_addr".to_string(), state_changes: (serde_json::Value::Null, 0), }; - SignedTransaction::from_transaction_body(body, SignaturePrivateKey::random(&mut rng)) + Transaction::new(body, SignaturePrivateKey::random(&mut rng)) } fn common_setup(sequencer: &mut SequencerCore) { From e79c30f765d45eb65eb761bb429dca89ca345d75 Mon Sep 17 00:00:00 2001 From: Sergio Chouhy Date: Wed, 16 Jul 2025 11:43:40 -0300 Subject: [PATCH 17/36] add test for signing key getter --- accounts/src/key_management/mod.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/accounts/src/key_management/mod.rs b/accounts/src/key_management/mod.rs index e871a0f..e3ba4b3 100644 --- a/accounts/src/key_management/mod.rs +++ b/accounts/src/key_management/mod.rs @@ -325,6 +325,16 @@ mod tests { 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] fn key_generation_test() { let seed_holder = SeedHolder::new_os_random(); From c60c7235c13ab8d5e38ae03a8877a71ee4b0304c Mon Sep 17 00:00:00 2001 From: Sergio Chouhy Date: Wed, 16 Jul 2025 11:54:11 -0300 Subject: [PATCH 18/36] add getter for transaction body and test it --- accounts/src/key_management/mod.rs | 1 + .../src/merkle_tree_public/tree_leav_item.rs | 2 +- common/src/transaction.rs | 61 +++++++++++++++---- node_core/src/chain_storage/mod.rs | 15 ++--- node_core/src/lib.rs | 20 +++--- node_rpc/src/process.rs | 16 ++--- sequencer_core/src/lib.rs | 26 ++++---- ...tion_mempool.rs => mempool_transaction.rs} | 8 +-- 8 files changed, 94 insertions(+), 55 deletions(-) rename sequencer_core/src/{transaction_mempool.rs => mempool_transaction.rs} (72%) diff --git a/accounts/src/key_management/mod.rs b/accounts/src/key_management/mod.rs index e3ba4b3..ea4eff2 100644 --- a/accounts/src/key_management/mod.rs +++ b/accounts/src/key_management/mod.rs @@ -58,6 +58,7 @@ impl AddressKeyHolder { } } + /// 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 diff --git a/common/src/merkle_tree_public/tree_leav_item.rs b/common/src/merkle_tree_public/tree_leav_item.rs index fadc4c8..3b919a8 100644 --- a/common/src/merkle_tree_public/tree_leav_item.rs +++ b/common/src/merkle_tree_public/tree_leav_item.rs @@ -8,7 +8,7 @@ pub trait TreeLeavItem { impl TreeLeavItem for Transaction { fn hash(&self) -> TreeHashType { - self.body.hash() + self.body().hash() } } diff --git a/common/src/transaction.rs b/common/src/transaction.rs index d79c832..b48afce 100644 --- a/common/src/transaction.rs +++ b/common/src/transaction.rs @@ -231,16 +231,18 @@ pub type TransactionSignature = Signature; pub type SignaturePublicKey = VerifyingKey; pub type SignaturePrivateKey = SigningKey; -/// A transaction with a signature. +/// 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 { - pub body: TransactionBody, + 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 hash = body.hash(); let signature: TransactionSignature = private_key.sign(&hash); @@ -252,6 +254,8 @@ impl Transaction { } } + /// Converts the transaction into an `AuthenticatedTransaction` by verifying its signature. + /// Returns an error if the signature verification fails. pub fn into_authenticated(self) -> Result { let hash = self.body.hash(); @@ -264,6 +268,11 @@ impl Transaction { 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. @@ -276,14 +285,12 @@ pub struct AuthenticatedTransaction { } impl AuthenticatedTransaction { - pub fn as_transaction(&self) -> &Transaction { + /// Returns the underlying transaction + pub fn transaction(&self) -> &Transaction { &self.transaction } - pub fn body(&self) -> &TransactionBody { - &self.transaction.body - } - + /// Returns the precomputed hash over the body of the transaction pub fn hash(&self) -> &TransactionHash { &self.hash } @@ -320,6 +327,13 @@ mod tests { } } + 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(); @@ -349,20 +363,26 @@ mod tests { } #[test] - fn test_into_authenticated_succeeds_for_valid_signature() { + 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, private_key.clone()); + 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.as_transaction().signature; + let signature = authenticated_tx.transaction().signature; let hash = authenticated_tx.hash(); - assert_eq!(authenticated_tx.as_transaction(), &transaction); - assert_eq!(hash, &transaction.body.hash()); + assert_eq!(authenticated_tx.transaction(), &transaction); + assert_eq!(hash, &transaction.body.hash()); assert!(authenticated_tx - .as_transaction() + .transaction() .public_key .verify(hash, &signature) .is_ok()); @@ -380,9 +400,24 @@ mod tests { 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()); + } } diff --git a/node_core/src/chain_storage/mod.rs b/node_core/src/chain_storage/mod.rs index 32a2eea..f190ff3 100644 --- a/node_core/src/chain_storage/mod.rs +++ b/node_core/src/chain_storage/mod.rs @@ -127,8 +127,9 @@ impl NodeChainStore { let block_id = block.block_id; for tx in &block.transactions { - if !tx.body.execution_input.is_empty() { - let public_action = serde_json::from_slice::(&tx.body.execution_input); + if !tx.body().execution_input.is_empty() { + let public_action = + serde_json::from_slice::(&tx.body().execution_input); if let Ok(public_action) = public_action { match public_action { @@ -162,7 +163,7 @@ impl NodeChainStore { } self.utxo_commitments_store.add_tx_multiple( - tx.body + tx.body() .utxo_commitments_created_hashes .clone() .into_iter() @@ -170,17 +171,17 @@ impl NodeChainStore { .collect(), ); - for nullifier in tx.body.nullifier_created_hashes.iter() { + for nullifier in tx.body().nullifier_created_hashes.iter() { self.nullifier_store.insert(UTXONullifier { utxo_hash: *nullifier, }); } - if !tx.body.encoded_data.is_empty() { + if !tx.body().encoded_data.is_empty() { let ephemeral_public_key_sender = - serde_json::from_slice::(&tx.body.ephemeral_pub_key)?; + serde_json::from_slice::(&tx.body().ephemeral_pub_key)?; - for (ciphertext, nonce, tag) in tx.body.encoded_data.clone() { + for (ciphertext, nonce, tag) in tx.body().encoded_data.clone() { let slice = nonce.as_slice(); let nonce = accounts::key_management::constants_types::Nonce::clone_from_slice(slice); diff --git a/node_core/src/lib.rs b/node_core/src/lib.rs index 45b0988..7debc2f 100644 --- a/node_core/src/lib.rs +++ b/node_core/src/lib.rs @@ -860,10 +860,10 @@ impl NodeCore { let point_before_prove = std::time::Instant::now(); let (tx, utxo_hash) = self.mint_utxo_private(acc, amount).await?; - tx.body.log(); + tx.body().log(); let point_after_prove = std::time::Instant::now(); - let commitment_generated_hash = tx.body.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(); info!("Mint utxo proof spent {timedelta:?} milliseconds"); @@ -888,10 +888,10 @@ impl NodeCore { let (tx, utxo_hashes) = self .mint_utxo_multiple_assets_private(acc, amount, number_of_assets) .await?; - tx.body.log(); + tx.body().log(); let point_after_prove = std::time::Instant::now(); - let commitment_generated_hashes = tx.body.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(); info!("Mint utxo proof spent {timedelta:?} milliseconds"); @@ -961,7 +961,7 @@ impl NodeCore { let (tx, utxo_hashes) = self .transfer_utxo_private(utxo, comm_hash, receivers) .await?; - tx.body.log(); + tx.body().log(); let point_after_prove = std::time::Instant::now(); let timedelta = (point_after_prove - point_before_prove).as_millis(); @@ -987,7 +987,7 @@ impl NodeCore { let (tx, utxo_hashes_received, utxo_hashes_not_spent) = self .transfer_utxo_multiple_assets_private(utxos, comm_hashes, number_to_send, receiver) .await?; - tx.body.log(); + tx.body().log(); let point_after_prove = std::time::Instant::now(); let timedelta = (point_after_prove - point_before_prove).as_millis(); @@ -1013,7 +1013,7 @@ impl NodeCore { let (tx, utxo_hashes) = self .transfer_balance_shielded(acc, amount, receivers) .await?; - tx.body.log(); + tx.body().log(); let point_after_prove = std::time::Instant::now(); let timedelta = (point_after_prove - point_before_prove).as_millis(); @@ -1038,7 +1038,7 @@ impl NodeCore { let tx = self .transfer_utxo_deshielded(utxo, comm_gen_hash, receivers) .await?; - tx.body.log(); + tx.body().log(); let point_after_prove = std::time::Instant::now(); let timedelta = (point_after_prove - point_before_prove).as_millis(); @@ -1507,13 +1507,13 @@ impl NodeCore { let (tx, utxo_hashes) = self .split_utxo(utxo, comm_hash, receivers, visibility_list) .await?; - tx.body.log(); + tx.body().log(); let point_after_prove = std::time::Instant::now(); let timedelta = (point_after_prove - point_before_prove).as_millis(); info!("Send private utxo proof spent {timedelta:?} milliseconds"); - let commitments = tx.body.utxo_commitments_created_hashes.clone(); + let commitments = tx.body().utxo_commitments_created_hashes.clone(); Ok(( self.sequencer_client.send_tx(tx, tx_roots).await?, diff --git a/node_rpc/src/process.rs b/node_rpc/src/process.rs index a3acd3e..be44794 100644 --- a/node_rpc/src/process.rs +++ b/node_rpc/src/process.rs @@ -303,46 +303,46 @@ impl JsonHandler { ShowTransactionResponse { hash: req.tx_hash, - tx_kind: tx.body.tx_kind, + tx_kind: tx.body().tx_kind, public_input: if let Ok(action) = - serde_json::from_slice::(&tx.body.execution_input) + serde_json::from_slice::(&tx.body().execution_input) { action.into_hexed_print() } else { "".to_string() }, public_output: if let Ok(action) = - serde_json::from_slice::(&tx.body.execution_output) + serde_json::from_slice::(&tx.body().execution_output) { action.into_hexed_print() } else { "".to_string() }, utxo_commitments_created_hashes: tx - .body + .body() .utxo_commitments_created_hashes .iter() .map(|val| hex::encode(val.clone())) .collect::>(), utxo_commitments_spent_hashes: tx - .body + .body() .utxo_commitments_spent_hashes .iter() .map(|val| hex::encode(val.clone())) .collect::>(), utxo_nullifiers_created_hashes: tx - .body + .body() .nullifier_created_hashes .iter() .map(|val| hex::encode(val.clone())) .collect::>(), encoded_data: tx - .body + .body() .encoded_data .iter() .map(|val| (hex::encode(val.0.clone()), hex::encode(val.1.clone()))) .collect::>(), - ephemeral_pub_key: hex::encode(tx.body.ephemeral_pub_key.clone()), + ephemeral_pub_key: hex::encode(tx.body().ephemeral_pub_key.clone()), } } }; diff --git a/sequencer_core/src/lib.rs b/sequencer_core/src/lib.rs index 3a74119..7ee365c 100644 --- a/sequencer_core/src/lib.rs +++ b/sequencer_core/src/lib.rs @@ -10,13 +10,13 @@ use common::{ }; use config::SequencerConfig; use mempool::MemPool; +use mempool_transaction::MempoolTransaction; use sequencer_store::{accounts_store::AccountPublicData, SequecerChainStore}; use serde::{Deserialize, Serialize}; -use transaction_mempool::MempoolTransaction; pub mod config; +pub mod mempool_transaction; pub mod sequencer_store; -pub mod transaction_mempool; pub struct SequencerCore { pub store: SequecerChainStore, @@ -86,7 +86,7 @@ impl SequencerCore { ref utxo_commitments_created_hashes, ref nullifier_created_hashes, .. - } = tx.body(); + } = tx.transaction().body(); let tx_hash = *tx.hash(); @@ -180,7 +180,7 @@ impl SequencerCore { 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(), + tx: transaction.body().hash(), }); } @@ -193,13 +193,13 @@ impl SequencerCore { fn execute_check_transaction_on_state( &mut self, - tx: &MempoolTransaction, + mempool_tx: &MempoolTransaction, ) -> Result<(), TransactionMalformationErrorKind> { let TransactionBody { ref utxo_commitments_created_hashes, ref nullifier_created_hashes, .. - } = tx.tx.body(); + } = mempool_tx.auth_tx.transaction().body(); for utxo_comm in utxo_commitments_created_hashes { self.store @@ -213,7 +213,9 @@ impl SequencerCore { }); } - self.store.pub_tx_store.add_tx(tx.tx.as_transaction()); + self.store + .pub_tx_store + .add_tx(mempool_tx.auth_tx.transaction()); Ok(()) } @@ -248,7 +250,7 @@ impl SequencerCore { prev_block_id: self.chain_height, transactions: transactions .into_iter() - .map(|tx_mem| tx_mem.tx.as_transaction().clone()) + .map(|tx_mem| tx_mem.auth_tx.transaction().clone()) .collect(), data: vec![], prev_block_hash, @@ -270,9 +272,9 @@ mod tests { use std::path::PathBuf; use common::transaction::{SignaturePrivateKey, Transaction, TransactionBody, TxKind}; + use mempool_transaction::MempoolTransaction; use rand::Rng; use secp256k1_zkp::Tweak; - use transaction_mempool::MempoolTransaction; fn setup_sequencer_config() -> SequencerConfig { let mut rng = rand::thread_rng(); @@ -320,7 +322,7 @@ mod tests { fn common_setup(sequencer: &mut SequencerCore) { let tx = create_dummy_transaction(vec![[9; 32]], vec![[7; 32]], vec![[8; 32]]); let tx_mempool = MempoolTransaction { - tx: tx.into_authenticated().unwrap(), + auth_tx: tx.into_authenticated().unwrap(), }; sequencer.mempool.push_item(tx_mempool); @@ -377,7 +379,7 @@ mod tests { // Fill the mempool let dummy_tx = MempoolTransaction { - tx: tx.clone().into_authenticated().unwrap(), + auth_tx: tx.clone().into_authenticated().unwrap(), }; sequencer.mempool.push_item(dummy_tx); @@ -411,7 +413,7 @@ mod tests { let tx = create_dummy_transaction(vec![[94; 32]], vec![[7; 32]], vec![[8; 32]]); let tx_mempool = MempoolTransaction { - tx: tx.into_authenticated().unwrap(), + auth_tx: tx.into_authenticated().unwrap(), }; sequencer.mempool.push_item(tx_mempool); diff --git a/sequencer_core/src/transaction_mempool.rs b/sequencer_core/src/mempool_transaction.rs similarity index 72% rename from sequencer_core/src/transaction_mempool.rs rename to sequencer_core/src/mempool_transaction.rs index fc73fc9..104e063 100644 --- a/sequencer_core/src/transaction_mempool.rs +++ b/sequencer_core/src/mempool_transaction.rs @@ -3,12 +3,12 @@ use mempool::mempoolitem::MemPoolItem; use serde::{Deserialize, Serialize}; pub struct MempoolTransaction { - pub tx: AuthenticatedTransaction, + pub auth_tx: AuthenticatedTransaction, } impl From for MempoolTransaction { - fn from(value: AuthenticatedTransaction) -> Self { - Self { tx: value } + fn from(auth_tx: AuthenticatedTransaction) -> Self { + Self { auth_tx } } } @@ -16,6 +16,6 @@ impl MemPoolItem for MempoolTransaction { type Identifier = TreeHashType; fn identifier(&self) -> Self::Identifier { - *self.tx.hash() + *self.auth_tx.hash() } } From 079b3439819a44f2e2975a28926110e6958fcfaf Mon Sep 17 00:00:00 2001 From: Sergio Chouhy Date: Wed, 16 Jul 2025 13:51:13 -0300 Subject: [PATCH 19/36] remove unused hash parameter in dummy function --- node_core/src/chain_storage/mod.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/node_core/src/chain_storage/mod.rs b/node_core/src/chain_storage/mod.rs index f190ff3..09240fd 100644 --- a/node_core/src/chain_storage/mod.rs +++ b/node_core/src/chain_storage/mod.rs @@ -297,8 +297,6 @@ mod tests { } fn create_dummy_transaction( - hash: TreeHashType, - // execution_input: Vec, nullifier_created_hashes: Vec<[u8; 32]>, utxo_commitments_spent_hashes: Vec<[u8; 32]>, utxo_commitments_created_hashes: Vec<[u8; 32]>, @@ -418,7 +416,6 @@ mod tests { .utxo_commitments_store .add_tx_multiple(vec![UTXOCommitment { hash: [3u8; 32] }]); store.pub_tx_store.add_tx(&create_dummy_transaction( - [12; 32], vec![[9; 32]], vec![[7; 32]], vec![[8; 32]], From 6d5e2a1a9ffbd8832d7c231bafcbd4674e0b6c96 Mon Sep 17 00:00:00 2001 From: Sergio Chouhy Date: Thu, 17 Jul 2025 08:36:46 -0300 Subject: [PATCH 20/36] change variable name --- accounts/src/key_management/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/accounts/src/key_management/mod.rs b/accounts/src/key_management/mod.rs index 0ad0b4c..66c02c6 100644 --- a/accounts/src/key_management/mod.rs +++ b/accounts/src/key_management/mod.rs @@ -42,7 +42,7 @@ impl AddressKeyHolder { 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 pub_account_secret_key = { + let pub_account_signing_key = { let mut bytes = [0; 32]; OsRng.fill_bytes(&mut bytes); bytes @@ -54,7 +54,7 @@ impl AddressKeyHolder { address, nullifer_public_key, viewing_public_key, - pub_account_signing_key: pub_account_secret_key, + pub_account_signing_key, } } From b9d3f921e916a703aac75fd6339008b6a4c17f0f Mon Sep 17 00:00:00 2001 From: Oleksandr Pravdyvyi Date: Fri, 18 Jul 2025 11:13:45 +0300 Subject: [PATCH 21/36] fix: latest lint fixes --- node_core/src/lib.rs | 14 ++++++------ sc_core/src/blob_utils.rs | 22 +++++++------------ sc_core/src/proofs_circuits.rs | 8 +++---- sc_core/src/transaction_payloads_tools.rs | 2 +- sequencer_core/src/lib.rs | 8 +++---- .../src/sequencer_store/accounts_store.rs | 13 +++++++++++ storage/src/sc_db_utils.rs | 3 +-- 7 files changed, 38 insertions(+), 32 deletions(-) diff --git a/node_core/src/lib.rs b/node_core/src/lib.rs index 6db11b4..a7aa422 100644 --- a/node_core/src/lib.rs +++ b/node_core/src/lib.rs @@ -207,7 +207,7 @@ impl NodeCore { serde_json::to_vec(&ephm_key_holder.generate_ephemeral_public_key()).unwrap(); let encoded_data = Account::encrypt_data( - ephm_key_holder, + &ephm_key_holder, account.key_holder.viewing_public_key, &serde_json::to_vec(&utxo).unwrap(), ); @@ -299,7 +299,7 @@ impl NodeCore { .map(|utxo| { ( Account::encrypt_data( - ephm_key_holder, + &ephm_key_holder, account.key_holder.viewing_public_key, &serde_json::to_vec(&utxo).unwrap(), ), @@ -413,7 +413,7 @@ impl NodeCore { let accout_enc = acc_map_read_guard.acc_map.get(&utxo_enc.owner).unwrap(); let (ciphertext, nonce) = Account::encrypt_data( - ephm_key_holder, + &ephm_key_holder, accout_enc.key_holder.viewing_public_key, &serde_json::to_vec(&utxo_enc).unwrap(), ); @@ -534,7 +534,7 @@ impl NodeCore { let accout_enc = acc_map_read_guard.acc_map.get(&utxo_enc.owner).unwrap(); let (ciphertext, nonce) = Account::encrypt_data( - ephm_key_holder, + &ephm_key_holder, accout_enc.key_holder.viewing_public_key, &serde_json::to_vec(&utxo_enc).unwrap(), ); @@ -551,7 +551,7 @@ impl NodeCore { let accout_enc = acc_map_read_guard.acc_map.get(&utxo_enc.owner).unwrap(); let (ciphertext, nonce) = Account::encrypt_data( - ephm_key_holder, + &ephm_key_holder, accout_enc.key_holder.viewing_public_key, &serde_json::to_vec(&utxo_enc).unwrap(), ); @@ -678,7 +678,7 @@ impl NodeCore { let accout_enc = acc_map_read_guard.acc_map.get(&utxo_enc.owner).unwrap(); let (ciphertext, nonce) = Account::encrypt_data( - ephm_key_holder, + &ephm_key_holder, accout_enc.key_holder.viewing_public_key, &serde_json::to_vec(&utxo_enc).unwrap(), ); @@ -1392,7 +1392,7 @@ impl NodeCore { let accout_enc = acc_map_read_guard.acc_map.get(&utxo_enc.owner).unwrap(); let (ciphertext, nonce) = Account::encrypt_data( - ephm_key_holder, + &ephm_key_holder, accout_enc.key_holder.viewing_public_key, &serde_json::to_vec(&utxo_enc).unwrap(), ); diff --git a/sc_core/src/blob_utils.rs b/sc_core/src/blob_utils.rs index d0a3485..7c5a34c 100644 --- a/sc_core/src/blob_utils.rs +++ b/sc_core/src/blob_utils.rs @@ -16,19 +16,13 @@ pub fn produce_blob_list_from_sc_public_state( //`ToDo` Replace with `next_chunk` usage, when feature stabilizes in Rust for i in 0..=(ser_data.len() / SC_DATA_BLOB_SIZE) { - let next_chunk: Vec; - - if (i + 1) * SC_DATA_BLOB_SIZE < ser_data.len() { - next_chunk = ser_data[(i * SC_DATA_BLOB_SIZE)..((i + 1) * SC_DATA_BLOB_SIZE)] - .iter() - .cloned() - .collect(); + let next_chunk: Vec = if (i + 1) * SC_DATA_BLOB_SIZE < ser_data.len() { + ser_data[(i * SC_DATA_BLOB_SIZE)..((i + 1) * SC_DATA_BLOB_SIZE)] + .to_vec() } else { - next_chunk = ser_data[(i * SC_DATA_BLOB_SIZE)..(ser_data.len())] - .iter() - .cloned() - .collect(); - } + ser_data[(i * SC_DATA_BLOB_SIZE)..(ser_data.len())] + .to_vec() + }; blob_list.push(produce_blob_from_fit_vec(next_chunk)); } @@ -52,10 +46,10 @@ pub fn compare_blob_lists( changed_ids.push(DataBlobChangeVariant::Deleted { id }); } } else if new_len > old_len { - for id in old_len..new_len { + for (id, blob) in blob_list_new.iter().enumerate().take(new_len).skip(old_len) { changed_ids.push(DataBlobChangeVariant::Created { id, - blob: blob_list_new[id], + blob: *blob, }); } } diff --git a/sc_core/src/proofs_circuits.rs b/sc_core/src/proofs_circuits.rs index 24e7175..5143922 100644 --- a/sc_core/src/proofs_circuits.rs +++ b/sc_core/src/proofs_circuits.rs @@ -52,10 +52,10 @@ pub fn generate_commitments(input_utxos: &[UTXO]) -> Vec> { /// /// ToDo: Solve it in more scalable way pub fn validate_in_commitments_tree( - in_commitment: &Vec, + in_commitment: &[u8], commitment_tree: &UTXOCommitmentsMerkleTree, ) -> bool { - let alighned_hash: [u8; 32] = in_commitment.clone().try_into().unwrap(); + let alighned_hash: [u8; 32] = in_commitment.try_into().unwrap(); commitment_tree.get_proof(alighned_hash).is_some() } @@ -104,7 +104,7 @@ pub fn private_circuit( assert!(!public_context.nullifiers_set.contains(&nullifier)); } - (in_nullifiers, generate_commitments(&output_utxos)) + (in_nullifiers, generate_commitments(output_utxos)) } /// Check balances DE @@ -124,7 +124,7 @@ pub fn deshielded_circuit( ) -> Vec> { assert!(check_balances_de(input_utxos, output_balance)); - let in_commitments = generate_commitments(&input_utxos); + let in_commitments = generate_commitments(input_utxos); let mut in_nullifiers = vec![]; diff --git a/sc_core/src/transaction_payloads_tools.rs b/sc_core/src/transaction_payloads_tools.rs index fffde71..bf138d4 100644 --- a/sc_core/src/transaction_payloads_tools.rs +++ b/sc_core/src/transaction_payloads_tools.rs @@ -43,7 +43,7 @@ pub fn encode_utxos_to_receivers( let ephm_key_holder = EphemeralKeyHolder::new_os_random(); let encoded_data = Account::encrypt_data( - ephm_key_holder, + &ephm_key_holder, receiver.key_holder.viewing_public_key, &serde_json::to_vec(&utxo).unwrap(), ); diff --git a/sequencer_core/src/lib.rs b/sequencer_core/src/lib.rs index d75ce1f..83ee5c7 100644 --- a/sequencer_core/src/lib.rs +++ b/sequencer_core/src/lib.rs @@ -344,13 +344,13 @@ mod tests { assert_eq!(sequencer.sequencer_config.port, 8080); let acc1_addr: [u8; 32] = hex::decode( - "bfd91e6703273a115ad7f099ef32f621243be69369d00ddef5d3a25117d09a8c".to_string(), + "bfd91e6703273a115ad7f099ef32f621243be69369d00ddef5d3a25117d09a8c", ) .unwrap() .try_into() .unwrap(); let acc2_addr: [u8; 32] = hex::decode( - "20573479053979b98d2ad09ef31a0750f22c77709bed51c4e64946bd1e376f31".to_string(), + "20573479053979b98d2ad09ef31a0750f22c77709bed51c4e64946bd1e376f31", ) .unwrap() .try_into() @@ -398,13 +398,13 @@ mod tests { let sequencer = SequencerCore::start_from_config(config.clone()); let acc1_addr: [u8; 32] = hex::decode( - "bfd91e6703273a115ad7f099ef32f621243be69369d00ddef5d3a25117ffffff".to_string(), + "bfd91e6703273a115ad7f099ef32f621243be69369d00ddef5d3a25117ffffff", ) .unwrap() .try_into() .unwrap(); let acc2_addr: [u8; 32] = hex::decode( - "20573479053979b98d2ad09ef31a0750f22c77709bed51c4e64946bd1effffff".to_string(), + "20573479053979b98d2ad09ef31a0750f22c77709bed51c4e64946bd1effffff", ) .unwrap() .try_into() diff --git a/sequencer_core/src/sequencer_store/accounts_store.rs b/sequencer_core/src/sequencer_store/accounts_store.rs index 853247f..8e0d61b 100644 --- a/sequencer_core/src/sequencer_store/accounts_store.rs +++ b/sequencer_core/src/sequencer_store/accounts_store.rs @@ -85,6 +85,11 @@ impl SequencerAccountsStore { pub fn len(&self) -> usize { self.accounts.len() } + + ///Is accounts store empty + pub fn is_empty(&self) -> bool { + self.accounts.is_empty() + } } impl Default for SequencerAccountsStore { @@ -213,4 +218,12 @@ mod tests { assert!(acc_balance.is_none()); } + + #[test] + fn account_sequencer_store_is_empty_test() { + let seq_acc_store = + SequencerAccountsStore::default(); + + assert!(seq_acc_store.is_empty()); + } } diff --git a/storage/src/sc_db_utils.rs b/storage/src/sc_db_utils.rs index 0a682ba..c86828e 100644 --- a/storage/src/sc_db_utils.rs +++ b/storage/src/sc_db_utils.rs @@ -1,5 +1,3 @@ -use std::cmp::Ordering; - use serde::{de::Error, Deserialize, Serialize}; use crate::SC_DATA_BLOB_SIZE; @@ -51,6 +49,7 @@ impl DataBlob { } } +#[allow(clippy::large_enum_variant)] #[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)] pub enum DataBlobChangeVariant { Created { From eb16534ad92444908c05f4e89bc48ad3501cf4b7 Mon Sep 17 00:00:00 2001 From: Oleksandr Pravdyvyi Date: Fri, 18 Jul 2025 11:25:50 +0300 Subject: [PATCH 22/36] fix: fmt --- sc_core/src/blob_utils.rs | 11 ++--- sequencer_core/src/lib.rs | 44 +++++++++---------- .../src/sequencer_store/accounts_store.rs | 5 +-- 3 files changed, 25 insertions(+), 35 deletions(-) diff --git a/sc_core/src/blob_utils.rs b/sc_core/src/blob_utils.rs index 7c5a34c..d1210ba 100644 --- a/sc_core/src/blob_utils.rs +++ b/sc_core/src/blob_utils.rs @@ -17,11 +17,9 @@ pub fn produce_blob_list_from_sc_public_state( //`ToDo` Replace with `next_chunk` usage, when feature stabilizes in Rust for i in 0..=(ser_data.len() / SC_DATA_BLOB_SIZE) { let next_chunk: Vec = if (i + 1) * SC_DATA_BLOB_SIZE < ser_data.len() { - ser_data[(i * SC_DATA_BLOB_SIZE)..((i + 1) * SC_DATA_BLOB_SIZE)] - .to_vec() + ser_data[(i * SC_DATA_BLOB_SIZE)..((i + 1) * SC_DATA_BLOB_SIZE)].to_vec() } else { - ser_data[(i * SC_DATA_BLOB_SIZE)..(ser_data.len())] - .to_vec() + ser_data[(i * SC_DATA_BLOB_SIZE)..(ser_data.len())].to_vec() }; blob_list.push(produce_blob_from_fit_vec(next_chunk)); @@ -47,10 +45,7 @@ pub fn compare_blob_lists( } } else if new_len > old_len { for (id, blob) in blob_list_new.iter().enumerate().take(new_len).skip(old_len) { - changed_ids.push(DataBlobChangeVariant::Created { - id, - blob: *blob, - }); + changed_ids.push(DataBlobChangeVariant::Created { id, blob: *blob }); } } diff --git a/sequencer_core/src/lib.rs b/sequencer_core/src/lib.rs index 83ee5c7..1129e31 100644 --- a/sequencer_core/src/lib.rs +++ b/sequencer_core/src/lib.rs @@ -343,18 +343,16 @@ mod tests { assert_eq!(sequencer.sequencer_config.max_num_tx_in_block, 10); assert_eq!(sequencer.sequencer_config.port, 8080); - let acc1_addr: [u8; 32] = hex::decode( - "bfd91e6703273a115ad7f099ef32f621243be69369d00ddef5d3a25117d09a8c", - ) - .unwrap() - .try_into() - .unwrap(); - let acc2_addr: [u8; 32] = hex::decode( - "20573479053979b98d2ad09ef31a0750f22c77709bed51c4e64946bd1e376f31", - ) - .unwrap() - .try_into() - .unwrap(); + let acc1_addr: [u8; 32] = + hex::decode("bfd91e6703273a115ad7f099ef32f621243be69369d00ddef5d3a25117d09a8c") + .unwrap() + .try_into() + .unwrap(); + let acc2_addr: [u8; 32] = + hex::decode("20573479053979b98d2ad09ef31a0750f22c77709bed51c4e64946bd1e376f31") + .unwrap() + .try_into() + .unwrap(); assert!(sequencer.store.acc_store.contains_account(&acc1_addr)); assert!(sequencer.store.acc_store.contains_account(&acc2_addr)); @@ -397,18 +395,16 @@ mod tests { let config = setup_sequencer_config_variable_initial_accounts(initial_accounts); let sequencer = SequencerCore::start_from_config(config.clone()); - let acc1_addr: [u8; 32] = hex::decode( - "bfd91e6703273a115ad7f099ef32f621243be69369d00ddef5d3a25117ffffff", - ) - .unwrap() - .try_into() - .unwrap(); - let acc2_addr: [u8; 32] = hex::decode( - "20573479053979b98d2ad09ef31a0750f22c77709bed51c4e64946bd1effffff", - ) - .unwrap() - .try_into() - .unwrap(); + let acc1_addr: [u8; 32] = + hex::decode("bfd91e6703273a115ad7f099ef32f621243be69369d00ddef5d3a25117ffffff") + .unwrap() + .try_into() + .unwrap(); + let acc2_addr: [u8; 32] = + hex::decode("20573479053979b98d2ad09ef31a0750f22c77709bed51c4e64946bd1effffff") + .unwrap() + .try_into() + .unwrap(); assert!(sequencer.store.acc_store.contains_account(&acc1_addr)); assert!(sequencer.store.acc_store.contains_account(&acc2_addr)); diff --git a/sequencer_core/src/sequencer_store/accounts_store.rs b/sequencer_core/src/sequencer_store/accounts_store.rs index 8e0d61b..7d64491 100644 --- a/sequencer_core/src/sequencer_store/accounts_store.rs +++ b/sequencer_core/src/sequencer_store/accounts_store.rs @@ -89,7 +89,7 @@ impl SequencerAccountsStore { ///Is accounts store empty pub fn is_empty(&self) -> bool { self.accounts.is_empty() - } + } } impl Default for SequencerAccountsStore { @@ -221,8 +221,7 @@ mod tests { #[test] fn account_sequencer_store_is_empty_test() { - let seq_acc_store = - SequencerAccountsStore::default(); + let seq_acc_store = SequencerAccountsStore::default(); assert!(seq_acc_store.is_empty()); } From 3bc2f6aba7b88f489e21b09982598fe42bfd45f1 Mon Sep 17 00:00:00 2001 From: Oleksandr Pravdyvyi Date: Fri, 18 Jul 2025 12:29:32 +0300 Subject: [PATCH 23/36] fix: refetch --- node_core/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/node_core/src/lib.rs b/node_core/src/lib.rs index a7aa422..d18a79a 100644 --- a/node_core/src/lib.rs +++ b/node_core/src/lib.rs @@ -36,6 +36,8 @@ pub mod config; pub mod pre_start; pub mod sequencer_client; +// + fn vec_u8_to_vec_u64(bytes: Vec) -> Vec { // Pad with zeros to make sure it's a multiple of 8 let mut padded = bytes.clone(); From 7d11c95be8519898bd9c79ea558f267cd3665bdd Mon Sep 17 00:00:00 2001 From: Pravdyvy <46261001+Pravdyvy@users.noreply.github.com> Date: Fri, 18 Jul 2025 12:36:53 +0300 Subject: [PATCH 24/36] Update lint-ubuntu.sh --- ci_scripts/lint-ubuntu.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ci_scripts/lint-ubuntu.sh b/ci_scripts/lint-ubuntu.sh index 7def8fa..35a0e4a 100644 --- a/ci_scripts/lint-ubuntu.sh +++ b/ci_scripts/lint-ubuntu.sh @@ -1,7 +1,5 @@ set -e -curl -L https://risczero.com/install | bash -/home/runner/.risc0/bin/rzup install source env.sh cargo install taplo-cli --locked @@ -9,4 +7,4 @@ cargo fmt -- --check taplo fmt --check export RISC0_SKIP_BUILD=1 -cargo clippy --workspace --all-targets -- -D warnings \ No newline at end of file +cargo clippy --workspace --all-targets -- -D warnings From 9646152550115ea873edb09c2bf6e045cd4f5886 Mon Sep 17 00:00:00 2001 From: Oleksandr Pravdyvyi Date: Fri, 18 Jul 2025 14:07:06 +0300 Subject: [PATCH 25/36] fix: more lints fix --- node_core/src/chain_storage/mod.rs | 2 +- node_core/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/node_core/src/chain_storage/mod.rs b/node_core/src/chain_storage/mod.rs index 38dfa4a..6412ca0 100644 --- a/node_core/src/chain_storage/mod.rs +++ b/node_core/src/chain_storage/mod.rs @@ -209,7 +209,7 @@ impl NodeChainStore { self.block_store.put_block_at_id(block)?; //Snapshot - if block_id % self.node_config.shapshot_frequency_in_blocks == 0 { + if block_id.is_multiple_of(self.node_config.shapshot_frequency_in_blocks) { //Serializing all important data structures //If we fail serialization, it is not the reason to stop running diff --git a/node_core/src/lib.rs b/node_core/src/lib.rs index d18a79a..bab62c1 100644 --- a/node_core/src/lib.rs +++ b/node_core/src/lib.rs @@ -41,7 +41,7 @@ pub mod sequencer_client; fn vec_u8_to_vec_u64(bytes: Vec) -> Vec { // Pad with zeros to make sure it's a multiple of 8 let mut padded = bytes.clone(); - while padded.len() % 8 != 0 { + while !padded.len().is_multiple_of(8) { padded.push(0); } From 59501f2ca5312c2b29e8216d68beb97b9c8c5656 Mon Sep 17 00:00:00 2001 From: Oleksandr Pravdyvyi Date: Fri, 18 Jul 2025 15:36:01 +0300 Subject: [PATCH 26/36] fix: run retry --- node_core/src/lib.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/node_core/src/lib.rs b/node_core/src/lib.rs index bab62c1..e76dd43 100644 --- a/node_core/src/lib.rs +++ b/node_core/src/lib.rs @@ -36,8 +36,6 @@ pub mod config; pub mod pre_start; pub mod sequencer_client; -// - fn vec_u8_to_vec_u64(bytes: Vec) -> Vec { // Pad with zeros to make sure it's a multiple of 8 let mut padded = bytes.clone(); From ca3a63a885331f12036957bce9ceb5dc6b848882 Mon Sep 17 00:00:00 2001 From: Oleksandr Pravdyvyi Date: Mon, 21 Jul 2025 11:46:01 +0300 Subject: [PATCH 27/36] fix: ci update test --- .github/workflows/ci.yml | 48 +++++----------------------------------- node_core/src/lib.rs | 2 ++ 2 files changed, 7 insertions(+), 43 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b717c10..9a8a6ff 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,35 +14,13 @@ on: name: General jobs: - build-ubuntu-latest: + ubuntu-latest-pipeline: runs-on: ubuntu-latest timeout-minutes: 60 - name: build - ubuntu-latest + name: ubuntu-latest-pipeline steps: - uses: actions/checkout@v3 - - name: Install stable toolchain - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: nightly - override: true - - name: build - ubuntu-latest - if: success() || failure() - run: chmod 777 ./ci_scripts/build-ubuntu.sh && ./ci_scripts/build-ubuntu.sh - - - lint: - strategy: - matrix: - platform: [ ubuntu-latest ] - runs-on: ${{ matrix.platform }} - timeout-minutes: 60 - - name: lint - ${{ matrix.crate }} - ${{ matrix.platform }} - steps: - - name: Checkout sources - uses: actions/checkout@v3 - name: Install stable toolchain uses: actions-rs/toolchain@v1 with: @@ -53,25 +31,9 @@ jobs: - name: lint - ubuntu-latest if: success() || failure() run: chmod 777 ./ci_scripts/lint-ubuntu.sh && ./ci_scripts/lint-ubuntu.sh - - - test: - strategy: - matrix: - platform: [ ubuntu-latest ] - runs-on: ${{ matrix.platform }} - timeout-minutes: 60 - - name: test - ${{ matrix.crate }} - ${{ matrix.platform }} - steps: - - name: Checkout sources - uses: actions/checkout@v3 - - name: Install stable toolchain - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: nightly - override: true + - name: build - ubuntu-latest + if: success() || failure() + run: chmod 777 ./ci_scripts/build-ubuntu.sh && ./ci_scripts/build-ubuntu.sh - name: test ubuntu-latest if: success() || failure() run: chmod 777 ./ci_scripts/test-ubuntu.sh && ./ci_scripts/test-ubuntu.sh diff --git a/node_core/src/lib.rs b/node_core/src/lib.rs index e76dd43..bab62c1 100644 --- a/node_core/src/lib.rs +++ b/node_core/src/lib.rs @@ -36,6 +36,8 @@ pub mod config; pub mod pre_start; pub mod sequencer_client; +// + fn vec_u8_to_vec_u64(bytes: Vec) -> Vec { // Pad with zeros to make sure it's a multiple of 8 let mut padded = bytes.clone(); From 5e3476673e47129f8643a33dcad5cf2646a9d679 Mon Sep 17 00:00:00 2001 From: Oleksandr Pravdyvyi Date: Mon, 21 Jul 2025 12:48:22 +0300 Subject: [PATCH 28/36] fix: build substraction --- .github/workflows/ci.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9a8a6ff..f7f923d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,9 +31,6 @@ jobs: - name: lint - ubuntu-latest if: success() || failure() run: chmod 777 ./ci_scripts/lint-ubuntu.sh && ./ci_scripts/lint-ubuntu.sh - - name: build - ubuntu-latest - if: success() || failure() - run: chmod 777 ./ci_scripts/build-ubuntu.sh && ./ci_scripts/build-ubuntu.sh - name: test ubuntu-latest if: success() || failure() run: chmod 777 ./ci_scripts/test-ubuntu.sh && ./ci_scripts/test-ubuntu.sh From 39b4c866a128feed88097deea32adc9fe0eef850 Mon Sep 17 00:00:00 2001 From: Sergio Chouhy Date: Mon, 21 Jul 2025 17:50:08 -0300 Subject: [PATCH 29/36] fix double-hashing bug --- common/src/transaction.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/common/src/transaction.rs b/common/src/transaction.rs index b48afce..779a19e 100644 --- a/common/src/transaction.rs +++ b/common/src/transaction.rs @@ -1,6 +1,6 @@ use k256::{ ecdsa::{ - signature::{Signer, Verifier}, + signature::hazmat::{PrehashSigner, PrehashVerifier}, Signature, SigningKey, VerifyingKey, }, EncodedPoint, Scalar, @@ -245,7 +245,7 @@ impl Transaction { /// 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 hash = body.hash(); - let signature: TransactionSignature = private_key.sign(&hash); + let signature: TransactionSignature = private_key.sign_prehash(&hash).unwrap(); let public_key = VerifyingKey::from(&private_key); Self { body, @@ -260,7 +260,7 @@ impl Transaction { let hash = self.body.hash(); self.public_key - .verify(&hash, &self.signature) + .verify_prehash(&hash, &self.signature) .map_err(|_| TransactionSignatureError::InvalidSignature)?; Ok(AuthenticatedTransaction { @@ -299,7 +299,7 @@ impl AuthenticatedTransaction { #[cfg(test)] mod tests { use super::*; - use k256::FieldBytes; + use k256::{ecdsa::signature::Signer, FieldBytes}; use secp256k1_zkp::{constants::SECRET_KEY_SIZE, Tweak}; use sha2::{digest::FixedOutput, Digest}; @@ -384,7 +384,7 @@ mod tests { assert!(authenticated_tx .transaction() .public_key - .verify(hash, &signature) + .verify_prehash(hash, &signature) .is_ok()); } From b3323c78cf96a42169bc6e9cf6b6453c8c34c7e6 Mon Sep 17 00:00:00 2001 From: Sergio Chouhy Date: Mon, 21 Jul 2025 18:46:50 -0300 Subject: [PATCH 30/36] clippy --- common/src/merkle_tree_public/merkle_tree.rs | 2 +- common/src/rpc_primitives/requests.rs | 1 - common/src/transaction.rs | 19 +++++++------------ storage/src/lib.rs | 10 +++++----- utxo/src/utxo_core.rs | 2 +- 5 files changed, 14 insertions(+), 20 deletions(-) diff --git a/common/src/merkle_tree_public/merkle_tree.rs b/common/src/merkle_tree_public/merkle_tree.rs index 9b98a87..5e104f8 100644 --- a/common/src/merkle_tree_public/merkle_tree.rs +++ b/common/src/merkle_tree_public/merkle_tree.rs @@ -8,7 +8,7 @@ use serde::{ }; use crate::{ - transaction::{AuthenticatedTransaction, Transaction, TransactionBody}, + transaction::Transaction, utxo_commitment::UTXOCommitment, }; diff --git a/common/src/rpc_primitives/requests.rs b/common/src/rpc_primitives/requests.rs index 5bebfad..395badf 100644 --- a/common/src/rpc_primitives/requests.rs +++ b/common/src/rpc_primitives/requests.rs @@ -1,7 +1,6 @@ use crate::block::Block; use crate::parse_request; use crate::transaction::Transaction; -use crate::transaction::TransactionBody; use super::errors::RpcParseError; use super::parser::parse_params; diff --git a/common/src/transaction.rs b/common/src/transaction.rs index 779a19e..1704b4f 100644 --- a/common/src/transaction.rs +++ b/common/src/transaction.rs @@ -1,17 +1,12 @@ -use k256::{ - ecdsa::{ +use k256::ecdsa::{ signature::hazmat::{PrehashSigner, PrehashVerifier}, Signature, SigningKey, VerifyingKey, - }, - EncodedPoint, Scalar, -}; + }; use log::info; use secp256k1_zkp::{PedersenCommitment, Tweak}; -use serde::de::{Error as DeError, Visitor}; -use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use serde::{Deserialize, Serialize}; use sha2::{digest::FixedOutput, Digest}; -use std::fmt; use crate::merkle_tree_public::TreeHashType; @@ -156,7 +151,7 @@ impl ActionData { .into_iter() .map(|owned_utxo| owned_utxo.into()) .collect(); - format!("Published utxos {:?}", pub_own_utxo) + format!("Published utxos {pub_own_utxo:?}") } } } @@ -195,21 +190,21 @@ impl TransactionBody { "Transaction utxo_commitments_spent_hashes is {:?}", self.utxo_commitments_spent_hashes .iter() - .map(|val| hex::encode(val.clone())) + .map(|val| hex::encode(*val)) .collect::>() ); info!( "Transaction utxo_commitments_created_hashes is {:?}", self.utxo_commitments_created_hashes .iter() - .map(|val| hex::encode(val.clone())) + .map(|val| hex::encode(*val)) .collect::>() ); info!( "Transaction nullifier_created_hashes is {:?}", self.nullifier_created_hashes .iter() - .map(|val| hex::encode(val.clone())) + .map(|val| hex::encode(*val)) .collect::>() ); info!( diff --git a/storage/src/lib.rs b/storage/src/lib.rs index 7616842..ac54406 100644 --- a/storage/src/lib.rs +++ b/storage/src/lib.rs @@ -316,7 +316,7 @@ impl RocksDBIO { let cf_sc = self.sc_column(); let sc_addr_loc = format!("{sc_addr:?}{SC_LEN_SUFFIX}"); - let sc_len_addr = sc_addr_loc.as_str().as_bytes(); + let sc_len_addr = sc_addr_loc.as_bytes(); self.db .put_cf(&cf_sc, sc_len_addr, length.to_be_bytes()) @@ -360,7 +360,7 @@ impl RocksDBIO { let cf_sc = self.sc_column(); let sc_addr_loc = format!("{sc_addr:?}{SC_LEN_SUFFIX}"); - let sc_len_addr = sc_addr_loc.as_str().as_bytes(); + let sc_len_addr = sc_addr_loc.as_bytes(); let sc_len = self .db @@ -379,11 +379,11 @@ impl RocksDBIO { ///Get full sc state from DB pub fn get_sc_sc_state(&self, sc_addr: &str) -> DbResult> { let cf_sc = self.sc_column(); - let sc_len = self.get_sc_sc_state_len(&sc_addr)?; + let sc_len = self.get_sc_sc_state_len(sc_addr)?; let mut data_blob_list = vec![]; for id in 0..sc_len { - let blob_addr = produce_address_for_data_blob_at_id(&sc_addr, id); + let blob_addr = produce_address_for_data_blob_at_id(sc_addr, id); let blob = self .db @@ -541,7 +541,7 @@ impl RocksDBIO { ///Creates address for sc data blob at corresponding id fn produce_address_for_data_blob_at_id(sc_addr: &str, id: usize) -> Vec { - let mut prefix_bytes: Vec = sc_addr.as_bytes().iter().cloned().collect(); + let mut prefix_bytes: Vec = sc_addr.as_bytes().to_vec(); let id_bytes = id.to_be_bytes(); diff --git a/utxo/src/utxo_core.rs b/utxo/src/utxo_core.rs index 4e40ce3..07a8830 100644 --- a/utxo/src/utxo_core.rs +++ b/utxo/src/utxo_core.rs @@ -58,7 +58,7 @@ impl UTXO { } pub fn create_utxo_from_payload(payload_with_asset: UTXOPayload) -> Self { let mut hasher = sha2::Sha256::new(); - hasher.update(&payload_with_asset.to_bytes()); + hasher.update(payload_with_asset.to_bytes()); let hash = ::from(hasher.finalize_fixed()); Self { From 361e3b6f76def95627eba7274c2907cface24c35 Mon Sep 17 00:00:00 2001 From: Sergio Chouhy Date: Mon, 21 Jul 2025 19:04:49 -0300 Subject: [PATCH 31/36] fmt --- accounts/src/account_core/mod.rs | 2 +- accounts/src/key_management/mod.rs | 1 - common/src/merkle_tree_public/merkle_tree.rs | 5 +---- common/src/transaction.rs | 6 +++--- 4 files changed, 5 insertions(+), 9 deletions(-) diff --git a/accounts/src/account_core/mod.rs b/accounts/src/account_core/mod.rs index bb0fd41..b1b4a91 100644 --- a/accounts/src/account_core/mod.rs +++ b/accounts/src/account_core/mod.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use anyhow::Result; use common::{merkle_tree_public::TreeHashType, transaction::Tag}; -use k256::{ecdsa::VerifyingKey, AffinePoint}; +use k256::AffinePoint; use log::info; use serde::{Deserialize, Serialize}; use utxo::utxo_core::UTXO; diff --git a/accounts/src/key_management/mod.rs b/accounts/src/key_management/mod.rs index 66c02c6..98a8b39 100644 --- a/accounts/src/key_management/mod.rs +++ b/accounts/src/key_management/mod.rs @@ -2,7 +2,6 @@ use aes_gcm::{aead::Aead, Aes256Gcm, KeyInit}; use common::merkle_tree_public::TreeHashType; use constants_types::{CipherText, Nonce}; use elliptic_curve::point::AffineCoordinates; -use ephemeral_key_holder::EphemeralKeyHolder; use k256::{ecdsa::SigningKey, AffinePoint, FieldBytes}; use log::info; use rand::{rngs::OsRng, RngCore}; diff --git a/common/src/merkle_tree_public/merkle_tree.rs b/common/src/merkle_tree_public/merkle_tree.rs index 5e104f8..e2eb715 100644 --- a/common/src/merkle_tree_public/merkle_tree.rs +++ b/common/src/merkle_tree_public/merkle_tree.rs @@ -7,10 +7,7 @@ use serde::{ Deserialize, Deserializer, Serialize, }; -use crate::{ - transaction::Transaction, - utxo_commitment::UTXOCommitment, -}; +use crate::{transaction::Transaction, utxo_commitment::UTXOCommitment}; use super::{hasher::OwnHasher, tree_leav_item::TreeLeavItem, TreeHashType}; diff --git a/common/src/transaction.rs b/common/src/transaction.rs index 1704b4f..e5d0721 100644 --- a/common/src/transaction.rs +++ b/common/src/transaction.rs @@ -1,7 +1,7 @@ use k256::ecdsa::{ - signature::hazmat::{PrehashSigner, PrehashVerifier}, - Signature, SigningKey, VerifyingKey, - }; + signature::hazmat::{PrehashSigner, PrehashVerifier}, + Signature, SigningKey, VerifyingKey, +}; use log::info; use secp256k1_zkp::{PedersenCommitment, Tweak}; use serde::{Deserialize, Serialize}; From 71fdce8050763c50894e4079e3dea82a597a1033 Mon Sep 17 00:00:00 2001 From: Sergio Chouhy Date: Mon, 21 Jul 2025 19:13:43 -0300 Subject: [PATCH 32/36] remove unused dependencies --- node_core/src/chain_storage/block_store.rs | 2 +- node_rpc/src/process.rs | 3 +-- sequencer_core/src/lib.rs | 2 +- sequencer_core/src/mempool_transaction.rs | 1 - 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/node_core/src/chain_storage/block_store.rs b/node_core/src/chain_storage/block_store.rs index bcb988b..677f426 100644 --- a/node_core/src/chain_storage/block_store.rs +++ b/node_core/src/chain_storage/block_store.rs @@ -6,7 +6,7 @@ use anyhow::{anyhow, Result}; use common::block::Block; use common::merkle_tree_public::merkle_tree::HashStorageMerkleTree; use common::nullifier::UTXONullifier; -use common::transaction::{AuthenticatedTransaction, Transaction, TransactionBody}; +use common::transaction::Transaction; use common::utxo_commitment::UTXOCommitment; use log::error; use storage::sc_db_utils::{DataBlob, DataBlobChangeVariant}; diff --git a/node_rpc/src/process.rs b/node_rpc/src/process.rs index be44794..5fa52ad 100644 --- a/node_rpc/src/process.rs +++ b/node_rpc/src/process.rs @@ -23,8 +23,7 @@ use crate::types::{ ExecuteScenarioSplitResponse, ExecuteSubscenarioRequest, ExecuteSubscenarioResponse, ShowAccountPublicBalanceRequest, ShowAccountPublicBalanceResponse, ShowAccountUTXORequest, ShowAccountUTXOResponse, ShowTransactionRequest, ShowTransactionResponse, - UTXOShortEssentialStruct, WriteDepositPublicBalanceRequest, - WriteDepositPublicBalanceResponse, WriteMintPrivateUTXOMultipleAssetsRequest, + UTXOShortEssentialStruct, WriteMintPrivateUTXOMultipleAssetsRequest, WriteMintPrivateUTXOMultipleAssetsResponse, WriteMintPrivateUTXORequest, WriteMintPrivateUTXOResponse, WriteSendDeshieldedBalanceRequest, WriteSendDeshieldedUTXOResponse, WriteSendPrivateUTXORequest, WriteSendPrivateUTXOResponse, diff --git a/sequencer_core/src/lib.rs b/sequencer_core/src/lib.rs index 1e6d199..40ff1a2 100644 --- a/sequencer_core/src/lib.rs +++ b/sequencer_core/src/lib.rs @@ -12,7 +12,7 @@ use common::{ use config::SequencerConfig; use mempool::MemPool; use mempool_transaction::MempoolTransaction; -use sequencer_store::{accounts_store::AccountPublicData, SequecerChainStore}; +use sequencer_store::SequecerChainStore; use serde::{Deserialize, Serialize}; pub mod config; diff --git a/sequencer_core/src/mempool_transaction.rs b/sequencer_core/src/mempool_transaction.rs index 104e063..551aaf3 100644 --- a/sequencer_core/src/mempool_transaction.rs +++ b/sequencer_core/src/mempool_transaction.rs @@ -1,6 +1,5 @@ use common::{merkle_tree_public::TreeHashType, transaction::AuthenticatedTransaction}; use mempool::mempoolitem::MemPoolItem; -use serde::{Deserialize, Serialize}; pub struct MempoolTransaction { pub auth_tx: AuthenticatedTransaction, From 5de28c062e94dc3a8bcef616d0a48459e685496f Mon Sep 17 00:00:00 2001 From: Sergio Chouhy Date: Mon, 21 Jul 2025 21:07:16 -0300 Subject: [PATCH 33/36] remove usage of prehash sinc it is hazard material. Prefer use of secure api --- common/src/transaction.rs | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/common/src/transaction.rs b/common/src/transaction.rs index e5d0721..26dc670 100644 --- a/common/src/transaction.rs +++ b/common/src/transaction.rs @@ -1,5 +1,5 @@ use k256::ecdsa::{ - signature::hazmat::{PrehashSigner, PrehashVerifier}, + signature::{Signer, Verifier}, Signature, SigningKey, VerifyingKey, }; use log::info; @@ -160,13 +160,17 @@ impl ActionData { impl TransactionBody { /// Computes and returns the SHA-256 hash of the JSON-serialized representation of `self`. 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 { // TODO: Remove `unwrap` by implementing a `to_bytes` method // that deterministically encodes all transaction fields to bytes // and guarantees serialization will succeed. - let raw_data = serde_json::to_vec(&self).unwrap(); - let mut hasher = sha2::Sha256::new(); - hasher.update(&raw_data); - TreeHashType::from(hasher.finalize_fixed()) + serde_json::to_vec(&self).unwrap() } pub fn log(&self) { @@ -239,8 +243,7 @@ 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 hash = body.hash(); - let signature: TransactionSignature = private_key.sign_prehash(&hash).unwrap(); + let signature: TransactionSignature = private_key.sign(&body.to_bytes()); let public_key = VerifyingKey::from(&private_key); Self { body, @@ -255,7 +258,7 @@ impl Transaction { let hash = self.body.hash(); self.public_key - .verify_prehash(&hash, &self.signature) + .verify(&self.body.to_bytes(), &self.signature) .map_err(|_| TransactionSignatureError::InvalidSignature)?; Ok(AuthenticatedTransaction { @@ -379,7 +382,7 @@ mod tests { assert!(authenticated_tx .transaction() .public_key - .verify_prehash(hash, &signature) + .verify(&transaction.body.to_bytes(), &signature) .is_ok()); } From 8604a672bdeadddbe168cbcc8e016293a62ef2f6 Mon Sep 17 00:00:00 2001 From: Oleksandr Pravdyvyi Date: Wed, 23 Jul 2025 15:53:00 +0300 Subject: [PATCH 34/36] fix: merge fix --- node_core/src/chain_storage/mod.rs | 2 -- node_core/src/lib.rs | 24 ++++++++-------------- sequencer_core/src/lib.rs | 32 +++++++++++++----------------- 3 files changed, 22 insertions(+), 36 deletions(-) diff --git a/node_core/src/chain_storage/mod.rs b/node_core/src/chain_storage/mod.rs index 3ee0e0b..21d9da0 100644 --- a/node_core/src/chain_storage/mod.rs +++ b/node_core/src/chain_storage/mod.rs @@ -299,7 +299,6 @@ mod tests { } fn create_dummy_transaction( - hash: TreeHashType, // execution_input: Vec, nullifier_created_hashes: Vec<[u8; 32]>, utxo_commitments_spent_hashes: Vec<[u8; 32]>, @@ -419,7 +418,6 @@ mod tests { .utxo_commitments_store .add_tx_multiple(vec![UTXOCommitment { hash: [3u8; 32] }]); store.pub_tx_store.add_tx(create_dummy_transaction( - [12; 32], vec![[9; 32]], vec![[7; 32]], vec![[8; 32]], diff --git a/node_core/src/lib.rs b/node_core/src/lib.rs index b8ea8fe..eab83ba 100644 --- a/node_core/src/lib.rs +++ b/node_core/src/lib.rs @@ -271,8 +271,7 @@ impl NodeCore { secret_r, sc_addr, state_changes, - } - .into(), + }, result_hash, )) } @@ -367,8 +366,7 @@ impl NodeCore { secret_r, sc_addr, state_changes, - } - .into(), + }, result_hashes, )) } @@ -481,8 +479,7 @@ impl NodeCore { secret_r, sc_addr, state_changes, - } - .into(), + }, utxo_hashes, )) } @@ -625,8 +622,7 @@ impl NodeCore { secret_r, sc_addr, state_changes, - } - .into(), + }, utxo_hashes_receiver, utxo_hashes_not_spent, )) @@ -752,8 +748,7 @@ impl NodeCore { secret_r, sc_addr, state_changes, - } - .into(), + }, utxo_hashes, )) } @@ -837,8 +832,7 @@ impl NodeCore { secret_r, sc_addr, state_changes, - } - .into()) + }) } pub async fn send_private_mint_tx( @@ -932,8 +926,7 @@ impl NodeCore { secret_r, sc_addr, state_changes, - ) - .into(); + ); tx.log(); Ok(self.sequencer_client.send_tx(tx, tx_roots).await?) @@ -1475,8 +1468,7 @@ impl NodeCore { secret_r, sc_addr, state_changes, - } - .into(), + }, utxo_hashes, )) } diff --git a/sequencer_core/src/lib.rs b/sequencer_core/src/lib.rs index 1129e31..e5ddef8 100644 --- a/sequencer_core/src/lib.rs +++ b/sequencer_core/src/lib.rs @@ -77,7 +77,6 @@ impl SequencerCore { tx_roots: [[u8; 32]; 2], ) -> Result<(), TransactionMalformationErrorKind> { let Transaction { - hash, tx_kind, ref execution_input, ref execution_output, @@ -85,11 +84,12 @@ impl SequencerCore { ref nullifier_created_hashes, .. } = tx; + let hash = tx.hash(); let mempool_size = self.mempool.len(); if mempool_size >= self.sequencer_config.max_num_tx_in_block { - return Err(TransactionMalformationErrorKind::MempoolFullForRound { tx: *hash }); + return Err(TransactionMalformationErrorKind::MempoolFullForRound { tx: hash }); } let curr_sequencer_roots = self.get_tree_roots(); @@ -97,7 +97,7 @@ impl SequencerCore { if tx_roots != curr_sequencer_roots { return Err( TransactionMalformationErrorKind::ChainStateFurtherThanTransactionState { - tx: *hash, + tx: hash, }, ); } @@ -111,7 +111,7 @@ impl SequencerCore { //Public transactions can not make private operations. return Err( TransactionMalformationErrorKind::PublicTransactionChangedPrivateData { - tx: *hash, + tx: hash, }, ); } @@ -123,7 +123,7 @@ impl SequencerCore { //between public and private state. return Err( TransactionMalformationErrorKind::PrivateTransactionChangedPublicData { - tx: *hash, + tx: hash, }, ); } @@ -132,7 +132,7 @@ impl SequencerCore { }; //Tree checks - let tx_tree_check = self.store.pub_tx_store.get_tx(*hash).is_some(); + let tx_tree_check = self.store.pub_tx_store.get_tx(hash).is_some(); let nullifier_tree_check = nullifier_created_hashes.iter().any(|nullifier_hash| { self.store.nullifier_store.contains(&UTXONullifier { utxo_hash: *nullifier_hash, @@ -149,18 +149,18 @@ impl SequencerCore { }); if tx_tree_check { - return Err(TransactionMalformationErrorKind::TxHashAlreadyPresentInTree { tx: *hash }); + return Err(TransactionMalformationErrorKind::TxHashAlreadyPresentInTree { tx: hash }); } if nullifier_tree_check { return Err( - TransactionMalformationErrorKind::NullifierAlreadyPresentInTree { tx: *hash }, + TransactionMalformationErrorKind::NullifierAlreadyPresentInTree { tx: hash }, ); } if utxo_commitments_check { return Err( - TransactionMalformationErrorKind::UTXOCommitmentAlreadyPresentInTree { tx: *hash }, + TransactionMalformationErrorKind::UTXOCommitmentAlreadyPresentInTree { tx: hash }, ); } @@ -184,8 +184,6 @@ impl SequencerCore { tx: TransactionMempool, ) -> Result<(), TransactionMalformationErrorKind> { let Transaction { - // ToDo: remove hashing of transactions on node side [Issue #66] - hash: _, ref utxo_commitments_created_hashes, ref nullifier_created_hashes, .. @@ -298,7 +296,6 @@ mod tests { } fn create_dummy_transaction( - hash: TreeHashType, nullifier_created_hashes: Vec<[u8; 32]>, utxo_commitments_spent_hashes: Vec<[u8; 32]>, utxo_commitments_created_hashes: Vec<[u8; 32]>, @@ -306,7 +303,6 @@ mod tests { let mut rng = rand::thread_rng(); Transaction { - hash, tx_kind: TxKind::Private, execution_input: vec![], execution_output: vec![], @@ -325,7 +321,7 @@ mod tests { } fn common_setup(sequencer: &mut SequencerCore) { - let tx = create_dummy_transaction([12; 32], 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 }; sequencer.mempool.push_item(tx_mempool); @@ -447,7 +443,7 @@ mod tests { common_setup(&mut sequencer); - let tx = create_dummy_transaction([1; 32], 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 result = sequencer.transaction_pre_check(&tx, tx_roots); @@ -464,7 +460,7 @@ mod tests { common_setup(&mut sequencer); - let tx = create_dummy_transaction([2; 32], vec![[92; 32]], vec![[72; 32]], vec![[82; 32]]); + let tx = create_dummy_transaction(vec![[92; 32]], vec![[72; 32]], vec![[82; 32]]); let tx_roots = sequencer.get_tree_roots(); // Fill the mempool @@ -486,7 +482,7 @@ mod tests { common_setup(&mut sequencer); - let tx = create_dummy_transaction([3; 32], 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_mempool = TransactionMempool { tx }; @@ -500,7 +496,7 @@ mod tests { let config = setup_sequencer_config(); let mut sequencer = SequencerCore::start_from_config(config); - let tx = create_dummy_transaction([4; 32], 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 }; sequencer.mempool.push_item(tx_mempool); From dfb28abbe7492ca00f4be019a851dc5c71a19008 Mon Sep 17 00:00:00 2001 From: Oleksandr Pravdyvyi Date: Wed, 23 Jul 2025 16:12:37 +0300 Subject: [PATCH 35/36] fix: ci rerun --- node_core/src/lib.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/node_core/src/lib.rs b/node_core/src/lib.rs index eab83ba..995b723 100644 --- a/node_core/src/lib.rs +++ b/node_core/src/lib.rs @@ -36,8 +36,6 @@ pub mod config; pub mod pre_start; pub mod sequencer_client; -// - fn vec_u8_to_vec_u64(bytes: Vec) -> Vec { // Pad with zeros to make sure it's a multiple of 8 let mut padded = bytes.clone(); From 872986926e03a003e9d8ec9053c9479683478194 Mon Sep 17 00:00:00 2001 From: Oleksandr Pravdyvyi Date: Wed, 23 Jul 2025 17:44:40 +0300 Subject: [PATCH 36/36] fix: merge clippy fix --- accounts/src/key_management/mod.rs | 2 +- sequencer_core/src/lib.rs | 16 +++++++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/accounts/src/key_management/mod.rs b/accounts/src/key_management/mod.rs index 9b63a36..6fa1462 100644 --- a/accounts/src/key_management/mod.rs +++ b/accounts/src/key_management/mod.rs @@ -61,7 +61,7 @@ impl AddressKeyHolder { 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() + SigningKey::from_bytes(field_bytes).unwrap() } pub fn calculate_shared_secret_receiver( diff --git a/sequencer_core/src/lib.rs b/sequencer_core/src/lib.rs index 5ac482e..bfde1f6 100644 --- a/sequencer_core/src/lib.rs +++ b/sequencer_core/src/lib.rs @@ -92,12 +92,18 @@ impl SequencerCore { let tx_hash = *tx.hash(); + let mempool_size = self.mempool.len(); + + if mempool_size >= self.sequencer_config.max_num_tx_in_block { + return Err(TransactionMalformationErrorKind::MempoolFullForRound { tx: tx_hash }); + } + let curr_sequencer_roots = self.get_tree_roots(); if tx_roots != curr_sequencer_roots { return Err( TransactionMalformationErrorKind::ChainStateFurtherThanTransactionState { - tx: hash, + tx: tx_hash, }, ); } @@ -111,7 +117,7 @@ impl SequencerCore { //Public transactions can not make private operations. return Err( TransactionMalformationErrorKind::PublicTransactionChangedPrivateData { - tx: hash, + tx: tx_hash, }, ); } @@ -123,7 +129,7 @@ impl SequencerCore { //between public and private state. return Err( TransactionMalformationErrorKind::PrivateTransactionChangedPublicData { - tx: hash, + tx: tx_hash, }, ); } @@ -132,7 +138,7 @@ impl SequencerCore { }; //Tree checks - let tx_tree_check = self.store.pub_tx_store.get_tx(hash).is_some(); + let tx_tree_check = self.store.pub_tx_store.get_tx(tx_hash).is_some(); let nullifier_tree_check = nullifier_created_hashes.iter().any(|nullifier_hash| { self.store.nullifier_store.contains(&UTXONullifier { utxo_hash: *nullifier_hash, @@ -232,7 +238,7 @@ impl SequencerCore { .pop_size(self.sequencer_config.max_num_tx_in_block); for tx in &transactions { - self.execute_check_transaction_on_state(&tx)?; + self.execute_check_transaction_on_state(tx)?; } let prev_block_hash = self