Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Reworked the signature of inner transactions to improve safety and fix replay
protection. ([\#1867](https://github.com/anoma/namada/pull/1867))
26 changes: 8 additions & 18 deletions apps/src/lib/node/ledger/shell/finalize_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,9 +213,7 @@ where
.pop()
.expect("Missing wrapper tx in queue")
.tx
.clone()
.update_header(TxType::Raw)
.header_hash();
.raw_header_hash();
let tx_hash_key =
replay_protection::get_replay_protection_key(&tx_hash);
self.wl_storage
Expand Down Expand Up @@ -276,7 +274,7 @@ where
continue;
}

let (mut tx_event, tx_unsigned_hash, mut tx_gas_meter, wrapper) =
let (mut tx_event, tx_header_hash, mut tx_gas_meter, wrapper) =
match &tx_header.tx_type {
TxType::Wrapper(wrapper) => {
stats.increment_wrapper_txs();
Expand All @@ -286,7 +284,7 @@ where
}
TxType::Decrypted(inner) => {
// We remove the corresponding wrapper tx from the queue
let mut tx_in_queue = self
let tx_in_queue = self
.wl_storage
.storage
.tx_queue
Expand Down Expand Up @@ -323,12 +321,7 @@ where

(
event,
Some(
tx_in_queue
.tx
.update_header(TxType::Raw)
.header_hash(),
),
Some(tx_in_queue.tx.raw_header_hash()),
TxGasMeter::new_from_sub_limit(tx_in_queue.gas),
None,
)
Expand Down Expand Up @@ -511,7 +504,7 @@ where
// If transaction type is Decrypted and failed because of
// out of gas, remove its hash from storage to allow
// rewrapping it
if let Some(hash) = tx_unsigned_hash {
if let Some(hash) = tx_header_hash {
if let Error::TxApply(protocol::Error::GasError(_)) =
msg
{
Expand Down Expand Up @@ -2272,11 +2265,8 @@ mod test_finalize_block {
let wrapper_hash_key = replay_protection::get_replay_protection_key(
&wrapper_tx.header_hash(),
);
let mut decrypted_tx = wrapper_tx;

decrypted_tx.update_header(TxType::Raw);
let decrypted_hash_key = replay_protection::get_replay_protection_key(
&decrypted_tx.header_hash(),
&wrapper_tx.raw_header_hash(),
);

// merkle tree root before finalize_block
Expand Down Expand Up @@ -2362,7 +2352,7 @@ mod test_finalize_block {

// Write inner hash in storage
let inner_hash_key = replay_protection::get_replay_protection_key(
&wrapper_tx.clone().update_header(TxType::Raw).header_hash(),
&wrapper_tx.raw_header_hash(),
);
shell
.wl_storage
Expand Down Expand Up @@ -2439,7 +2429,7 @@ mod test_finalize_block {
&wrapper.header_hash(),
);
let inner_hash_key = replay_protection::get_replay_protection_key(
&wrapper.clone().update_header(TxType::Raw).header_hash(),
&wrapper.raw_header_hash(),
);

let processed_tx = ProcessedTx {
Expand Down
63 changes: 24 additions & 39 deletions apps/src/lib/node/ledger/shell/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,22 +146,19 @@ impl From<Error> for TxResult {
#[derive(Debug, Copy, Clone, FromPrimitive, ToPrimitive, PartialEq, Eq)]
pub enum ErrorCodes {
Ok = 0,
InvalidDecryptedChainId = 1,
ExpiredDecryptedTx = 2,
DecryptedTxGasLimit = 3,
WasmRuntimeError = 4,
InvalidTx = 5,
InvalidSig = 6,
InvalidOrder = 7,
ExtraTxs = 8,
Undecryptable = 9,
AllocationError = 10,
ReplayTx = 11,
InvalidChainId = 12,
ExpiredTx = 13,
TxGasLimit = 14,
FeeError = 15,
InvalidVoteExtension = 16,
WasmRuntimeError = 1,
InvalidTx = 2,
InvalidSig = 3,
InvalidOrder = 4,
ExtraTxs = 5,
Undecryptable = 6,
AllocationError = 7,
ReplayTx = 8,
InvalidChainId = 9,
ExpiredTx = 10,
TxGasLimit = 11,
FeeError = 12,
InvalidVoteExtension = 13,
}

impl ErrorCodes {
Expand All @@ -172,11 +169,7 @@ impl ErrorCodes {
// NOTE: pattern match on all `ErrorCodes` variants, in order
// to catch potential bugs when adding new codes
match self {
Ok
| InvalidDecryptedChainId
| ExpiredDecryptedTx
| WasmRuntimeError
| DecryptedTxGasLimit => true,
Ok | WasmRuntimeError => true,
InvalidTx | InvalidSig | InvalidOrder | ExtraTxs
| Undecryptable | AllocationError | ReplayTx | InvalidChainId
| ExpiredTx | TxGasLimit | FeeError | InvalidVoteExtension => false,
Expand Down Expand Up @@ -929,11 +922,9 @@ where
pub fn replay_protection_checks(
&self,
wrapper: &Tx,
tx_bytes: &[u8],
temp_wl_storage: &mut TempWlStorage<D, H>,
) -> Result<()> {
let inner_tx_hash =
wrapper.clone().update_header(TxType::Raw).header_hash();
let inner_tx_hash = wrapper.raw_header_hash();
let inner_hash_key =
replay_protection::get_replay_protection_key(&inner_tx_hash);
if temp_wl_storage
Expand All @@ -952,9 +943,7 @@ where
.write(&inner_hash_key, vec![])
.expect("Couldn't write inner transaction hash to write log");

let tx =
Tx::try_from(tx_bytes).expect("Deserialization shouldn't fail");
let wrapper_hash = tx.header_hash();
let wrapper_hash = wrapper.header_hash();
let wrapper_hash_key =
replay_protection::get_replay_protection_key(&wrapper_hash);
if temp_wl_storage
Expand Down Expand Up @@ -1089,22 +1078,19 @@ where
}
};

let tx_chain_id = tx.header.chain_id.clone();
let tx_expiration = tx.header.expiration;

// Tx chain id
if tx_chain_id != self.chain_id {
if tx.header.chain_id != self.chain_id {
response.code = ErrorCodes::InvalidChainId.into();
response.log = format!(
"{INVALID_MSG}: Tx carries a wrong chain id: expected {}, \
found {}",
self.chain_id, tx_chain_id
self.chain_id, tx.header.chain_id
);
return response;
}

// Tx expiration
if let Some(exp) = tx_expiration {
if let Some(exp) = tx.header.expiration {
let last_block_timestamp = self.get_block_timestamp(None);

if last_block_timestamp > exp {
Expand Down Expand Up @@ -1263,11 +1249,11 @@ where
}

// Replay protection check
let mut inner_tx = tx;
inner_tx.update_header(TxType::Raw);
let inner_tx_hash = &inner_tx.header_hash();
let inner_tx_hash = tx.raw_header_hash();
let inner_hash_key =
replay_protection::get_replay_protection_key(inner_tx_hash);
replay_protection::get_replay_protection_key(
&inner_tx_hash,
);
if self
.wl_storage
.storage
Expand Down Expand Up @@ -2502,8 +2488,7 @@ mod tests {
)
);

let inner_tx_hash =
wrapper.clone().update_header(TxType::Raw).header_hash();
let inner_tx_hash = wrapper.raw_header_hash();
// Write inner hash in storage
let inner_hash_key =
replay_protection::get_replay_protection_key(&inner_tx_hash);
Expand Down
5 changes: 2 additions & 3 deletions apps/src/lib/node/ledger/shell/prepare_proposal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ where
tx_gas_meter.add_tx_size_gas(tx_bytes).map_err(|_| ())?;

// Check replay protection
self.replay_protection_checks(&tx, tx_bytes, temp_wl_storage)
self.replay_protection_checks(&tx, temp_wl_storage)
.map_err(|_| ())?;

// Check fees
Expand Down Expand Up @@ -1279,8 +1279,7 @@ mod test_prepare_proposal {
[(0, keypair)].into_iter().collect(),
None,
)));
let inner_unsigned_hash =
wrapper.clone().update_header(TxType::Raw).header_hash();
let inner_unsigned_hash = wrapper.raw_header_hash();

// Write inner hash to storage
let hash_key =
Expand Down
Loading