Skip to content

Commit

Permalink
Merge branch 'grarco/tx-lifetime' (#1123)
Browse files Browse the repository at this point in the history
* grarco/tx-lifetime:
  changelog: add #1123
  [ci] wasm checksums update
  Misc adjustments
  Refactors `prepare_proposal` tx validation
  Refactors block time retrieval
  Clippy + fmt
  Tx expiration check in `prepare_proposal`. Unit test
  Improves tx expiration checks. Adds unit tests
  Tx expiration validation
  Updates client for tx expiration
  Adds `expiration` field to `Tx`
  Wrapper `epoch` in replay protection specs
  • Loading branch information
tzemanovic committed Apr 7, 2023
2 parents 909f11a + 76ad54b commit de1d07b
Show file tree
Hide file tree
Showing 31 changed files with 619 additions and 149 deletions.
2 changes: 2 additions & 0 deletions .changelog/unreleased/features/1123-tx-lifetime.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Adds expiration field to transactions
([#1123](https://github.com/anoma/namada/pull/1123))
11 changes: 11 additions & 0 deletions apps/src/lib/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1620,6 +1620,7 @@ pub mod args {
const DRY_RUN_TX: ArgFlag = flag("dry-run");
const DUMP_TX: ArgFlag = flag("dump-tx");
const EPOCH: ArgOpt<Epoch> = arg_opt("epoch");
const EXPIRATION_OPT: ArgOpt<DateTimeUtc> = arg_opt("expiration");
const FORCE: ArgFlag = flag("force");
const DONT_PREFETCH_WASM: ArgFlag = flag("dont-prefetch-wasm");
const GAS_AMOUNT: ArgDefault<token::Amount> =
Expand Down Expand Up @@ -2897,6 +2898,8 @@ pub mod args {
pub fee_token: WalletAddress,
/// The max amount of gas used to process tx
pub gas_limit: GasLimit,
/// The optional expiration of the transaction
pub expiration: Option<DateTimeUtc>,
/// Sign the tx with the key for the given alias from your wallet
pub signing_key: Option<WalletKeypair>,
/// Sign the tx with the keypair of the public key of the given address
Expand Down Expand Up @@ -2963,6 +2966,12 @@ pub mod args {
"The maximum amount of gas needed to run transaction",
),
)
.arg(EXPIRATION_OPT.def().about(
"The expiration datetime of the transaction, after which the \
tx won't be accepted anymore. All of these examples are \
equivalent:\n2012-12-12T12:12:12Z\n2012-12-12 \
12:12:12Z\n2012- 12-12T12: 12:12Z",
))
.arg(
SIGNING_KEY_OPT
.def()
Expand Down Expand Up @@ -2994,6 +3003,7 @@ pub mod args {
let fee_amount = GAS_AMOUNT.parse(matches);
let fee_token = GAS_TOKEN.parse(matches);
let gas_limit = GAS_LIMIT.parse(matches).into();
let expiration = EXPIRATION_OPT.parse(matches);

let signing_key = SIGNING_KEY_OPT.parse(matches);
let signer = SIGNER.parse(matches);
Expand All @@ -3007,6 +3017,7 @@ pub mod args {
fee_amount,
fee_token,
gas_limit,
expiration,
signing_key,
signer,
}
Expand Down
2 changes: 1 addition & 1 deletion apps/src/lib/client/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ pub async fn query_tx_deltas(
let mut transfer = None;
extract_payload(tx, &mut wrapper, &mut transfer);
// Epoch data is not needed for transparent transactions
let epoch = wrapper.map(|x| x.epoch).unwrap_or_default();
let epoch = Epoch::default();
if let Some(transfer) = transfer {
// Skip MASP addresses as they are already handled by
// ShieldedContext
Expand Down
4 changes: 2 additions & 2 deletions apps/src/lib/client/signing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@

use borsh::BorshSerialize;
use namada::ledger::parameters::storage as parameter_storage;
use namada::proof_of_stake::Epoch;
use namada::proto::Tx;
use namada::types::address::{Address, ImplicitAddress};
use namada::types::hash::Hash;
use namada::types::key::*;
use namada::types::storage::Epoch;
use namada::types::token;
use namada::types::token::Amount;
use namada::types::transaction::{hash_tx, Fee, WrapperTx, MIN_FEE};
Expand Down Expand Up @@ -310,7 +310,7 @@ pub async fn sign_wrapper(
let decrypted_hash = tx.tx_hash.to_string();
TxBroadcastData::Wrapper {
tx: tx
.sign(keypair, ctx.config.ledger.chain_id.clone())
.sign(keypair, ctx.config.ledger.chain_id.clone(), args.expiration)
.expect("Wrapper tx signing keypair should be correct"),
wrapper_hash,
decrypted_hash,
Expand Down
81 changes: 68 additions & 13 deletions apps/src/lib/client/tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,12 @@ pub async fn submit_custom(ctx: Context, args: args::TxCustom) {
let data = args.data_path.map(|data_path| {
std::fs::read(data_path).expect("Expected a file at given data path")
});
let tx = Tx::new(tx_code, data, ctx.config.ledger.chain_id.clone());
let tx = Tx::new(
tx_code,
data,
ctx.config.ledger.chain_id.clone(),
args.tx.expiration,
);
let (ctx, initialized_accounts) = process_tx(
ctx,
&args.tx,
Expand Down Expand Up @@ -170,7 +175,12 @@ pub async fn submit_update_vp(ctx: Context, args: args::TxUpdateVp) {
let data = UpdateVp { addr, vp_code };
let data = data.try_to_vec().expect("Encoding tx data shouldn't fail");

let tx = Tx::new(tx_code, Some(data), ctx.config.ledger.chain_id.clone());
let tx = Tx::new(
tx_code,
Some(data),
ctx.config.ledger.chain_id.clone(),
args.tx.expiration,
);
process_tx(
ctx,
&args.tx,
Expand Down Expand Up @@ -203,7 +213,12 @@ pub async fn submit_init_account(mut ctx: Context, args: args::TxInitAccount) {
};
let data = data.try_to_vec().expect("Encoding tx data shouldn't fail");

let tx = Tx::new(tx_code, Some(data), ctx.config.ledger.chain_id.clone());
let tx = Tx::new(
tx_code,
Some(data),
ctx.config.ledger.chain_id.clone(),
args.tx.expiration,
);
let (ctx, initialized_accounts) = process_tx(
ctx,
&args.tx,
Expand Down Expand Up @@ -336,7 +351,12 @@ pub async fn submit_init_validator(
validator_vp_code,
};
let data = data.try_to_vec().expect("Encoding tx data shouldn't fail");
let tx = Tx::new(tx_code, Some(data), ctx.config.ledger.chain_id.clone());
let tx = Tx::new(
tx_code,
Some(data),
ctx.config.ledger.chain_id.clone(),
tx_args.expiration,
);
let (mut ctx, initialized_accounts) = process_tx(
ctx,
&tx_args,
Expand Down Expand Up @@ -1678,7 +1698,12 @@ pub async fn submit_transfer(mut ctx: Context, args: args::TxTransfer) {
.try_to_vec()
.expect("Encoding tx data shouldn't fail");
let tx_code = ctx.read_wasm(TX_TRANSFER_WASM);
let tx = Tx::new(tx_code, Some(data), ctx.config.ledger.chain_id.clone());
let tx = Tx::new(
tx_code,
Some(data),
ctx.config.ledger.chain_id.clone(),
args.tx.expiration,
);
let signing_address = TxSigningKey::WalletAddress(args.source.to_address());

process_tx(
Expand Down Expand Up @@ -1798,7 +1823,12 @@ pub async fn submit_ibc_transfer(ctx: Context, args: args::TxIbcTransfer) {
prost::Message::encode(&any_msg, &mut data)
.expect("Encoding tx data shouldn't fail");

let tx = Tx::new(tx_code, Some(data), ctx.config.ledger.chain_id.clone());
let tx = Tx::new(
tx_code,
Some(data),
ctx.config.ledger.chain_id.clone(),
args.tx.expiration,
);
process_tx(
ctx,
&args.tx,
Expand Down Expand Up @@ -1943,8 +1973,12 @@ pub async fn submit_init_proposal(mut ctx: Context, args: args::InitProposal) {
.try_to_vec()
.expect("Encoding proposal data shouldn't fail");
let tx_code = ctx.read_wasm(TX_INIT_PROPOSAL);
let tx =
Tx::new(tx_code, Some(data), ctx.config.ledger.chain_id.clone());
let tx = Tx::new(
tx_code,
Some(data),
ctx.config.ledger.chain_id.clone(),
args.tx.expiration,
);

process_tx(
ctx,
Expand Down Expand Up @@ -2199,6 +2233,7 @@ pub async fn submit_vote_proposal(mut ctx: Context, args: args::VoteProposal) {
tx_code,
Some(data),
ctx.config.ledger.chain_id.clone(),
args.tx.expiration,
);

process_tx(
Expand Down Expand Up @@ -2272,7 +2307,7 @@ pub async fn submit_reveal_pk_aux(
.expect("Encoding a public key shouldn't fail");
let tx_code = ctx.read_wasm(TX_REVEAL_PK);
let chain_id = ctx.config.ledger.chain_id.clone();
let tx = Tx::new(tx_code, Some(tx_data), chain_id);
let tx = Tx::new(tx_code, Some(tx_data), chain_id, args.expiration);

// submit_tx without signing the inner tx
let keypair = if let Some(signing_key) = &args.signing_key {
Expand Down Expand Up @@ -2475,7 +2510,12 @@ pub async fn submit_bond(ctx: Context, args: args::Bond) {
};
let data = bond.try_to_vec().expect("Encoding tx data shouldn't fail");

let tx = Tx::new(tx_code, Some(data), ctx.config.ledger.chain_id.clone());
let tx = Tx::new(
tx_code,
Some(data),
ctx.config.ledger.chain_id.clone(),
args.tx.expiration,
);
let default_signer = args.source.unwrap_or(args.validator);
process_tx(
ctx,
Expand Down Expand Up @@ -2530,7 +2570,12 @@ pub async fn submit_unbond(ctx: Context, args: args::Unbond) {
let data = data.try_to_vec().expect("Encoding tx data shouldn't fail");

let tx_code = ctx.read_wasm(TX_UNBOND_WASM);
let tx = Tx::new(tx_code, Some(data), ctx.config.ledger.chain_id.clone());
let tx = Tx::new(
tx_code,
Some(data),
ctx.config.ledger.chain_id.clone(),
args.tx.expiration,
);
let default_signer = args.source.unwrap_or(args.validator);
let (_ctx, _) = process_tx(
ctx,
Expand Down Expand Up @@ -2595,7 +2640,12 @@ pub async fn submit_withdraw(ctx: Context, args: args::Withdraw) {
let data = data.try_to_vec().expect("Encoding tx data shouldn't fail");

let tx_code = ctx.read_wasm(TX_WITHDRAW_WASM);
let tx = Tx::new(tx_code, Some(data), ctx.config.ledger.chain_id.clone());
let tx = Tx::new(
tx_code,
Some(data),
ctx.config.ledger.chain_id.clone(),
args.tx.expiration,
);
let default_signer = args.source.unwrap_or(args.validator);
process_tx(
ctx,
Expand Down Expand Up @@ -2681,7 +2731,12 @@ pub async fn submit_validator_commission_change(
};
let data = data.try_to_vec().expect("Encoding tx data shouldn't fail");

let tx = Tx::new(tx_code, Some(data), ctx.config.ledger.chain_id.clone());
let tx = Tx::new(
tx_code,
Some(data),
ctx.config.ledger.chain_id.clone(),
args.tx.expiration,
);
let default_signer = args.validator;
process_tx(
ctx,
Expand Down
9 changes: 7 additions & 2 deletions apps/src/lib/node/ledger/shell/finalize_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -941,6 +941,7 @@ mod test_finalize_block {
"wasm_code".as_bytes().to_owned(),
Some(format!("transaction data: {}", i).as_bytes().to_owned()),
shell.chain_id.clone(),
None,
);
let wrapper = WrapperTx::new(
Fee {
Expand All @@ -956,7 +957,7 @@ mod test_finalize_block {
None,
);
let tx = wrapper
.sign(&keypair, shell.chain_id.clone())
.sign(&keypair, shell.chain_id.clone(), None)
.expect("Test failed");
if i > 1 {
processed_txs.push(ProcessedTx {
Expand Down Expand Up @@ -1017,6 +1018,7 @@ mod test_finalize_block {
"wasm_code".as_bytes().to_owned(),
Some(String::from("transaction data").as_bytes().to_owned()),
shell.chain_id.clone(),
None,
);
let wrapper = WrapperTx::new(
Fee {
Expand Down Expand Up @@ -1152,6 +1154,7 @@ mod test_finalize_block {
.to_owned(),
),
shell.chain_id.clone(),
None,
);
let wrapper_tx = WrapperTx::new(
Fee {
Expand Down Expand Up @@ -1190,6 +1193,7 @@ mod test_finalize_block {
.to_owned(),
),
shell.chain_id.clone(),
None,
);
let wrapper_tx = WrapperTx::new(
Fee {
Expand All @@ -1205,7 +1209,7 @@ mod test_finalize_block {
None,
);
let wrapper = wrapper_tx
.sign(&keypair, shell.chain_id.clone())
.sign(&keypair, shell.chain_id.clone(), None)
.expect("Test failed");
valid_txs.push(wrapper_tx);
processed_txs.push(ProcessedTx {
Expand Down Expand Up @@ -1698,6 +1702,7 @@ mod test_finalize_block {
tx_code,
Some("Encrypted transaction data".as_bytes().to_owned()),
shell.chain_id.clone(),
None,
);
let wrapper_tx = WrapperTx::new(
Fee {
Expand Down
1 change: 1 addition & 0 deletions apps/src/lib/node/ledger/shell/governance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ where
proposal_code,
Some(encode(&id)),
shell.chain_id.clone(),
None,
);
let tx_type = TxType::Decrypted(DecryptedTx::Decrypted {
tx,
Expand Down
Loading

0 comments on commit de1d07b

Please sign in to comment.