Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Murisi/alternative txs #1156

Closed
wants to merge 10 commits into from
2 changes: 2 additions & 0 deletions .changelog/unreleased/improvements/1093-signable-txs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Make Namada transactions signable on hardware constrained wallets by making
them smaller. ([#1093](https://github.com/anoma/namada/pull/1093))
20 changes: 12 additions & 8 deletions apps/src/lib/client/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -386,18 +386,22 @@ fn extract_payload(
wrapper: &mut Option<WrapperTx>,
transfer: &mut Option<Transfer>,
) {
match process_tx(tx) {
match process_tx(tx.clone()) {
Ok(TxType::Wrapper(wrapper_tx)) => {
let privkey = <EllipticCurve as PairingEngine>::G2Affine::prime_subgroup_generator();
extract_payload(
Tx::from(match wrapper_tx.decrypt(privkey) {
Ok(tx) => DecryptedTx::Decrypted {
tx,
#[cfg(not(feature = "mainnet"))]
has_valid_pow: false,
Tx::from(
match tx.inner_tx.and_then(|inner_tx| {
wrapper_tx.decrypt(privkey, inner_tx).ok()
}) {
Some(tx) => DecryptedTx::Decrypted {
tx,
#[cfg(not(feature = "mainnet"))]
has_valid_pow: false,
},
_ => DecryptedTx::Undecryptable(wrapper_tx.clone()),
},
_ => DecryptedTx::Undecryptable(wrapper_tx.clone()),
}),
),
wrapper,
transfer,
);
Expand Down
28 changes: 17 additions & 11 deletions apps/src/lib/client/signing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,8 +236,8 @@ pub async fn sign_wrapper(
None
}
};

let tx = {
// This object governs how the payload will be processed
let wrapper_tx = {
WrapperTx::new(
Fee {
amount: fee_amount,
Expand All @@ -246,23 +246,29 @@ pub async fn sign_wrapper(
keypair,
epoch,
args.gas_limit.clone(),
tx,
// TODO: Actually use the fetched encryption key
Default::default(),
#[cfg(not(feature = "mainnet"))]
pow_solution,
)
// Bind the inner transaction to the wrapper
.bind(tx.clone())
};

// Then sign over the bound wrapper
let mut stx = wrapper_tx
.sign(keypair)
.expect("Wrapper tx signing keypair should be correct");
// Then encrypt and attach the payload to the wrapper
stx = stx.attach_inner_tx(
&tx,
// TODO: Actually use the fetched encryption key
Default::default(),
);
// We use this to determine when the wrapper tx makes it on-chain
let wrapper_hash = hash_tx(&tx.try_to_vec().unwrap()).to_string();
let wrapper_hash = hash_tx(&wrapper_tx.try_to_vec().unwrap()).to_string();
// We use this to determine when the decrypted inner tx makes it
// on-chain
let decrypted_hash = tx.tx_hash.to_string();
let decrypted_hash = wrapper_tx.tx_hash.to_string();
TxBroadcastData::Wrapper {
tx: tx
.sign(keypair)
.expect("Wrapper tx signing keypair should be correct"),
tx: stx,
wrapper_hash,
decrypted_hash,
}
Expand Down
8 changes: 3 additions & 5 deletions apps/src/lib/client/tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,13 +196,11 @@ pub async fn submit_init_account(mut ctx: Context, args: args::TxInitAccount) {
}

let tx_code = ctx.read_wasm(TX_INIT_ACCOUNT_WASM);
let data = InitAccount {
public_key,
vp_code,
};
let data = InitAccount { public_key };
let data = data.try_to_vec().expect("Encoding tx data shouldn't fail");

let tx = Tx::new(tx_code, Some(data));
let mut tx = Tx::new(tx_code, Some(data));
tx.extra = Some(vp_code);
let (ctx, initialized_accounts) = process_tx(
ctx,
&args.tx,
Expand Down
49 changes: 28 additions & 21 deletions apps/src/lib/node/ledger/shell/finalize_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ where
continue;
}

let tx_type = if let Ok(tx_type) = process_tx(tx) {
let tx_type = if let Ok(tx_type) = process_tx(tx.clone()) {
tx_type
} else {
tracing::error!(
Expand Down Expand Up @@ -215,8 +215,9 @@ where
}
}

self.storage.tx_queue.push(WrapperTxInQueue {
self.storage.tx_queue.push(TxInQueue {
tx: wrapper.clone(),
inner_tx: tx.inner_tx,
#[cfg(not(feature = "mainnet"))]
has_valid_pow,
});
Expand Down Expand Up @@ -453,6 +454,7 @@ where
#[cfg(test)]
mod test_finalize_block {
use namada::types::storage::Epoch;
use namada::types::transaction::encrypted::EncryptedTx;
use namada::types::transaction::{EncryptionKey, Fee, WrapperTx, MIN_FEE};

use super::*;
Expand Down Expand Up @@ -495,12 +497,14 @@ mod test_finalize_block {
&keypair,
Epoch(0),
0.into(),
raw_tx.clone(),
Default::default(),
#[cfg(not(feature = "mainnet"))]
None,
);
let tx = wrapper.sign(&keypair).expect("Test failed");
)
.bind(raw_tx.clone());
let tx = wrapper
.sign(&keypair)
.expect("Test failed")
.attach_inner_tx(&raw_tx, Default::default());
if i > 1 {
processed_txs.push(ProcessedTx {
tx: tx.to_bytes(),
Expand All @@ -511,7 +515,7 @@ mod test_finalize_block {
},
});
} else {
shell.enqueue_tx(wrapper.clone());
shell.enqueue_tx(wrapper.clone(), tx.inner_tx);
}

if i != 3 {
Expand Down Expand Up @@ -560,6 +564,8 @@ mod test_finalize_block {
"wasm_code".as_bytes().to_owned(),
Some(String::from("transaction data").as_bytes().to_owned()),
);
let encrypted_raw_tx =
EncryptedTx::encrypt(&raw_tx.to_bytes(), Default::default());
let wrapper = WrapperTx::new(
Fee {
amount: 0.into(),
Expand All @@ -568,11 +574,10 @@ mod test_finalize_block {
&keypair,
Epoch(0),
0.into(),
raw_tx.clone(),
Default::default(),
#[cfg(not(feature = "mainnet"))]
None,
);
)
.bind(raw_tx.clone());

let processed_tx = ProcessedTx {
tx: Tx::from(TxType::Decrypted(DecryptedTx::Decrypted {
Expand All @@ -586,7 +591,7 @@ mod test_finalize_block {
info: "".into(),
},
};
shell.enqueue_tx(wrapper);
shell.enqueue_tx(wrapper, Some(encrypted_raw_tx));

// check that the decrypted tx was not applied
for event in shell
Expand Down Expand Up @@ -626,7 +631,6 @@ mod test_finalize_block {
pk: keypair.ref_to(),
epoch: Epoch(0),
gas_limit: 0.into(),
inner_tx,
tx_hash: hash_tx(&tx),
#[cfg(not(feature = "mainnet"))]
pow_solution: None,
Expand All @@ -642,7 +646,7 @@ mod test_finalize_block {
},
};

shell.enqueue_tx(wrapper);
shell.enqueue_tx(wrapper, Some(inner_tx));

// check that correct error message is returned
for event in shell
Expand Down Expand Up @@ -696,6 +700,8 @@ mod test_finalize_block {
.to_owned(),
),
);
let encrypted_raw_tx =
EncryptedTx::encrypt(&raw_tx.to_bytes(), Default::default());
let wrapper_tx = WrapperTx::new(
Fee {
amount: MIN_FEE.into(),
Expand All @@ -704,12 +710,11 @@ mod test_finalize_block {
&keypair,
Epoch(0),
0.into(),
raw_tx.clone(),
Default::default(),
#[cfg(not(feature = "mainnet"))]
None,
);
shell.enqueue_tx(wrapper_tx);
)
.bind(raw_tx.clone());
shell.enqueue_tx(wrapper_tx, Some(encrypted_raw_tx));
processed_txs.push(ProcessedTx {
tx: Tx::from(TxType::Decrypted(DecryptedTx::Decrypted {
tx: raw_tx,
Expand Down Expand Up @@ -741,12 +746,14 @@ mod test_finalize_block {
&keypair,
Epoch(0),
0.into(),
raw_tx.clone(),
Default::default(),
#[cfg(not(feature = "mainnet"))]
None,
);
let wrapper = wrapper_tx.sign(&keypair).expect("Test failed");
)
.bind(raw_tx.clone());
let wrapper = wrapper_tx
.sign(&keypair)
.expect("Test failed")
.attach_inner_tx(&raw_tx, Default::default());
valid_txs.push(wrapper_tx);
processed_txs.push(ProcessedTx {
tx: wrapper.to_bytes(),
Expand Down
24 changes: 16 additions & 8 deletions apps/src/lib/node/ledger/shell/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ use namada::proto::{self, Tx};
use namada::types::address;
use namada::types::address::{masp, masp_tx_key, Address};
use namada::types::chain::ChainId;
use namada::types::internal::WrapperTxInQueue;
use namada::types::internal::TxInQueue;
use namada::types::key::*;
use namada::types::storage::{BlockHeight, Key, TxIndex};
use namada::types::time::{DateTimeUtc, TimeZone, Utc};
Expand Down Expand Up @@ -353,7 +353,7 @@ where

/// Iterate over the wrapper txs in order
#[allow(dead_code)]
fn iter_tx_queue(&mut self) -> impl Iterator<Item = &WrapperTxInQueue> {
fn iter_tx_queue(&mut self) -> impl Iterator<Item = &TxInQueue> {
self.storage.tx_queue.iter()
}

Expand Down Expand Up @@ -773,6 +773,7 @@ mod test_utils {
use namada::types::hash::Hash;
use namada::types::key::*;
use namada::types::storage::{BlockHash, BlockResults, Epoch, Header};
use namada::types::transaction::encrypted::EncryptedTx;
use namada::types::transaction::{Fee, WrapperTx};
use tempfile::tempdir;
use tokio::sync::mpsc::UnboundedReceiver;
Expand Down Expand Up @@ -921,9 +922,14 @@ mod test_utils {
/// Add a wrapper tx to the queue of txs to be decrypted
/// in the current block proposal
#[cfg(test)]
pub fn enqueue_tx(&mut self, wrapper: WrapperTx) {
self.shell.storage.tx_queue.push(WrapperTxInQueue {
pub fn enqueue_tx(
&mut self,
wrapper: WrapperTx,
inner_tx: Option<EncryptedTx>,
) {
self.shell.storage.tx_queue.push(TxInQueue {
tx: wrapper,
inner_tx,
#[cfg(not(feature = "mainnet"))]
has_valid_pow: false,
});
Expand Down Expand Up @@ -992,6 +998,8 @@ mod test_utils {
"wasm_code".as_bytes().to_owned(),
Some("transaction data".as_bytes().to_owned()),
);
let encrypted_tx =
EncryptedTx::encrypt(&tx.to_bytes(), Default::default());
let wrapper = WrapperTx::new(
Fee {
amount: 0.into(),
Expand All @@ -1000,13 +1008,13 @@ mod test_utils {
&keypair,
Epoch(0),
0.into(),
tx,
Default::default(),
#[cfg(not(feature = "mainnet"))]
None,
);
shell.storage.tx_queue.push(WrapperTxInQueue {
)
.bind(tx);
shell.storage.tx_queue.push(TxInQueue {
tx: wrapper,
inner_tx: Some(encrypted_tx),
#[cfg(not(feature = "mainnet"))]
has_valid_pow: false,
});
Expand Down
Loading