diff --git a/.changelog/unreleased/testing/3401-test-batch-tx-events.md b/.changelog/unreleased/testing/3401-test-batch-tx-events.md new file mode 100644 index 0000000000..cf1c7ce7ef --- /dev/null +++ b/.changelog/unreleased/testing/3401-test-batch-tx-events.md @@ -0,0 +1,3 @@ +- Adds additional test coverage to batch tx events emission, to make + sure we correctly build a batch of inner tx events from a batched tx. + ([\#3401](https://github.com/anoma/namada/pull/3401)) \ No newline at end of file diff --git a/crates/node/src/shell/finalize_block.rs b/crates/node/src/shell/finalize_block.rs index 7adbcd17ba..e2599edd46 100644 --- a/crates/node/src/shell/finalize_block.rs +++ b/crates/node/src/shell/finalize_block.rs @@ -5796,4 +5796,165 @@ mod test_finalize_block { assert!(!shell.state.has_key(&key.parse().unwrap()).unwrap()); } } + + #[test] + fn test_multiple_events_from_batch_tx_all_valid() { + let (mut shell, _, _, _) = setup(); + + let sk = wallet::defaults::bertha_keypair(); + + let batch_tx = { + let mut batch = + Tx::from_type(TxType::Wrapper(Box::new(WrapperTx::new( + Fee { + amount_per_gas_unit: DenominatedAmount::native( + 1.into(), + ), + token: shell.state.in_mem().native_token.clone(), + }, + sk.ref_to(), + WRAPPER_GAS_LIMIT.into(), + )))); + batch.header.chain_id = shell.chain_id.clone(); + batch.header.atomic = false; + + // append first inner tx to batch + batch.set_code(Code::new(TestWasms::TxNoOp.read_bytes(), None)); + batch.set_data(Data::new("bing".as_bytes().to_owned())); + + // append second inner tx to batch + batch.push_default_inner_tx(); + + batch.set_code(Code::new(TestWasms::TxNoOp.read_bytes(), None)); + batch.set_data(Data::new("bong".as_bytes().to_owned())); + + // sign the batch of txs + batch.sign_raw( + vec![sk.clone()], + vec![sk.ref_to()].into_iter().collect(), + None, + ); + batch.sign_wrapper(sk); + + batch + }; + + let processed_txs = vec![ProcessedTx { + tx: batch_tx.to_bytes().into(), + result: TxResult { + code: ResultCode::Ok.into(), + info: "".into(), + }, + }]; + + let mut events = shell + .finalize_block(FinalizeBlock { + txs: processed_txs, + ..Default::default() + }) + .expect("Test failed"); + + // one top level event + assert_eq!(events.len(), 1); + let event = events.remove(0); + + // multiple tx results (2) + let tx_results = event.read_attribute::>().unwrap(); + assert_eq!(tx_results.batch_results.0.len(), 2); + + // all txs should have succeeded + assert!( + tx_results + .batch_results + .0 + .values() + .all(|result| result.is_ok()) + ); + } + + #[test] + fn test_multiple_events_from_batch_tx_one_valid_other_invalid() { + let (mut shell, _, _, _) = setup(); + + let sk = wallet::defaults::bertha_keypair(); + + let batch_tx = { + let mut batch = + Tx::from_type(TxType::Wrapper(Box::new(WrapperTx::new( + Fee { + amount_per_gas_unit: DenominatedAmount::native( + 1.into(), + ), + token: shell.state.in_mem().native_token.clone(), + }, + sk.ref_to(), + WRAPPER_GAS_LIMIT.into(), + )))); + batch.header.chain_id = shell.chain_id.clone(); + batch.header.atomic = false; + + // append first inner tx to batch (this one is valid) + batch.set_code(Code::new(TestWasms::TxNoOp.read_bytes(), None)); + batch.set_data(Data::new("bing".as_bytes().to_owned())); + + // append second inner tx to batch (this one is invalid, because + // we pass the wrong data) + batch.push_default_inner_tx(); + + batch.set_code(Code::new( + TestWasms::TxWriteStorageKey.read_bytes(), + None, + )); + batch.set_data(Data::new("bong".as_bytes().to_owned())); + + // sign the batch of txs + batch.sign_raw( + vec![sk.clone()], + vec![sk.ref_to()].into_iter().collect(), + None, + ); + batch.sign_wrapper(sk); + + batch + }; + + let processed_txs = vec![ProcessedTx { + tx: batch_tx.to_bytes().into(), + result: TxResult { + code: ResultCode::Ok.into(), + info: "".into(), + }, + }]; + + let mut events = shell + .finalize_block(FinalizeBlock { + txs: processed_txs, + ..Default::default() + }) + .expect("Test failed"); + + // one top level event + assert_eq!(events.len(), 1); + let event = events.remove(0); + + // multiple tx results (2) + let tx_results = event.read_attribute::>().unwrap(); + assert_eq!(tx_results.batch_results.0.len(), 2); + + // check one succeeded and the other failed + assert!( + tx_results + .batch_results + .0 + .values() + .any(|result| result.is_ok()) + ); + assert!( + tx_results + .batch_results + .0 + .values() + .any(|result| result.is_err()) + ); + } } diff --git a/crates/tx/src/data/mod.rs b/crates/tx/src/data/mod.rs index 20c4019fc2..d0fcd218d0 100644 --- a/crates/tx/src/data/mod.rs +++ b/crates/tx/src/data/mod.rs @@ -258,7 +258,6 @@ impl Default for ExtendedTxResult { } /// Transaction application result -// TODO derive BorshSchema after #[derive( Clone, Debug, BorshSerialize, BorshDeserialize, Serialize, Deserialize, )]