diff --git a/common/src/transaction.rs b/common/src/transaction.rs index 78e1930..fd8af6e 100644 --- a/common/src/transaction.rs +++ b/common/src/transaction.rs @@ -62,6 +62,8 @@ pub struct TransactionBody { /// /// First value represents vector of changes, second is new length of a state pub state_changes: (serde_json::Value, usize), + + pub nonce: u64, } #[derive(Debug, Serialize, Deserialize)] @@ -322,6 +324,7 @@ mod tests { secret_r: [8; 32], sc_addr: "someAddress".to_string(), state_changes: (serde_json::Value::Null, 10), + nonce: 1, } } diff --git a/node_core/src/chain_storage/mod.rs b/node_core/src/chain_storage/mod.rs index 126574f..017f9cc 100644 --- a/node_core/src/chain_storage/mod.rs +++ b/node_core/src/chain_storage/mod.rs @@ -337,6 +337,7 @@ mod tests { secret_r: [0; 32], sc_addr: "sc_addr".to_string(), state_changes: (serde_json::Value::Null, 0), + nonce: 1, }; Transaction::new(body, SignaturePrivateKey::random(&mut rng)) } diff --git a/node_core/src/lib.rs b/node_core/src/lib.rs index a8ca0b9..ea571f1 100644 --- a/node_core/src/lib.rs +++ b/node_core/src/lib.rs @@ -274,6 +274,7 @@ impl NodeCore { secret_r, sc_addr, state_changes, + nonce: 1, }; let key_to_sign_transaction = account.key_holder.get_pub_account_signing_key(); @@ -370,6 +371,7 @@ impl NodeCore { secret_r, sc_addr, state_changes, + nonce: 1, }; let key_to_sign_transaction = account.key_holder.get_pub_account_signing_key(); @@ -484,6 +486,7 @@ impl NodeCore { secret_r, sc_addr, state_changes, + nonce: 1 }; let key_to_sign_transaction = account.key_holder.get_pub_account_signing_key(); @@ -629,6 +632,7 @@ impl NodeCore { secret_r, sc_addr, state_changes, + nonce: 1, }; let key_to_sign_transaction = account.key_holder.get_pub_account_signing_key(); @@ -757,6 +761,7 @@ impl NodeCore { secret_r, sc_addr, state_changes, + nonce: 1 }; let key_to_sign_transaction = account.key_holder.get_pub_account_signing_key(); @@ -846,6 +851,7 @@ impl NodeCore { secret_r, sc_addr, state_changes, + nonce: 1 }; let key_to_sign_transaction = account.key_holder.get_pub_account_signing_key(); @@ -992,6 +998,7 @@ impl NodeCore { secret_r, sc_addr, state_changes, + 1, ); tx.log(); @@ -1548,6 +1555,7 @@ impl NodeCore { secret_r, sc_addr, state_changes, + nonce: 1, }; let key_to_sign_transaction = account.key_holder.get_pub_account_signing_key(); diff --git a/sc_core/src/transaction_payloads_tools.rs b/sc_core/src/transaction_payloads_tools.rs index fa0e28e..f8d075d 100644 --- a/sc_core/src/transaction_payloads_tools.rs +++ b/sc_core/src/transaction_payloads_tools.rs @@ -15,6 +15,7 @@ pub fn create_public_transaction_payload( secret_r: [u8; 32], sc_addr: String, state_changes: (serde_json::Value, usize), + nonce: u64 ) -> TransactionBody { TransactionBody { tx_kind: TxKind::Public, @@ -31,6 +32,7 @@ pub fn create_public_transaction_payload( secret_r, sc_addr, state_changes, + nonce, } } diff --git a/sequencer_core/src/lib.rs b/sequencer_core/src/lib.rs index cacf01b..6e7165a 100644 --- a/sequencer_core/src/lib.rs +++ b/sequencer_core/src/lib.rs @@ -41,6 +41,7 @@ pub enum TransactionMalformationErrorKind { InvalidSignature, IncorrectSender, BalanceMismatch { tx: TreeHashType }, + NonceMismatch { tx: TreeHashType }, FailedToDecode { tx: TreeHashType }, } @@ -223,11 +224,21 @@ impl SequencerCore { ref utxo_commitments_created_hashes, ref nullifier_created_hashes, execution_input, + nonce, .. } = mempool_tx.auth_tx.transaction().body(); let tx_hash = *mempool_tx.auth_tx.hash(); + // Nonce check + let mut signer_addres = [0; 32]; + let mut keccak_hasher = Keccak::v256(); + keccak_hasher.update(&mempool_tx.auth_tx.transaction().public_key.to_sec1_bytes()); + keccak_hasher.finalize(&mut signer_addres); + if self.store.acc_store.get_account_nonce(&signer_addres) != *nonce { + return Err(TransactionMalformationErrorKind::NonceMismatch { tx: tx_hash }); + } + //Balance check if let Ok(native_transfer_action) = serde_json::from_slice::(execution_input) @@ -250,6 +261,9 @@ impl SequencerCore { &native_transfer_action.to, to_balance + native_transfer_action.balance_to_move, ); + + // Update nonce + let _new_nonce = self.store.acc_store.increase_nonce(&signer_addres); } else { return Err(TransactionMalformationErrorKind::BalanceMismatch { tx: tx_hash }); } @@ -287,7 +301,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 @@ -612,6 +626,7 @@ mod tests { secret_r: [0; 32], sc_addr: "sc_addr".to_string(), state_changes: (serde_json::Value::Null, 0), + nonce: 0, }; Transaction::new(body, SignaturePrivateKey::random(&mut rng)) } diff --git a/sequencer_core/src/sequencer_store/accounts_store.rs b/sequencer_core/src/sequencer_store/accounts_store.rs index f522202..63da3f5 100644 --- a/sequencer_core/src/sequencer_store/accounts_store.rs +++ b/sequencer_core/src/sequencer_store/accounts_store.rs @@ -74,6 +74,13 @@ impl SequencerAccountsStore { .unwrap_or(0) } + pub fn get_account_nonce(&self, account_addr: &AccountAddress) -> u64 { + self.accounts + .get(account_addr) + .map(|acc| acc.nonce) + .unwrap_or(0) + } + ///Update `account_addr` balance, /// /// returns 0, if account address not found, otherwise returns previous balance @@ -91,6 +98,12 @@ impl SequencerAccountsStore { .unwrap_or(0) } + pub fn increase_nonce(&mut self, account_addr: &AccountAddress) -> Option { + let acc_data = self.accounts.get_mut(account_addr)?; + acc_data.nonce += 1; + Some(acc_data.nonce) + } + ///Remove account from storage /// /// Fails, if `balance` is != 0 diff --git a/sequencer_core/src/sequencer_store/block_store.rs b/sequencer_core/src/sequencer_store/block_store.rs index dbefdc2..aabc315 100644 --- a/sequencer_core/src/sequencer_store/block_store.rs +++ b/sequencer_core/src/sequencer_store/block_store.rs @@ -95,6 +95,7 @@ mod tests { secret_r: Default::default(), sc_addr: Default::default(), state_changes: Default::default(), + nonce: 1 }; let tx = Transaction::new(body, SignaturePrivateKey::from_slice(&[1; 32]).unwrap()); ( diff --git a/sequencer_rpc/src/process.rs b/sequencer_rpc/src/process.rs index 41d2261..7d8240e 100644 --- a/sequencer_rpc/src/process.rs +++ b/sequencer_rpc/src/process.rs @@ -506,6 +506,7 @@ mod tests { secret_r: Default::default(), sc_addr: Default::default(), state_changes: Default::default(), + nonce: 1, }; let tx = Transaction::new(tx_body, SignaturePrivateKey::from_slice(&[1; 32]).unwrap());