diff --git a/.changelog/unreleased/SDK/2315-tx-expiration-update.md b/.changelog/unreleased/SDK/2315-tx-expiration-update.md new file mode 100644 index 0000000000..058aa005f9 --- /dev/null +++ b/.changelog/unreleased/SDK/2315-tx-expiration-update.md @@ -0,0 +1,2 @@ +- Updated `gen_shielded_transfer` to attach a sensible expiration to a MASP + `Transaction`. ([\#2315](https://github.com/anoma/namada/pull/2315)) \ No newline at end of file diff --git a/.changelog/unreleased/improvements/2315-tx-expiration-update.md b/.changelog/unreleased/improvements/2315-tx-expiration-update.md new file mode 100644 index 0000000000..3259838811 --- /dev/null +++ b/.changelog/unreleased/improvements/2315-tx-expiration-update.md @@ -0,0 +1,2 @@ +- Improved validation on transaction's expiration. Added an expiration for MASP + transfers. ([\#2315](https://github.com/anoma/namada/pull/2315)) \ No newline at end of file diff --git a/apps/src/lib/node/ledger/shell/process_proposal.rs b/apps/src/lib/node/ledger/shell/process_proposal.rs index 4e7ec9d73a..5677e67fc0 100644 --- a/apps/src/lib/node/ledger/shell/process_proposal.rs +++ b/apps/src/lib/node/ledger/shell/process_proposal.rs @@ -546,11 +546,26 @@ where .into(), } } else { - TxResult { - code: ResultCode::Ok.into(), - info: "Process Proposal accepted this \ - transaction" - .into(), + match tx.header().expiration { + Some(tx_expiration) + if block_time > tx_expiration => + { + TxResult { + code: ResultCode::ExpiredDecryptedTx + .into(), + info: format!( + "Tx expired at {:#?}, block time: \ + {:#?}", + tx_expiration, block_time + ), + } + } + _ => TxResult { + code: ResultCode::Ok.into(), + info: "Process Proposal accepted this \ + transaction" + .into(), + }, } } } @@ -1751,6 +1766,55 @@ mod test_process_proposal { } } + /// Test that an expired decrypted transaction is marked as rejected but + /// still allows the block to be accepted + #[test] + fn test_expired_decrypted() { + let (mut shell, _recv, _, _) = test_utils::setup(); + let keypair = crate::wallet::defaults::daewon_keypair(); + + let mut wrapper = + Tx::from_type(TxType::Wrapper(Box::new(WrapperTx::new( + Fee { + amount_per_gas_unit: DenominatedAmount::native(1.into()), + token: shell.wl_storage.storage.native_token.clone(), + }, + keypair.ref_to(), + Epoch(0), + GAS_LIMIT_MULTIPLIER.into(), + None, + )))); + wrapper.header.chain_id = shell.chain_id.clone(); + wrapper.header.expiration = Some(DateTimeUtc::default()); + wrapper.set_code(Code::new("wasm_code".as_bytes().to_owned(), None)); + wrapper.set_data(Data::new("transaction data".as_bytes().to_owned())); + wrapper.add_section(Section::Signature(Signature::new( + wrapper.sechashes(), + [(0, keypair)].into_iter().collect(), + None, + ))); + + shell.enqueue_tx(wrapper.clone(), GAS_LIMIT_MULTIPLIER.into()); + + let decrypted = + wrapper.update_header(TxType::Decrypted(DecryptedTx::Decrypted)); + + // Run validation + let request = ProcessProposal { + txs: vec![decrypted.to_bytes()], + }; + match shell.process_proposal(request) { + Ok(txs) => { + assert_eq!(txs.len(), 1); + assert_eq!( + txs[0].result.code, + u32::from(ResultCode::ExpiredDecryptedTx) + ); + } + Err(_) => panic!("Test failed"), + } + } + /// Check that a tx requiring more gas than the block limit causes a block /// rejection #[test] diff --git a/core/src/types/transaction/mod.rs b/core/src/types/transaction/mod.rs index 1019b208d9..95b32b473f 100644 --- a/core/src/types/transaction/mod.rs +++ b/core/src/types/transaction/mod.rs @@ -84,6 +84,8 @@ pub enum ResultCode { InvalidVoteExtension = 13, /// Tx is too large TooLarge = 14, + /// Decrypted tx is expired + ExpiredDecryptedTx = 15, // ========================================================================= // WARN: These codes shouldn't be changed between version! } @@ -96,7 +98,7 @@ impl ResultCode { // NOTE: pattern match on all `ResultCode` variants, in order // to catch potential bugs when adding new codes match self { - Ok | WasmRuntimeError => true, + Ok | WasmRuntimeError | ExpiredDecryptedTx => true, InvalidTx | InvalidSig | InvalidOrder | ExtraTxs | Undecryptable | AllocationError | ReplayTx | InvalidChainId | ExpiredTx | TxGasLimit | FeeError | InvalidVoteExtension diff --git a/sdk/src/masp.rs b/sdk/src/masp.rs index 382296b783..576f311cb1 100644 --- a/sdk/src/masp.rs +++ b/sdk/src/masp.rs @@ -55,6 +55,7 @@ use namada_core::types::masp::{ TransferTarget, }; use namada_core::types::storage::{BlockHeight, Epoch, Key, KeySeg, TxIndex}; +use namada_core::types::time::{DateTimeUtc, DurationSecs}; use namada_core::types::token; use namada_core::types::token::{ Change, MaspDenom, Transfer, HEAD_TX_KEY, PIN_KEY_PREFIX, TX_KEY_PREFIX, @@ -1590,8 +1591,50 @@ impl ShieldedContext { }; // Now we build up the transaction within this object - let mut builder = - Builder::::new_with_rng(NETWORK, 1.into(), rng); + let expiration_height: u32 = match context.tx_builder().expiration { + Some(expiration) => { + // Try to match a DateTime expiration with a plausible + // corresponding block height + let last_block_height: u64 = + crate::rpc::query_block(context.client()) + .await? + .map_or_else(|| 1, |block| u64::from(block.height)); + let current_time = DateTimeUtc::now(); + let delta_time = + expiration.0.signed_duration_since(current_time.0); + + let max_expected_time_per_block_key = + namada_core::ledger::parameters::storage::get_max_expected_time_per_block_key(); + let max_block_time = + crate::rpc::query_storage_value::<_, DurationSecs>( + context.client(), + &max_expected_time_per_block_key, + ) + .await?; + + let delta_blocks = u32::try_from( + delta_time.num_seconds() / max_block_time.0 as i64, + ) + .map_err(|e| Error::Other(e.to_string()))?; + u32::try_from(last_block_height) + .map_err(|e| Error::Other(e.to_string()))? + + delta_blocks + } + None => { + // NOTE: The masp library doesn't support optional expiration so + // we set the max to mimic a never-expiring tx. We also need to + // remove 20 which is going to be added back by the builder + u32::MAX - 20 + } + }; + let mut builder = Builder::::new_with_rng( + NETWORK, + // NOTE: this is going to add 20 more blocks to the actual + // expiration but there's no other exposed function that we could + // use from the masp crate to specify the expiration better + expiration_height.into(), + rng, + ); // Convert transaction amount into MASP types let (asset_types, masp_amount) = diff --git a/sdk/src/wallet/mod.rs b/sdk/src/wallet/mod.rs index c69300052f..04d6d13796 100644 --- a/sdk/src/wallet/mod.rs +++ b/sdk/src/wallet/mod.rs @@ -683,8 +683,9 @@ impl Wallet { alias = format!("disposable_{ctr}"); } // Generate a disposable keypair to sign the wrapper if requested - // TODO: once the wrapper transaction has been accepted, this key can be - // deleted from wallet + // TODO: once the wrapper transaction has been applied, this key can be + // deleted from wallet (the transaction being accepted is not enough + // cause we could end up doing a rollback) let (alias, disposable_keypair) = self .gen_store_secret_key( SchemeType::Ed25519, diff --git a/test_fixtures/masp_proofs/30E148B3F9E8D21A41ABB09756027024E9AC79985302DD15C96CB57743A74CC3.bin b/test_fixtures/masp_proofs/28A7EA5FE79BA929443DE88963FFC7D83CE95D11AC98C8B9343E5EED170119A9.bin similarity index 74% rename from test_fixtures/masp_proofs/30E148B3F9E8D21A41ABB09756027024E9AC79985302DD15C96CB57743A74CC3.bin rename to test_fixtures/masp_proofs/28A7EA5FE79BA929443DE88963FFC7D83CE95D11AC98C8B9343E5EED170119A9.bin index fde4e2a7fa..dab2128885 100644 Binary files a/test_fixtures/masp_proofs/30E148B3F9E8D21A41ABB09756027024E9AC79985302DD15C96CB57743A74CC3.bin and b/test_fixtures/masp_proofs/28A7EA5FE79BA929443DE88963FFC7D83CE95D11AC98C8B9343E5EED170119A9.bin differ diff --git a/test_fixtures/masp_proofs/8BA2DA741BF1FE1CDEC5295AE3ECBE1A9EAF3496A30D69069DE2FBD293EEC978.bin b/test_fixtures/masp_proofs/2E68959DFE3412D892C1EB6A83C733C557AA7C18902CB851BB4DB93A834ED187.bin similarity index 72% rename from test_fixtures/masp_proofs/8BA2DA741BF1FE1CDEC5295AE3ECBE1A9EAF3496A30D69069DE2FBD293EEC978.bin rename to test_fixtures/masp_proofs/2E68959DFE3412D892C1EB6A83C733C557AA7C18902CB851BB4DB93A834ED187.bin index f12fd7b24f..d7589ef1fa 100644 Binary files a/test_fixtures/masp_proofs/8BA2DA741BF1FE1CDEC5295AE3ECBE1A9EAF3496A30D69069DE2FBD293EEC978.bin and b/test_fixtures/masp_proofs/2E68959DFE3412D892C1EB6A83C733C557AA7C18902CB851BB4DB93A834ED187.bin differ diff --git a/test_fixtures/masp_proofs/553C507BF748CC2353DCE98EB91B5464810F6974083CC2FEE2756ED1E97B8143.bin b/test_fixtures/masp_proofs/375F008787D3797A051D288892F6B0C21274416797B6508AE6C759537F947AC8.bin similarity index 80% rename from test_fixtures/masp_proofs/553C507BF748CC2353DCE98EB91B5464810F6974083CC2FEE2756ED1E97B8143.bin rename to test_fixtures/masp_proofs/375F008787D3797A051D288892F6B0C21274416797B6508AE6C759537F947AC8.bin index 674b3da69d..506df0e8de 100644 Binary files a/test_fixtures/masp_proofs/553C507BF748CC2353DCE98EB91B5464810F6974083CC2FEE2756ED1E97B8143.bin and b/test_fixtures/masp_proofs/375F008787D3797A051D288892F6B0C21274416797B6508AE6C759537F947AC8.bin differ diff --git a/test_fixtures/masp_proofs/F0471ECBD3AF04B4A373D2966781D5DEF92B9A9BB3A159947560514682CC3877.bin b/test_fixtures/masp_proofs/68DE980FCC7CC858B090D50340BAE37AFDAA28B0701ED5D313EA859FC8153343.bin similarity index 75% rename from test_fixtures/masp_proofs/F0471ECBD3AF04B4A373D2966781D5DEF92B9A9BB3A159947560514682CC3877.bin rename to test_fixtures/masp_proofs/68DE980FCC7CC858B090D50340BAE37AFDAA28B0701ED5D313EA859FC8153343.bin index 19d464857f..6c150f6d2c 100644 Binary files a/test_fixtures/masp_proofs/F0471ECBD3AF04B4A373D2966781D5DEF92B9A9BB3A159947560514682CC3877.bin and b/test_fixtures/masp_proofs/68DE980FCC7CC858B090D50340BAE37AFDAA28B0701ED5D313EA859FC8153343.bin differ diff --git a/test_fixtures/masp_proofs/4B412E2EA5AC98758E696AB36327E2CFFC5F8055CE2E2FAFB4DE8E7C2216D5F8.bin b/test_fixtures/masp_proofs/852AFF2FF8758999DA709605017C1886347E49C18C8E0F35D25956CA06390B17.bin similarity index 79% rename from test_fixtures/masp_proofs/4B412E2EA5AC98758E696AB36327E2CFFC5F8055CE2E2FAFB4DE8E7C2216D5F8.bin rename to test_fixtures/masp_proofs/852AFF2FF8758999DA709605017C1886347E49C18C8E0F35D25956CA06390B17.bin index 71fac439cc..80ce280428 100644 Binary files a/test_fixtures/masp_proofs/4B412E2EA5AC98758E696AB36327E2CFFC5F8055CE2E2FAFB4DE8E7C2216D5F8.bin and b/test_fixtures/masp_proofs/852AFF2FF8758999DA709605017C1886347E49C18C8E0F35D25956CA06390B17.bin differ diff --git a/test_fixtures/masp_proofs/C506FA6C2EFB37B06CD5A473AF5CC6F78791F8954A0219C07B15344AEE0D2E0F.bin b/test_fixtures/masp_proofs/9267939E4DFBF958BF98337A9099BB39683C7B8AAB924B267369B3143A3FBF89.bin similarity index 73% rename from test_fixtures/masp_proofs/C506FA6C2EFB37B06CD5A473AF5CC6F78791F8954A0219C07B15344AEE0D2E0F.bin rename to test_fixtures/masp_proofs/9267939E4DFBF958BF98337A9099BB39683C7B8AAB924B267369B3143A3FBF89.bin index 14228ec97b..57a0d2c390 100644 Binary files a/test_fixtures/masp_proofs/C506FA6C2EFB37B06CD5A473AF5CC6F78791F8954A0219C07B15344AEE0D2E0F.bin and b/test_fixtures/masp_proofs/9267939E4DFBF958BF98337A9099BB39683C7B8AAB924B267369B3143A3FBF89.bin differ diff --git a/test_fixtures/masp_proofs/60C29BD5C1B461533ECD82F3A0A71E2A0FD100F99D737415E6D9125F5A7046D4.bin b/test_fixtures/masp_proofs/94DF56F3CCC7E6F588F0CB82C2ABE40E759AD9C4F4F6475A419BFD56CE76BA68.bin similarity index 69% rename from test_fixtures/masp_proofs/60C29BD5C1B461533ECD82F3A0A71E2A0FD100F99D737415E6D9125F5A7046D4.bin rename to test_fixtures/masp_proofs/94DF56F3CCC7E6F588F0CB82C2ABE40E759AD9C4F4F6475A419BFD56CE76BA68.bin index b018e93ecb..a139159fa4 100644 Binary files a/test_fixtures/masp_proofs/60C29BD5C1B461533ECD82F3A0A71E2A0FD100F99D737415E6D9125F5A7046D4.bin and b/test_fixtures/masp_proofs/94DF56F3CCC7E6F588F0CB82C2ABE40E759AD9C4F4F6475A419BFD56CE76BA68.bin differ diff --git a/test_fixtures/masp_proofs/15532D31AA5AD33E5557378544DE72EFEA51E775954A8230E3ADD9CDB4E75B23.bin b/test_fixtures/masp_proofs/A2385FC511BDA00B7E8605BF05958D4A1929918AB0A43EEAE93AE8BBC515E18C.bin similarity index 74% rename from test_fixtures/masp_proofs/15532D31AA5AD33E5557378544DE72EFEA51E775954A8230E3ADD9CDB4E75B23.bin rename to test_fixtures/masp_proofs/A2385FC511BDA00B7E8605BF05958D4A1929918AB0A43EEAE93AE8BBC515E18C.bin index a0042ed1ad..dba4c4a242 100644 Binary files a/test_fixtures/masp_proofs/15532D31AA5AD33E5557378544DE72EFEA51E775954A8230E3ADD9CDB4E75B23.bin and b/test_fixtures/masp_proofs/A2385FC511BDA00B7E8605BF05958D4A1929918AB0A43EEAE93AE8BBC515E18C.bin differ diff --git a/test_fixtures/masp_proofs/BB9AA71A4227C9E62948CBA8DB4A5C2232840271F032F756953233DB3E53E757.bin b/test_fixtures/masp_proofs/AA4BBAF45B9610AD4D2BCBDDF61E860D9B5DF041F4645BFC329BE9A03AABFE47.bin similarity index 76% rename from test_fixtures/masp_proofs/BB9AA71A4227C9E62948CBA8DB4A5C2232840271F032F756953233DB3E53E757.bin rename to test_fixtures/masp_proofs/AA4BBAF45B9610AD4D2BCBDDF61E860D9B5DF041F4645BFC329BE9A03AABFE47.bin index 8415f24762..c368a61e3e 100644 Binary files a/test_fixtures/masp_proofs/BB9AA71A4227C9E62948CBA8DB4A5C2232840271F032F756953233DB3E53E757.bin and b/test_fixtures/masp_proofs/AA4BBAF45B9610AD4D2BCBDDF61E860D9B5DF041F4645BFC329BE9A03AABFE47.bin differ diff --git a/test_fixtures/masp_proofs/473EDF0B2908F047110AC52C7F7ECD8CFD237A237C63AA565FC44893414EE7FC.bin b/test_fixtures/masp_proofs/D32DFDE8713AB8AAD01125856B8F934075535EBBEC567084302C3D9B469B83FA.bin similarity index 76% rename from test_fixtures/masp_proofs/473EDF0B2908F047110AC52C7F7ECD8CFD237A237C63AA565FC44893414EE7FC.bin rename to test_fixtures/masp_proofs/D32DFDE8713AB8AAD01125856B8F934075535EBBEC567084302C3D9B469B83FA.bin index ca0a828092..a5ec743370 100644 Binary files a/test_fixtures/masp_proofs/473EDF0B2908F047110AC52C7F7ECD8CFD237A237C63AA565FC44893414EE7FC.bin and b/test_fixtures/masp_proofs/D32DFDE8713AB8AAD01125856B8F934075535EBBEC567084302C3D9B469B83FA.bin differ diff --git a/test_fixtures/masp_proofs/DEDF664AD06184041515677A72699E65D4B40A4E1BC9E7A32D63CF28466A2F20.bin b/test_fixtures/masp_proofs/DA1D4780CBA612D7CBA0004D16FF5FEC42C100CEB0B19DC6C47DBFE88D42FFFC.bin similarity index 72% rename from test_fixtures/masp_proofs/DEDF664AD06184041515677A72699E65D4B40A4E1BC9E7A32D63CF28466A2F20.bin rename to test_fixtures/masp_proofs/DA1D4780CBA612D7CBA0004D16FF5FEC42C100CEB0B19DC6C47DBFE88D42FFFC.bin index f1f8461139..9ed88be93f 100644 Binary files a/test_fixtures/masp_proofs/DEDF664AD06184041515677A72699E65D4B40A4E1BC9E7A32D63CF28466A2F20.bin and b/test_fixtures/masp_proofs/DA1D4780CBA612D7CBA0004D16FF5FEC42C100CEB0B19DC6C47DBFE88D42FFFC.bin differ diff --git a/test_fixtures/masp_proofs/978C35E058808D61F0E265D72DE8DD6A8E6226394EA6E3DFE1CFC10F69C0ACE0.bin b/test_fixtures/masp_proofs/DC5FEEE0E4971DF2083A9D17D645FC957F905749C47816C307B4B8D580DAE5D9.bin similarity index 78% rename from test_fixtures/masp_proofs/978C35E058808D61F0E265D72DE8DD6A8E6226394EA6E3DFE1CFC10F69C0ACE0.bin rename to test_fixtures/masp_proofs/DC5FEEE0E4971DF2083A9D17D645FC957F905749C47816C307B4B8D580DAE5D9.bin index e61f6b714e..b502e0a0bf 100644 Binary files a/test_fixtures/masp_proofs/978C35E058808D61F0E265D72DE8DD6A8E6226394EA6E3DFE1CFC10F69C0ACE0.bin and b/test_fixtures/masp_proofs/DC5FEEE0E4971DF2083A9D17D645FC957F905749C47816C307B4B8D580DAE5D9.bin differ diff --git a/test_fixtures/masp_proofs/4CCB9ADD3188CD893508CBB4FCB62D08DAA52F4DE496209BDAEFD36E75EAE98D.bin b/test_fixtures/masp_proofs/E3409A9853B0ECDBE4147AD52CF288D9729C50CA4AE4D1635C6D82007461517F.bin similarity index 79% rename from test_fixtures/masp_proofs/4CCB9ADD3188CD893508CBB4FCB62D08DAA52F4DE496209BDAEFD36E75EAE98D.bin rename to test_fixtures/masp_proofs/E3409A9853B0ECDBE4147AD52CF288D9729C50CA4AE4D1635C6D82007461517F.bin index 956da9a414..d0fc8f7171 100644 Binary files a/test_fixtures/masp_proofs/4CCB9ADD3188CD893508CBB4FCB62D08DAA52F4DE496209BDAEFD36E75EAE98D.bin and b/test_fixtures/masp_proofs/E3409A9853B0ECDBE4147AD52CF288D9729C50CA4AE4D1635C6D82007461517F.bin differ diff --git a/test_fixtures/masp_proofs/AE4CEC9192B52E8CE5AB0C25936D2AEEF55A6F202D8EB4564017DB5BEF872107.bin b/test_fixtures/masp_proofs/E93FF3062E6FCF83381BEE364347FA3E6D650FE0B00B7DF477B409EEADFE64C8.bin similarity index 77% rename from test_fixtures/masp_proofs/AE4CEC9192B52E8CE5AB0C25936D2AEEF55A6F202D8EB4564017DB5BEF872107.bin rename to test_fixtures/masp_proofs/E93FF3062E6FCF83381BEE364347FA3E6D650FE0B00B7DF477B409EEADFE64C8.bin index 4b507a1956..93c04891d7 100644 Binary files a/test_fixtures/masp_proofs/AE4CEC9192B52E8CE5AB0C25936D2AEEF55A6F202D8EB4564017DB5BEF872107.bin and b/test_fixtures/masp_proofs/E93FF3062E6FCF83381BEE364347FA3E6D650FE0B00B7DF477B409EEADFE64C8.bin differ diff --git a/test_fixtures/masp_proofs/D007D1734AD42D34174F04566899481AB5F7C8F57502C5EAB2BF7594EA6CED8F.bin b/test_fixtures/masp_proofs/ECBEE7807835F2DF39FA2924DC51842690C36EA86369DC2145AED8B139748042.bin similarity index 77% rename from test_fixtures/masp_proofs/D007D1734AD42D34174F04566899481AB5F7C8F57502C5EAB2BF7594EA6CED8F.bin rename to test_fixtures/masp_proofs/ECBEE7807835F2DF39FA2924DC51842690C36EA86369DC2145AED8B139748042.bin index 4e2cbaabe4..aa956f7ebd 100644 Binary files a/test_fixtures/masp_proofs/D007D1734AD42D34174F04566899481AB5F7C8F57502C5EAB2BF7594EA6CED8F.bin and b/test_fixtures/masp_proofs/ECBEE7807835F2DF39FA2924DC51842690C36EA86369DC2145AED8B139748042.bin differ