diff --git a/chain/chain/src/chain.rs b/chain/chain/src/chain.rs index 8d73a3eee56..06d48a500f9 100644 --- a/chain/chain/src/chain.rs +++ b/chain/chain/src/chain.rs @@ -3011,7 +3011,7 @@ impl Chain { self.chain_store() .check_transaction_validity_period( prev_block_header, - &transaction.transaction.block_hash, + transaction.transaction.block_hash(), transaction_validity_period, ) .map_err(|_| Error::from(Error::InvalidTransactions))?; @@ -3029,7 +3029,7 @@ impl Chain { self.chain_store() .check_transaction_validity_period( &prev_block_header, - &tx.transaction.block_hash, + tx.transaction.block_hash(), self.transaction_validity_period, ) .is_ok() @@ -4406,7 +4406,7 @@ impl Chain { ) -> HashMap> { let mut result = HashMap::new(); for receipt in receipts { - let shard_id = account_id_to_shard_id(&receipt.receiver_id, shard_layout); + let shard_id = account_id_to_shard_id(receipt.receiver_id(), shard_layout); let entry = result.entry(shard_id).or_insert_with(Vec::new); entry.push(receipt) } @@ -4427,8 +4427,8 @@ impl Chain { let mut cache = HashMap::new(); for receipt in receipts { let &mut shard_id = cache - .entry(&receipt.receiver_id) - .or_insert_with(|| account_id_to_shard_id(&receipt.receiver_id, shard_layout)); + .entry(receipt.receiver_id()) + .or_insert_with(|| account_id_to_shard_id(receipt.receiver_id(), shard_layout)); // This unwrap should be safe as we pre-populated the map with all // valid shard ids. result.get_mut(&shard_id).unwrap().push(receipt); diff --git a/chain/chain/src/chain_update.rs b/chain/chain/src/chain_update.rs index bc9b61d90ce..c940c2c9ea1 100644 --- a/chain/chain/src/chain_update.rs +++ b/chain/chain/src/chain_update.rs @@ -137,7 +137,10 @@ impl<'a> ChainUpdate<'a> { let outgoing_receipts = outgoing_receipts .iter() .map(|receipt| { - (receipt.receipt_id, account_id_to_shard_id(&receipt.receiver_id, &shard_layout)) + ( + *receipt.receipt_id(), + account_id_to_shard_id(receipt.receiver_id(), &shard_layout), + ) }) .collect(); Ok(outgoing_receipts) diff --git a/chain/chain/src/garbage_collection.rs b/chain/chain/src/garbage_collection.rs index 13ba45c91ca..d719dc2a9c3 100644 --- a/chain/chain/src/garbage_collection.rs +++ b/chain/chain/src/garbage_collection.rs @@ -876,10 +876,9 @@ impl<'a> ChainStoreUpdate<'a> { fn gc_outgoing_receipts(&mut self, block_hash: &CryptoHash, shard_id: ShardId) { let mut store_update = self.store().store_update(); - match self - .get_outgoing_receipts(block_hash, shard_id) - .map(|receipts| receipts.iter().map(|receipt| receipt.receipt_id).collect::>()) - { + match self.get_outgoing_receipts(block_hash, shard_id).map(|receipts| { + receipts.iter().map(|receipt| *receipt.receipt_id()).collect::>() + }) { Ok(receipt_ids) => { for receipt_id in receipt_ids { let key: Vec = receipt_id.into(); diff --git a/chain/chain/src/runtime/mod.rs b/chain/chain/src/runtime/mod.rs index 9b8190d762c..2bba53c5ac1 100644 --- a/chain/chain/src/runtime/mod.rs +++ b/chain/chain/src/runtime/mod.rs @@ -650,7 +650,7 @@ impl RuntimeAdapter for NightshadeRuntime { if let Some(state_root) = state_root { let shard_uid = - self.account_id_to_shard_uid(&transaction.transaction.signer_id, epoch_id)?; + self.account_id_to_shard_uid(transaction.transaction.signer_id(), epoch_id)?; let mut state_update = self.tries.new_trie_update(shard_uid, state_root); match verify_and_charge_transaction( @@ -825,7 +825,7 @@ impl RuntimeAdapter for NightshadeRuntime { if ProtocolFeature::CongestionControl.enabled(protocol_version) { let receiving_shard = EpochManagerAdapter::account_id_to_shard_id( self.epoch_manager.as_ref(), - &tx.transaction.receiver_id, + tx.transaction.receiver_id(), &epoch_id, )?; if let Some(shard_congestion) = diff --git a/chain/chain/src/runtime/tests.rs b/chain/chain/src/runtime/tests.rs index e39cd949e3e..ee04b38023a 100644 --- a/chain/chain/src/runtime/tests.rs +++ b/chain/chain/src/runtime/tests.rs @@ -59,6 +59,7 @@ fn stake( vec![Action::Stake(Box::new(StakeAction { stake, public_key: sender.public_key() }))], // runtime does not validate block history CryptoHash::default(), + 0, ) } @@ -355,7 +356,7 @@ impl TestEnv { let shard_layout = self.epoch_manager.get_shard_layout_from_prev_block(&new_hash).unwrap(); let mut new_receipts = HashMap::<_, Vec>::new(); for receipt in all_receipts { - let shard_id = account_id_to_shard_id(&receipt.receiver_id, &shard_layout); + let shard_id = account_id_to_shard_id(receipt.receiver_id(), &shard_layout); new_receipts.entry(shard_id).or_default().push(receipt); } self.last_receipts = new_receipts; @@ -1389,6 +1390,7 @@ fn test_delete_account_after_unstake() { })], // runtime does not validate block history CryptoHash::default(), + 0, ); env.step_default(vec![delete_account_transaction]); for _ in 15..=17 { @@ -1480,6 +1482,7 @@ fn test_trie_and_flat_state_equality() { vec![Action::Transfer(TransferAction { deposit: 10 })], // runtime does not validate block history CryptoHash::default(), + 0, ); env.step_default(vec![transfer_tx]); for _ in 1..=5 { @@ -1650,7 +1653,7 @@ fn prepare_transactions( .chain_store() .check_transaction_validity_period( &chain.get_block_header(&env.head.prev_block_hash).unwrap(), - &tx.transaction.block_hash, + tx.transaction.block_hash(), chain.transaction_validity_period, ) .is_ok() diff --git a/chain/chain/src/store/mod.rs b/chain/chain/src/store/mod.rs index 865a046c251..15cd3614290 100644 --- a/chain/chain/src/store/mod.rs +++ b/chain/chain/src/store/mod.rs @@ -383,12 +383,12 @@ fn filter_incoming_receipts_for_shard( let ReceiptProof(receipts, shard_proof) = receipt_proof.clone(); for receipt in receipts { let receiver_shard_id = - account_id_to_shard_id(&receipt.receiver_id, target_shard_layout); + account_id_to_shard_id(receipt.receiver_id(), target_shard_layout); if receiver_shard_id == target_shard_id { - tracing::trace!(target: "chain", receipt_id=?receipt.receipt_id, "including receipt"); + tracing::trace!(target: "chain", receipt_id=?receipt.receipt_id(), "including receipt"); filtered_receipts.push(receipt); } else { - tracing::trace!(target: "chain", receipt_id=?receipt.receipt_id, "excluding receipt"); + tracing::trace!(target: "chain", receipt_id=?receipt.receipt_id(), "excluding receipt"); } } // TODO(resharding) adjust the shard proof accordingly @@ -689,7 +689,7 @@ impl ChainStore { shard_id: ShardId, ) -> Result<(), Error> { receipts.retain(|receipt| { - account_id_to_shard_id(&receipt.receiver_id, &shard_layout) == shard_id + account_id_to_shard_id(receipt.receiver_id(), &shard_layout) == shard_id }); Ok(()) } @@ -1977,7 +1977,7 @@ impl<'a> ChainStoreUpdate<'a> { for receipt in chunk.prev_outgoing_receipts() { self.chain_store_cache_update .receipts - .insert(receipt.receipt_id, Arc::new(receipt.clone())); + .insert(*receipt.receipt_id(), Arc::new(receipt.clone())); } self.chain_store_cache_update.chunks.insert(chunk.chunk_hash(), Arc::new(chunk)); } diff --git a/chain/chain/src/test_utils.rs b/chain/chain/src/test_utils.rs index 849c62f5d28..0fe9ffc1387 100644 --- a/chain/chain/src/test_utils.rs +++ b/chain/chain/src/test_utils.rs @@ -276,7 +276,7 @@ mod test { use rand::Rng; use near_primitives::hash::CryptoHash; - use near_primitives::receipt::Receipt; + use near_primitives::receipt::{Receipt, ReceiptPriority}; use near_primitives::sharding::ReceiptList; use near_primitives::types::{AccountId, NumShards}; @@ -293,7 +293,7 @@ mod test { let shard_receipts: Vec = receipts .iter() .filter(|&receipt| { - account_id_to_shard_id(&receipt.receiver_id, shard_layout) == shard_id + account_id_to_shard_id(receipt.receiver_id(), shard_layout) == shard_id }) .cloned() .collect(); @@ -305,7 +305,7 @@ mod test { fn test_build_receipt_hashes_with_num_shard(num_shards: NumShards) { let shard_layout = ShardLayout::v0(num_shards, 0); let create_receipt_from_receiver_id = - |receiver_id| Receipt::new_balance_refund(&receiver_id, 0); + |receiver_id| Receipt::new_balance_refund(&receiver_id, 0, ReceiptPriority::NoPriority); let mut rng = rand::thread_rng(); let receipts = (0..3000) .map(|_| { diff --git a/chain/chain/src/test_utils/kv_runtime.rs b/chain/chain/src/test_utils/kv_runtime.rs index a3ab495a032..fb5f6388ad1 100644 --- a/chain/chain/src/test_utils/kv_runtime.rs +++ b/chain/chain/src/test_utils/kv_runtime.rs @@ -25,7 +25,7 @@ use near_primitives::epoch_manager::ShardConfig; use near_primitives::epoch_manager::ValidatorSelectionConfig; use near_primitives::errors::{EpochError, InvalidTxError}; use near_primitives::hash::{hash, CryptoHash}; -use near_primitives::receipt::{ActionReceipt, Receipt, ReceiptEnum}; +use near_primitives::receipt::{ActionReceipt, Receipt, ReceiptEnum, ReceiptV0}; use near_primitives::shard_layout::{ShardLayout, ShardUId}; use near_primitives::sharding::{ChunkHash, ShardChunkHeader}; use near_primitives::state_part::PartId; @@ -1145,16 +1145,19 @@ impl RuntimeAdapter for KeyValueRuntime { for receipt in receipts.iter() { if let ReceiptEnum::Action(action) | ReceiptEnum::PromiseYield(action) = - &receipt.receipt + receipt.receipt() { - assert_eq!(account_id_to_shard_id(&receipt.receiver_id, self.num_shards), shard_id); - if !state.receipt_nonces.contains(&receipt.receipt_id) { - state.receipt_nonces.insert(receipt.receipt_id); + assert_eq!( + account_id_to_shard_id(receipt.receiver_id(), self.num_shards), + shard_id + ); + if !state.receipt_nonces.contains(receipt.receipt_id()) { + state.receipt_nonces.insert(*receipt.receipt_id()); if let Action::Transfer(TransferAction { deposit }) = action.actions[0] { balance_transfers.push(( receipt.get_hash(), - receipt.predecessor_id.clone(), - receipt.receiver_id.clone(), + receipt.predecessor_id().clone(), + receipt.receiver_id().clone(), deposit, 0, )); @@ -1169,36 +1172,37 @@ impl RuntimeAdapter for KeyValueRuntime { for transaction in transactions { assert_eq!( - account_id_to_shard_id(&transaction.transaction.signer_id, self.num_shards), + account_id_to_shard_id(transaction.transaction.signer_id(), self.num_shards), shard_id ); - if transaction.transaction.actions.is_empty() { + if transaction.transaction.actions().is_empty() { continue; } - if let Action::Transfer(TransferAction { deposit }) = transaction.transaction.actions[0] + if let Action::Transfer(TransferAction { deposit }) = + transaction.transaction.actions()[0] { if !state.tx_nonces.contains(&AccountNonce( - transaction.transaction.receiver_id.clone(), - transaction.transaction.nonce, + transaction.transaction.receiver_id().clone(), + transaction.transaction.nonce(), )) { state.tx_nonces.insert(AccountNonce( - transaction.transaction.receiver_id.clone(), - transaction.transaction.nonce, + transaction.transaction.receiver_id().clone(), + transaction.transaction.nonce(), )); balance_transfers.push(( transaction.get_hash(), - transaction.transaction.signer_id.clone(), - transaction.transaction.receiver_id.clone(), + transaction.transaction.signer_id().clone(), + transaction.transaction.receiver_id().clone(), deposit, - transaction.transaction.nonce, + transaction.transaction.nonce(), )); } else { balance_transfers.push(( transaction.get_hash(), - transaction.transaction.signer_id.clone(), - transaction.transaction.receiver_id.clone(), + transaction.transaction.signer_id().clone(), + transaction.transaction.receiver_id().clone(), 0, - transaction.transaction.nonce, + transaction.transaction.nonce(), )); } } else { @@ -1229,7 +1233,7 @@ impl RuntimeAdapter for KeyValueRuntime { vec![] } else { assert_ne!(nonce, 0); - let receipt = Receipt { + let receipt = Receipt::V0(ReceiptV0 { predecessor_id: from.clone(), receiver_id: to.clone(), receipt_id: create_receipt_nonce(from.clone(), to.clone(), amount, nonce), @@ -1241,7 +1245,7 @@ impl RuntimeAdapter for KeyValueRuntime { input_data_ids: vec![], actions: vec![Action::Transfer(TransferAction { deposit: amount })], }), - }; + }); let receipt_hash = receipt.get_hash(); outgoing_receipts.push(receipt); vec![receipt_hash] diff --git a/chain/chain/src/validate.rs b/chain/chain/src/validate.rs index a6c5d4d4849..02e9aa8cea8 100644 --- a/chain/chain/src/validate.rs +++ b/chain/chain/src/validate.rs @@ -78,10 +78,10 @@ pub fn validate_transactions_order(transactions: &[SignedTransaction]) -> bool { let mut current_batch = 1; for tx in transactions { - let key = (&tx.transaction.signer_id, &tx.transaction.public_key); + let key = (tx.transaction.signer_id(), tx.transaction.public_key()); // Verifying nonce - let nonce = tx.transaction.nonce; + let nonce = tx.transaction.nonce(); if let Some(last_nonce) = nonces.get(&key) { if nonce <= *last_nonce { // Nonces should increase. diff --git a/chain/chunks/src/client.rs b/chain/chunks/src/client.rs index b360db58bfc..5678f0ef5fe 100644 --- a/chain/chunks/src/client.rs +++ b/chain/chunks/src/client.rs @@ -143,7 +143,7 @@ impl ShardedTransactionPool { } for tx in transactions { - let signer_id = &tx.transaction.signer_id; + let signer_id = tx.transaction.signer_id(); let new_shard_uid = account_id_to_shard_uid(&signer_id, new_shard_layout); self.insert_transaction(new_shard_uid, tx); } @@ -266,8 +266,8 @@ mod tests { while let Some(group) = pool_iter.next() { while let Some(tx) = group.next() { total += 1; - let account_id = tx.transaction.signer_id; - let tx_shard_uid = account_id_to_shard_uid(&account_id, &new_shard_layout); + let account_id = tx.transaction.signer_id(); + let tx_shard_uid = account_id_to_shard_uid(account_id, &new_shard_layout); tracing::debug!("checking {account_id:?}:{tx_shard_uid} in {shard_uid}"); assert_eq!(shard_uid, tx_shard_uid); } diff --git a/chain/client/src/client.rs b/chain/client/src/client.rs index a1816957a3a..3326671d903 100644 --- a/chain/client/src/client.rs +++ b/chain/client/src/client.rs @@ -1013,6 +1013,7 @@ impl Client { "other".parse().unwrap(), 3, prev_block_hash, + 0, ), )); if txs.storage_proof.is_none() { @@ -2112,7 +2113,7 @@ impl Client { /// Forwards given transaction to upcoming validators. fn forward_tx(&self, epoch_id: &EpochId, tx: &SignedTransaction) -> Result<(), Error> { let shard_id = - self.epoch_manager.account_id_to_shard_id(&tx.transaction.signer_id, epoch_id)?; + self.epoch_manager.account_id_to_shard_id(tx.transaction.signer_id(), epoch_id)?; // Use the header head to make sure the list of validators is as // up-to-date as possible. let head = self.chain.header_head()?; @@ -2129,7 +2130,7 @@ impl Client { if let Some(next_epoch_id) = &maybe_next_epoch_id { let next_shard_id = self .epoch_manager - .account_id_to_shard_id(&tx.transaction.signer_id, next_epoch_id)?; + .account_id_to_shard_id(tx.transaction.signer_id(), next_epoch_id)?; let validator = self.epoch_manager.get_chunk_producer( next_epoch_id, target_height, @@ -2220,7 +2221,7 @@ impl Client { // `cur_block_header`. if let Err(e) = self.chain.chain_store().check_transaction_validity_period( &cur_block_header, - &tx.transaction.block_hash, + tx.transaction.block_hash(), transaction_validity_period, ) { debug!(target: "client", ?tx, "Invalid tx: expired or from a different fork"); @@ -2241,7 +2242,7 @@ impl Client { } let shard_id = - self.epoch_manager.account_id_to_shard_id(&tx.transaction.signer_id, &epoch_id)?; + self.epoch_manager.account_id_to_shard_id(tx.transaction.signer_id(), &epoch_id)?; let care_about_shard = self.shard_tracker.care_about_shard(me, &head.last_block_hash, shard_id, true); let will_care_about_shard = diff --git a/chain/client/src/test_utils/test_env.rs b/chain/client/src/test_utils/test_env.rs index 54285692b66..dcb858eb902 100644 --- a/chain/client/src/test_utils/test_env.rs +++ b/chain/client/src/test_utils/test_env.rs @@ -697,6 +697,7 @@ impl TestEnv { signer, actions, tip.last_block_hash, + 0, ) } @@ -735,6 +736,7 @@ impl TestEnv { &relayer_signer, vec![Action::Delegate(Box::new(signed_delegate_action))], tip.last_block_hash, + 0, ) } diff --git a/chain/indexer/src/streamer/utils.rs b/chain/indexer/src/streamer/utils.rs index 15d559b8ac8..6c8a14c7440 100644 --- a/chain/indexer/src/streamer/utils.rs +++ b/chain/indexer/src/streamer/utils.rs @@ -27,26 +27,29 @@ pub(crate) async fn convert_transactions_sir_into_local_receipts( .map(|tx| { let cost = tx_cost( &runtime_config, - &near_primitives::transaction::Transaction { - signer_id: tx.transaction.signer_id.clone(), - public_key: tx.transaction.public_key.clone(), - nonce: tx.transaction.nonce, - receiver_id: tx.transaction.receiver_id.clone(), - block_hash: block.header.hash, - actions: tx - .transaction - .actions - .clone() - .into_iter() - .map(|action| { - near_primitives::transaction::Action::try_from(action).unwrap() - }) - .collect(), - }, + &near_primitives::transaction::Transaction::V0( + near_primitives::transaction::TransactionV0 { + signer_id: tx.transaction.signer_id.clone(), + public_key: tx.transaction.public_key.clone(), + nonce: tx.transaction.nonce, + receiver_id: tx.transaction.receiver_id.clone(), + block_hash: block.header.hash, + actions: tx + .transaction + .actions + .clone() + .into_iter() + .map(|action| { + near_primitives::transaction::Action::try_from(action).unwrap() + }) + .collect(), + }, + ), prev_block_gas_price, true, protocol_version, - ); + ) + .expect("TransactionCost returned IntegerOverflowError"); views::ReceiptView { predecessor_id: tx.transaction.signer_id.clone(), receiver_id: tx.transaction.receiver_id.clone(), @@ -56,14 +59,13 @@ pub(crate) async fn convert_transactions_sir_into_local_receipts( receipt: views::ReceiptEnumView::Action { signer_id: tx.transaction.signer_id.clone(), signer_public_key: tx.transaction.public_key.clone(), - gas_price: cost - .expect("TransactionCost returned IntegerOverflowError") - .receipt_gas_price, + gas_price: cost.receipt_gas_price, output_data_receivers: vec![], input_data_ids: vec![], actions: tx.transaction.actions.clone(), is_promise_yield: false, }, + priority: 0, } }) .collect(); diff --git a/chain/jsonrpc-primitives/src/types/transactions.rs b/chain/jsonrpc-primitives/src/types/transactions.rs index f6f0efc49c3..30d00838035 100644 --- a/chain/jsonrpc-primitives/src/types/transactions.rs +++ b/chain/jsonrpc-primitives/src/types/transactions.rs @@ -81,7 +81,7 @@ impl TransactionInfo { match self { TransactionInfo::Transaction(tx) => match tx { SignedTransaction::SignedTransaction(tx) => { - (tx.get_hash(), &tx.transaction.signer_id) + (tx.get_hash(), tx.transaction.signer_id()) } }, TransactionInfo::TransactionId { tx_hash, sender_account_id } => { diff --git a/chain/jsonrpc/res/rpc_errors_schema.json b/chain/jsonrpc/res/rpc_errors_schema.json index 5725f0c95e1..a09dfebc2fe 100644 --- a/chain/jsonrpc/res/rpc_errors_schema.json +++ b/chain/jsonrpc/res/rpc_errors_schema.json @@ -547,6 +547,11 @@ "account_id": "" } }, + "InvalidTransactionVersion": { + "name": "InvalidTransactionVersion", + "subtypes": [], + "props": {} + }, "InvalidTxError": { "name": "InvalidTxError", "subtypes": [ @@ -563,7 +568,8 @@ "InvalidChain", "Expired", "ActionsValidation", - "TransactionSizeExceeded" + "TransactionSizeExceeded", + "InvalidTransactionVersion" ], "props": {} }, diff --git a/chain/jsonrpc/src/lib.rs b/chain/jsonrpc/src/lib.rs index e12f81c4e7f..5504e22ab53 100644 --- a/chain/jsonrpc/src/lib.rs +++ b/chain/jsonrpc/src/lib.rs @@ -659,7 +659,7 @@ impl JsonRpcHandler { ) -> Result { let tx_hash = tx.get_hash(); - let signer_account_id = tx.transaction.signer_id.clone(); + let signer_account_id = tx.transaction.signer_id().clone(); let response = self .client_sender .send_async(ProcessTxRequest { transaction: tx, is_forwarded: false, check_only }) diff --git a/chain/pool/src/lib.rs b/chain/pool/src/lib.rs index 56708b95507..9a28a374502 100644 --- a/chain/pool/src/lib.rs +++ b/chain/pool/src/lib.rs @@ -103,8 +103,8 @@ impl TransactionPool { // At this point transaction is accepted to the pool. self.total_transaction_size = new_total_transaction_size; - let signer_id = &signed_transaction.transaction.signer_id; - let signer_public_key = &signed_transaction.transaction.public_key; + let signer_id = signed_transaction.transaction.signer_id(); + let signer_public_key = signed_transaction.transaction.public_key(); self.transactions .entry(self.key(signer_id, signer_public_key)) .or_insert_with(Vec::new) @@ -134,8 +134,8 @@ impl TransactionPool { continue; } - let signer_id = &tx.transaction.signer_id; - let signer_public_key = &tx.transaction.public_key; + let signer_id = tx.transaction.signer_id(); + let signer_public_key = tx.transaction.public_key(); grouped_transactions .entry(self.key(signer_id, signer_public_key)) .or_insert_with(HashSet::new) @@ -230,7 +230,7 @@ impl<'a> TransactionGroupIterator for PoolIteratorWrapper<'a> { self.pool.last_used_key = key; let mut transactions = self.pool.transactions.remove(&key).expect("just checked existence"); - transactions.sort_by_key(|st| std::cmp::Reverse(st.transaction.nonce)); + transactions.sort_by_key(|st| std::cmp::Reverse(st.transaction.nonce())); self.sorted_groups.push_back(TransactionGroup { key, transactions, @@ -380,7 +380,7 @@ mod tests { ( prepare_transactions(&mut pool, expected_weight) .iter() - .map(|tx| tx.transaction.nonce) + .map(|tx| tx.transaction.nonce()) .collect(), pool, ) @@ -455,7 +455,7 @@ mod tests { sort_pairs(&mut nonces[..6]); assert_eq!(nonces, vec![1, 21, 2, 22, 3, 23, 24, 25, 26, 27]); let nonces: Vec = - prepare_transactions(&mut pool, 10).iter().map(|tx| tx.transaction.nonce).collect(); + prepare_transactions(&mut pool, 10).iter().map(|tx| tx.transaction.nonce()).collect(); assert_eq!(nonces, vec![28, 29, 30, 31]); } @@ -498,9 +498,9 @@ mod tests { assert_eq!(pool.len(), txs_to_check.len()); let mut pool_txs = prepare_transactions(&mut pool, txs_to_check.len() as u32); - pool_txs.sort_by_key(|tx| tx.transaction.nonce); + pool_txs.sort_by_key(|tx| tx.transaction.nonce()); let mut expected_txs = txs_to_check.to_vec(); - expected_txs.sort_by_key(|tx| tx.transaction.nonce); + expected_txs.sort_by_key(|tx| tx.transaction.nonce()); assert_eq!(pool_txs, expected_txs); } @@ -518,7 +518,7 @@ mod tests { let mut pool_iter = pool.pool_iterator(); while let Some(iter) = pool_iter.next() { while let Some(tx) = iter.next() { - if tx.transaction.nonce & 1 == 1 { + if tx.transaction.nonce() & 1 == 1 { res.push(tx); break; } @@ -527,7 +527,7 @@ mod tests { drop(pool_iter); assert_eq!(pool.len(), 0); assert_eq!(pool.transaction_size(), 0); - let mut nonces: Vec<_> = res.into_iter().map(|tx| tx.transaction.nonce).collect(); + let mut nonces: Vec<_> = res.into_iter().map(|tx| tx.transaction.nonce()).collect(); sort_pairs(&mut nonces[..4]); assert_eq!(nonces, vec![1, 21, 3, 23, 25, 27, 29, 31]); } @@ -590,7 +590,7 @@ mod tests { let txs = prepare_transactions(&mut pool, 5); assert_eq!(txs.len(), 5); nonces.sort(); - let mut new_nonces = txs.iter().map(|tx| tx.transaction.nonce).collect::>(); + let mut new_nonces = txs.iter().map(|tx| tx.transaction.nonce()).collect::>(); new_nonces.sort(); assert_ne!(nonces, new_nonces); } diff --git a/chain/rosetta-rpc/src/lib.rs b/chain/rosetta-rpc/src/lib.rs index e8be28019ed..99965c02e77 100644 --- a/chain/rosetta-rpc/src/lib.rs +++ b/chain/rosetta-rpc/src/lib.rs @@ -650,19 +650,21 @@ async fn construction_payloads( } = operations.try_into()?; let models::ConstructionMetadata { recent_block_hash, signer_public_access_key_nonce } = metadata; - let unsigned_transaction = near_primitives::transaction::Transaction { - block_hash: recent_block_hash.parse().map_err(|err| { - errors::ErrorKind::InvalidInput(format!( - "block hash could not be parsed due to: {:?}", - err - )) - })?, - signer_id: signer_account_id.clone(), - public_key: signer_public_access_key.clone(), - nonce: signer_public_access_key_nonce, - receiver_id: receiver_account_id, - actions, - }; + let unsigned_transaction = near_primitives::transaction::Transaction::V0( + near_primitives::transaction::TransactionV0 { + block_hash: recent_block_hash.parse().map_err(|err| { + errors::ErrorKind::InvalidInput(format!( + "block hash could not be parsed due to: {:?}", + err + )) + })?, + signer_id: signer_account_id.clone(), + public_key: signer_public_access_key.clone(), + nonce: signer_public_access_key_nonce, + receiver_id: receiver_account_id, + actions, + }, + ); let (transaction_hash, _) = unsigned_transaction.get_hash_and_size(); @@ -727,12 +729,7 @@ async fn construction_parse( check_network_identifier(&client_addr, network_identifier).await?; - let near_primitives::transaction::Transaction { - actions, - signer_id: sender_account_id, - receiver_id: receiver_account_id, - .. - } = if signed { + let transaction = if signed { near_primitives::transaction::SignedTransaction::try_from_slice(&transaction.into_inner()) .map_err(|err| { errors::ErrorKind::InvalidInput(format!( @@ -752,10 +749,13 @@ async fn construction_parse( }; let account_identifier_signers = - if signed { vec![sender_account_id.clone().into()] } else { vec![] }; + if signed { vec![transaction.signer_id().clone().into()] } else { vec![] }; - let near_actions = - crate::adapters::NearActions { sender_account_id, receiver_account_id, actions }; + let near_actions = crate::adapters::NearActions { + sender_account_id: transaction.signer_id().clone(), + receiver_account_id: transaction.receiver_id().clone(), + actions: transaction.take_actions(), + }; Ok(Json(models::ConstructionParseResponse { account_identifier_signers, diff --git a/core/primitives/benches/serialization.rs b/core/primitives/benches/serialization.rs index c00064c6516..4ec41c1ccfd 100644 --- a/core/primitives/benches/serialization.rs +++ b/core/primitives/benches/serialization.rs @@ -11,7 +11,9 @@ use near_primitives::block::{genesis_chunks, Block}; use near_primitives::hash::CryptoHash; use near_primitives::merkle::combine_hash; use near_primitives::test_utils::account_new; -use near_primitives::transaction::{Action, SignedTransaction, Transaction, TransferAction}; +use near_primitives::transaction::{ + Action, SignedTransaction, Transaction, TransactionV0, TransferAction, +}; use near_primitives::types::{EpochId, StateRoot}; use near_primitives::validator_signer::InMemoryValidatorSigner; use near_primitives::version::PROTOCOL_VERSION; @@ -25,14 +27,14 @@ fn create_transaction() -> SignedTransaction { } SignedTransaction::new( Signature::empty(KeyType::ED25519), - Transaction { + Transaction::V0(TransactionV0 { signer_id: "123213123123".parse().unwrap(), public_key: PublicKey::empty(KeyType::ED25519), nonce: 123, receiver_id: "1231231232131".parse().unwrap(), block_hash: Default::default(), actions, - }, + }), ) } diff --git a/core/primitives/src/errors.rs b/core/primitives/src/errors.rs index 4ace4cee370..5f0f5e7715a 100644 --- a/core/primitives/src/errors.rs +++ b/core/primitives/src/errors.rs @@ -178,6 +178,8 @@ pub enum InvalidTxError { ActionsValidation(ActionsValidationError), /// The size of serialized transaction exceeded the limit. TransactionSizeExceeded { size: u64, limit: u64 }, + /// Transaction version is invalid. + InvalidTransactionVersion, } impl std::error::Error for InvalidTxError {} @@ -573,6 +575,9 @@ impl Display for InvalidTxError { InvalidTxError::TransactionSizeExceeded { size, limit } => { write!(f, "Size of serialized transaction {} exceeded the limit {}", size, limit) } + InvalidTxError::InvalidTransactionVersion => { + write!(f, "Transaction version is invalid") + } } } } diff --git a/core/primitives/src/receipt.rs b/core/primitives/src/receipt.rs index a6230d45e73..293e1728a2b 100644 --- a/core/primitives/src/receipt.rs +++ b/core/primitives/src/receipt.rs @@ -10,6 +10,8 @@ use serde_with::serde_as; use std::borrow::Borrow; use std::collections::{BTreeMap, HashMap}; use std::fmt; +use std::io::{self, Read}; +use std::io::{Error, ErrorKind}; /// The outgoing (egress) data which will be transformed /// to a `DataReceipt` to be sent to a `receipt.receiver` @@ -41,7 +43,7 @@ pub struct DataReceiver { serde::Serialize, serde::Deserialize, )] -pub struct Receipt { +pub struct ReceiptV0 { /// An issuer account_id of a particular receipt. /// `predecessor_id` could be either `Transaction` `signer_id` or intermediate contract's `account_id`. pub predecessor_id: AccountId, @@ -53,34 +55,243 @@ pub struct Receipt { pub receipt: ReceiptEnum, } +#[derive( + BorshSerialize, + BorshDeserialize, + Debug, + PartialEq, + Eq, + Clone, + serde::Serialize, + serde::Deserialize, +)] +pub struct ReceiptV1 { + /// An issuer account_id of a particular receipt. + /// `predecessor_id` could be either `Transaction` `signer_id` or intermediate contract's `account_id`. + pub predecessor_id: AccountId, + /// `receiver_id` is a receipt destination. + pub receiver_id: AccountId, + /// An unique id for the receipt + pub receipt_id: CryptoHash, + /// A receipt type + pub receipt: ReceiptEnum, + /// Priority of a receipt + pub priority: u64, +} + +#[derive(Debug, PartialEq, Eq, Clone, serde::Serialize, serde::Deserialize)] +#[serde(untagged)] +pub enum Receipt { + V0(ReceiptV0), + V1(ReceiptV1), +} + +impl BorshSerialize for Receipt { + fn serialize(&self, writer: &mut W) -> io::Result<()> { + match self { + Receipt::V0(receipt) => receipt.serialize(writer), + Receipt::V1(receipt) => { + BorshSerialize::serialize(&1_u8, writer)?; + receipt.serialize(writer) + } + } + } +} + +impl BorshDeserialize for Receipt { + /// Deserialize based on the first and second bytes of the stream. For V0, we do backward compatible deserialization by deserializing + /// the entire stream into V0. For V1, we consume the first byte and then deserialize the rest. + fn deserialize_reader(reader: &mut R) -> std::io::Result { + let u1 = u8::deserialize_reader(reader)?; + let u2 = u8::deserialize_reader(reader)?; + let u3 = u8::deserialize_reader(reader)?; + let u4 = u8::deserialize_reader(reader)?; + // This is a ridiculous hackery: because the first field in `ReceiptV0` is an `AccountId` + // and an account id is at most 64 bytes, for all valid `ReceiptV0` the second byte must be 0 + // because of the littel endian encoding of the length of the account id. + // On the other hand, for `ReceiptV0`, since the first byte is 1 and an account id must have nonzero + // length, so the second byte must not be zero. Therefore, we can distinguish between the two versions + // by looking at the second byte. + + let read_predecessor_id = |buf: [u8; 4], reader: &mut R| -> std::io::Result { + let str_len = u32::from_le_bytes(buf); + let mut str_vec = Vec::with_capacity(str_len as usize); + for _ in 0..str_len { + str_vec.push(u8::deserialize_reader(reader)?); + } + AccountId::try_from(String::from_utf8(str_vec).map_err(|_| { + Error::new(ErrorKind::InvalidData, "Failed to parse AccountId from bytes") + })?) + .map_err(|e| Error::new(ErrorKind::InvalidData, e.to_string())) + }; + + if u2 == 0 { + let signer_id = read_predecessor_id([u1, u2, u3, u4], reader)?; + let receiver_id = AccountId::deserialize_reader(reader)?; + let receipt_id = CryptoHash::deserialize_reader(reader)?; + let receipt = ReceiptEnum::deserialize_reader(reader)?; + Ok(Receipt::V0(ReceiptV0 { + predecessor_id: signer_id, + receiver_id, + receipt_id, + receipt, + })) + } else { + let u5 = u8::deserialize_reader(reader)?; + let signer_id = read_predecessor_id([u2, u3, u4, u5], reader)?; + let receiver_id = AccountId::deserialize_reader(reader)?; + let receipt_id = CryptoHash::deserialize_reader(reader)?; + let receipt = ReceiptEnum::deserialize_reader(reader)?; + let priority = u64::deserialize_reader(reader)?; + Ok(Receipt::V1(ReceiptV1 { + predecessor_id: signer_id, + receiver_id, + receipt_id, + receipt, + priority, + })) + } + } +} + +pub enum ReceiptPriority { + /// Used in ReceiptV1 + Priority(u64), + /// Used in ReceiptV0 + NoPriority, +} + +impl ReceiptPriority { + pub fn value(&self) -> u64 { + match self { + ReceiptPriority::Priority(value) => *value, + ReceiptPriority::NoPriority => 0, + } + } +} + impl Borrow for Receipt { fn borrow(&self) -> &CryptoHash { - &self.receipt_id + match self { + Receipt::V0(receipt) => &receipt.receipt_id, + Receipt::V1(receipt) => &receipt.receipt_id, + } } } impl Receipt { + pub fn receiver_id(&self) -> &AccountId { + match self { + Receipt::V0(receipt) => &receipt.receiver_id, + Receipt::V1(receipt) => &receipt.receiver_id, + } + } + + pub fn set_receiver_id(&mut self, receiver_id: AccountId) { + match self { + Receipt::V0(receipt) => receipt.receiver_id = receiver_id, + Receipt::V1(receipt) => receipt.receiver_id = receiver_id, + } + } + + pub fn predecessor_id(&self) -> &AccountId { + match self { + Receipt::V0(receipt) => &receipt.predecessor_id, + Receipt::V1(receipt) => &receipt.predecessor_id, + } + } + + pub fn set_predecessor_id(&mut self, predecessor_id: AccountId) { + match self { + Receipt::V0(receipt) => receipt.predecessor_id = predecessor_id, + Receipt::V1(receipt) => receipt.predecessor_id = predecessor_id, + } + } + + pub fn receipt(&self) -> &ReceiptEnum { + match self { + Receipt::V0(receipt) => &receipt.receipt, + Receipt::V1(receipt) => &receipt.receipt, + } + } + + pub fn receipt_mut(&mut self) -> &mut ReceiptEnum { + match self { + Receipt::V0(receipt) => &mut receipt.receipt, + Receipt::V1(receipt) => &mut receipt.receipt, + } + } + + pub fn take_receipt(self) -> ReceiptEnum { + match self { + Receipt::V0(receipt) => receipt.receipt, + Receipt::V1(receipt) => receipt.receipt, + } + } + + pub fn receipt_id(&self) -> &CryptoHash { + match self { + Receipt::V0(receipt) => &receipt.receipt_id, + Receipt::V1(receipt) => &receipt.receipt_id, + } + } + + pub fn set_receipt_id(&mut self, receipt_id: CryptoHash) { + match self { + Receipt::V0(receipt) => receipt.receipt_id = receipt_id, + Receipt::V1(receipt) => receipt.receipt_id = receipt_id, + } + } + + pub fn priority(&self) -> ReceiptPriority { + match self { + Receipt::V0(_) => ReceiptPriority::NoPriority, + Receipt::V1(receipt) => ReceiptPriority::Priority(receipt.priority), + } + } + /// It's not a content hash, but receipt_id is unique. pub fn get_hash(&self) -> CryptoHash { - self.receipt_id + *self.receipt_id() } /// Generates a receipt with a transfer from system for a given balance without a receipt_id. - /// This should be used for token refunds instead of gas refunds. It doesn't refund the - /// allowance of the access key. For gas refunds use `new_gas_refund`. - pub fn new_balance_refund(receiver_id: &AccountId, refund: Balance) -> Self { - Receipt { - predecessor_id: "system".parse().unwrap(), - receiver_id: receiver_id.clone(), - receipt_id: CryptoHash::default(), + /// This should be used for token refunds instead of gas refunds. It inherits priority from the parent receipt. + /// It doesn't refund the allowance of the access key. For gas refunds use `new_gas_refund`. + pub fn new_balance_refund( + receiver_id: &AccountId, + refund: Balance, + priority: ReceiptPriority, + ) -> Self { + match priority { + ReceiptPriority::Priority(priority) => Receipt::V1(ReceiptV1 { + predecessor_id: "system".parse().unwrap(), + receiver_id: receiver_id.clone(), + receipt_id: CryptoHash::default(), - receipt: ReceiptEnum::Action(ActionReceipt { - signer_id: "system".parse().unwrap(), - signer_public_key: PublicKey::empty(KeyType::ED25519), - gas_price: 0, - output_data_receivers: vec![], - input_data_ids: vec![], - actions: vec![Action::Transfer(TransferAction { deposit: refund })], + receipt: ReceiptEnum::Action(ActionReceipt { + signer_id: "system".parse().unwrap(), + signer_public_key: PublicKey::empty(KeyType::ED25519), + gas_price: 0, + output_data_receivers: vec![], + input_data_ids: vec![], + actions: vec![Action::Transfer(TransferAction { deposit: refund })], + }), + priority, + }), + ReceiptPriority::NoPriority => Receipt::V0(ReceiptV0 { + predecessor_id: "system".parse().unwrap(), + receiver_id: receiver_id.clone(), + receipt_id: CryptoHash::default(), + + receipt: ReceiptEnum::Action(ActionReceipt { + signer_id: "system".parse().unwrap(), + signer_public_key: PublicKey::empty(KeyType::ED25519), + gas_price: 0, + output_data_receivers: vec![], + input_data_ids: vec![], + actions: vec![Action::Transfer(TransferAction { deposit: refund })], + }), }), } } @@ -89,25 +300,44 @@ impl Receipt { /// receipt_id. It contains `signer_id` and `signer_public_key` to indicate this is a gas /// refund. The execution of this receipt will try to refund the allowance of the /// access key with the given public key. + /// Gas refund does not inherit priority from its parent receipt and has no priority associated with it /// NOTE: The access key may be replaced by the owner, so the execution can't rely that the /// access key is the same and it should use best effort for the refund. pub fn new_gas_refund( receiver_id: &AccountId, refund: Balance, signer_public_key: PublicKey, + priority: ReceiptPriority, ) -> Self { - Receipt { - predecessor_id: "system".parse().unwrap(), - receiver_id: receiver_id.clone(), - receipt_id: CryptoHash::default(), + match priority { + ReceiptPriority::Priority(priority) => Receipt::V1(ReceiptV1 { + predecessor_id: "system".parse().unwrap(), + receiver_id: receiver_id.clone(), + receipt_id: CryptoHash::default(), - receipt: ReceiptEnum::Action(ActionReceipt { - signer_id: receiver_id.clone(), - signer_public_key, - gas_price: 0, - output_data_receivers: vec![], - input_data_ids: vec![], - actions: vec![Action::Transfer(TransferAction { deposit: refund })], + receipt: ReceiptEnum::Action(ActionReceipt { + signer_id: receiver_id.clone(), + signer_public_key, + gas_price: 0, + output_data_receivers: vec![], + input_data_ids: vec![], + actions: vec![Action::Transfer(TransferAction { deposit: refund })], + }), + priority, + }), + ReceiptPriority::NoPriority => Receipt::V0(ReceiptV0 { + predecessor_id: "system".parse().unwrap(), + receiver_id: receiver_id.clone(), + receipt_id: CryptoHash::default(), + + receipt: ReceiptEnum::Action(ActionReceipt { + signer_id: receiver_id.clone(), + signer_public_key, + gas_price: 0, + output_data_receivers: vec![], + input_data_ids: vec![], + actions: vec![Action::Transfer(TransferAction { deposit: refund })], + }), }), } } @@ -291,3 +521,49 @@ pub struct BufferedReceiptIndices { /// Map of shard to list of receipts to send to it. pub type ReceiptResult = HashMap>; + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_receipt_v0_serialization() { + let receipt_v0 = Receipt::V0(ReceiptV0 { + predecessor_id: "predecessor_id".parse().unwrap(), + receiver_id: "receiver_id".parse().unwrap(), + receipt_id: CryptoHash::default(), + receipt: ReceiptEnum::Action(ActionReceipt { + signer_id: "signer_id".parse().unwrap(), + signer_public_key: PublicKey::empty(KeyType::ED25519), + gas_price: 0, + output_data_receivers: vec![], + input_data_ids: vec![], + actions: vec![Action::Transfer(TransferAction { deposit: 0 })], + }), + }); + let serialized_receipt = borsh::to_vec(&receipt_v0).unwrap(); + let receipt2 = Receipt::try_from_slice(&serialized_receipt).unwrap(); + assert_eq!(receipt_v0, receipt2); + } + + #[test] + fn test_receipt_v1_serialization() { + let receipt_v1 = Receipt::V1(ReceiptV1 { + predecessor_id: "predecessor_id".parse().unwrap(), + receiver_id: "receiver_id".parse().unwrap(), + receipt_id: CryptoHash::default(), + receipt: ReceiptEnum::Action(ActionReceipt { + signer_id: "signer_id".parse().unwrap(), + signer_public_key: PublicKey::empty(KeyType::ED25519), + gas_price: 0, + output_data_receivers: vec![], + input_data_ids: vec![], + actions: vec![Action::Transfer(TransferAction { deposit: 0 })], + }), + priority: 1, + }); + let serialized_receipt = borsh::to_vec(&receipt_v1).unwrap(); + let receipt2 = Receipt::try_from_slice(&serialized_receipt).unwrap(); + assert_eq!(receipt_v1, receipt2); + } +} diff --git a/core/primitives/src/state_record.rs b/core/primitives/src/state_record.rs index 3b62a361906..1dab335f550 100644 --- a/core/primitives/src/state_record.rs +++ b/core/primitives/src/state_record.rs @@ -179,7 +179,7 @@ pub fn state_record_to_account_id(state_record: &StateRecord) -> &AccountId { | StateRecord::ReceivedData { account_id, .. } | StateRecord::Data { account_id, .. } => account_id, StateRecord::PostponedReceipt(receipt) | StateRecord::DelayedReceipt(receipt) => { - &receipt.receiver_id + receipt.receiver_id() } } } diff --git a/core/primitives/src/test_utils.rs b/core/primitives/src/test_utils.rs index fb3f4ce3eae..e488cc7cfa5 100644 --- a/core/primitives/src/test_utils.rs +++ b/core/primitives/src/test_utils.rs @@ -11,7 +11,7 @@ use crate::sharding::{ShardChunkHeader, ShardChunkHeaderV3}; use crate::transaction::{ Action, AddKeyAction, CreateAccountAction, DeleteAccountAction, DeleteKeyAction, DeployContractAction, FunctionCallAction, SignedTransaction, StakeAction, Transaction, - TransferAction, + TransactionV0, TransactionV1, TransferAction, }; use crate::types::{AccountId, Balance, EpochId, EpochInfoProvider, Gas, Nonce}; use crate::validator_signer::{InMemoryValidatorSigner, ValidatorSigner}; @@ -36,8 +36,31 @@ impl Transaction { receiver_id: AccountId, nonce: Nonce, block_hash: CryptoHash, + priority_fee: u64, ) -> Self { - Self { signer_id, public_key, nonce, receiver_id, block_hash, actions: vec![] } + Transaction::V1(TransactionV1 { + signer_id, + public_key, + nonce, + receiver_id, + block_hash, + actions: vec![], + priority_fee, + }) + } + + pub fn actions_mut(&mut self) -> &mut Vec { + match self { + Transaction::V0(tx) => &mut tx.actions, + Transaction::V1(tx) => &mut tx.actions, + } + } + + pub fn nonce_mut(&mut self) -> &mut Nonce { + match self { + Transaction::V0(tx) => &mut tx.nonce, + Transaction::V1(tx) => &mut tx.nonce, + } } pub fn sign(self, signer: &dyn Signer) -> SignedTransaction { @@ -46,12 +69,12 @@ impl Transaction { } pub fn create_account(mut self) -> Self { - self.actions.push(Action::CreateAccount(CreateAccountAction {})); + self.actions_mut().push(Action::CreateAccount(CreateAccountAction {})); self } pub fn deploy_contract(mut self, code: Vec) -> Self { - self.actions.push(Action::DeployContract(DeployContractAction { code })); + self.actions_mut().push(Action::DeployContract(DeployContractAction { code })); self } @@ -62,7 +85,7 @@ impl Transaction { gas: Gas, deposit: Balance, ) -> Self { - self.actions.push(Action::FunctionCall(Box::new(FunctionCallAction { + self.actions_mut().push(Action::FunctionCall(Box::new(FunctionCallAction { method_name, args, gas, @@ -72,31 +95,34 @@ impl Transaction { } pub fn transfer(mut self, deposit: Balance) -> Self { - self.actions.push(Action::Transfer(TransferAction { deposit })); + self.actions_mut().push(Action::Transfer(TransferAction { deposit })); self } pub fn stake(mut self, stake: Balance, public_key: PublicKey) -> Self { - self.actions.push(Action::Stake(Box::new(StakeAction { stake, public_key }))); + self.actions_mut().push(Action::Stake(Box::new(StakeAction { stake, public_key }))); self } pub fn add_key(mut self, public_key: PublicKey, access_key: AccessKey) -> Self { - self.actions.push(Action::AddKey(Box::new(AddKeyAction { public_key, access_key }))); + self.actions_mut().push(Action::AddKey(Box::new(AddKeyAction { public_key, access_key }))); self } pub fn delete_key(mut self, public_key: PublicKey) -> Self { - self.actions.push(Action::DeleteKey(Box::new(DeleteKeyAction { public_key }))); + self.actions_mut().push(Action::DeleteKey(Box::new(DeleteKeyAction { public_key }))); self } pub fn delete_account(mut self, beneficiary_id: AccountId) -> Self { - self.actions.push(Action::DeleteAccount(DeleteAccountAction { beneficiary_id })); + self.actions_mut().push(Action::DeleteAccount(DeleteAccountAction { beneficiary_id })); self } } +/// This block implements a set of helper functions to create transactions for testing purposes. impl SignedTransaction { + /// Creates v0 for now because v1 is prohibited in the protocol. + /// Once v1 is allowed, this function should be updated to create v1 transactions. pub fn from_actions( nonce: Nonce, signer_id: AccountId, @@ -104,15 +130,38 @@ impl SignedTransaction { signer: &dyn Signer, actions: Vec, block_hash: CryptoHash, + _priority_fee: u64, ) -> Self { - Transaction { + Transaction::V0(TransactionV0 { nonce, signer_id, public_key: signer.public_key(), receiver_id, block_hash, actions, - } + }) + .sign(signer) + } + + /// Explicitly create v1 transaction to test in cases where errors are expected. + pub fn from_actions_v1( + nonce: Nonce, + signer_id: AccountId, + receiver_id: AccountId, + signer: &dyn Signer, + actions: Vec, + block_hash: CryptoHash, + priority_fee: u64, + ) -> Self { + Transaction::V1(TransactionV1 { + nonce, + signer_id, + public_key: signer.public_key(), + receiver_id, + block_hash, + actions, + priority_fee, + }) .sign(signer) } @@ -131,6 +180,7 @@ impl SignedTransaction { signer, vec![Action::Transfer(TransferAction { deposit })], block_hash, + 0, ) } @@ -149,6 +199,7 @@ impl SignedTransaction { signer, vec![Action::Stake(Box::new(StakeAction { stake, public_key }))], block_hash, + 0, ) } @@ -175,6 +226,7 @@ impl SignedTransaction { Action::Transfer(TransferAction { deposit: amount }), ], block_hash, + 0, ) } @@ -203,6 +255,7 @@ impl SignedTransaction { Action::DeployContract(DeployContractAction { code }), ], block_hash, + 0, ) } @@ -229,6 +282,7 @@ impl SignedTransaction { deposit, }))], block_hash, + 0, ) } @@ -247,6 +301,7 @@ impl SignedTransaction { signer, vec![Action::DeleteAccount(DeleteAccountAction { beneficiary_id })], block_hash, + 0, ) } @@ -258,6 +313,7 @@ impl SignedTransaction { &EmptySigner {}, vec![], block_hash, + 0, ) } } diff --git a/core/primitives/src/transaction.rs b/core/primitives/src/transaction.rs index 1a7759c95f9..c0a1b15c13f 100644 --- a/core/primitives/src/transaction.rs +++ b/core/primitives/src/transaction.rs @@ -13,6 +13,7 @@ use serde::ser::Error as EncodeError; use std::borrow::Borrow; use std::fmt; use std::hash::{Hash, Hasher}; +use std::io::{Error, ErrorKind, Read, Write}; #[cfg(feature = "protocol_feature_nonrefundable_transfer_nep491")] pub use crate::action::NonrefundableStorageTransferAction; @@ -24,7 +25,7 @@ pub use crate::action::{ pub type LogEntry = String; #[derive(BorshSerialize, BorshDeserialize, serde::Serialize, PartialEq, Eq, Debug, Clone)] -pub struct Transaction { +pub struct TransactionV0 { /// An account on which behalf transaction is signed pub signer_id: AccountId, /// A public key of the access key which was used to sign an account. @@ -41,6 +42,26 @@ pub struct Transaction { pub actions: Vec, } +#[derive(BorshSerialize, BorshDeserialize, PartialEq, Eq, Debug, Clone)] +pub struct TransactionV1 { + /// An account on which behalf transaction is signed + pub signer_id: AccountId, + /// A public key of the access key which was used to sign an account. + /// Access key holds permissions for calling certain kinds of actions. + pub public_key: PublicKey, + /// Nonce is used to determine order of transaction in the pool. + /// It increments for a combination of `signer_id` and `public_key` + pub nonce: Nonce, + /// Receiver account for this transaction + pub receiver_id: AccountId, + /// The hash of the block in the blockchain on top of which the given transaction is valid + pub block_hash: CryptoHash, + /// A list of actions to be applied + pub actions: Vec, + /// Priority fee. Unit is 10^12 yotcoNEAR + pub priority_fee: u64, +} + impl Transaction { /// Computes a hash of the transaction for signing and size of serialized transaction pub fn get_hash_and_size(&self) -> (CryptoHash, u64) { @@ -49,6 +70,147 @@ impl Transaction { } } +#[derive(Eq, PartialEq, Debug, Clone)] +pub enum Transaction { + V0(TransactionV0), + V1(TransactionV1), +} + +impl Transaction { + pub fn signer_id(&self) -> &AccountId { + match self { + Transaction::V0(tx) => &tx.signer_id, + Transaction::V1(tx) => &tx.signer_id, + } + } + + pub fn receiver_id(&self) -> &AccountId { + match self { + Transaction::V0(tx) => &tx.receiver_id, + Transaction::V1(tx) => &tx.receiver_id, + } + } + + pub fn public_key(&self) -> &PublicKey { + match self { + Transaction::V0(tx) => &tx.public_key, + Transaction::V1(tx) => &tx.public_key, + } + } + + pub fn nonce(&self) -> Nonce { + match self { + Transaction::V0(tx) => tx.nonce, + Transaction::V1(tx) => tx.nonce, + } + } + + pub fn actions(&self) -> &[Action] { + match self { + Transaction::V0(tx) => &tx.actions, + Transaction::V1(tx) => &tx.actions, + } + } + + pub fn take_actions(self) -> Vec { + match self { + Transaction::V0(tx) => tx.actions, + Transaction::V1(tx) => tx.actions, + } + } + + pub fn block_hash(&self) -> &CryptoHash { + match self { + Transaction::V0(tx) => &tx.block_hash, + Transaction::V1(tx) => &tx.block_hash, + } + } + + pub fn priority_fee(&self) -> Option { + match self { + Transaction::V0(_) => None, + Transaction::V1(tx) => Some(tx.priority_fee), + } + } +} + +impl BorshSerialize for Transaction { + fn serialize(&self, writer: &mut W) -> Result<(), Error> { + match self { + Transaction::V0(tx) => tx.serialize(writer)?, + Transaction::V1(tx) => { + BorshSerialize::serialize(&1_u8, writer)?; + tx.serialize(writer)?; + } + } + Ok(()) + } +} + +impl BorshDeserialize for Transaction { + /// Deserialize based on the first and second bytes of the stream. For V0, we do backward compatible deserialization by deserializing + /// the entire stream into V0. For V1, we consume the first byte and then deserialize the rest. + fn deserialize_reader(reader: &mut R) -> std::io::Result { + let u1 = u8::deserialize_reader(reader)?; + let u2 = u8::deserialize_reader(reader)?; + let u3 = u8::deserialize_reader(reader)?; + let u4 = u8::deserialize_reader(reader)?; + // This is a ridiculous hackery: because the first field in `TransactionV0` is an `AccountId` + // and an account id is at most 64 bytes, for all valid `TransactionV0` the second byte must be 0 + // because of the littel endian encoding of the length of the account id. + // On the other hand, for `TransactionV1`, since the first byte is 1 and an account id must have nonzero + // length, so the second byte must not be zero. Therefore, we can distinguish between the two versions + // by looking at the second byte. + + let read_signer_id = |buf: [u8; 4], reader: &mut R| -> std::io::Result { + let str_len = u32::from_le_bytes(buf); + let mut str_vec = Vec::with_capacity(str_len as usize); + for _ in 0..str_len { + str_vec.push(u8::deserialize_reader(reader)?); + } + AccountId::try_from(String::from_utf8(str_vec).map_err(|_| { + Error::new(ErrorKind::InvalidData, "Failed to parse AccountId from bytes") + })?) + .map_err(|e| Error::new(ErrorKind::InvalidData, e.to_string())) + }; + + if u2 == 0 { + let signer_id = read_signer_id([u1, u2, u3, u4], reader)?; + let public_key = PublicKey::deserialize_reader(reader)?; + let nonce = Nonce::deserialize_reader(reader)?; + let receiver_id = AccountId::deserialize_reader(reader)?; + let block_hash = CryptoHash::deserialize_reader(reader)?; + let actions = Vec::::deserialize_reader(reader)?; + Ok(Transaction::V0(TransactionV0 { + signer_id, + public_key, + nonce, + receiver_id, + block_hash, + actions, + })) + } else { + let u5 = u8::deserialize_reader(reader)?; + let signer_id = read_signer_id([u2, u3, u4, u5], reader)?; + let public_key = PublicKey::deserialize_reader(reader)?; + let nonce = Nonce::deserialize_reader(reader)?; + let receiver_id = AccountId::deserialize_reader(reader)?; + let block_hash = CryptoHash::deserialize_reader(reader)?; + let actions = Vec::::deserialize_reader(reader)?; + let priority_fee = u64::deserialize_reader(reader)?; + Ok(Transaction::V1(TransactionV1 { + signer_id, + public_key, + nonce, + receiver_id, + block_hash, + actions, + priority_fee, + })) + } + } +} + #[derive(BorshSerialize, BorshDeserialize, Eq, Debug, Clone)] #[borsh(init=init)] pub struct SignedTransaction { @@ -319,14 +481,14 @@ mod tests { #[test] fn test_verify_transaction() { let signer = InMemorySigner::from_random("test".parse().unwrap(), KeyType::ED25519); - let transaction = Transaction { + let transaction = Transaction::V0(TransactionV0 { signer_id: "test".parse().unwrap(), public_key: signer.public_key(), nonce: 0, receiver_id: "test".parse().unwrap(), block_hash: Default::default(), actions: vec![], - } + }) .sign(&signer); let wrong_public_key = PublicKey::from_seed(KeyType::ED25519, "wrong"); let valid_keys = vec![signer.public_key(), wrong_public_key.clone()]; @@ -340,12 +502,9 @@ mod tests { assert!(verify_transaction_signature(&decoded_tx, &valid_keys)); } - /// This test is change checker for a reason - we don't expect transaction format to change. - /// If it does - you MUST update all of the dependencies: like nearlib and other clients. - #[test] - fn test_serialize_transaction() { + fn create_transaction_v0() -> TransactionV0 { let public_key: PublicKey = "22skMptHjFWNyuEWY22ftn2AbLPSYpmYwGJRGwpNHbTV".parse().unwrap(); - let transaction = Transaction { + TransactionV0 { signer_id: "test.near".parse().unwrap(), public_key: public_key.clone(), nonce: 1, @@ -381,7 +540,56 @@ mod tests { beneficiary_id: "123".parse().unwrap(), }), ], - }; + } + } + + fn create_transaction_v1() -> TransactionV1 { + let public_key: PublicKey = "22skMptHjFWNyuEWY22ftn2AbLPSYpmYwGJRGwpNHbTV".parse().unwrap(); + TransactionV1 { + signer_id: "test.near".parse().unwrap(), + public_key: public_key.clone(), + nonce: 1, + receiver_id: "123".parse().unwrap(), + block_hash: Default::default(), + actions: vec![ + Action::CreateAccount(CreateAccountAction {}), + Action::DeployContract(DeployContractAction { code: vec![1, 2, 3] }), + Action::FunctionCall(Box::new(FunctionCallAction { + method_name: "qqq".to_string(), + args: vec![1, 2, 3], + gas: 1_000, + deposit: 1_000_000, + })), + Action::Transfer(TransferAction { deposit: 123 }), + Action::Stake(Box::new(StakeAction { + public_key: public_key.clone(), + stake: 1_000_000, + })), + Action::AddKey(Box::new(AddKeyAction { + public_key: public_key.clone(), + access_key: AccessKey { + nonce: 0, + permission: AccessKeyPermission::FunctionCall(FunctionCallPermission { + allowance: None, + receiver_id: "zzz".parse().unwrap(), + method_names: vec!["www".to_string()], + }), + }, + })), + Action::DeleteKey(Box::new(DeleteKeyAction { public_key })), + Action::DeleteAccount(DeleteAccountAction { + beneficiary_id: "123".parse().unwrap(), + }), + ], + priority_fee: 1, + } + } + + /// This test is change checker for a reason - we don't expect transaction format to change. + /// If it does - you MUST update all of the dependencies: like nearlib and other clients. + #[test] + fn test_serialize_transaction() { + let transaction = Transaction::V0(create_transaction_v0()); let signed_tx = SignedTransaction::new(Signature::empty(KeyType::ED25519), transaction); let new_signed_tx = SignedTransaction::try_from_slice(&borsh::to_vec(&signed_tx).unwrap()).unwrap(); @@ -392,6 +600,19 @@ mod tests { ); } + #[test] + fn test_serialize_transaction_versions() { + let transaction_v0 = Transaction::V0(create_transaction_v0()); + let serialized_tx_v0 = borsh::to_vec(&transaction_v0).unwrap(); + let deserialized_tx_v0 = Transaction::try_from_slice(&serialized_tx_v0).unwrap(); + assert_eq!(transaction_v0, deserialized_tx_v0); + + let transaction_v1 = Transaction::V1(create_transaction_v1()); + let serialized_tx_v1 = borsh::to_vec(&transaction_v1).unwrap(); + let deserialized_tx_v1 = Transaction::try_from_slice(&serialized_tx_v1).unwrap(); + assert_eq!(transaction_v1, deserialized_tx_v1); + } + #[test] fn test_outcome_to_hashes() { let outcome = ExecutionOutcome { diff --git a/core/primitives/src/views.rs b/core/primitives/src/views.rs index cd347e43fae..1d873f2d8d0 100644 --- a/core/primitives/src/views.rs +++ b/core/primitives/src/views.rs @@ -18,7 +18,7 @@ use crate::errors::TxExecutionError; use crate::hash::{hash, CryptoHash}; use crate::merkle::{combine_hash, MerklePath}; use crate::network::PeerId; -use crate::receipt::{ActionReceipt, DataReceipt, DataReceiver, Receipt, ReceiptEnum}; +use crate::receipt::{ActionReceipt, DataReceipt, DataReceiver, Receipt, ReceiptEnum, ReceiptV1}; use crate::serialize::dec_format; use crate::sharding::{ ChunkHash, ShardChunk, ShardChunkHeader, ShardChunkHeaderInner, ShardChunkHeaderInnerV2, @@ -1353,6 +1353,7 @@ pub struct SignedTransactionView { pub nonce: Nonce, pub receiver_id: AccountId, pub actions: Vec, + pub priority_fee: u64, pub signature: Signature, pub hash: CryptoHash, } @@ -1360,19 +1361,17 @@ pub struct SignedTransactionView { impl From for SignedTransactionView { fn from(signed_tx: SignedTransaction) -> Self { let hash = signed_tx.get_hash(); + let transaction = signed_tx.transaction; + let priority_fee = transaction.priority_fee().unwrap_or_default(); SignedTransactionView { - signer_id: signed_tx.transaction.signer_id, - public_key: signed_tx.transaction.public_key, - nonce: signed_tx.transaction.nonce, - receiver_id: signed_tx.transaction.receiver_id, - actions: signed_tx - .transaction - .actions - .into_iter() - .map(|action| action.into()) - .collect(), + signer_id: transaction.signer_id().clone(), + public_key: transaction.public_key().clone(), + nonce: transaction.nonce(), + receiver_id: transaction.receiver_id().clone(), + actions: transaction.take_actions().into_iter().map(|action| action.into()).collect(), signature: signed_tx.signature, hash, + priority_fee, } } } @@ -1933,6 +1932,7 @@ pub struct ReceiptView { pub receipt_id: CryptoHash, pub receipt: ReceiptEnumView, + pub priority: u64, } #[derive( @@ -1991,14 +1991,15 @@ fn default_is_promise() -> bool { impl From for ReceiptView { fn from(receipt: Receipt) -> Self { - let is_promise_yield = matches!(&receipt.receipt, ReceiptEnum::PromiseYield(_)); - let is_promise_resume = matches!(&receipt.receipt, ReceiptEnum::PromiseResume(_)); + let is_promise_yield = matches!(receipt.receipt(), ReceiptEnum::PromiseYield(_)); + let is_promise_resume = matches!(receipt.receipt(), ReceiptEnum::PromiseResume(_)); + let priority = receipt.priority().value(); ReceiptView { - predecessor_id: receipt.predecessor_id, - receiver_id: receipt.receiver_id, - receipt_id: receipt.receipt_id, - receipt: match receipt.receipt { + predecessor_id: receipt.predecessor_id().clone(), + receiver_id: receipt.receiver_id().clone(), + receipt_id: *receipt.receipt_id(), + receipt: match receipt.take_receipt() { ReceiptEnum::Action(action_receipt) | ReceiptEnum::PromiseYield(action_receipt) => { ReceiptEnumView::Action { signer_id: action_receipt.signer_id, @@ -2029,6 +2030,7 @@ impl From for ReceiptView { } } }, + priority, } } } @@ -2037,7 +2039,7 @@ impl TryFrom for Receipt { type Error = Box; fn try_from(receipt_view: ReceiptView) -> Result { - Ok(Receipt { + Ok(Receipt::V1(ReceiptV1 { predecessor_id: receipt_view.predecessor_id, receiver_id: receipt_view.receiver_id, receipt_id: receipt_view.receipt_id, @@ -2085,7 +2087,8 @@ impl TryFrom for Receipt { } } }, - }) + priority: receipt_view.priority, + })) } } diff --git a/core/store/benches/finalize_bench.rs b/core/store/benches/finalize_bench.rs index 63d2e9f6126..fc6d9bb0730 100644 --- a/core/store/benches/finalize_bench.rs +++ b/core/store/benches/finalize_bench.rs @@ -22,7 +22,7 @@ use near_crypto::{InMemorySigner, KeyType, Signer}; use near_primitives::congestion_info::CongestionInfo; use near_primitives::hash::CryptoHash; use near_primitives::merkle::{merklize, MerklePathItem}; -use near_primitives::receipt::{ActionReceipt, DataReceipt, Receipt, ReceiptEnum}; +use near_primitives::receipt::{ActionReceipt, DataReceipt, Receipt, ReceiptEnum, ReceiptV0}; use near_primitives::shard_layout::ShardLayout; use near_primitives::sharding::{ ChunkHash, EncodedShardChunk, PartialEncodedChunk, PartialEncodedChunkPart, @@ -142,7 +142,7 @@ fn create_action_receipt( actions: Vec, input_data_ids: Vec, ) -> Receipt { - Receipt { + Receipt::V0(ReceiptV0 { predecessor_id: account_id.clone(), receiver_id: account_id.clone(), receipt_id: CryptoHash::hash_borsh(actions.clone()), @@ -154,16 +154,16 @@ fn create_action_receipt( input_data_ids, actions, }), - } + }) } fn create_data_receipt(account_id: &AccountId, data_id: CryptoHash, data_size: usize) -> Receipt { - Receipt { + Receipt::V0(ReceiptV0 { predecessor_id: account_id.clone(), receiver_id: account_id.clone(), receipt_id: CryptoHash::hash_borsh(data_id), receipt: ReceiptEnum::Data(DataReceipt { data_id, data: Some(vec![77u8; data_size]) }), - } + }) } fn create_shard_chunk( diff --git a/core/store/src/genesis/state_applier.rs b/core/store/src/genesis/state_applier.rs index 4a680bfc020..e0c4a187883 100644 --- a/core/store/src/genesis/state_applier.rs +++ b/core/store/src/genesis/state_applier.rs @@ -269,11 +269,11 @@ impl GenesisStateApplier { "processing postponed receipts…" ); for receipt in postponed_receipts { - let account_id = &receipt.receiver_id; + let account_id = receipt.receiver_id(); // Logic similar to `apply_receipt` - match receipt.receipt { - ReceiptEnum::Action(ref action_receipt) => { + match receipt.receipt() { + ReceiptEnum::Action(action_receipt) => { let mut pending_data_count: u32 = 0; for data_id in &action_receipt.input_data_ids { storage.modify(|state_update| { @@ -287,7 +287,7 @@ impl GenesisStateApplier { receiver_id: account_id.clone(), data_id: *data_id, }, - &receipt.receipt_id, + receipt.receipt_id(), ) } }); @@ -300,7 +300,7 @@ impl GenesisStateApplier { state_update, TrieKey::PendingDataCount { receiver_id: account_id.clone(), - receipt_id: receipt.receipt_id, + receipt_id: *receipt.receipt_id(), }, &pending_data_count, ); diff --git a/core/store/src/lib.rs b/core/store/src/lib.rs index a0c6613a532..234b537b05f 100644 --- a/core/store/src/lib.rs +++ b/core/store/src/lib.rs @@ -782,10 +782,10 @@ pub fn has_received_data( } pub fn set_postponed_receipt(state_update: &mut TrieUpdate, receipt: &Receipt) { - assert!(matches!(receipt.receipt, ReceiptEnum::Action(_))); + assert!(matches!(receipt.receipt(), ReceiptEnum::Action(_))); let key = TrieKey::PostponedReceipt { - receiver_id: receipt.receiver_id.clone(), - receipt_id: receipt.receipt_id, + receiver_id: receipt.receiver_id().clone(), + receipt_id: *receipt.receipt_id(), }; set(state_update, key, receipt); } @@ -862,11 +862,11 @@ pub fn enqueue_promise_yield_timeout( } pub fn set_promise_yield_receipt(state_update: &mut TrieUpdate, receipt: &Receipt) { - match &receipt.receipt { + match receipt.receipt() { ReceiptEnum::PromiseYield(ref action_receipt) => { assert!(action_receipt.input_data_ids.len() == 1); let key = TrieKey::PromiseYieldReceipt { - receiver_id: receipt.receiver_id.clone(), + receiver_id: receipt.receiver_id().clone(), data_id: action_receipt.input_data_ids[0], }; set(state_update, key, receipt); diff --git a/core/store/src/test_utils.rs b/core/store/src/test_utils.rs index 3aab48d8d6f..694f4729331 100644 --- a/core/store/src/test_utils.rs +++ b/core/store/src/test_utils.rs @@ -10,7 +10,7 @@ use crate::{ use itertools::Itertools; use near_primitives::account::id::AccountId; use near_primitives::hash::CryptoHash; -use near_primitives::receipt::{DataReceipt, PromiseYieldTimeout, Receipt, ReceiptEnum}; +use near_primitives::receipt::{DataReceipt, PromiseYieldTimeout, Receipt, ReceiptEnum, ReceiptV1}; use near_primitives::shard_layout::{ShardUId, ShardVersion}; use near_primitives::state::FlatStateValue; use near_primitives::trie_key::TrieKey; @@ -266,11 +266,17 @@ pub fn gen_receipts(rng: &mut impl Rng, max_size: usize) -> Vec { let accounts = gen_accounts_from_alphabet(rng, 1, max_size, &alphabet); accounts .iter() - .map(|account_id| Receipt { - predecessor_id: account_id.clone(), - receiver_id: account_id.clone(), - receipt_id: CryptoHash::default(), - receipt: ReceiptEnum::Data(DataReceipt { data_id: CryptoHash::default(), data: None }), + .map(|account_id| { + Receipt::V1(ReceiptV1 { + predecessor_id: account_id.clone(), + receiver_id: account_id.clone(), + receipt_id: CryptoHash::default(), + receipt: ReceiptEnum::Data(DataReceipt { + data_id: CryptoHash::default(), + data: None, + }), + priority: 0, + }) }) .collect() } diff --git a/core/store/src/trie/resharding.rs b/core/store/src/trie/resharding.rs index ca29c451a4f..72787da61ba 100644 --- a/core/store/src/trie/resharding.rs +++ b/core/store/src/trie/resharding.rs @@ -266,11 +266,11 @@ fn apply_delayed_receipts_to_children_states_impl( } for receipt in insert_receipts { - let new_shard_uid: ShardUId = account_id_to_shard_uid(&receipt.receiver_id); + let new_shard_uid: ShardUId = account_id_to_shard_uid(receipt.receiver_id()); if !trie_updates.contains_key(&new_shard_uid) { let err = format!( "Account {} is in new shard {:?} but state_roots only contains {:?}", - receipt.receiver_id, + receipt.receiver_id(), new_shard_uid, trie_updates.keys(), ); @@ -295,11 +295,11 @@ fn apply_delayed_receipts_to_children_states_impl( } for receipt in delete_receipts { - let new_shard_uid: ShardUId = account_id_to_shard_uid(&receipt.receiver_id); + let new_shard_uid: ShardUId = account_id_to_shard_uid(receipt.receiver_id()); if !trie_updates.contains_key(&new_shard_uid) { let err = format!( "Account {} is in new shard {:?} but state_roots only contains {:?}", - receipt.receiver_id, + receipt.receiver_id(), new_shard_uid, trie_updates.keys(), ); @@ -706,7 +706,7 @@ mod tests { let mut expected_receipts_by_shard: HashMap<_, _> = state_roots.iter().map(|(shard_uid, _)| (shard_uid, vec![])).collect(); for receipt in expected_all_receipts { - let shard_uid = account_id_to_shard_id(&receipt.receiver_id); + let shard_uid = account_id_to_shard_id(receipt.receiver_id()); expected_receipts_by_shard.get_mut(&shard_uid).unwrap().push(receipt.clone()); } assert_eq!(expected_receipts_by_shard, receipts_by_shard); diff --git a/genesis-tools/genesis-csv-to-json/src/csv_parser.rs b/genesis-tools/genesis-csv-to-json/src/csv_parser.rs index 4a16c517e59..e717877b162 100644 --- a/genesis-tools/genesis-csv-to-json/src/csv_parser.rs +++ b/genesis-tools/genesis-csv-to-json/src/csv_parser.rs @@ -6,6 +6,7 @@ use near_crypto::{KeyType, PublicKey}; use near_network::types::PeerInfo; use near_primitives::account::{AccessKey, AccessKeyPermission, Account, FunctionCallPermission}; use near_primitives::hash::{hash, CryptoHash}; +use near_primitives::receipt::ReceiptV0; use near_primitives::receipt::{ActionReceipt, Receipt, ReceiptEnum}; use near_primitives::state_record::StateRecord; use near_primitives::transaction::{Action, FunctionCallAction}; @@ -253,7 +254,7 @@ fn account_records(row: &Row, gas_price: Balance) -> Vec { } _ => unimplemented!(), }; - let receipt = Receipt { + let receipt = Receipt::V0(ReceiptV0 { predecessor_id: row.account_id.clone(), receiver_id: row.account_id.clone(), // `receipt_id` can be anything as long as it is unique. @@ -273,7 +274,7 @@ fn account_records(row: &Row, gas_price: Balance) -> Vec { deposit: 0, }))], }), - }; + }); res.push(StateRecord::PostponedReceipt(Box::new(receipt))); } res diff --git a/integration-tests/src/tests/client/benchmarks.rs b/integration-tests/src/tests/client/benchmarks.rs index 1d865d4c6ca..ebd1860a628 100644 --- a/integration-tests/src/tests/client/benchmarks.rs +++ b/integration-tests/src/tests/client/benchmarks.rs @@ -41,6 +41,7 @@ fn benchmark_large_chunk_production_time() { &signer, vec![Action::DeployContract(DeployContractAction { code: vec![92; tx_size] })], last_block_hash, + 0, ); assert_eq!(env.clients[0].process_tx(tx, false, false), ProcessTxResponse::ValidTx); } diff --git a/integration-tests/src/tests/client/cold_storage.rs b/integration-tests/src/tests/client/cold_storage.rs index 57655f5c68a..3e625de9af9 100644 --- a/integration-tests/src/tests/client/cold_storage.rs +++ b/integration-tests/src/tests/client/cold_storage.rs @@ -87,7 +87,7 @@ fn create_tx_deploy_contract( let code = near_test_contracts::rs_contract().to_vec(); let action = DeployContractAction { code }; let action = Action::DeployContract(action); - SignedTransaction::from_actions(height, test0(), test0(), signer, vec![action], block_hash) + SignedTransaction::from_actions(height, test0(), test0(), signer, vec![action], block_hash, 0) } fn create_tx_function_call( @@ -101,7 +101,7 @@ fn create_tx_function_call( gas: 100_000_000_000_000, deposit: 0, })); - SignedTransaction::from_actions(nonce, test0(), test0(), signer, vec![action], block_hash) + SignedTransaction::from_actions(nonce, test0(), test0(), signer, vec![action], block_hash, 0) } /// Deploying test contract and calling write_random_value 5 times every block for 4 epochs. diff --git a/integration-tests/src/tests/client/epoch_sync.rs b/integration-tests/src/tests/client/epoch_sync.rs index 95931a702a3..1b5c1f18d2c 100644 --- a/integration-tests/src/tests/client/epoch_sync.rs +++ b/integration-tests/src/tests/client/epoch_sync.rs @@ -48,6 +48,7 @@ fn generate_transactions(last_hash: &CryptoHash, h: BlockHeight) -> Vec Vec usize { } fn receipt_action(receipt: &Receipt) -> &Action { - match &receipt.receipt { + match receipt.receipt() { ReceiptEnum::Action(action_receipt) => &action_receipt.actions[0], _ => panic!("Expected Action receipt"), } diff --git a/integration-tests/src/tests/client/features/wallet_contract.rs b/integration-tests/src/tests/client/features/wallet_contract.rs index 2c3f8e68fab..da5f7a605a6 100644 --- a/integration-tests/src/tests/client/features/wallet_contract.rs +++ b/integration-tests/src/tests/client/features/wallet_contract.rs @@ -212,6 +212,7 @@ fn test_transaction_from_eth_implicit_account_fail() { access_key: AccessKey::full_access(), }))], *block.hash(), + 0, ); let response = env.clients[0].process_tx(add_access_key_to_eth_implicit_account_tx, false, false); @@ -226,6 +227,7 @@ fn test_transaction_from_eth_implicit_account_fail() { ð_implicit_account_signer, vec![Action::DeployContract(DeployContractAction { code: wallet_contract_code })], *block.hash(), + 0, ); let response = env.clients[0].process_tx(add_access_key_to_eth_implicit_account_tx, false, false); @@ -273,6 +275,7 @@ fn test_wallet_contract_interaction() { &relayer_signer.signer, actions, block_hash, + 0, ); height = check_tx_processing(&mut env, signed_transaction, height, blocks_number); @@ -395,6 +398,7 @@ fn create_rlp_execute_tx( &near_signer.signer, actions, block_hash, + 0, ) } diff --git a/integration-tests/src/tests/client/features/yield_timeouts.rs b/integration-tests/src/tests/client/features/yield_timeouts.rs index c3b383ac702..476edb51c36 100644 --- a/integration-tests/src/tests/client/features/yield_timeouts.rs +++ b/integration-tests/src/tests/client/features/yield_timeouts.rs @@ -41,10 +41,10 @@ fn find_yield_data_ids_from_latest_block(env: &TestEnv) -> Vec { .get_outgoing_receipts_for_shard(last_block_hash, shard_id, last_block_height) .unwrap() { - if let PromiseYield(ref action_receipt) = receipt.receipt { + if let PromiseYield(ref action_receipt) = receipt.receipt() { result.push(action_receipt.input_data_ids[0]); } - if let PromiseResume(ref data_receipt) = receipt.receipt { + if let PromiseResume(ref data_receipt) = receipt.receipt() { result.push(data_receipt.data_id); } } @@ -77,6 +77,7 @@ fn prepare_env_with_yield( code: near_test_contracts::nightly_rs_contract().to_vec(), })], *genesis_block.hash(), + 0, ); let tx_hash = tx.get_hash(); assert_eq!(env.clients[0].process_tx(tx, false, false), ProcessTxResponse::ValidTx); @@ -103,6 +104,7 @@ fn prepare_env_with_yield( deposit: 0, }))], *genesis_block.hash(), + 0, ); let yield_tx_hash = yield_transaction.get_hash(); assert_eq!( @@ -145,6 +147,7 @@ fn invoke_yield_resume( deposit: 0, }))], *genesis_block.hash(), + 0, ); let tx_hash = resume_transaction.get_hash(); assert_eq!( @@ -177,6 +180,7 @@ fn create_congestion(env: &mut TestEnv) { deposit: 0, }))], *genesis_block.hash(), + 0, ); tx_hashes.push(signed_transaction.get_hash()); assert_eq!( diff --git a/integration-tests/src/tests/client/features/zero_balance_account.rs b/integration-tests/src/tests/client/features/zero_balance_account.rs index dd5ed8da9ca..432dab19d4d 100644 --- a/integration-tests/src/tests/client/features/zero_balance_account.rs +++ b/integration-tests/src/tests/client/features/zero_balance_account.rs @@ -192,6 +192,7 @@ fn test_zero_balance_account_add_key() { &new_signer, actions, *genesis_block.hash(), + 0, ); assert_eq!(env.clients[0].process_tx(add_key_tx, false, false), ProcessTxResponse::ValidTx); for i in 5..10 { @@ -222,6 +223,7 @@ fn test_zero_balance_account_add_key() { public_key: keys.last().unwrap().clone(), }))], *genesis_block.hash(), + 0, ); assert_eq!(env.clients[0].process_tx(delete_key_tx, false, false), ProcessTxResponse::ValidTx); for i in 10..15 { diff --git a/integration-tests/src/tests/client/process_blocks.rs b/integration-tests/src/tests/client/process_blocks.rs index cf27df7f166..d2392f69c88 100644 --- a/integration-tests/src/tests/client/process_blocks.rs +++ b/integration-tests/src/tests/client/process_blocks.rs @@ -53,7 +53,7 @@ use near_primitives::test_utils::create_test_signer; use near_primitives::test_utils::TestBlockBuilder; use near_primitives::transaction::{ Action, DeployContractAction, ExecutionStatus, FunctionCallAction, SignedTransaction, - Transaction, + Transaction, TransactionV0, }; use near_primitives::trie_key::TrieKey; use near_primitives::types::validator_stake::ValidatorStake; @@ -163,6 +163,7 @@ pub(crate) fn deploy_test_contract_with_protocol_version( &signer, vec![Action::DeployContract(DeployContractAction { code: wasm_code.to_vec() })], *block.hash(), + 0, ); assert_eq!(env.clients[0].process_tx(tx, false, false), ProcessTxResponse::ValidTx); produce_blocks_from_height_with_protocol_version(env, epoch_length, height, protocol_version) @@ -214,6 +215,7 @@ pub(crate) fn prepare_env_with_congestion( code: near_test_contracts::backwards_compatible_rs_contract().to_vec(), })], *genesis_block.hash(), + 0, ); assert_eq!(env.clients[0].process_tx(tx, false, false), ProcessTxResponse::ValidTx); for i in 1..3 { @@ -248,6 +250,7 @@ pub(crate) fn prepare_env_with_congestion( deposit: 0, }))], *genesis_block.hash(), + 0, ); tx_hashes.push(signed_transaction.get_hash()); assert_eq!( @@ -1025,14 +1028,14 @@ fn test_process_invalid_tx() { let signer = InMemorySigner::from_seed("test1".parse().unwrap(), KeyType::ED25519, "test0"); let tx = SignedTransaction::new( Signature::empty(KeyType::ED25519), - Transaction { + Transaction::V0(TransactionV0 { signer_id: "test".parse().unwrap(), public_key: signer.public_key(), nonce: 0, receiver_id: "test".parse().unwrap(), block_hash: *env.clients[0].chain.genesis().hash(), actions: vec![], - }, + }), ); for i in 1..12 { env.produce_block(0, i); @@ -1043,14 +1046,14 @@ fn test_process_invalid_tx() { ); let tx2 = SignedTransaction::new( Signature::empty(KeyType::ED25519), - Transaction { + Transaction::V0(TransactionV0 { signer_id: "test".parse().unwrap(), public_key: signer.public_key(), nonce: 0, receiver_id: "test".parse().unwrap(), block_hash: hash(&[1]), actions: vec![], - }, + }), ); assert_eq!( env.clients[0].process_tx(tx2, false, false), @@ -2193,6 +2196,7 @@ fn test_validate_chunk_extra() { code: near_test_contracts::rs_contract().to_vec(), })], *genesis_block.hash(), + 0, ); assert_eq!(env.clients[0].process_tx(tx, false, false), ProcessTxResponse::ValidTx); let mut last_block = genesis_block; @@ -2215,6 +2219,7 @@ fn test_validate_chunk_extra() { deposit: 0, }))], *last_block.hash(), + 0, ); assert_eq!( env.clients[0].process_tx(function_call_tx, false, false), @@ -2616,6 +2621,7 @@ fn test_delayed_receipt_count_limit() { &signer, vec![Action::DeployContract(DeployContractAction { code: vec![92; 10000] })], *genesis_block.hash(), + 0, ); assert_eq!(env.clients[0].process_tx(tx, false, false), ProcessTxResponse::ValidTx); } @@ -3293,6 +3299,7 @@ fn test_validator_stake_host_function() { deposit: 0, }))], *genesis_block.hash(), + 0, ); assert_eq!( env.clients[0].process_tx(signed_transaction, false, false), diff --git a/integration-tests/src/tests/client/resharding.rs b/integration-tests/src/tests/client/resharding.rs index 45bc5938a5d..9c71e30be9a 100644 --- a/integration-tests/src/tests/client/resharding.rs +++ b/integration-tests/src/tests/client/resharding.rs @@ -545,7 +545,7 @@ impl TestReshardingEnv { for tx in txs_to_check { let id = &tx.get_hash(); - let signer_account_id = &tx.transaction.signer_id; + let signer_account_id = tx.transaction.signer_id(); let shard_uid = account_id_to_shard_uid(signer_account_id, &shard_layout); tracing::trace!(target: "test", tx=?id, ?signer_account_id, ?shard_uid, "checking tx"); @@ -627,10 +627,10 @@ impl TestReshardingEnv { .clone(); for receipt in outgoing_receipts.iter() { let target_shard_id = - client.chain.get_shard_id_for_receipt_id(&receipt.receipt_id).unwrap(); + client.chain.get_shard_id_for_receipt_id(receipt.receipt_id()).unwrap(); assert_eq!( target_shard_id, - account_id_to_shard_id(&receipt.receiver_id, &shard_layout) + account_id_to_shard_id(receipt.receiver_id(), &shard_layout) ); } } @@ -810,8 +810,8 @@ fn check_outgoing_receipts_reassigned_impl( // In V0->V1 resharding the outgoing receipts should be reassigned // to the receipt receiver's shard id. for receipt in outgoing_receipts { - let receiver = receipt.receiver_id; - let receiver_shard_id = account_id_to_shard_id(&receiver, &shard_layout); + let receiver_shard_id = + account_id_to_shard_id(receipt.receiver_id(), &shard_layout); assert_eq!(receiver_shard_id, shard_id); } } @@ -1285,6 +1285,7 @@ fn setup_test_env_with_cross_contract_txs( &signer, actions, genesis_hash, + 0, ); init_txs.push(tx); } @@ -1458,6 +1459,7 @@ fn gen_cross_contract_tx_impl( deposit: 0, }))], *block_hash, + 0, ) } @@ -1603,6 +1605,7 @@ fn generate_yield_create_tx( deposit: 0, }))], *block_hash, + 0, ) } @@ -1631,6 +1634,7 @@ fn setup_test_env_with_promise_yield_txs( &signer, actions, genesis_hash, + 0, ); init_txs.push(init_tx); } diff --git a/integration-tests/src/tests/client/sandbox.rs b/integration-tests/src/tests/client/sandbox.rs index 20c960065b1..2545e1f3b8b 100644 --- a/integration-tests/src/tests/client/sandbox.rs +++ b/integration-tests/src/tests/client/sandbox.rs @@ -69,7 +69,8 @@ fn send_tx( actions: Vec, ) -> ProcessTxResponse { let hash = env.clients[0].chain.head().unwrap().last_block_hash; - let tx = SignedTransaction::from_actions(nonce, signer_id, receiver_id, signer, actions, hash); + let tx = + SignedTransaction::from_actions(nonce, signer_id, receiver_id, signer, actions, hash, 0); env.clients[0].process_tx(tx, false, false) } diff --git a/integration-tests/src/tests/nearcore/rpc_nodes.rs b/integration-tests/src/tests/nearcore/rpc_nodes.rs index 5f95324a68f..4a9063d055d 100644 --- a/integration-tests/src/tests/nearcore/rpc_nodes.rs +++ b/integration-tests/src/tests/nearcore/rpc_nodes.rs @@ -453,7 +453,7 @@ fn test_check_unknown_tx_must_return_error() { .EXPERIMENTAL_tx_status(RpcTransactionStatusRequest { transaction_info: TransactionInfo::TransactionId { tx_hash, - sender_account_id: transaction.transaction.signer_id, + sender_account_id: transaction.transaction.signer_id().clone(), }, wait_until: TxExecutionStatus::None, }) diff --git a/integration-tests/src/tests/runtime/deployment.rs b/integration-tests/src/tests/runtime/deployment.rs index 850e869c601..1d036325063 100644 --- a/integration-tests/src/tests/runtime/deployment.rs +++ b/integration-tests/src/tests/runtime/deployment.rs @@ -30,6 +30,7 @@ fn test_deploy_max_size_contract() { &*node_user.signer(), vec![Action::DeployContract(DeployContractAction { code: vec![0u8] })], block_hash, + 0, ); let tx_overhead = signed_transaction.get_size(); diff --git a/integration-tests/src/tests/standard_cases/mod.rs b/integration-tests/src/tests/standard_cases/mod.rs index a61a45bcac6..4f66a885e89 100644 --- a/integration-tests/src/tests/standard_cases/mod.rs +++ b/integration-tests/src/tests/standard_cases/mod.rs @@ -27,7 +27,7 @@ use std::sync::Arc; use crate::node::Node; use crate::user::User; use near_parameters::RuntimeConfig; -use near_primitives::receipt::{ActionReceipt, Receipt, ReceiptEnum}; +use near_primitives::receipt::{ActionReceipt, Receipt, ReceiptEnum, ReceiptV0}; use near_primitives::test_utils; use near_primitives::transaction::{Action, DeployContractAction, FunctionCallAction}; use testlib::fees_utils::FeeHelper; @@ -1441,12 +1441,12 @@ fn make_receipt(node: &impl Node, actions: Vec, receiver_id: AccountId) input_data_ids: vec![], actions, }); - Receipt { + Receipt::V0(ReceiptV0 { predecessor_id: alice_account(), receiver_id, receipt_id: CryptoHash::hash_borsh(&receipt_enum), receipt: receipt_enum, - } + }) } /// Check that numbers of charged trie node accesses during execution of the given receipts matches the provided @@ -1462,7 +1462,7 @@ fn check_trie_nodes_count( let node_user = node.user(); let mut node_touches: Vec<_> = vec![]; let receipt_hashes: Vec = - receipts.iter().map(|receipt| receipt.receipt_id).collect(); + receipts.iter().map(|receipt| *receipt.receipt_id()).collect(); for i in 0..2 { node_user.add_receipts(receipts.clone(), use_flat_storage).unwrap(); diff --git a/integration-tests/src/tests/test_errors.rs b/integration-tests/src/tests/test_errors.rs index 991ce7f2238..9fbd1d67f8a 100644 --- a/integration-tests/src/tests/test_errors.rs +++ b/integration-tests/src/tests/test_errors.rs @@ -49,6 +49,7 @@ fn test_check_tx_error_log() { })), ], block_hash, + 0, ); let tx_result = node.user().commit_transaction(tx).unwrap_err(); @@ -89,6 +90,7 @@ fn test_deliver_tx_error_log() { })), ], block_hash, + 0, ); let tx_result = node.user().commit_transaction(tx).unwrap_err(); diff --git a/integration-tests/src/user/mod.rs b/integration-tests/src/user/mod.rs index 0799bf4570a..e489aa4887d 100644 --- a/integration-tests/src/user/mod.rs +++ b/integration-tests/src/user/mod.rs @@ -106,6 +106,7 @@ pub trait User { &*self.signer(), actions, block_hash, + 0, ); self.commit_transaction(signed_transaction) } diff --git a/integration-tests/src/user/runtime_user.rs b/integration-tests/src/user/runtime_user.rs index cca24e9f94a..a5486511205 100644 --- a/integration-tests/src/user/runtime_user.rs +++ b/integration-tests/src/user/runtime_user.rs @@ -145,7 +145,7 @@ impl RuntimeUser { return Ok(()); } for receipt in apply_result.outgoing_receipts.iter() { - self.receipts.borrow_mut().insert(receipt.receipt_id, receipt.clone()); + self.receipts.borrow_mut().insert(*receipt.receipt_id(), receipt.clone()); } receipts = apply_result.outgoing_receipts; txs = vec![]; diff --git a/nearcore/src/metrics.rs b/nearcore/src/metrics.rs index 4eaab934c73..cf7b67c15b9 100644 --- a/nearcore/src/metrics.rs +++ b/nearcore/src/metrics.rs @@ -98,8 +98,8 @@ fn log_trie_item(key: Vec, value: Vec) { tracing::trace!( target: "metrics", "trie-stats - PostponedReceipt(predecessor_id: {:?}, receiver_id: {:?})", - receipt.predecessor_id, - receipt.receiver_id, + receipt.predecessor_id(), + receipt.receiver_id(), ); } _ => { diff --git a/runtime/runtime-params-estimator/src/action_costs.rs b/runtime/runtime-params-estimator/src/action_costs.rs index 8b0f2951a12..8184e9059a2 100644 --- a/runtime/runtime-params-estimator/src/action_costs.rs +++ b/runtime/runtime-params-estimator/src/action_costs.rs @@ -13,7 +13,7 @@ use crate::utils::{average_cost, percentiles}; use near_crypto::{KeyType, PublicKey}; use near_primitives::account::{AccessKey, AccessKeyPermission, FunctionCallPermission}; use near_primitives::hash::CryptoHash; -use near_primitives::receipt::{ActionReceipt, Receipt}; +use near_primitives::receipt::{ActionReceipt, Receipt, ReceiptV0}; use near_primitives::transaction::Action; use near_primitives::types::{AccountId, Gas}; use std::iter; @@ -264,12 +264,12 @@ impl ActionEstimation { input_data_ids: vec![], actions, }; - let receipt = Receipt { + let receipt = Receipt::V0(ReceiptV0 { predecessor_id, receiver_id, receipt_id: CryptoHash::new(), receipt: near_primitives::receipt::ReceiptEnum::Action(action_receipt), - }; + }); testbed.apply_action_receipt(&receipt, self.metric) } diff --git a/runtime/runtime-params-estimator/src/transaction_builder.rs b/runtime/runtime-params-estimator/src/transaction_builder.rs index d19040f3936..412fea0d5cd 100644 --- a/runtime/runtime-params-estimator/src/transaction_builder.rs +++ b/runtime/runtime-params-estimator/src/transaction_builder.rs @@ -62,6 +62,7 @@ impl TransactionBuilder { &signer, actions, CryptoHash::default(), + 0, ) } diff --git a/runtime/runtime/src/actions.rs b/runtime/runtime/src/actions.rs index 34a3d0fbafc..4a595bb302e 100644 --- a/runtime/runtime/src/actions.rs +++ b/runtime/runtime/src/actions.rs @@ -14,7 +14,9 @@ use near_primitives::checked_feature; use near_primitives::config::ViewConfig; use near_primitives::errors::{ActionError, ActionErrorKind, InvalidAccessKeyError, RuntimeError}; use near_primitives::hash::CryptoHash; -use near_primitives::receipt::{ActionReceipt, DataReceipt, Receipt, ReceiptEnum}; +use near_primitives::receipt::{ + ActionReceipt, DataReceipt, Receipt, ReceiptEnum, ReceiptPriority, ReceiptV0, +}; use near_primitives::transaction::{ Action, AddKeyAction, DeleteAccountAction, DeleteKeyAction, DeployContractAction, FunctionCallAction, StakeAction, @@ -268,7 +270,7 @@ pub(crate) fn action_function_call( apply_state, &mut runtime_ext, account, - &receipt.predecessor_id, + receipt.predecessor_id(), action_receipt, promise_results, function_call, @@ -363,7 +365,7 @@ pub(crate) fn action_function_call( actions: receipt.actions, }; - Receipt { + Receipt::V0(ReceiptV0 { predecessor_id: account_id.clone(), receiver_id: receipt.receiver_id, // Actual receipt ID is set in the Runtime.apply_action_receipt(...) in the @@ -374,7 +376,7 @@ pub(crate) fn action_function_call( } else { ReceiptEnum::Action(new_action_receipt) }, - } + }) }) .collect(); @@ -382,7 +384,7 @@ pub(crate) fn action_function_call( new_receipts.extend(receipt_manager.data_receipts.into_iter().map(|receipt| { let new_data_receipt = DataReceipt { data_id: receipt.data_id, data: receipt.data }; - Receipt { + Receipt::V0(ReceiptV0 { predecessor_id: account_id.clone(), receiver_id: account_id.clone(), // Actual receipt ID is set in the Runtime.apply_action_receipt(...) in the @@ -393,7 +395,7 @@ pub(crate) fn action_function_call( } else { ReceiptEnum::Data(new_data_receipt) }, - } + }) })); // Commit metadata for yielded promises queue @@ -726,12 +728,14 @@ pub(crate) fn action_delete_account( // We use current amount as a pay out to beneficiary. let account_balance = account.as_ref().unwrap().amount(); if account_balance > 0 { - result - .new_receipts - .push(Receipt::new_balance_refund(&delete_account.beneficiary_id, account_balance)); + result.new_receipts.push(Receipt::new_balance_refund( + &delete_account.beneficiary_id, + account_balance, + ReceiptPriority::NoPriority, + )); } remove_account(state_update, account_id)?; - *actor_id = receipt.predecessor_id.clone(); + *actor_id = receipt.predecessor_id().clone(); *account = None; Ok(()) } @@ -826,6 +830,7 @@ pub(crate) fn apply_delegate_action( sender_id: &AccountId, signed_delegate_action: &SignedDelegateAction, result: &mut ActionResult, + _priority: ReceiptPriority, ) -> Result<(), RuntimeError> { let delegate_action = &signed_delegate_action.delegate_action; @@ -854,7 +859,7 @@ pub(crate) fn apply_delegate_action( } // Generate a new receipt from DelegateAction. - let new_receipt = Receipt { + let new_receipt = Receipt::V0(ReceiptV0 { predecessor_id: sender_id.clone(), receiver_id: delegate_action.receiver_id.clone(), receipt_id: CryptoHash::default(), @@ -867,7 +872,7 @@ pub(crate) fn apply_delegate_action( input_data_ids: vec![], actions: delegate_action.get_actions(), }), - }; + }); // Note, Relayer prepaid all fees and all things required by actions: attached deposits and attached gas. // If something goes wrong, deposit is refunded to the predecessor, this is sender_id/Sender in DelegateAction. @@ -892,13 +897,13 @@ pub(crate) fn apply_delegate_action( /// Returns Gas amount is required to execute Receipt and all actions it contains fn receipt_required_gas(apply_state: &ApplyState, receipt: &Receipt) -> Result { - Ok(match &receipt.receipt { + Ok(match receipt.receipt() { ReceiptEnum::Action(action_receipt) | ReceiptEnum::PromiseYield(action_receipt) => { let mut required_gas = safe_add_gas( total_prepaid_exec_fees( &apply_state.config, &action_receipt.actions, - &receipt.receiver_id, + receipt.receiver_id(), )?, total_prepaid_gas(&action_receipt.actions)?, )?; @@ -1310,7 +1315,11 @@ mod tests { Some(Account::new(100, 0, 0, *code_hash, storage_usage, PROTOCOL_VERSION)); let mut actor_id = account_id.clone(); let mut action_result = ActionResult::default(); - let receipt = Receipt::new_balance_refund(&"alice.near".parse().unwrap(), 0); + let receipt = Receipt::new_balance_refund( + &"alice.near".parse().unwrap(), + 0, + ReceiptPriority::NoPriority, + ); let res = action_delete_account( state_update, &mut account, @@ -1484,13 +1493,14 @@ mod tests { &sender_id, &signed_delegate_action, &mut result, + ReceiptPriority::NoPriority, ) .expect("Expect ok"); assert!(result.result.is_ok(), "Result error: {:?}", result.result.err()); assert_eq!( result.new_receipts, - vec![Receipt { + vec![Receipt::V0(ReceiptV0 { predecessor_id: sender_id.clone(), receiver_id: signed_delegate_action.delegate_action.receiver_id.clone(), receipt_id: CryptoHash::default(), @@ -1501,8 +1511,8 @@ mod tests { output_data_receivers: Vec::new(), input_data_ids: Vec::new(), actions: signed_delegate_action.delegate_action.get_actions(), - }) - }] + }), + })] ); } @@ -1528,6 +1538,7 @@ mod tests { &sender_id, &signed_delegate_action, &mut result, + ReceiptPriority::NoPriority, ) .expect("Expect ok"); @@ -1554,6 +1565,7 @@ mod tests { &sender_id, &signed_delegate_action, &mut result, + ReceiptPriority::NoPriority, ) .expect("Expect ok"); @@ -1580,6 +1592,7 @@ mod tests { &"www.test.near".parse().unwrap(), &signed_delegate_action, &mut result, + ReceiptPriority::NoPriority, ) .expect("Expect ok"); diff --git a/runtime/runtime/src/balance_checker.rs b/runtime/runtime/src/balance_checker.rs index 27cfc8c7add..5fcdb293cd6 100644 --- a/runtime/runtime/src/balance_checker.rs +++ b/runtime/runtime/src/balance_checker.rs @@ -39,13 +39,17 @@ fn receipt_cost( config: &RuntimeConfig, receipt: &Receipt, ) -> Result { - Ok(match &receipt.receipt { + Ok(match receipt.receipt() { ReceiptEnum::Action(action_receipt) | ReceiptEnum::PromiseYield(action_receipt) => { let mut total_cost = total_deposit(&action_receipt.actions)?; - if !receipt.predecessor_id.is_system() { + if !receipt.predecessor_id().is_system() { let mut total_gas = safe_add_gas( config.fees.fee(ActionCosts::new_action_receipt).exec_fee(), - total_prepaid_exec_fees(config, &action_receipt.actions, &receipt.receiver_id)?, + total_prepaid_exec_fees( + config, + &action_receipt.actions, + receipt.receiver_id(), + )?, )?; total_gas = safe_add_gas(total_gas, total_prepaid_gas(&action_receipt.actions)?)?; total_gas = safe_add_gas( @@ -159,10 +163,10 @@ pub(crate) fn check_balance( // Accounts let mut all_accounts_ids: HashSet = transactions .iter() - .map(|tx| tx.transaction.signer_id.clone()) - .chain(incoming_receipts.iter().map(|r| r.receiver_id.clone())) - .chain(yield_timeout_receipts.iter().map(|r| r.receiver_id.clone())) - .chain(processed_delayed_receipts.iter().map(|r| r.receiver_id.clone())) + .map(|tx| tx.transaction.signer_id().clone()) + .chain(incoming_receipts.iter().map(|r| r.receiver_id().clone())) + .chain(yield_timeout_receipts.iter().map(|r| r.receiver_id().clone())) + .chain(processed_delayed_receipts.iter().map(|r| r.receiver_id().clone())) .collect(); let incoming_validator_rewards = if let Some(validator_accounts_update) = validator_accounts_update { @@ -202,11 +206,13 @@ pub(crate) fn check_balance( .chain(processed_delayed_receipts.iter()) .chain(yield_timeout_receipts.iter()) .filter_map(|receipt| { - let account_id = &receipt.receiver_id; - match &receipt.receipt { - ReceiptEnum::Action(_) => { - Some(Ok((PostponedReceiptType::Action, account_id.clone(), receipt.receipt_id))) - } + let account_id = receipt.receiver_id(); + match receipt.receipt() { + ReceiptEnum::Action(_) => Some(Ok(( + PostponedReceiptType::Action, + account_id.clone(), + *receipt.receipt_id(), + ))), ReceiptEnum::Data(data_receipt) => { let result = get( initial_state, @@ -288,7 +294,7 @@ mod tests { use crate::ApplyStats; use near_crypto::{InMemorySigner, KeyType}; use near_primitives::hash::{hash, CryptoHash}; - use near_primitives::receipt::ActionReceipt; + use near_primitives::receipt::{ActionReceipt, ReceiptPriority, ReceiptV0}; use near_primitives::test_utils::account_new; use near_primitives::transaction::{Action, TransferAction}; use near_primitives::types::{MerkleHash, StateChangeCause}; @@ -332,7 +338,7 @@ mod tests { &RuntimeConfig::test(), &final_state, &None, - &[Receipt::new_balance_refund(&alice_account(), 1000)], + &[Receipt::new_balance_refund(&alice_account(), 1000, ReceiptPriority::NoPriority)], &[], &[], &[], @@ -392,7 +398,11 @@ mod tests { &RuntimeConfig::test(), &final_state, &None, - &[Receipt::new_balance_refund(&account_id, refund_balance)], + &[Receipt::new_balance_refund( + &account_id, + refund_balance, + ReceiptPriority::NoPriority, + )], &[], &[], &[], @@ -443,19 +453,19 @@ mod tests { deposit, CryptoHash::default(), ); - let receipt = Receipt { - predecessor_id: tx.transaction.signer_id.clone(), - receiver_id: tx.transaction.receiver_id.clone(), + let receipt = Receipt::V0(ReceiptV0 { + predecessor_id: tx.transaction.signer_id().clone(), + receiver_id: tx.transaction.receiver_id().clone(), receipt_id: Default::default(), receipt: ReceiptEnum::Action(ActionReceipt { - signer_id: tx.transaction.signer_id.clone(), - signer_public_key: tx.transaction.public_key.clone(), + signer_id: tx.transaction.signer_id().clone(), + signer_public_key: tx.transaction.public_key().clone(), gas_price, output_data_receivers: vec![], input_data_ids: vec![], actions: vec![Action::Transfer(TransferAction { deposit })], }), - }; + }); check_balance( &cfg, @@ -502,19 +512,19 @@ mod tests { let tx = SignedTransaction::send_money(0, alice_id, bob_id, &signer, 2, CryptoHash::default()); - let receipt = Receipt { - predecessor_id: tx.transaction.signer_id.clone(), - receiver_id: tx.transaction.receiver_id.clone(), + let receipt = Receipt::V0(ReceiptV0 { + predecessor_id: tx.transaction.signer_id().clone(), + receiver_id: tx.transaction.receiver_id().clone(), receipt_id: Default::default(), receipt: ReceiptEnum::Action(ActionReceipt { - signer_id: tx.transaction.signer_id.clone(), - signer_public_key: tx.transaction.public_key.clone(), + signer_id: tx.transaction.signer_id().clone(), + signer_public_key: tx.transaction.public_key().clone(), gas_price, output_data_receivers: vec![], input_data_ids: vec![], actions: vec![Action::Transfer(TransferAction { deposit })], }), - }; + }); assert_eq!( check_balance( @@ -557,19 +567,19 @@ mod tests { let tx = SignedTransaction::send_money(0, alice_id, bob_id, &signer, 1, CryptoHash::default()); - let receipt = Receipt { - predecessor_id: tx.transaction.signer_id.clone(), - receiver_id: tx.transaction.receiver_id.clone(), + let receipt = Receipt::V0(ReceiptV0 { + predecessor_id: tx.transaction.signer_id().clone(), + receiver_id: tx.transaction.receiver_id().clone(), receipt_id: Default::default(), receipt: ReceiptEnum::Action(ActionReceipt { - signer_id: tx.transaction.signer_id.clone(), - signer_public_key: tx.transaction.public_key.clone(), + signer_id: tx.transaction.signer_id().clone(), + signer_public_key: tx.transaction.public_key().clone(), gas_price, output_data_receivers: vec![], input_data_ids: vec![], actions: vec![Action::Transfer(TransferAction { deposit })], }), - }; + }); // Alice's balance becomes u128::MAX, which causes it is interpreted as // the Alice's account version to be 2 or higher, instead of being interpreted diff --git a/runtime/runtime/src/config.rs b/runtime/runtime/src/config.rs index c5681c8481f..a833af19697 100644 --- a/runtime/runtime/src/config.rs +++ b/runtime/runtime/src/config.rs @@ -259,17 +259,18 @@ pub fn tx_cost( total_send_fees( config, sender_is_receiver, - &transaction.actions, - &transaction.receiver_id, + transaction.actions(), + transaction.receiver_id(), )?, )?; let prepaid_gas = safe_add_gas( - total_prepaid_gas(&transaction.actions)?, - total_prepaid_send_fees(config, &transaction.actions)?, + total_prepaid_gas(&transaction.actions())?, + total_prepaid_send_fees(config, &transaction.actions())?, )?; // If signer is equals to receiver the receipt will be processed at the same block as this // transaction. Otherwise it will processed in the next block and the gas might be inflated. - let initial_receipt_hop = if transaction.signer_id == transaction.receiver_id { 0 } else { 1 }; + let initial_receipt_hop = + if transaction.signer_id() == transaction.receiver_id() { 0 } else { 1 }; let minimum_new_receipt_gas = if protocol_version < FIXED_MINIMUM_NEW_RECEIPT_GAS_VERSION { fees.min_receipt_with_function_call_gas() } else { @@ -298,12 +299,12 @@ pub fn tx_cost( safe_add_gas(prepaid_gas, fees.fee(ActionCosts::new_action_receipt).exec_fee())?; gas_remaining = safe_add_gas( gas_remaining, - total_prepaid_exec_fees(config, &transaction.actions, &transaction.receiver_id)?, + total_prepaid_exec_fees(config, transaction.actions(), transaction.receiver_id())?, )?; let burnt_amount = safe_gas_to_balance(gas_price, gas_burnt)?; let remaining_gas_amount = safe_gas_to_balance(receipt_gas_price, gas_remaining)?; let mut total_cost = safe_add_balance(burnt_amount, remaining_gas_amount)?; - total_cost = safe_add_balance(total_cost, total_deposit(&transaction.actions)?)?; + total_cost = safe_add_balance(total_cost, total_deposit(&transaction.actions())?)?; Ok(TransactionCost { gas_burnt, gas_remaining, receipt_gas_price, total_cost, burnt_amount }) } diff --git a/runtime/runtime/src/congestion_control.rs b/runtime/runtime/src/congestion_control.rs index d5b73e9e981..85d233e9463 100644 --- a/runtime/runtime/src/congestion_control.rs +++ b/runtime/runtime/src/congestion_control.rs @@ -186,7 +186,7 @@ impl ReceiptSinkV2<'_> { epoch_info_provider: &dyn EpochInfoProvider, ) -> Result<(), RuntimeError> { let shard = epoch_info_provider - .account_id_to_shard_id(&receipt.receiver_id, &apply_state.epoch_id)?; + .account_id_to_shard_id(receipt.receiver_id(), &apply_state.epoch_id)?; if shard == apply_state.shard_id { // No limits on receipts that stay on the same shard. Backpressure // wouldn't help, the receipt takes the same memory if buffered or @@ -260,11 +260,11 @@ fn receipt_congestion_gas( receipt: &Receipt, config: &RuntimeConfig, ) -> Result { - match &receipt.receipt { + match receipt.receipt() { ReceiptEnum::Action(action_receipt) => { // account for gas guaranteed to be used for executing the receipts let prepaid_exec_gas = safe_add_gas( - total_prepaid_exec_fees(config, &action_receipt.actions, &receipt.receiver_id)?, + total_prepaid_exec_fees(config, &action_receipt.actions, receipt.receiver_id())?, config.fees.fee(ActionCosts::new_action_receipt).exec_fee(), )?; // account for gas guaranteed to be used for creating new receipts diff --git a/runtime/runtime/src/lib.rs b/runtime/runtime/src/lib.rs index a65065c43b4..41ce027bda4 100644 --- a/runtime/runtime/src/lib.rs +++ b/runtime/runtime/src/lib.rs @@ -25,7 +25,7 @@ use near_primitives::errors::{ use near_primitives::hash::CryptoHash; use near_primitives::receipt::{ ActionReceipt, DataReceipt, DelayedReceiptIndices, PromiseYieldIndices, PromiseYieldTimeout, - Receipt, ReceiptEnum, ReceivedData, + Receipt, ReceiptEnum, ReceiptV0, ReceivedData, }; use near_primitives::runtime::migration_data::{MigrationData, MigrationFlags}; use near_primitives::sandbox::state_patch::SandboxStatePatch; @@ -307,19 +307,19 @@ impl Runtime { &apply_state.prev_block_hash, &apply_state.block_hash, ); - let receipt = Receipt { - predecessor_id: transaction.signer_id.clone(), - receiver_id: transaction.receiver_id.clone(), + let receipt = Receipt::V0(ReceiptV0 { + predecessor_id: transaction.signer_id().clone(), + receiver_id: transaction.receiver_id().clone(), receipt_id, receipt: ReceiptEnum::Action(ActionReceipt { - signer_id: transaction.signer_id.clone(), - signer_public_key: transaction.public_key.clone(), + signer_id: transaction.signer_id().clone(), + signer_public_key: transaction.public_key().clone(), gas_price: verification_result.receipt_gas_price, output_data_receivers: vec![], input_data_ids: vec![], - actions: transaction.actions.clone(), + actions: transaction.actions().to_vec(), }), - }; + }); stats.tx_burnt_amount = safe_add_balance(stats.tx_burnt_amount, verification_result.burnt_amount)?; let gas_burnt = verification_result.gas_burnt; @@ -327,14 +327,14 @@ impl Runtime { let outcome = ExecutionOutcomeWithId { id: signed_transaction.get_hash(), outcome: ExecutionOutcome { - status: ExecutionStatus::SuccessReceiptId(receipt.receipt_id), + status: ExecutionStatus::SuccessReceiptId(*receipt.receipt_id()), logs: vec![], - receipt_ids: vec![receipt.receipt_id], + receipt_ids: vec![*receipt.receipt_id()], gas_burnt, // TODO(#8806): Support compute costs for actions. For now they match burnt gas. compute_usage: Some(compute_usage), tokens_burnt: verification_result.burnt_amount, - executor_id: transaction.signer_id.clone(), + executor_id: transaction.signer_id().clone(), // TODO: profile data is only counted in apply_action, which only happened at process_receipt // VerificationResult needs updates to incorporate profile data to support profile data of txns metadata: ExecutionMetadata::V1, @@ -367,14 +367,14 @@ impl Runtime { actions: &[Action], epoch_info_provider: &dyn EpochInfoProvider, ) -> Result { - let exec_fees = exec_fee(&apply_state.config, action, &receipt.receiver_id); + let exec_fees = exec_fee(&apply_state.config, action, receipt.receiver_id()); let mut result = ActionResult::default(); result.gas_used = exec_fees; result.gas_burnt = exec_fees; // TODO(#8806): Support compute costs for actions. For now they match burnt gas. result.compute_usage = exec_fees; - let account_id = &receipt.receiver_id; - let is_refund = receipt.predecessor_id.is_system(); + let account_id = receipt.receiver_id(); + let is_refund = receipt.predecessor_id().is_system(); let is_the_only_action = actions.len() == 1; let implicit_account_creation_eligible = is_the_only_action && !is_refund; @@ -405,8 +405,8 @@ impl Runtime { &apply_state.config.account_creation_config, account, actor_id, - &receipt.receiver_id, - &receipt.predecessor_id, + receipt.receiver_id(), + receipt.predecessor_id(), &mut result, apply_state.current_protocol_version, ); @@ -519,6 +519,7 @@ impl Runtime { account_id, signed_delegate_action, &mut result, + receipt.priority(), )?; } }; @@ -536,13 +537,13 @@ impl Runtime { stats: &mut ApplyStats, epoch_info_provider: &dyn EpochInfoProvider, ) -> Result { - let action_receipt = match &receipt.receipt { + let action_receipt = match receipt.receipt() { ReceiptEnum::Action(action_receipt) | ReceiptEnum::PromiseYield(action_receipt) => { action_receipt } _ => unreachable!("given receipt should be an action receipt"), }; - let account_id = &receipt.receiver_id; + let account_id = receipt.receiver_id(); // Collecting input data and removing it from the state let promise_results = action_receipt .input_data_ids @@ -572,7 +573,7 @@ impl Runtime { }); let mut account = get_account(state_update, account_id)?; - let mut actor_id = receipt.predecessor_id.clone(); + let mut actor_id = receipt.predecessor_id().clone(); let mut result = ActionResult::default(); let exec_fees = apply_state.config.fees.fee(ActionCosts::new_action_receipt).exec_fee(); result.gas_used = exec_fees; @@ -586,7 +587,7 @@ impl Runtime { for (action_index, action) in action_receipt.actions.iter().enumerate() { let action_hash = create_action_hash_from_receipt_id( apply_state.current_protocol_version, - &receipt.receipt_id, + receipt.receipt_id(), &apply_state.prev_block_hash, &apply_state.block_hash, action_index, @@ -664,7 +665,7 @@ impl Runtime { } } - let gas_deficit_amount = if receipt.predecessor_id.is_system() { + let gas_deficit_amount = if receipt.predecessor_id().is_system() { // We will set gas_burnt for refund receipts to be 0 when we calculate tx_burnt_amount // Here we don't set result.gas_burnt to be zero if CountRefundReceiptsInGasLimit is // enabled because we want it to be counted in gas limit calculation later @@ -720,7 +721,8 @@ impl Runtime { } // If the receipt is a refund, then we consider it free without burnt gas. - let gas_burnt: Gas = if receipt.predecessor_id.is_system() { 0 } else { result.gas_burnt }; + let gas_burnt: Gas = + if receipt.predecessor_id().is_system() { 0 } else { result.gas_burnt }; // `gas_deficit_amount` is strictly less than `gas_price * gas_burnt`. let mut tx_burnt_amount = safe_gas_to_balance(apply_state.gas_price, gas_burnt)? - gas_deficit_amount; @@ -766,7 +768,7 @@ impl Runtime { .new_receipts .get_mut(receipt_index as usize) .expect("the receipt for the given receipt index should exist") - .receipt + .receipt_mut() { ReceiptEnum::Action(ref mut new_action_receipt) | ReceiptEnum::PromiseYield(ref mut new_action_receipt) => new_action_receipt @@ -781,14 +783,16 @@ impl Runtime { Err(_) => None, }; result.new_receipts.extend(action_receipt.output_data_receivers.iter().map( - |data_receiver| Receipt { - predecessor_id: account_id.clone(), - receiver_id: data_receiver.receiver_id.clone(), - receipt_id: CryptoHash::default(), - receipt: ReceiptEnum::Data(DataReceipt { - data_id: data_receiver.data_id, - data: data.clone(), - }), + |data_receiver| { + Receipt::V0(ReceiptV0 { + predecessor_id: account_id.clone(), + receiver_id: data_receiver.receiver_id.clone(), + receipt_id: CryptoHash::default(), + receipt: ReceiptEnum::Data(DataReceipt { + data_id: data_receiver.data_id, + data: data.clone(), + }), + }) }, )); }; @@ -802,15 +806,15 @@ impl Runtime { .filter_map(|(receipt_index, mut new_receipt)| { let receipt_id = create_receipt_id_from_receipt_id( apply_state.current_protocol_version, - &receipt.receipt_id, + receipt.receipt_id(), &apply_state.prev_block_hash, &apply_state.block_hash, receipt_index, ); - new_receipt.receipt_id = receipt_id; + new_receipt.set_receipt_id(receipt_id); let is_action = matches!( - &new_receipt.receipt, + new_receipt.receipt(), ReceiptEnum::Action(_) | ReceiptEnum::PromiseYield(_) ); @@ -834,7 +838,7 @@ impl Runtime { Ok(ReturnData::ReceiptIndex(receipt_index)) => { ExecutionStatus::SuccessReceiptId(create_receipt_id_from_receipt_id( apply_state.current_protocol_version, - &receipt.receipt_id, + receipt.receipt_id(), &apply_state.prev_block_hash, &apply_state.block_hash, receipt_index as usize, @@ -848,7 +852,7 @@ impl Runtime { Self::print_log(&result.logs); Ok(ExecutionOutcomeWithId { - id: receipt.receipt_id, + id: *receipt.receipt_id(), outcome: ExecutionOutcome { status, logs: result.logs, @@ -876,7 +880,7 @@ impl Runtime { total_prepaid_send_fees(config, &action_receipt.actions)?, )?; let prepaid_exec_gas = safe_add_gas( - total_prepaid_exec_fees(config, &action_receipt.actions, &receipt.receiver_id)?, + total_prepaid_exec_fees(config, &action_receipt.actions, receipt.receiver_id())?, config.fees.fee(ActionCosts::new_action_receipt).exec_fee(), )?; let deposit_refund = if result.result.is_err() { total_deposit } else { 0 }; @@ -916,9 +920,11 @@ impl Runtime { } if deposit_refund > 0 { - result - .new_receipts - .push(Receipt::new_balance_refund(&receipt.predecessor_id, deposit_refund)); + result.new_receipts.push(Receipt::new_balance_refund( + receipt.predecessor_id(), + deposit_refund, + receipt.priority(), + )); } if gas_balance_refund > 0 { // Gas refunds refund the allowance of the access key, so if the key exists on the @@ -927,6 +933,7 @@ impl Runtime { &action_receipt.signer_id, gas_balance_refund, action_receipt.signer_public_key.clone(), + receipt.priority(), )); } Ok(gas_deficit_amount) @@ -942,8 +949,8 @@ impl Runtime { stats: &mut ApplyStats, epoch_info_provider: &dyn EpochInfoProvider, ) -> Result, RuntimeError> { - let account_id = &receipt.receiver_id; - match receipt.receipt { + let account_id = receipt.receiver_id(); + match receipt.receipt() { ReceiptEnum::Data(ref data_receipt) => { // Received a new data receipt. // Saving the data into the state keyed by the data_id. @@ -1047,7 +1054,7 @@ impl Runtime { receiver_id: account_id.clone(), data_id: *data_id, }, - &receipt.receipt_id, + receipt.receipt_id(), ) } } @@ -1072,7 +1079,7 @@ impl Runtime { state_update, TrieKey::PendingDataCount { receiver_id: account_id.clone(), - receipt_id: receipt.receipt_id, + receipt_id: *receipt.receipt_id(), }, &pending_data_count, ); @@ -1425,7 +1432,7 @@ impl Runtime { signed_transaction, &mut stats, )?; - if receipt.receiver_id == signed_transaction.transaction.signer_id { + if receipt.receiver_id() == signed_transaction.transaction.signer_id() { local_receipts.push(receipt); } else { receipt_sink.forward_or_buffer_receipt( @@ -1458,10 +1465,10 @@ impl Runtime { let span = tracing::debug_span!( target: "runtime", "process_receipt", - receipt_id = %receipt.receipt_id, - predecessor = %receipt.predecessor_id, - receiver = %receipt.receiver_id, - id = %receipt.receipt_id, + receipt_id = %receipt.receipt_id(), + predecessor = %receipt.predecessor_id(), + receiver = %receipt.receiver_id(), + id = %receipt.receipt_id(), gas_burnt = tracing::field::Empty, compute_usage = tracing::field::Empty, ) @@ -1680,7 +1687,7 @@ impl Runtime { new_receipt_index += 1; // Create a PromiseResume receipt to resolve the timed-out yield. - let resume_receipt = Receipt { + let resume_receipt = Receipt::V0(ReceiptV0 { predecessor_id: queue_entry.account_id.clone(), receiver_id: queue_entry.account_id.clone(), receipt_id: new_receipt_id, @@ -1688,7 +1695,7 @@ impl Runtime { data_id: queue_entry.data_id, data: None, }), - }; + }); // The receipt is destined for the local shard and will be placed in the outgoing // receipts buffer. It is possible that there is already an outgoing receipt resolving @@ -1878,10 +1885,10 @@ fn action_transfer_or_implicit_account_creation( action_transfer(account, deposit)?; } // Check if this is a gas refund, then try to refund the access key allowance. - if is_refund && action_receipt.signer_id == receipt.receiver_id { + if is_refund && &action_receipt.signer_id == receipt.receiver_id() { try_refund_allowance( state_update, - &receipt.receiver_id, + receipt.receiver_id(), &action_receipt.signer_public_key, deposit, )?; @@ -1896,7 +1903,7 @@ fn action_transfer_or_implicit_account_creation( &apply_state.config.fees, account, actor_id, - &receipt.receiver_id, + receipt.receiver_id(), deposit, apply_state.block_height, apply_state.current_protocol_version, @@ -1934,6 +1941,7 @@ mod tests { use near_parameters::{ExtCosts, ParameterCost, RuntimeConfig}; use near_primitives::account::AccessKey; use near_primitives::hash::hash; + use near_primitives::receipt::ReceiptPriority; use near_primitives::shard_layout::ShardUId; use near_primitives::test_utils::{account_new, MockEpochInfoProvider}; use near_primitives::transaction::{ @@ -1959,7 +1967,7 @@ mod tests { signer: Arc, actions: Vec, ) -> Receipt { - Receipt { + Receipt::V0(ReceiptV0 { predecessor_id: account_id.clone(), receiver_id: account_id.clone(), receipt_id: CryptoHash::hash_borsh(actions.clone()), @@ -1971,7 +1979,7 @@ mod tests { input_data_ids: vec![], actions, }), - } + }) } #[test] @@ -2106,7 +2114,11 @@ mod tests { tries.get_trie_for_shard(ShardUId::single_shard(), root), &Some(validator_accounts_update), &apply_state, - &[Receipt::new_balance_refund(&alice_account(), small_refund)], + &[Receipt::new_balance_refund( + &alice_account(), + small_refund, + ReceiptPriority::NoPriority, + )], &[], &epoch_info_provider, Default::default(), @@ -2329,7 +2341,7 @@ mod tests { (0..n) .map(|i| { receipt_id = hash(receipt_id.as_ref()); - Receipt { + Receipt::V0(ReceiptV0 { predecessor_id: bob_account(), receiver_id: alice_account(), receipt_id, @@ -2343,7 +2355,7 @@ mod tests { deposit: small_transfer + Balance::from(i), })], }), - } + }) }) .collect() } @@ -2353,7 +2365,11 @@ mod tests { (0..n) .map(|i| { receipt_id = hash(receipt_id.as_ref()); - Receipt::new_balance_refund(&alice_account(), small_transfer + Balance::from(i)) + Receipt::new_balance_refund( + &alice_account(), + small_transfer + Balance::from(i), + ReceiptPriority::NoPriority, + ) }) .collect() } @@ -2482,7 +2498,7 @@ mod tests { &apply_state.prev_block_hash, &apply_state.block_hash, ), // receipt for tx 3 - receipts[0].receipt_id, // receipt #0 + *receipts[0].receipt_id(), // receipt #0 ], "STEP #2 failed", ); @@ -2565,8 +2581,8 @@ mod tests { assert_eq!( apply_result.outcomes.iter().map(|o| o.id).collect::>(), vec![ - receipts[1].receipt_id, // receipt #1 - receipts[2].receipt_id, // receipt #2 + *receipts[1].receipt_id(), // receipt #1 + *receipts[2].receipt_id(), // receipt #2 create_receipt_id_from_transaction( PROTOCOL_VERSION, &local_transactions[8], @@ -2595,9 +2611,9 @@ mod tests { assert_eq!( apply_result.outcomes.iter().map(|o| o.id).collect::>(), vec![ - receipts[3].receipt_id, // receipt #3 - receipts[4].receipt_id, // receipt #4 - receipts[5].receipt_id, // receipt #5 + *receipts[3].receipt_id(), // receipt #3 + *receipts[4].receipt_id(), // receipt #4 + *receipts[5].receipt_id(), // receipt #5 ], "STEP #5 failed", ); @@ -2614,7 +2630,7 @@ mod tests { let n = 1; let mut receipts = generate_receipts(small_transfer, n); - if let ReceiptEnum::Action(action_receipt) = &mut receipts.get_mut(0).unwrap().receipt { + if let ReceiptEnum::Action(action_receipt) = receipts.get_mut(0).unwrap().receipt_mut() { action_receipt.gas_price = GAS_PRICE / 10; } @@ -2654,7 +2670,7 @@ mod tests { total_prepaid_exec_fees(&apply_state.config, &actions, &alice_account()).unwrap(), ) .unwrap(); - let receipts = vec![Receipt { + let receipts = vec![Receipt::V0(ReceiptV0 { predecessor_id: bob_account(), receiver_id: alice_account(), receipt_id: CryptoHash::default(), @@ -2666,7 +2682,7 @@ mod tests { input_data_ids: vec![], actions, }), - }]; + })]; let total_receipt_cost = Balance::from(gas + expected_gas_burnt) * gas_price; let expected_gas_burnt_amount = Balance::from(expected_gas_burnt) * GAS_PRICE; let expected_refund = total_receipt_cost - expected_gas_burnt_amount; @@ -2685,7 +2701,7 @@ mod tests { // We used part of the prepaid gas to paying extra fees. assert_eq!(result.stats.gas_deficit_amount, 0); // The refund is less than the received amount. - match &result.outgoing_receipts[0].receipt { + match result.outgoing_receipts[0].receipt() { ReceiptEnum::Action(ActionReceipt { actions, .. }) => { assert!( matches!(actions[0], Action::Transfer(TransferAction { deposit }) if deposit == expected_refund) @@ -2717,7 +2733,7 @@ mod tests { total_prepaid_exec_fees(&apply_state.config, &actions, &alice_account()).unwrap(), ) .unwrap(); - let receipts = vec![Receipt { + let receipts = vec![Receipt::V0(ReceiptV0 { predecessor_id: bob_account(), receiver_id: alice_account(), receipt_id: CryptoHash::default(), @@ -2729,7 +2745,7 @@ mod tests { input_data_ids: vec![], actions, }), - }]; + })]; let total_receipt_cost = Balance::from(gas + expected_gas_burnt) * gas_price; let expected_gas_burnt_amount = Balance::from(expected_gas_burnt) * GAS_PRICE; let expected_deficit = expected_gas_burnt_amount - total_receipt_cost; @@ -2956,10 +2972,10 @@ mod tests { // Only first two receipts should fit into the chunk due to the compute usage limit. assert_matches!(&apply_result.outcomes[..], [first, second] => { - assert_eq!(first.id, deploy_contract_receipt.receipt_id); + assert_eq!(first.id, *deploy_contract_receipt.receipt_id()); assert_matches!(first.outcome.status, ExecutionStatus::SuccessValue(_)); - assert_eq!(second.id, first_call_receipt.receipt_id); + assert_eq!(second.id, *first_call_receipt.receipt_id()); assert_eq!(second.outcome.compute_usage.unwrap(), sha256_cost.compute); assert_matches!(second.outcome.status, ExecutionStatus::SuccessValue(_)); }); @@ -2977,7 +2993,7 @@ mod tests { .unwrap(); assert_matches!(&apply_result.outcomes[..], [ExecutionOutcomeWithId { id, outcome }] => { - assert_eq!(*id, second_call_receipt.receipt_id); + assert_eq!(id, second_call_receipt.receipt_id()); assert_eq!(outcome.compute_usage.unwrap(), sha256_cost.compute); assert_matches!(outcome.status, ExecutionStatus::SuccessValue(_)); }); @@ -3020,10 +3036,10 @@ mod tests { .unwrap(); assert_matches!(&apply_result.outcomes[..], [first, second] => { - assert_eq!(first.id, deploy_contract_receipt.receipt_id); + assert_eq!(first.id, *deploy_contract_receipt.receipt_id()); assert_matches!(first.outcome.status, ExecutionStatus::SuccessValue(_)); - assert_eq!(second.id, first_call_receipt.receipt_id); + assert_eq!(second.id, *first_call_receipt.receipt_id()); assert_matches!(second.outcome.status, ExecutionStatus::Failure(_)); }); } diff --git a/runtime/runtime/src/prefetch.rs b/runtime/runtime/src/prefetch.rs index a3cd5c790da..340a7e0d0b8 100644 --- a/runtime/runtime/src/prefetch.rs +++ b/runtime/runtime/src/prefetch.rs @@ -92,8 +92,8 @@ impl TriePrefetcher { receipts: &[Receipt], ) -> Result<(), PrefetchError> { for receipt in receipts.iter() { - let is_refund = receipt.predecessor_id.is_system(); - let action_receipt = match &receipt.receipt { + let is_refund = receipt.predecessor_id().is_system(); + let action_receipt = match receipt.receipt() { ReceiptEnum::Action(action_receipt) | ReceiptEnum::PromiseYield(action_receipt) => { action_receipt } @@ -101,7 +101,7 @@ impl TriePrefetcher { continue; } }; - let account_id = receipt.receiver_id.clone(); + let account_id = receipt.receiver_id().clone(); // general-purpose account prefetching if self.prefetch_api.enable_receipt_prefetching { @@ -154,7 +154,7 @@ impl TriePrefetcher { } if self.prefetch_api.sweat_prefetch_receivers.contains(&account_id) - && self.prefetch_api.sweat_prefetch_senders.contains(&receipt.predecessor_id) + && self.prefetch_api.sweat_prefetch_senders.contains(receipt.predecessor_id()) { if fn_call.method_name == "record_batch" { self.prefetch_sweat_record_batch(account_id.clone(), &fn_call.args)?; @@ -166,7 +166,7 @@ impl TriePrefetcher { let config = claim_sweat_cfg.iter().find(|cfg| { cfg.receiver == account_id.as_str() && cfg.method_name == fn_call.method_name - && cfg.sender == receipt.predecessor_id.as_str() + && cfg.sender == receipt.predecessor_id().as_str() }); if config.is_some() { self.prefetch_claim_sweat_record_batch_for_hold( @@ -183,13 +183,13 @@ impl TriePrefetcher { if config.is_some() { self.prefetch_claim_sweat_claim( account_id.clone(), - receipt.predecessor_id.clone(), + receipt.predecessor_id().clone(), )? } } if self.prefetch_api.kaiching_prefetch_config.iter().any(|cfg| { - cfg.sender == receipt.predecessor_id.as_str() + cfg.sender == receipt.predecessor_id().as_str() && cfg.receiver == account_id.as_str() && cfg.method_name == fn_call.method_name }) { @@ -211,13 +211,13 @@ impl TriePrefetcher { ) -> Result<(), PrefetchError> { if self.prefetch_api.enable_receipt_prefetching { for t in transactions { - let account_id = t.transaction.signer_id.clone(); + let account_id = t.transaction.signer_id().clone(); let trie_key = TrieKey::Account { account_id }; self.prefetch_trie_key(trie_key)?; let trie_key = TrieKey::AccessKey { - account_id: t.transaction.signer_id.clone(), - public_key: t.transaction.public_key.clone(), + account_id: t.transaction.signer_id().clone(), + public_key: t.transaction.public_key().clone(), }; self.prefetch_trie_key(trie_key)?; } diff --git a/runtime/runtime/src/verifier.rs b/runtime/runtime/src/verifier.rs index 2c4647e80e3..14c1c9e4029 100644 --- a/runtime/runtime/src/verifier.rs +++ b/runtime/runtime/src/verifier.rs @@ -98,13 +98,17 @@ pub fn validate_transaction( verify_signature: bool, current_protocol_version: ProtocolVersion, ) -> Result { + // Don't allow V1 currently. This will be changed when the new protocol version is introduced. + if matches!(signed_transaction.transaction, near_primitives::transaction::Transaction::V1(_)) { + return Err(InvalidTxError::InvalidTransactionVersion.into()); + } let transaction = &signed_transaction.transaction; - let signer_id = &transaction.signer_id; + let signer_id = transaction.signer_id(); if verify_signature && !signed_transaction .signature - .verify(signed_transaction.get_hash().as_ref(), &transaction.public_key) + .verify(signed_transaction.get_hash().as_ref(), transaction.public_key()) { return Err(InvalidTxError::InvalidSignature.into()); } @@ -121,12 +125,12 @@ pub fn validate_transaction( validate_actions( &config.wasm_config.limit_config, - &transaction.actions, + transaction.actions(), current_protocol_version, ) .map_err(InvalidTxError::ActionsValidation)?; - let sender_is_receiver = &transaction.receiver_id == signer_id; + let sender_is_receiver = transaction.receiver_id() == signer_id; tx_cost(&config, transaction, gas_price, sender_is_receiver, current_protocol_version) .map_err(|_| InvalidTxError::CostOverflow.into()) @@ -151,8 +155,9 @@ pub fn verify_and_charge_transaction( verify_signature, current_protocol_version, )?; + let transaction = &signed_transaction.transaction; - let signer_id = &transaction.signer_id; + let signer_id = transaction.signer_id(); let mut signer = match get_account(state_update, signer_id)? { Some(signer) => signer, @@ -160,22 +165,22 @@ pub fn verify_and_charge_transaction( return Err(InvalidTxError::SignerDoesNotExist { signer_id: signer_id.clone() }.into()); } }; - let mut access_key = match get_access_key(state_update, signer_id, &transaction.public_key)? { + let mut access_key = match get_access_key(state_update, signer_id, transaction.public_key())? { Some(access_key) => access_key, None => { return Err(InvalidTxError::InvalidAccessKeyError( InvalidAccessKeyError::AccessKeyNotFound { account_id: signer_id.clone(), - public_key: transaction.public_key.clone().into(), + public_key: transaction.public_key().clone().into(), }, ) .into()); } }; - if transaction.nonce <= access_key.nonce { + if transaction.nonce() <= access_key.nonce { return Err(InvalidTxError::InvalidNonce { - tx_nonce: transaction.nonce, + tx_nonce: transaction.nonce(), ak_nonce: access_key.nonce, } .into()); @@ -184,9 +189,9 @@ pub fn verify_and_charge_transaction( if let Some(height) = block_height { let upper_bound = height * near_primitives::account::AccessKey::ACCESS_KEY_NONCE_RANGE_MULTIPLIER; - if transaction.nonce >= upper_bound { + if transaction.nonce() >= upper_bound { return Err(InvalidTxError::NonceTooLarge { - tx_nonce: transaction.nonce, + tx_nonce: transaction.nonce(), upper_bound, } .into()); @@ -194,7 +199,7 @@ pub fn verify_and_charge_transaction( } }; - access_key.nonce = transaction.nonce; + access_key.nonce = transaction.nonce(); signer.set_amount(signer.amount().checked_sub(total_cost).ok_or_else(|| { InvalidTxError::NotEnoughBalance { @@ -211,7 +216,7 @@ pub fn verify_and_charge_transaction( *allowance = allowance.checked_sub(total_cost).ok_or_else(|| { InvalidTxError::InvalidAccessKeyError(InvalidAccessKeyError::NotEnoughAllowance { account_id: signer_id.clone(), - public_key: transaction.public_key.clone().into(), + public_key: transaction.public_key().clone().into(), allowance: *allowance, cost: total_cost, }) @@ -234,23 +239,23 @@ pub fn verify_and_charge_transaction( }; if let AccessKeyPermission::FunctionCall(ref function_call_permission) = access_key.permission { - if transaction.actions.len() != 1 { + if transaction.actions().len() != 1 { return Err(InvalidTxError::InvalidAccessKeyError( InvalidAccessKeyError::RequiresFullAccess, ) .into()); } - if let Some(Action::FunctionCall(ref function_call)) = transaction.actions.get(0) { + if let Some(Action::FunctionCall(ref function_call)) = transaction.actions().get(0) { if function_call.deposit > 0 { return Err(InvalidTxError::InvalidAccessKeyError( InvalidAccessKeyError::DepositWithFunctionCall, ) .into()); } - if transaction.receiver_id != function_call_permission.receiver_id { + if transaction.receiver_id() != &function_call_permission.receiver_id { return Err(InvalidTxError::InvalidAccessKeyError( InvalidAccessKeyError::ReceiverMismatch { - tx_receiver: transaction.receiver_id.clone(), + tx_receiver: transaction.receiver_id().clone(), ak_receiver: function_call_permission.receiver_id.clone(), }, ) @@ -277,7 +282,7 @@ pub fn verify_and_charge_transaction( } }; - set_access_key(state_update, signer_id.clone(), transaction.public_key.clone(), &access_key); + set_access_key(state_update, signer_id.clone(), transaction.public_key().clone(), &access_key); set_account(state_update, signer_id.clone(), &signer); Ok(VerificationResult { gas_burnt, gas_remaining, receipt_gas_price, burnt_amount }) @@ -292,16 +297,16 @@ pub(crate) fn validate_receipt( // We retain these checks here as to maintain backwards compatibility // with AccountId validation since we illegally parse an AccountId // in near-vm-logic/logic.rs#fn(VMLogic::read_and_parse_account_id) - AccountId::validate(receipt.predecessor_id.as_ref()).map_err(|_| { + AccountId::validate(receipt.predecessor_id().as_ref()).map_err(|_| { ReceiptValidationError::InvalidPredecessorId { - account_id: receipt.predecessor_id.to_string(), + account_id: receipt.predecessor_id().to_string(), } })?; - AccountId::validate(receipt.receiver_id.as_ref()).map_err(|_| { - ReceiptValidationError::InvalidReceiverId { account_id: receipt.receiver_id.to_string() } + AccountId::validate(receipt.receiver_id().as_ref()).map_err(|_| { + ReceiptValidationError::InvalidReceiverId { account_id: receipt.receiver_id().to_string() } })?; - match &receipt.receipt { + match receipt.receipt() { ReceiptEnum::Action(action_receipt) | ReceiptEnum::PromiseYield(action_receipt) => { validate_action_receipt(limit_config, action_receipt, current_protocol_version) } @@ -573,6 +578,7 @@ mod tests { use near_primitives::account::{AccessKey, FunctionCallPermission}; use near_primitives::action::delegate::{DelegateAction, NonDelegateAction}; use near_primitives::hash::{hash, CryptoHash}; + use near_primitives::receipt::ReceiptPriority; use near_primitives::test_utils::account_new; use near_primitives::transaction::{ CreateAccountAction, DeleteAccountAction, DeleteKeyAction, StakeAction, TransferAction, @@ -960,6 +966,7 @@ mod tests { deposit: 0, }))], CryptoHash::default(), + 0, ), RuntimeError::InvalidTxError(InvalidTxError::ActionsValidation( ActionsValidationError::TotalPrepaidGasExceeded { @@ -1053,6 +1060,29 @@ mod tests { ); } + #[test] + fn test_validate_transaction_invalid_transaction_version() { + let config = RuntimeConfig::test(); + let (signer, mut state_update, gas_price) = + setup_common(TESTING_INIT_BALANCE, 0, Some(AccessKey::full_access())); + + assert_err_both_validations( + &config, + &mut state_update, + gas_price, + &SignedTransaction::from_actions_v1( + 1, + alice_account(), + bob_account(), + &*signer, + vec![Action::Transfer(TransferAction { deposit: 100 })], + CryptoHash::default(), + 1, + ), + RuntimeError::InvalidTxError(InvalidTxError::InvalidTransactionVersion), + ); + } + #[test] fn test_validate_transaction_invalid_not_enough_balance() { let config = RuntimeConfig::test(); @@ -1122,6 +1152,7 @@ mod tests { deposit: 0, }))], CryptoHash::default(), + 0, ), true, None, @@ -1257,6 +1288,7 @@ mod tests { Action::CreateAccount(CreateAccountAction {}) ], CryptoHash::default(), + 0 ), true, None, @@ -1280,6 +1312,7 @@ mod tests { &*signer, vec![], CryptoHash::default(), + 0 ), true, None, @@ -1303,6 +1336,7 @@ mod tests { &*signer, vec![Action::CreateAccount(CreateAccountAction {})], CryptoHash::default(), + 0 ), true, None, @@ -1348,6 +1382,7 @@ mod tests { deposit: 0, })),], CryptoHash::default(), + 0 ), true, None, @@ -1396,6 +1431,7 @@ mod tests { deposit: 0, })),], CryptoHash::default(), + 0 ), true, None, @@ -1441,6 +1477,7 @@ mod tests { deposit: 100, })),], CryptoHash::default(), + 0 ), true, None, @@ -1465,6 +1502,7 @@ mod tests { &*signer, vec![Action::DeployContract(DeployContractAction { code: vec![1; 5] })], CryptoHash::default(), + 0, ); let transaction_size = transaction.get_size(); @@ -1509,7 +1547,7 @@ mod tests { let limit_config = test_limit_config(); validate_receipt( &limit_config, - &Receipt::new_balance_refund(&alice_account(), 10), + &Receipt::new_balance_refund(&alice_account(), 10, ReceiptPriority::NoPriority), PROTOCOL_VERSION, ) .expect("valid receipt"); diff --git a/runtime/runtime/tests/runtime_group_tools/mod.rs b/runtime/runtime/tests/runtime_group_tools/mod.rs index dbc04c0804a..950a8a8a96b 100644 --- a/runtime/runtime/tests/runtime_group_tools/mod.rs +++ b/runtime/runtime/tests/runtime_group_tools/mod.rs @@ -268,7 +268,7 @@ impl RuntimeGroup { .0 .lock() .unwrap() - .get_mut(&transaction.transaction.signer_id) + .get_mut(transaction.transaction.signer_id()) .unwrap() .incoming_transactions .push(transaction); @@ -334,7 +334,8 @@ impl RuntimeGroup { mailbox.incoming_transactions.clear(); group.transaction_logs.lock().unwrap().extend(transaction_results); for new_receipt in new_receipts { - let locked_other_mailbox = mailboxes.get_mut(&new_receipt.receiver_id).unwrap(); + let locked_other_mailbox = + mailboxes.get_mut(new_receipt.receiver_id()).unwrap(); locked_other_mailbox.incoming_receipts.push(new_receipt); } group.mailboxes.1.notify_all(); @@ -421,9 +422,9 @@ macro_rules! assert_receipts { $($action_name:ident, $action_pat:pat, $action_assert:block ),+ => [ $($produced_receipt:ident),*] ) => { let r = $group.get_receipt($to, $receipt); - assert_eq!(r.predecessor_id, $from); - assert_eq!(r.receiver_id, $to); - match &r.receipt { + assert_eq!(r.predecessor_id().clone(), $from); + assert_eq!(r.receiver_id().clone(), $to); + match r.receipt() { $receipt_pat => { $receipt_assert tuplet!(( $($action_name),* ) = $actions_name, "Incorrect number of actions"); diff --git a/runtime/runtime/tests/test_async_calls.rs b/runtime/runtime/tests/test_async_calls.rs index e8fe09ed609..d849cefd239 100644 --- a/runtime/runtime/tests/test_async_calls.rs +++ b/runtime/runtime/tests/test_async_calls.rs @@ -37,6 +37,7 @@ fn test_simple_func_call() { deposit: 0, }))], CryptoHash::default(), + 0, ); let handles = RuntimeGroup::start_runtimes(group.clone(), vec![signed_transaction.clone()]); @@ -83,6 +84,7 @@ fn test_single_promise_no_callback() { deposit: 0, }))], CryptoHash::default(), + 0, ); let handles = RuntimeGroup::start_runtimes(group.clone(), vec![signed_transaction.clone()]); @@ -149,6 +151,7 @@ fn test_single_promise_with_callback() { deposit: 0, }))], CryptoHash::default(), + 0, ); let handles = RuntimeGroup::start_runtimes(group.clone(), vec![signed_transaction.clone()]); @@ -233,6 +236,7 @@ fn test_two_promises_no_callbacks() { deposit: 0, }))], CryptoHash::default(), + 0, ); let handles = RuntimeGroup::start_runtimes(group.clone(), vec![signed_transaction.clone()]); @@ -327,6 +331,7 @@ fn test_two_promises_with_two_callbacks() { deposit: 0, }))], CryptoHash::default(), + 0, ); let handles = RuntimeGroup::start_runtimes(group.clone(), vec![signed_transaction.clone()]); @@ -418,6 +423,7 @@ fn test_single_promise_no_callback_batch() { deposit: 0, }))], CryptoHash::default(), + 0, ); let handles = RuntimeGroup::start_runtimes(group.clone(), vec![signed_transaction.clone()]); @@ -490,6 +496,7 @@ fn test_single_promise_with_callback_batch() { deposit: 0, }))], CryptoHash::default(), + 0, ); let handles = RuntimeGroup::start_runtimes(group.clone(), vec![signed_transaction.clone()]); @@ -564,6 +571,7 @@ fn test_simple_transfer() { deposit: 0, }))], CryptoHash::default(), + 0, ); let handles = RuntimeGroup::start_runtimes(group.clone(), vec![signed_transaction.clone()]); @@ -631,6 +639,7 @@ fn test_create_account_with_transfer_and_full_key() { deposit: 0, }))], CryptoHash::default(), + 0, ); let handles = RuntimeGroup::start_runtimes(group.clone(), vec![signed_transaction.clone()]); @@ -743,6 +752,7 @@ fn test_account_factory() { deposit: 0, }))], CryptoHash::default(), + 0, ); let handles = RuntimeGroup::start_runtimes(group.clone(), vec![signed_transaction.clone()]); @@ -889,6 +899,7 @@ fn test_create_account_add_key_call_delete_key_delete_account() { deposit: 0, }))], CryptoHash::default(), + 0, ); let handles = RuntimeGroup::start_runtimes(group.clone(), vec![signed_transaction.clone()]); @@ -983,6 +994,7 @@ fn test_transfer_64len_hex() { deposit: 0, }))], CryptoHash::default(), + 0, ); let handles = RuntimeGroup::start_runtimes(group.clone(), vec![signed_transaction.clone()]); @@ -1049,6 +1061,7 @@ fn test_create_transfer_64len_hex_fail() { deposit: 0, }))], CryptoHash::default(), + 0, ); let handles = RuntimeGroup::start_runtimes(group.clone(), vec![signed_transaction.clone()]); diff --git a/test-utils/runtime-tester/src/run_test.rs b/test-utils/runtime-tester/src/run_test.rs index c885a525c65..56540ba0b06 100644 --- a/test-utils/runtime-tester/src/run_test.rs +++ b/test-utils/runtime-tester/src/run_test.rs @@ -185,6 +185,7 @@ impl TransactionConfig { &self.signer, self.actions.clone(), *last_block.hash(), + 0, ) } } diff --git a/tools/fork-network/src/single_shard_storage_mutator.rs b/tools/fork-network/src/single_shard_storage_mutator.rs index 7206dda2e91..70bf695c689 100644 --- a/tools/fork-network/src/single_shard_storage_mutator.rs +++ b/tools/fork-network/src/single_shard_storage_mutator.rs @@ -94,8 +94,8 @@ impl SingleShardStorageMutator { pub(crate) fn set_postponed_receipt(&mut self, receipt: &Receipt) -> anyhow::Result<()> { self.set( TrieKey::PostponedReceipt { - receiver_id: receipt.receiver_id.clone(), - receipt_id: receipt.receipt_id, + receiver_id: receipt.receiver_id().clone(), + receipt_id: *receipt.receipt_id(), }, borsh::to_vec(&receipt)?, ) @@ -103,8 +103,8 @@ impl SingleShardStorageMutator { pub(crate) fn delete_postponed_receipt(&mut self, receipt: &Receipt) -> anyhow::Result<()> { self.remove(TrieKey::PostponedReceipt { - receiver_id: receipt.receiver_id.clone(), - receipt_id: receipt.receipt_id, + receiver_id: receipt.receiver_id().clone(), + receipt_id: *receipt.receipt_id(), }) } diff --git a/tools/mirror/src/chain_tracker.rs b/tools/mirror/src/chain_tracker.rs index a232ce0802d..7cd21994d2a 100644 --- a/tools/mirror/src/chain_tracker.rs +++ b/tools/mirror/src/chain_tracker.rs @@ -45,14 +45,14 @@ impl TxSendInfo { target_height: BlockHeight, now: Instant, ) -> Self { - let target_signer_id = if &tx.source_signer_id != &tx.target_tx.transaction.signer_id { - Some(tx.target_tx.transaction.signer_id.clone()) + let target_signer_id = if &tx.source_signer_id != tx.target_tx.transaction.signer_id() { + Some(tx.target_tx.transaction.signer_id().clone()) } else { None }; - let target_receiver_id = if &tx.source_receiver_id != &tx.target_tx.transaction.receiver_id + let target_receiver_id = if &tx.source_receiver_id != tx.target_tx.transaction.receiver_id() { - Some(tx.target_tx.transaction.receiver_id.clone()) + Some(tx.target_tx.transaction.receiver_id().clone()) } else { None }; @@ -68,7 +68,7 @@ impl TxSendInfo { actions: tx .target_tx .transaction - .actions + .actions() .iter() .map(|a| a.as_ref().to_string()) .collect::>(), @@ -421,8 +421,8 @@ impl TxTracker { let info = self .nonces .get_mut(&( - tx.target_tx.transaction.signer_id.clone(), - tx.target_tx.transaction.public_key.clone(), + tx.target_tx.transaction.signer_id().clone(), + tx.target_tx.transaction.public_key().clone(), )) .unwrap(); info.queued_txs.insert(tx_ref.clone()); @@ -439,8 +439,8 @@ impl TxTracker { let info = self .nonces .get_mut(&( - tx.target_tx.signer_id.clone(), - tx.target_tx.public_key.clone(), + tx.target_tx.signer_id().clone(), + tx.target_tx.public_key().clone(), )) .unwrap(); info.txs_awaiting_nonce.insert(tx_ref.clone()); @@ -481,8 +481,10 @@ impl TxTracker { for c in self.queued_blocks[0].chunks.iter_mut() { for tx in c.txs.iter_mut() { if let TargetChainTx::AwaitingNonce(t) = tx { - needed_access_keys - .insert((t.target_tx.signer_id.clone(), t.target_tx.public_key.clone())); + needed_access_keys.insert(( + t.target_tx.signer_id().clone(), + t.target_tx.public_key().clone(), + )); } } } @@ -505,12 +507,12 @@ impl TxTracker { TargetChainTx::Ready(t) => { tracing::debug!( target: "mirror", "Prepared {} for ({}, {:?}) with nonce {} even though there are still pending outcomes that may affect the access key", - &t.provenance, &t.target_tx.transaction.signer_id, &t.target_tx.transaction.public_key, t.target_tx.transaction.nonce + &t.provenance, t.target_tx.transaction.signer_id(), t.target_tx.transaction.public_key(), t.target_tx.transaction.nonce() ); self.nonces .get_mut(&( - t.target_tx.transaction.signer_id.clone(), - t.target_tx.transaction.public_key.clone(), + t.target_tx.transaction.signer_id().clone(), + t.target_tx.transaction.public_key().clone(), )) .unwrap() .txs_awaiting_nonce @@ -519,12 +521,12 @@ impl TxTracker { TargetChainTx::AwaitingNonce(t) => { tracing::warn!( target: "mirror", "Could not prepare {} for ({}, {:?}). Nonce unknown", - &t.provenance, &t.target_tx.signer_id, &t.target_tx.public_key, + &t.provenance, t.target_tx.signer_id(), t.target_tx.public_key(), ); self.nonces .get_mut(&( - t.target_tx.signer_id.clone(), - t.target_tx.public_key.clone(), + t.target_tx.signer_id().clone(), + t.target_tx.public_key().clone(), )) .unwrap() .txs_awaiting_nonce @@ -750,7 +752,7 @@ impl TxTracker { tx.try_set_nonce(nonce); match tx { TargetChainTx::Ready(t) => { - tracing::debug!(target: "mirror", "set nonce for {:?}'s {} to {}", access_key, r, t.target_tx.transaction.nonce); + tracing::debug!(target: "mirror", "set nonce for {:?}'s {} to {}", access_key, r, t.target_tx.transaction.nonce()); } _ => { tracing::warn!(target: "mirror", "Couldn't set nonce for {:?}'s {}", access_key, r); @@ -929,12 +931,12 @@ impl TxTracker { { tracing::debug!( target: "mirror", "Successfully sent transaction {} for {}: {:?}", - &hash, &tx.provenance, &tx.target_tx.transaction.actions, + &hash, &tx.provenance, tx.target_tx.transaction.actions(), ); } let access_key = ( - tx.target_tx.transaction.signer_id.clone(), - tx.target_tx.transaction.public_key.clone(), + tx.target_tx.transaction.signer_id().clone(), + tx.target_tx.transaction.public_key().clone(), ); let source_height = tx_ref.as_ref().map(|t| t.source_height); // TODO: don't keep adding txs if we're not ever finding them on chain, since we'll OOM eventually @@ -943,14 +945,14 @@ impl TxTracker { let txs = self.txs_by_signer.entry(access_key.clone()).or_default(); if let Some(highest_nonce) = txs.iter().next_back() { - if highest_nonce.nonce > tx.target_tx.transaction.nonce { + if highest_nonce.nonce > tx.target_tx.transaction.nonce() { tracing::warn!( target: "mirror", "transaction sent with out of order nonce: {}: {}. Sent so far: {:?}", - &hash, tx.target_tx.transaction.nonce, txs + &hash, tx.target_tx.transaction.nonce(), txs ); } } - if !txs.insert(TxId { hash, nonce: tx.target_tx.transaction.nonce }) { + if !txs.insert(TxId { hash, nonce: tx.target_tx.transaction.nonce() }) { tracing::warn!(target: "mirror", "inserted tx {} twice into txs_by_signer", &hash); } @@ -999,15 +1001,15 @@ impl TxTracker { let mut t = crate::read_target_nonce( db, - &tx.target_tx.transaction.signer_id, - &tx.target_tx.transaction.public_key, + tx.target_tx.transaction.signer_id(), + tx.target_tx.transaction.public_key(), )? .unwrap(); - t.nonce = std::cmp::max(t.nonce, Some(tx.target_tx.transaction.nonce)); + t.nonce = std::cmp::max(t.nonce, Some(tx.target_tx.transaction.nonce())); crate::put_target_nonce( db, - &tx.target_tx.transaction.signer_id, - &tx.target_tx.transaction.public_key, + tx.target_tx.transaction.signer_id(), + tx.target_tx.transaction.public_key(), &t, )?; let info = self.nonces.get_mut(&access_key).unwrap(); @@ -1101,7 +1103,7 @@ impl TxTracker { target_tx.try_set_nonce(None); match target_tx { TargetChainTx::Ready(t) => { - tracing::debug!(target: "mirror", "After skipping {} setting nonce for {:?}'s {} to {}", tx_ref, &access_key, r, t.target_tx.transaction.nonce); + tracing::debug!(target: "mirror", "After skipping {} setting nonce for {:?}'s {} to {}", tx_ref, &access_key, r, t.target_tx.transaction.nonce()); } _ => { tracing::warn!(target: "mirror", "After skipping {} could not set nonce for {:?}'s {}", tx_ref, &access_key, r); @@ -1125,7 +1127,7 @@ impl TxTracker { } } } - let access_key = (tx.signer_id.clone(), tx.public_key.clone()); + let access_key = (tx.signer_id().clone(), tx.public_key().clone()); let info = self.nonces.get_mut(&access_key).unwrap(); if info.last_height <= Some(tx_ref.source_height) { access_keys_to_remove.insert(access_key); diff --git a/tools/mirror/src/genesis.rs b/tools/mirror/src/genesis.rs index a84d05d2eb2..dd6f0382ed4 100644 --- a/tools/mirror/src/genesis.rs +++ b/tools/mirror/src/genesis.rs @@ -155,9 +155,9 @@ pub fn map_receipt( secret: Option<&[u8; crate::secret::SECRET_LEN]>, default_key: &PublicKey, ) { - receipt.predecessor_id = crate::key_mapping::map_account(&receipt.predecessor_id, secret); - receipt.receiver_id = crate::key_mapping::map_account(&receipt.receiver_id, secret); - match &mut receipt.receipt { + receipt.set_predecessor_id(crate::key_mapping::map_account(receipt.predecessor_id(), secret)); + receipt.set_receiver_id(crate::key_mapping::map_account(receipt.receiver_id(), secret)); + match receipt.receipt_mut() { ReceiptEnum::Action(r) | ReceiptEnum::PromiseYield(r) => { map_action_receipt(r, secret, default_key); } @@ -268,7 +268,7 @@ mod test { use near_primitives::account::{AccessKeyPermission, FunctionCallPermission}; use near_primitives::action::delegate::{DelegateAction, SignedDelegateAction}; use near_primitives::hash::CryptoHash; - use near_primitives::receipt::{ActionReceipt, Receipt, ReceiptEnum}; + use near_primitives::receipt::{ActionReceipt, Receipt, ReceiptEnum, ReceiptV0}; use near_primitives::transaction::{Action, AddKeyAction, CreateAccountAction}; use near_primitives_core::account::AccessKey; @@ -276,7 +276,7 @@ mod test { fn test_map_receipt() { let default_key = crate::key_mapping::default_extra_key(None).public_key(); - let mut receipt0 = Receipt { + let mut receipt0 = Receipt::V0(ReceiptV0 { predecessor_id: "foo.near".parse().unwrap(), receiver_id: "foo.foo.near".parse().unwrap(), receipt_id: CryptoHash::default(), @@ -305,8 +305,8 @@ mod test { })), ], }), - }; - let want_receipt0 = Receipt { + }); + let want_receipt0 = Receipt::V0(ReceiptV0 { predecessor_id: "foo.near".parse().unwrap(), receiver_id: "foo.foo.near".parse().unwrap(), receipt_id: CryptoHash::default(), @@ -339,7 +339,7 @@ mod test { })), ], }), - }; + }); let secret_key = SecretKey::from_random(KeyType::ED25519); let delegate_action = DelegateAction { @@ -360,7 +360,7 @@ mod test { let tx_hash = delegate_action.get_nep461_hash(); let signature = secret_key.sign(tx_hash.as_ref()); - let mut receipt1 = Receipt { + let mut receipt1 = Receipt::V0(ReceiptV0 { predecessor_id: "757a45019f9a3e5bd475586c31f63d6e15d50f5366caf4643f6f69731a222cad" .parse() .unwrap(), @@ -383,7 +383,7 @@ mod test { signature, }))], }), - }; + }); let mapped_secret_key = crate::key_mapping::map_key(&secret_key.public_key(), None); let delegate_action = DelegateAction { @@ -403,7 +403,7 @@ mod test { }; let tx_hash = delegate_action.get_nep461_hash(); let signature = mapped_secret_key.sign(tx_hash.as_ref()); - let want_receipt1 = Receipt { + let want_receipt1 = Receipt::V0(ReceiptV0 { predecessor_id: "3f8c3be8929e5fa61907f13a6247e7e452b92bb7d224cf691a9aa67814eb509b" .parse() .unwrap(), @@ -426,7 +426,7 @@ mod test { signature, }))], }), - }; + }); crate::genesis::map_receipt(&mut receipt0, None, &default_key); assert_eq!(receipt0, want_receipt0); diff --git a/tools/mirror/src/lib.rs b/tools/mirror/src/lib.rs index 49d32eae816..4cf82668d4b 100644 --- a/tools/mirror/src/lib.rs +++ b/tools/mirror/src/lib.rs @@ -261,28 +261,28 @@ impl SourceTransaction { fn public_key(&self) -> &PublicKey { match self { - Self::Tx(tx) => &tx.transaction.public_key, + Self::Tx(tx) => tx.transaction.public_key(), Self::TxView(tx) => &tx.public_key, } } fn signer_id(&self) -> &AccountId { match self { - Self::Tx(tx) => &tx.transaction.signer_id, + Self::Tx(tx) => tx.transaction.signer_id(), Self::TxView(tx) => &tx.signer_id, } } fn receiver_id(&self) -> &AccountId { match self { - Self::Tx(tx) => &tx.transaction.receiver_id, + Self::Tx(tx) => tx.transaction.receiver_id(), Self::TxView(tx) => &tx.receiver_id, } } fn actions<'a>(&'a self) -> Cow<'a, [Action]> { match self { - Self::Tx(tx) => Cow::Borrowed(&tx.transaction.actions), + Self::Tx(tx) => Cow::Borrowed(tx.transaction.actions()), Self::TxView(tx) => { Cow::Owned(tx.actions.iter().map(|a| a.clone().try_into().unwrap()).collect()) } @@ -597,9 +597,15 @@ impl TxAwaitingNonce { provenance: MappedTxProvenance, nonce_updates: HashSet<(AccountId, PublicKey)>, ) -> Self { - let mut target_tx = - Transaction::new(target_signer_id, target_public_key, target_receiver_id, 0, *ref_hash); - target_tx.actions = actions; + let mut target_tx = Transaction::new( + target_signer_id, + target_public_key, + target_receiver_id, + 0, + *ref_hash, + 0, + ); + *target_tx.actions_mut() = actions; Self { source_signer_id, source_receiver_id, @@ -645,8 +651,9 @@ impl MappedTx { target_receiver_id, nonce, *ref_hash, + 0, ); - target_tx.actions = actions; + *target_tx.actions_mut() = actions; let target_tx = SignedTransaction::new( target_secret_key.sign(&target_tx.get_hash_and_size().0.as_ref()), target_tx, @@ -663,7 +670,7 @@ impl MappedTx { fn inc_nonce(&mut self, target_secret_key: &SecretKey) { let mut tx = self.target_tx.transaction.clone(); - tx.nonce += 1; + *tx.nonce_mut() += 1; self.target_tx = SignedTransaction::new(target_secret_key.sign(&tx.get_hash_and_size().0.as_ref()), tx); } @@ -679,7 +686,7 @@ impl TargetChainTx { fn set_nonce(&mut self, nonce: Nonce) { match self { Self::AwaitingNonce(t) => { - t.target_tx.nonce = nonce; + *t.target_tx.nonce_mut() = nonce; let target_tx = SignedTransaction::new( t.target_secret_key.sign(&t.target_tx.get_hash_and_size().0.as_ref()), t.target_tx.clone(), @@ -769,7 +776,7 @@ impl TargetChainTx { fn target_nonce(&self) -> TargetNonce { match self { Self::Ready(t) => TargetNonce { - nonce: Some(t.target_tx.transaction.nonce), + nonce: Some(t.target_tx.transaction.nonce()), pending_outcomes: HashSet::new(), }, Self::AwaitingNonce(t) => t.target_nonce.clone(), @@ -938,7 +945,7 @@ impl TxMirror { // only once instance of this code will run, but this is the place to detect if that's not the case. tracing::error!( target: "mirror", "Tried to send an invalid tx for ({}, {:?}) from {}: {:?}", - &tx.target_tx.transaction.signer_id, &tx.target_tx.transaction.public_key, &tx.provenance, e + tx.target_tx.transaction.signer_id(), tx.target_tx.transaction.public_key(), &tx.provenance, e ); crate::metrics::TRANSACTIONS_SENT.with_label_values(&["invalid"]).inc(); } @@ -957,7 +964,7 @@ impl TxMirror { // TODO: here we should just save this transaction for later and send it when it's known tracing::warn!( target: "mirror", "skipped sending transaction for ({}, {:?}) because valid target chain nonce not known", - &tx.target_tx.signer_id, &tx.target_tx.public_key + tx.target_tx.signer_id(), tx.target_tx.public_key() ); } } @@ -1312,10 +1319,11 @@ impl TxMirror { Err(ChainError::Other(e)) => return Err(e), }; - if let ReceiptEnum::Action(r) | ReceiptEnum::PromiseYield(r) = &receipt.receipt { - if (provenance.is_create_account() && receipt.predecessor_id == receipt.receiver_id) + if let ReceiptEnum::Action(r) | ReceiptEnum::PromiseYield(r) = receipt.receipt() { + if (provenance.is_create_account() + && receipt.predecessor_id() == receipt.receiver_id()) || (!provenance.is_create_account() - && receipt.predecessor_id != receipt.receiver_id) + && receipt.predecessor_id() != receipt.receiver_id()) { continue; } @@ -1341,19 +1349,19 @@ impl TxMirror { if account_created { tracing::warn!( target: "mirror", "for receipt {} predecessor and receiver are the same but there's a create account in the actions: {:?}", - &receipt.receipt_id, &r.actions, + receipt.receipt_id(), &r.actions, ); } } let outcome = self .source_chain_access .get_outcome(TransactionOrReceiptId::Receipt { - receipt_id: receipt.receipt_id, - receiver_id: receipt.receiver_id.clone(), + receipt_id: *receipt.receipt_id(), + receiver_id: receipt.receiver_id().clone(), }) .await .with_context(|| { - format!("failed fetching outcome for receipt {}", receipt.receipt_id) + format!("failed fetching outcome for receipt {}", receipt.receipt_id()) })?; if !execution_status_good(&outcome.outcome.status) { continue; @@ -1363,8 +1371,8 @@ impl TxMirror { tracker, outcome.block_hash, txs, - receipt.predecessor_id.clone(), - receipt.receiver_id.clone(), + receipt.predecessor_id().clone(), + receipt.receiver_id().clone(), &r.actions, ref_hash, provenance, @@ -1426,13 +1434,13 @@ impl TxMirror { tracker: &mut crate::chain_tracker::TxTracker, txs: &mut Vec, ) -> anyhow::Result<()> { - if let ReceiptEnum::Action(r) | ReceiptEnum::PromiseYield(r) = &receipt.receipt { + if let ReceiptEnum::Action(r) | ReceiptEnum::PromiseYield(r) = receipt.receipt() { if r.actions.iter().any(|a| matches!(a, Action::FunctionCall(_))) { self.add_function_call_keys( tracker, txs, - &receipt.receipt_id, - &receipt.receiver_id, + receipt.receipt_id(), + receipt.receiver_id(), ref_hash, provenance, source_height, diff --git a/tools/state-viewer/src/apply_chain_range.rs b/tools/state-viewer/src/apply_chain_range.rs index 046aca676a5..54b5e8bace2 100644 --- a/tools/state-viewer/src/apply_chain_range.rs +++ b/tools/state-viewer/src/apply_chain_range.rs @@ -222,7 +222,7 @@ fn apply_block_from_range( if only_contracts { let mut has_contracts = false; for tx in chunk.transactions() { - for action in &tx.transaction.actions { + for action in tx.transaction.actions() { has_contracts = has_contracts || matches!(action, Action::FunctionCall(_) | Action::DeployContract(_)); } diff --git a/tools/state-viewer/src/apply_chunk.rs b/tools/state-viewer/src/apply_chunk.rs index a8ca73b051b..9f12d4c66fb 100644 --- a/tools/state-viewer/src/apply_chunk.rs +++ b/tools/state-viewer/src/apply_chunk.rs @@ -189,7 +189,7 @@ fn find_tx_or_receipt( let shard_layout = epoch_manager.get_shard_layout_from_prev_block(chunk.prev_block())?; let to_shard = - shard_layout::account_id_to_shard_id(&receipt.receiver_id, &shard_layout); + shard_layout::account_id_to_shard_id(receipt.receiver_id(), &shard_layout); return Ok(Some((HashType::Receipt, to_shard))); } } @@ -397,7 +397,7 @@ fn apply_receipt_in_chunk( let shard_layout = epoch_manager.get_shard_layout_from_prev_block(chunk.prev_block())?; let to_shard = shard_layout::account_id_to_shard_id( - &receipt.receiver_id, + receipt.receiver_id(), &shard_layout, ); to_apply.insert((height, to_shard)); @@ -684,7 +684,7 @@ mod test { for receipt in chunk.prev_outgoing_receipts() { let to_shard = shard_layout::account_id_to_shard_id( - &receipt.receiver_id, + receipt.receiver_id(), &shard_layout, ); diff --git a/tools/state-viewer/src/contract_accounts.rs b/tools/state-viewer/src/contract_accounts.rs index 025fe5b4719..fce79dca2e1 100644 --- a/tools/state-viewer/src/contract_accounts.rs +++ b/tools/state-viewer/src/contract_accounts.rs @@ -295,16 +295,16 @@ fn try_find_actions_spawned_by_receipt( .map_err(|e| ContractAccountError::InvalidReceipt(e, key))?; // Skip refunds. - if receipt.receiver_id.is_system() { + if receipt.receiver_id().is_system() { return Ok(()); } // Note: We could use the entry API here to avoid the double hash, but we // would have to clone the key string. It's unclear which is better, I will // avoid the entry API because normal contains/get_mut seems simpler. - if accounts.contains_key(&receipt.receiver_id) { + if accounts.contains_key(receipt.receiver_id()) { // yes, this is a contract in our map (skip/select filtering has already been applied when constructing the map) - let entry = accounts.get_mut(&receipt.receiver_id).unwrap(); + let entry = accounts.get_mut(receipt.receiver_id()).unwrap(); if filter.receipts_in { *entry.receipts_in.get_or_insert(0) += 1; } @@ -327,7 +327,7 @@ fn try_find_actions_spawned_by_receipt( let outgoing_receipt = maybe_outgoing_receipt.ok_or_else(|| { ContractAccountError::MissingOutgoingReceipt(*outgoing_receipt_id) })?; - match outgoing_receipt.receipt { + match outgoing_receipt.receipt() { ReceiptEnum::Action(action_receipt) | ReceiptEnum::PromiseYield(action_receipt) => { for action in &action_receipt.actions { @@ -493,7 +493,7 @@ mod tests { use borsh::BorshSerialize; use near_crypto::{InMemorySigner, Signer}; use near_primitives::hash::CryptoHash; - use near_primitives::receipt::{ActionReceipt, Receipt, ReceiptEnum}; + use near_primitives::receipt::{ActionReceipt, Receipt, ReceiptEnum, ReceiptV0}; use near_primitives::transaction::{ Action, CreateAccountAction, DeployContractAction, ExecutionMetadata, ExecutionOutcome, ExecutionOutcomeWithProof, ExecutionStatus, FunctionCallAction, TransferAction, @@ -722,7 +722,7 @@ mod tests { let sender_id: AccountId = sender.parse().unwrap(); let signer = InMemorySigner::from_seed(sender_id.clone(), near_crypto::KeyType::ED25519, "seed"); - Receipt { + Receipt::V0(ReceiptV0 { predecessor_id: sender_id.clone(), receiver_id: receiver.parse().unwrap(), receipt_id: CryptoHash::default(), @@ -734,6 +734,6 @@ mod tests { input_data_ids: vec![], actions, }), - } + }) } } diff --git a/tools/state-viewer/src/state_dump.rs b/tools/state-viewer/src/state_dump.rs index 4a6e68732a3..4328bc0e281 100644 --- a/tools/state-viewer/src/state_dump.rs +++ b/tools/state-viewer/src/state_dump.rs @@ -458,6 +458,7 @@ mod test { code: near_test_contracts::backwards_compatible_rs_contract().to_vec(), })], genesis_hash, + 0, ); let tx01 = SignedTransaction::stake( 1, diff --git a/tools/state-viewer/src/tx_dump.rs b/tools/state-viewer/src/tx_dump.rs index e69bee4d1a1..291f18f7f5c 100644 --- a/tools/state-viewer/src/tx_dump.rs +++ b/tools/state-viewer/src/tx_dump.rs @@ -35,6 +35,6 @@ fn should_include_signed_transaction( ) -> bool { match select_account_ids { None => true, - Some(specified_ids) => specified_ids.contains(&signed_transaction.transaction.receiver_id), + Some(specified_ids) => specified_ids.contains(signed_transaction.transaction.receiver_id()), } }