diff --git a/.changelog/unreleased/improvements/1884-multisig-fixes.md b/.changelog/unreleased/improvements/1884-multisig-fixes.md new file mode 100644 index 00000000000..3c380fb3f4b --- /dev/null +++ b/.changelog/unreleased/improvements/1884-multisig-fixes.md @@ -0,0 +1,2 @@ +- Enable hardware wallets to participate in nondegenerate multisignature + transactions. ([\#1884](https://github.com/anoma/namada/pull/1884)) \ No newline at end of file diff --git a/apps/src/lib/cli/client.rs b/apps/src/lib/cli/client.rs index 675c5b4aea4..418e3645396 100644 --- a/apps/src/lib/cli/client.rs +++ b/apps/src/lib/cli/client.rs @@ -246,7 +246,7 @@ impl CliApi { &client, &mut ctx.wallet, &args.tx, - &Some(args.sender.clone()), + Some(args.sender.clone()), default_signer, ) .await?; diff --git a/apps/src/lib/client/tx.rs b/apps/src/lib/client/tx.rs index c3a46d3fd7f..8ee9dab8a50 100644 --- a/apps/src/lib/client/tx.rs +++ b/apps/src/lib/client/tx.rs @@ -42,7 +42,7 @@ pub async fn aux_signing_data( client: &C, wallet: &mut Wallet, args: &args::Tx, - owner: &Option
, + owner: Option
, default_signer: Option
, ) -> Result { let signing_data = @@ -88,7 +88,7 @@ pub async fn submit_reveal_aux( if tx::is_reveal_pk_needed::(client, address, args.force).await? { let signing_data = - aux_signing_data(client, &mut ctx.wallet, &args, &None, None) + aux_signing_data(client, &mut ctx.wallet, &args, None, None) .await?; let (mut tx, _epoch) = tx::build_reveal_pk( @@ -126,7 +126,7 @@ where client, &mut ctx.wallet, &args.tx, - &Some(args.owner.clone()), + Some(args.owner.clone()), default_signer, ) .await?; @@ -168,7 +168,7 @@ where client, &mut ctx.wallet, &args.tx, - &Some(args.addr.clone()), + Some(args.addr.clone()), default_signer, ) .await?; @@ -203,8 +203,7 @@ where C::Error: std::fmt::Display, { let signing_data = - aux_signing_data(client, &mut ctx.wallet, &args.tx, &None, None) - .await?; + aux_signing_data(client, &mut ctx.wallet, &args.tx, None, None).await?; let (mut tx, _epoch) = tx::build_init_account( client, @@ -429,8 +428,7 @@ pub async fn submit_init_validator< tx.add_code_from_hash(tx_code_hash).add_data(data); let signing_data = - aux_signing_data(client, &mut ctx.wallet, &tx_args, &None, None) - .await?; + aux_signing_data(client, &mut ctx.wallet, &tx_args, None, None).await?; tx::prepare_tx( client, @@ -647,7 +645,7 @@ pub async fn submit_transfer( client, &mut ctx.wallet, &args.tx, - &Some(args.source.effective_address()), + Some(args.source.effective_address()), default_signer, ) .await?; @@ -720,7 +718,7 @@ where client, &mut ctx.wallet, &args.tx, - &Some(args.source.clone()), + Some(args.source.clone()), default_signer, ) .await?; @@ -775,7 +773,7 @@ where client, &mut ctx.wallet, &args.tx, - &Some(proposal.author.clone()), + Some(proposal.author.clone()), default_signer, ) .await?; @@ -810,7 +808,7 @@ where client, &mut ctx.wallet, &args.tx, - &Some(proposal.proposal.author.clone()), + Some(proposal.proposal.author.clone()), default_signer, ) .await?; @@ -862,7 +860,7 @@ where client, &mut ctx.wallet, &args.tx, - &Some(proposal.proposal.author.clone()), + Some(proposal.proposal.author.clone()), default_signer, ) .await?; @@ -912,7 +910,7 @@ where client, &mut ctx.wallet, &args.tx, - &Some(proposal.proposal.author.clone()), + Some(proposal.proposal.author.clone()), default_signer, ) .await?; @@ -971,7 +969,7 @@ where client, &mut ctx.wallet, &args.tx, - &Some(args.voter.clone()), + Some(args.voter.clone()), default_signer.clone(), ) .await?; @@ -1070,7 +1068,7 @@ where client, &mut ctx.wallet, &tx_args, - &Some(owner), + Some(owner.clone()), default_signer, ) .await?; @@ -1096,14 +1094,17 @@ where if let Some(account_public_keys_map) = signing_data.account_public_keys_map { - let signatures = - tx.compute_section_signature(secret_keys, &account_public_keys_map); + let signatures = tx.compute_section_signature( + secret_keys, + &account_public_keys_map, + Some(owner), + ); for signature in &signatures { let filename = format!( "offline_signature_{}_{}.tx", tx.header_hash(), - signature.index + signature.pubkey, ); let output_path = match &tx_args.output_folder { Some(path) => path.join(filename), @@ -1120,9 +1121,7 @@ where .expect("Signature should be deserializable."); println!( "Signature for {} serialized at {}", - &account_public_keys_map - .get_public_key_from_index(signature.index) - .unwrap(), + signature.pubkey, output_path.display() ); } @@ -1158,7 +1157,7 @@ where client, &mut ctx.wallet, &args.tx, - &Some(default_address.clone()), + Some(default_address.clone()), default_signer, ) .await?; @@ -1200,7 +1199,7 @@ where client, &mut ctx.wallet, &args.tx, - &Some(default_address), + Some(default_address), default_signer, ) .await?; @@ -1243,7 +1242,7 @@ where client, &mut ctx.wallet, &args.tx, - &Some(default_address), + Some(default_address), default_signer, ) .await?; @@ -1284,7 +1283,7 @@ where client, &mut ctx.wallet, &args.tx, - &Some(args.validator.clone()), + Some(args.validator.clone()), default_signer, ) .await?; @@ -1325,7 +1324,7 @@ where client, &mut ctx.wallet, &args.tx, - &Some(args.validator.clone()), + Some(args.validator.clone()), default_signer, ) .await?; @@ -1367,7 +1366,7 @@ where client, &mut ctx.wallet, &args.tx, - &Some(args.steward.clone()), + Some(args.steward.clone()), default_signer, ) .await?; @@ -1407,7 +1406,7 @@ where client, &mut ctx.wallet, &args.tx, - &Some(args.steward.clone()), + Some(args.steward.clone()), default_signer, ) .await?; diff --git a/apps/src/lib/node/ledger/shell/finalize_block.rs b/apps/src/lib/node/ledger/shell/finalize_block.rs index 57ed9269e0d..c286e4f5df0 100644 --- a/apps/src/lib/node/ledger/shell/finalize_block.rs +++ b/apps/src/lib/node/ledger/shell/finalize_block.rs @@ -1156,7 +1156,8 @@ mod test_finalize_block { )); wrapper_tx.add_section(Section::Signature(Signature::new( wrapper_tx.sechashes(), - keypair, + [(0, keypair.clone())].into_iter().collect(), + None, ))); let tx = wrapper_tx.to_bytes(); ( @@ -2489,7 +2490,8 @@ mod test_finalize_block { )); wrapper.add_section(Section::Signature(Signature::new( wrapper.sechashes(), - &keypair, + [(0, keypair)].into_iter().collect(), + None, ))); let wrapper_hash_key = replay_protection::get_replay_protection_key( @@ -2562,7 +2564,8 @@ mod test_finalize_block { )); wrapper.add_section(Section::Signature(Signature::new( wrapper.sechashes(), - &keypair, + [(0, keypair.clone())].into_iter().collect(), + None, ))); let processed_tx = ProcessedTx { @@ -2646,7 +2649,10 @@ mod test_finalize_block { )); wrapper.add_section(Section::Signature(Signature::new( wrapper.sechashes(), - &crate::wallet::defaults::albert_keypair(), + [(0, crate::wallet::defaults::albert_keypair())] + .into_iter() + .collect(), + None, ))); let fee_amount = wrapper.header().wrapper().unwrap().get_tx_fee().unwrap(); diff --git a/apps/src/lib/node/ledger/shell/mod.rs b/apps/src/lib/node/ledger/shell/mod.rs index 46a985b8fcf..6f5a1efb12e 100644 --- a/apps/src/lib/node/ledger/shell/mod.rs +++ b/apps/src/lib/node/ledger/shell/mod.rs @@ -2299,7 +2299,8 @@ mod abciplus_mempool_tests { tx.set_data(Data::new(ext.try_to_vec().expect("Test falied"))); tx.add_section(Section::Signature(Signature::new( tx.sechashes(), - &protocol_key, + [(0, protocol_key)].into_iter().collect(), + None, ))); tx } @@ -2384,7 +2385,8 @@ mod test_mempool_validate { .set_data(Data::new("transaction data".as_bytes().to_owned())); invalid_wrapper.add_section(Section::Signature(Signature::new( invalid_wrapper.sechashes(), - &keypair, + [(0, keypair)].into_iter().collect(), + None, ))); // we mount a malleability attack to try and remove the fee @@ -2452,7 +2454,8 @@ mod test_mempool_validate { wrapper.set_data(Data::new("transaction data".as_bytes().to_owned())); wrapper.add_section(Section::Signature(Signature::new( wrapper.sechashes(), - &keypair, + [(0, keypair)].into_iter().collect(), + None, ))); // Write wrapper hash to storage @@ -2611,7 +2614,8 @@ mod test_mempool_validate { wrapper.set_data(Data::new("transaction data".as_bytes().to_owned())); wrapper.add_section(Section::Signature(Signature::new( wrapper.sechashes(), - &keypair, + [(0, keypair)].into_iter().collect(), + None, ))); let result = shell.mempool_validate( @@ -2645,7 +2649,8 @@ mod test_mempool_validate { wrapper.set_data(Data::new("transaction data".as_bytes().to_owned())); wrapper.add_section(Section::Signature(Signature::new( wrapper.sechashes(), - &keypair, + [(0, keypair)].into_iter().collect(), + None, ))); let result = shell.mempool_validate( @@ -2679,7 +2684,10 @@ mod test_mempool_validate { wrapper.set_data(Data::new("transaction data".as_bytes().to_owned())); wrapper.add_section(Section::Signature(Signature::new( wrapper.sechashes(), - &crate::wallet::defaults::albert_keypair(), + [(0, crate::wallet::defaults::albert_keypair())] + .into_iter() + .collect(), + None, ))); let result = shell.mempool_validate( @@ -2713,7 +2721,10 @@ mod test_mempool_validate { wrapper.set_data(Data::new("transaction data".as_bytes().to_owned())); wrapper.add_section(Section::Signature(Signature::new( wrapper.sechashes(), - &crate::wallet::defaults::albert_keypair(), + [(0, crate::wallet::defaults::albert_keypair())] + .into_iter() + .collect(), + None, ))); let result = shell.mempool_validate( @@ -2746,7 +2757,10 @@ mod test_mempool_validate { wrapper.set_data(Data::new("transaction data".as_bytes().to_owned())); wrapper.add_section(Section::Signature(Signature::new( wrapper.sechashes(), - &crate::wallet::defaults::albert_keypair(), + [(0, crate::wallet::defaults::albert_keypair())] + .into_iter() + .collect(), + None, ))); let result = shell.mempool_validate( @@ -2779,7 +2793,10 @@ mod test_mempool_validate { wrapper.set_data(Data::new("transaction data".as_bytes().to_owned())); wrapper.add_section(Section::Signature(Signature::new( wrapper.sechashes(), - &crate::wallet::defaults::albert_keypair(), + [(0, crate::wallet::defaults::albert_keypair())] + .into_iter() + .collect(), + None, ))); let result = shell.mempool_validate( diff --git a/apps/src/lib/node/ledger/shell/prepare_proposal.rs b/apps/src/lib/node/ledger/shell/prepare_proposal.rs index e8633940b9a..ff73a2f74bb 100644 --- a/apps/src/lib/node/ledger/shell/prepare_proposal.rs +++ b/apps/src/lib/node/ledger/shell/prepare_proposal.rs @@ -1135,7 +1135,8 @@ mod test_prepare_proposal { )); tx.add_section(Section::Signature(Signature::new( tx.sechashes(), - &keypair, + [(0, keypair.clone())].into_iter().collect(), + None, ))); let gas = Gas::from( @@ -1208,7 +1209,8 @@ mod test_prepare_proposal { wrapper.set_data(Data::new("transaction data".as_bytes().to_owned())); wrapper.add_section(Section::Signature(Signature::new( wrapper.sechashes(), - &keypair, + [(0, keypair)].into_iter().collect(), + None, ))); // Write wrapper hash to storage @@ -1262,7 +1264,8 @@ mod test_prepare_proposal { wrapper.set_data(Data::new("transaction data".as_bytes().to_owned())); wrapper.add_section(Section::Signature(Signature::new( wrapper.sechashes(), - &keypair, + [(0, keypair)].into_iter().collect(), + None, ))); let req = RequestPrepareProposal { @@ -1304,7 +1307,8 @@ mod test_prepare_proposal { wrapper.set_data(Data::new("transaction data".as_bytes().to_owned())); wrapper.add_section(Section::Signature(Signature::new( wrapper.sechashes(), - &keypair, + [(0, keypair)].into_iter().collect(), + None, ))); let inner_unsigned_hash = wrapper.clone().update_header(TxType::Raw).header_hash(); @@ -1362,7 +1366,8 @@ mod test_prepare_proposal { let mut new_wrapper = wrapper.clone(); wrapper.add_section(Section::Signature(Signature::new( wrapper.sechashes(), - &keypair, + [(0, keypair)].into_iter().collect(), + None, ))); new_wrapper.update_header(TxType::Wrapper(Box::new(WrapperTx::new( @@ -1379,7 +1384,8 @@ mod test_prepare_proposal { )))); new_wrapper.add_section(Section::Signature(Signature::new( wrapper.sechashes(), - &keypair_2, + [(0, keypair_2)].into_iter().collect(), + None, ))); let req = RequestPrepareProposal { @@ -1421,7 +1427,8 @@ mod test_prepare_proposal { .set_data(Data::new("transaction data".as_bytes().to_owned())); wrapper_tx.add_section(Section::Signature(Signature::new( wrapper_tx.sechashes(), - &keypair, + [(0, keypair)].into_iter().collect(), + None, ))); let time = DateTimeUtc::now(); @@ -1471,7 +1478,8 @@ mod test_prepare_proposal { .set_data(Data::new("transaction data".as_bytes().to_owned())); wrapper_tx.add_section(Section::Signature(Signature::new( wrapper_tx.sechashes(), - &keypair, + [(0, keypair)].into_iter().collect(), + None, ))); let req = RequestPrepareProposal { @@ -1512,7 +1520,8 @@ mod test_prepare_proposal { .set_data(Data::new("transaction data".as_bytes().to_owned())); wrapper_tx.add_section(Section::Signature(Signature::new( wrapper_tx.sechashes(), - &keypair, + [(0, keypair)].into_iter().collect(), + None, ))); let req = RequestPrepareProposal { @@ -1552,7 +1561,10 @@ mod test_prepare_proposal { .set_data(Data::new("transaction data".as_bytes().to_owned())); wrapper_tx.add_section(Section::Signature(Signature::new( wrapper_tx.sechashes(), - &crate::wallet::defaults::albert_keypair(), + [(0, crate::wallet::defaults::albert_keypair())] + .into_iter() + .collect(), + None, ))); let req = RequestPrepareProposal { @@ -1591,7 +1603,10 @@ mod test_prepare_proposal { .set_data(Data::new("transaction data".as_bytes().to_owned())); wrapper_tx.add_section(Section::Signature(Signature::new( wrapper_tx.sechashes(), - &crate::wallet::defaults::albert_keypair(), + [(0, crate::wallet::defaults::albert_keypair())] + .into_iter() + .collect(), + None, ))); let req = RequestPrepareProposal { @@ -1629,7 +1644,10 @@ mod test_prepare_proposal { .set_data(Data::new("transaction data".as_bytes().to_owned())); wrapper_tx.add_section(Section::Signature(Signature::new( wrapper_tx.sechashes(), - &crate::wallet::defaults::albert_keypair(), + [(0, crate::wallet::defaults::albert_keypair())] + .into_iter() + .collect(), + None, ))); let req = RequestPrepareProposal { @@ -1667,7 +1685,10 @@ mod test_prepare_proposal { .set_data(Data::new("transaction data".as_bytes().to_owned())); wrapper_tx.add_section(Section::Signature(Signature::new( wrapper_tx.sechashes(), - &crate::wallet::defaults::albert_keypair(), + [(0, crate::wallet::defaults::albert_keypair())] + .into_iter() + .collect(), + None, ))); let req = RequestPrepareProposal { diff --git a/apps/src/lib/node/ledger/shell/process_proposal.rs b/apps/src/lib/node/ledger/shell/process_proposal.rs index dca2d4fe4ed..1dca7f88859 100644 --- a/apps/src/lib/node/ledger/shell/process_proposal.rs +++ b/apps/src/lib/node/ledger/shell/process_proposal.rs @@ -1660,7 +1660,8 @@ mod test_process_proposal { outer_tx.set_data(Data::new("transaction data".as_bytes().to_owned())); outer_tx.add_section(Section::Signature(Signature::new( outer_tx.sechashes(), - &keypair, + [(0, keypair)].into_iter().collect(), + None, ))); let mut new_tx = outer_tx.clone(); if let TxType::Wrapper(wrapper) = &mut new_tx.header.tx_type { @@ -1733,7 +1734,8 @@ mod test_process_proposal { outer_tx.set_data(Data::new("transaction data".as_bytes().to_owned())); outer_tx.add_section(Section::Signature(Signature::new( outer_tx.sechashes(), - &keypair, + [(0, keypair)].into_iter().collect(), + None, ))); let response = { @@ -1799,7 +1801,8 @@ mod test_process_proposal { outer_tx.set_data(Data::new("transaction data".as_bytes().to_owned())); outer_tx.add_section(Section::Signature(Signature::new( outer_tx.sechashes(), - &keypair, + [(0, keypair)].into_iter().collect(), + None, ))); let response = { @@ -2164,7 +2167,8 @@ mod test_process_proposal { wrapper.set_code(Code::new("wasm_code".as_bytes().to_owned())); wrapper.add_section(Section::Signature(Signature::new( wrapper.sechashes(), - &keypair, + [(0, keypair)].into_iter().collect(), + None, ))); // Write wrapper hash to storage @@ -2241,7 +2245,8 @@ mod test_process_proposal { wrapper.set_data(Data::new("transaction data".as_bytes().to_owned())); wrapper.add_section(Section::Signature(Signature::new( wrapper.sechashes(), - &keypair, + [(0, keypair)].into_iter().collect(), + None, ))); // Run validation @@ -2300,7 +2305,8 @@ mod test_process_proposal { wrapper.set_data(Data::new("transaction data".as_bytes().to_owned())); wrapper.add_section(Section::Signature(Signature::new( wrapper.sechashes(), - &keypair, + [(0, keypair)].into_iter().collect(), + None, ))); let inner_unsigned_hash = wrapper.clone().update_header(TxType::Raw).header_hash(); @@ -2365,7 +2371,8 @@ mod test_process_proposal { let mut new_wrapper = wrapper.clone(); wrapper.add_section(Section::Signature(Signature::new( wrapper.sechashes(), - &keypair, + [(0, keypair)].into_iter().collect(), + None, ))); let inner_unsigned_hash = wrapper.clone().update_header(TxType::Raw).header_hash(); @@ -2384,7 +2391,8 @@ mod test_process_proposal { )))); new_wrapper.add_section(Section::Signature(Signature::new( new_wrapper.sechashes(), - &keypair_2, + [(0, keypair_2)].into_iter().collect(), + None, ))); // Run validation @@ -2437,7 +2445,8 @@ mod test_process_proposal { wrapper.set_data(Data::new("transaction data".as_bytes().to_owned())); wrapper.add_section(Section::Signature(Signature::new( wrapper.sechashes(), - &keypair, + [(0, keypair)].into_iter().collect(), + None, ))); let protocol_key = shell.mode.get_protocol_key().expect("Test failed"); @@ -2506,7 +2515,8 @@ mod test_process_proposal { })); decrypted.add_section(Section::Signature(Signature::new( decrypted.sechashes(), - &keypair, + [(0, keypair)].into_iter().collect(), + None, ))); let gas_limit = Gas::from(wrapper.header.wrapper().unwrap().gas_limit) .checked_sub(Gas::from(wrapper.to_bytes().len() as u64)) @@ -2567,7 +2577,8 @@ mod test_process_proposal { wrapper.set_data(Data::new("transaction data".as_bytes().to_owned())); wrapper.add_section(Section::Signature(Signature::new( wrapper.sechashes(), - &keypair, + [(0, keypair)].into_iter().collect(), + None, ))); // Run validation @@ -2617,7 +2628,8 @@ mod test_process_proposal { })); decrypted.add_section(Section::Signature(Signature::new( decrypted.sechashes(), - &keypair, + [(0, keypair)].into_iter().collect(), + None, ))); let gas_limit = Gas::from(wrapper.header.wrapper().unwrap().gas_limit) .checked_sub(Gas::from(wrapper.to_bytes().len() as u64)) @@ -2674,7 +2686,8 @@ mod test_process_proposal { wrapper.set_data(Data::new("transaction data".as_bytes().to_owned())); wrapper.add_section(Section::Signature(Signature::new( wrapper.sechashes(), - &keypair, + [(0, keypair)].into_iter().collect(), + None, ))); // Run validation @@ -2717,7 +2730,8 @@ mod test_process_proposal { wrapper.set_data(Data::new("transaction data".as_bytes().to_owned())); wrapper.add_section(Section::Signature(Signature::new( wrapper.sechashes(), - &keypair, + [(0, keypair)].into_iter().collect(), + None, ))); // Run validation @@ -2759,7 +2773,10 @@ mod test_process_proposal { wrapper.set_data(Data::new("transaction data".as_bytes().to_owned())); wrapper.add_section(Section::Signature(Signature::new( wrapper.sechashes(), - &crate::wallet::defaults::albert_keypair(), + [(0, crate::wallet::defaults::albert_keypair())] + .into_iter() + .collect(), + None, ))); // Run validation @@ -2801,7 +2818,10 @@ mod test_process_proposal { wrapper.set_data(Data::new("transaction data".as_bytes().to_owned())); wrapper.add_section(Section::Signature(Signature::new( wrapper.sechashes(), - &crate::wallet::defaults::albert_keypair(), + [(0, crate::wallet::defaults::albert_keypair())] + .into_iter() + .collect(), + None, ))); // Run validation @@ -2843,7 +2863,10 @@ mod test_process_proposal { wrapper.set_data(Data::new("transaction data".as_bytes().to_owned())); wrapper.add_section(Section::Signature(Signature::new( wrapper.sechashes(), - &crate::wallet::defaults::albert_keypair(), + [(0, crate::wallet::defaults::albert_keypair())] + .into_iter() + .collect(), + None, ))); // Run validation @@ -2885,7 +2908,10 @@ mod test_process_proposal { wrapper.set_data(Data::new("transaction data".as_bytes().to_owned())); wrapper.add_section(Section::Signature(Signature::new( wrapper.sechashes(), - &crate::wallet::defaults::albert_keypair(), + [(0, crate::wallet::defaults::albert_keypair())] + .into_iter() + .collect(), + None, ))); // Run validation @@ -2930,7 +2956,8 @@ mod test_process_proposal { wrapper.set_data(Data::new("transaction data".as_bytes().to_owned())); wrapper.add_section(Section::Signature(Signature::new( wrapper.sechashes(), - &keypair, + [(0, keypair)].into_iter().collect(), + None, ))); let wrapper = wrapper.to_bytes(); for height in [1u64, 2] { diff --git a/benches/host_env.rs b/benches/host_env.rs index 6a3cc6e37b8..6f385b93bc7 100644 --- a/benches/host_env.rs +++ b/benches/host_env.rs @@ -1,9 +1,11 @@ +use std::collections::HashSet; + use borsh::BorshSerialize; use criterion::{criterion_group, criterion_main, Criterion}; use namada::core::types::account::AccountPublicKeysMap; use namada::core::types::address; use namada::core::types::token::{Amount, Transfer}; -use namada::proto::{Data, MultiSignature, Section}; +use namada::proto::{Data, Section, Signature}; use namada_apps::wallet::defaults; /// Benchmarks the validation of a single signature on a single `Section` of a @@ -24,17 +26,16 @@ fn tx_section_signature_validation(c: &mut Criterion) { defaults::albert_keypair().to_public() ]); - let multisig = MultiSignature::new( + let multisig = Signature::new( vec![section_hash], - &[defaults::albert_keypair()], - &pkim, + pkim.index_secret_keys(vec![defaults::albert_keypair()]), + None, ); - let signature_index = multisig.signatures.first().unwrap().clone(); c.bench_function("tx_section_signature_validation", |b| { b.iter(|| { - signature_index - .verify(&pkim, &multisig.get_raw_hash()) + multisig + .verify_signature(&mut HashSet::new(), &pkim, &None) .unwrap() }) }); diff --git a/benches/lib.rs b/benches/lib.rs index 11042c84b3a..463eefb600d 100644 --- a/benches/lib.rs +++ b/benches/lib.rs @@ -435,7 +435,8 @@ pub fn generate_tx( if let Some(signer) = signer { tx.add_section(Section::Signature(Signature::new( tx.sechashes(), - signer, + [(0, signer.clone())].into_iter().collect(), + None, ))); } @@ -481,7 +482,11 @@ pub fn generate_foreign_key_tx(signer: &SecretKey) -> Tx { .try_to_vec() .unwrap(), )); - tx.add_section(Section::Signature(Signature::new(tx.sechashes(), signer))); + tx.add_section(Section::Signature(Signature::new( + tx.sechashes(), + [(0, signer.clone())].into_iter().collect(), + None, + ))); tx } diff --git a/benches/process_wrapper.rs b/benches/process_wrapper.rs index 72b26e0cb18..55bbf02777b 100644 --- a/benches/process_wrapper.rs +++ b/benches/process_wrapper.rs @@ -49,7 +49,8 @@ fn process_tx(c: &mut Criterion) { ))); tx.add_section(namada::proto::Section::Signature(Signature::new( tx.sechashes(), - &defaults::albert_keypair(), + [(0, defaults::albert_keypair())].into_iter().collect(), + None, ))); let wrapper = tx.to_bytes(); diff --git a/core/src/ledger/governance/cli/offline.rs b/core/src/ledger/governance/cli/offline.rs index 3f9feeb1dce..fb56a1270a4 100644 --- a/core/src/ledger/governance/cli/offline.rs +++ b/core/src/ledger/governance/cli/offline.rs @@ -315,18 +315,13 @@ fn compute_signatures_index( account_public_keys_map: &AccountPublicKeysMap, hashed_data: &Hash, ) -> BTreeSet { - keys.iter() - .filter_map(|signing_key| { + account_public_keys_map + .index_secret_keys(keys.to_vec()) + .values() + .map(|signing_key| { let public_key = signing_key.ref_to(); - let public_key_index = - account_public_keys_map.get_index_from_public_key(&public_key); - if public_key_index.is_some() { - let signature = - common::SigScheme::sign(signing_key, hashed_data); - Some(SignatureIndex::from_single_signature(signature)) - } else { - None - } + let signature = common::SigScheme::sign(signing_key, hashed_data); + SignatureIndex::from_single_signature(public_key, signature) }) .collect::>() } @@ -338,11 +333,12 @@ fn compute_total_valid_signatures( hashed_data: &Hash, ) -> u8 { signatures.iter().fold(0_u8, |acc, signature_index| { - let public_key = account_public_keys_map - .get_public_key_from_index(signature_index.index); - if let Some(pk) = public_key { + if account_public_keys_map + .get_index_from_public_key(&signature_index.pubkey) + .is_some() + { let sig_check = common::SigScheme::verify_signature( - &pk, + &signature_index.pubkey, hashed_data, &signature_index.signature, ); diff --git a/core/src/proto/mod.rs b/core/src/proto/mod.rs index e8411a41d2d..9dfe32e6443 100644 --- a/core/src/proto/mod.rs +++ b/core/src/proto/mod.rs @@ -4,9 +4,9 @@ pub mod generated; mod types; pub use types::{ - Code, Commitment, Data, Dkg, Error, Header, MaspBuilder, MultiSignature, - Section, Signable, SignableEthMessage, Signature, SignatureIndex, Signed, - Tx, TxError, + Code, Commitment, CompressedSignature, Data, Dkg, Error, Header, + MaspBuilder, Section, Signable, SignableEthMessage, Signature, + SignatureIndex, Signed, Signer, Tx, TxError, }; #[cfg(test)] diff --git a/core/src/proto/types.rs b/core/src/proto/types.rs index 43da551d871..6c2b71fecad 100644 --- a/core/src/proto/types.rs +++ b/core/src/proto/types.rs @@ -1,6 +1,6 @@ use std::borrow::Cow; use std::cmp::Ordering; -use std::collections::{BTreeSet, HashMap, HashSet}; +use std::collections::{BTreeMap, HashMap, HashSet}; use std::convert::TryFrom; use std::hash::{Hash, Hasher}; use std::marker::PhantomData; @@ -389,15 +389,20 @@ impl Code { PartialEq, )] pub struct SignatureIndex { + pub pubkey: common::PublicKey, + pub index: Option<(Address, u8)>, pub signature: common::Signature, - pub index: u8, } impl SignatureIndex { - pub fn from_single_signature(signature: common::Signature) -> Self { + pub fn from_single_signature( + pubkey: common::PublicKey, + signature: common::Signature, + ) -> Self { Self { + pubkey, signature, - index: 0, + index: None, } } @@ -405,24 +410,6 @@ impl SignatureIndex { vec![self.clone()] } - pub fn verify( - &self, - public_key_index_map: &AccountPublicKeysMap, - data: &impl SignableBytes, - ) -> std::result::Result<(), VerifySigError> { - let public_key = - public_key_index_map.get_public_key_from_index(self.index); - if let Some(public_key) = public_key { - common::SigScheme::verify_signature( - &public_key, - data, - &self.signature, - ) - } else { - Err(VerifySigError::MissingData) - } - } - pub fn serialize(&self) -> String { let signature_bytes = self.try_to_vec().expect("Signature should be serializable"); @@ -444,7 +431,7 @@ impl SignatureIndex { impl Ord for SignatureIndex { fn cmp(&self, other: &Self) -> Ordering { - self.index.cmp(&other.index) + self.pubkey.cmp(&other.pubkey) } } @@ -454,6 +441,23 @@ impl PartialOrd for SignatureIndex { } } +/// Indicates the list of public keys against which signatures will be verified +#[derive( + Clone, + Debug, + BorshSerialize, + BorshDeserialize, + BorshSchema, + Serialize, + Deserialize, +)] +pub enum Signer { + /// The address of a multisignature account + Address(Address), + /// The public keys that constitute a signer + PubKeys(Vec), +} + /// A section representing a multisig over another section #[derive( Clone, @@ -464,45 +468,54 @@ impl PartialOrd for SignatureIndex { Serialize, Deserialize, )] -pub struct MultiSignature { +pub struct Signature { /// The hash of the section being signed pub targets: Vec, + /// The public keys against which the signatures should be verified + pub signer: Signer, /// The signature over the above hash - pub signatures: BTreeSet, + pub signatures: BTreeMap, } -impl MultiSignature { +impl Signature { /// Sign the given section hash with the given key and return a section pub fn new( targets: Vec, - secret_keys: &[common::SecretKey], - public_keys_index_map: &AccountPublicKeysMap, + secret_keys: BTreeMap, + signer: Option
, ) -> Self { - let target = Self { - targets: targets.clone(), - signatures: BTreeSet::new(), - } - .get_hash(); - - let signatures_public_keys_map = - secret_keys.iter().map(|secret_key: &common::SecretKey| { - let signature = common::SigScheme::sign(secret_key, target); - let public_key = secret_key.ref_to(); - (public_key, signature) - }); - - let signatures = signatures_public_keys_map - .filter_map(|(public_key, signature)| { - let public_key_index = public_keys_index_map - .get_index_from_public_key(&public_key); - public_key_index - .map(|index| SignatureIndex { signature, index }) - }) - .collect::>(); + // If no signer address is given, then derive the signer's public keys + // from the given secret keys. + let signer = if let Some(addr) = signer { + Signer::Address(addr) + } else { + // Make sure the corresponding public keys can be represented by a + // vector instead of a map + assert!( + secret_keys.keys().cloned().eq(0..(secret_keys.len() as u8)), + "secret keys must be enumerateed when signer address is absent" + ); + Signer::PubKeys(secret_keys.values().map(RefTo::ref_to).collect()) + }; - Self { + // Commit to the given targets + let partial = Self { targets, + signer, + signatures: BTreeMap::new(), + }; + let target = partial.get_raw_hash(); + // Turn the map of secret keys into a map of signatures over the + // commitment made above + let signatures = secret_keys + .iter() + .map(|(index, secret_key)| { + (*index, common::SigScheme::sign(secret_key, target)) + }) + .collect(); + Self { signatures, + ..partial } } @@ -528,14 +541,66 @@ impl MultiSignature { pub fn get_raw_hash(&self) -> crate::types::hash::Hash { Self { - signatures: BTreeSet::new(), + signer: Signer::PubKeys(vec![]), + signatures: BTreeMap::new(), ..self.clone() } .get_hash() } + + /// Verify that the signature contained in this section is valid + pub fn verify_signature( + &self, + verified_pks: &mut HashSet, + public_keys_index_map: &AccountPublicKeysMap, + signer: &Option
, + ) -> std::result::Result { + // Records whether there are any successful verifications + let mut verifications = 0; + match &self.signer { + // Verify the signatures against the given public keys if the + // account addresses match + Signer::Address(addr) if Some(addr) == signer.as_ref() => { + for (idx, sig) in &self.signatures { + if let Some(pk) = + public_keys_index_map.get_public_key_from_index(*idx) + { + common::SigScheme::verify_signature( + &pk, + &self.get_raw_hash(), + sig, + )?; + verified_pks.insert(*idx); + verifications += 1; + } + } + } + // If the account addresses do not match, then there is no efficient + // way to map signatures to the given public keys + Signer::Address(_) => {} + // Verify the signatures against the subset of this section's public + // keys that are also in the given map + Signer::PubKeys(pks) => { + for (idx, pk) in pks.iter().enumerate() { + if let Some(map_idx) = + public_keys_index_map.get_index_from_public_key(pk) + { + common::SigScheme::verify_signature( + pk, + &self.get_raw_hash(), + &self.signatures[&(idx as u8)], + )?; + verified_pks.insert(map_idx); + verifications += 1; + } + } + } + } + Ok(verifications) + } } -/// A section representing the signature over another section +/// A section representing a multisig over another section #[derive( Clone, Debug, @@ -545,58 +610,34 @@ impl MultiSignature { Serialize, Deserialize, )] -pub struct Signature { +pub struct CompressedSignature { /// The hash of the section being signed - targets: Vec, - /// The signature over the above hashes - pub signature: Option, -} - -impl Signature { - pub fn new( - targets: Vec, - sec_key: &common::SecretKey, - ) -> Self { - let mut sec = Self { - targets, - signature: None, - }; - sec.signature = Some(common::SigScheme::sign(sec_key, sec.get_hash())); - sec - } - - /// Hash this signature section - pub fn hash<'a>(&self, hasher: &'a mut Sha256) -> &'a mut Sha256 { - hasher.update( - self.try_to_vec() - .expect("unable to serialize signature section"), - ); - hasher - } - - /// Get the hash of this section - pub fn get_hash(&self) -> crate::types::hash::Hash { - crate::types::hash::Hash( - self.hash(&mut Sha256::new()).finalize_reset().into(), - ) - } - - /// Verify that the signature contained in this section is valid - pub fn verify_signature( - &self, - public_key: &common::PublicKey, - ) -> std::result::Result<(), VerifySigError> { - let signature = - self.signature.as_ref().ok_or(VerifySigError::MissingData)?; - common::SigScheme::verify_signature( - public_key, - &Self { - signature: None, - ..self.clone() + pub targets: Vec, + /// The public keys against which the signatures should be verified + pub signer: Signer, + /// The signature over the above hash + pub signatures: BTreeMap, +} + +impl CompressedSignature { + /// Decompress this signature object with respect to the given transaction + /// by looking up the necessary section hashes. Used by constrained hardware + /// wallets. + pub fn expand(self, tx: &Tx) -> Signature { + let mut targets = Vec::new(); + for idx in self.targets { + if idx == 0 { + // The "zeroth" section is the header + targets.push(tx.header_hash()); + } else { + targets.push(tx.sections[idx as usize - 1].get_hash()); } - .get_hash(), - signature, - ) + } + Signature { + targets, + signer: self.signer, + signatures: self.signatures, + } } } @@ -900,8 +941,6 @@ pub enum Section { ExtraData(Code), /// Transaction code. Sending to hardware wallets optional Code(Code), - /// A transaction signature. Often produced by hardware wallets - SectionSignature(MultiSignature), /// A transaction header/protocol signature Signature(Signature), /// Ciphertext obtained by encrypting arbitrary transaction sections @@ -933,7 +972,6 @@ impl Section { Self::ExtraData(extra) => extra.hash(hasher), Self::Code(code) => code.hash(hasher), Self::Signature(signature) => signature.hash(hasher), - Self::SectionSignature(signatures) => signatures.hash(hasher), Self::Ciphertext(ct) => ct.hash(hasher), Self::MaspBuilder(mb) => mb.hash(hasher), Self::MaspTx(tx) => { @@ -1005,15 +1043,6 @@ impl Section { } } - /// Extract the section signature from this section if possible - pub fn section_signature(&self) -> Option { - if let Self::SectionSignature(data) = self { - Some(data.clone()) - } else { - None - } - } - /// Extract the ciphertext from this section if possible pub fn ciphertext(&self) -> Option { if let Self::Ciphertext(data) = self { @@ -1346,68 +1375,73 @@ impl Tx { /// Verify that the section with the given hash has been signed by the given /// public key - pub fn verify_section_signatures( + pub fn verify_signatures( &self, hashes: &[crate::types::hash::Hash], public_keys_index_map: AccountPublicKeysMap, + signer: &Option
, threshold: u8, max_signatures: Option, - gas_meter: &mut VpGasMeter, - ) -> std::result::Result<(), Error> { + mut gas_meter: Option<&mut VpGasMeter>, + ) -> std::result::Result, Error> { let max_signatures = max_signatures.unwrap_or(u8::MAX); - let mut valid_signatures = 0; + // Records the public key indices used in successful signatures + let mut verified_pks = HashSet::new(); + // Records the sections instrumental in verifying signatures + let mut witnesses = Vec::new(); for section in &self.sections { - if let Section::SectionSignature(signatures) = section { - if !hashes.iter().all(|x| { + if let Section::Signature(signatures) = section { + // Check that the hashes being checked are a subset of those in + // this section. Also ensure that all the sections the signature + // signs over are present. + if hashes.iter().all(|x| { signatures.targets.contains(x) || section.get_hash() == *x - }) { - return Err(Error::InvalidSectionSignature( - "missing target hash.".to_string(), - )); - } - - for target in &signatures.targets { - if self.get_section(target).is_none() { + }) && signatures + .targets + .iter() + .all(|x| self.get_section(x).is_some()) + { + if signatures.total_signatures() > max_signatures { return Err(Error::InvalidSectionSignature( - "Missing target section.".to_string(), + "too many signatures.".to_string(), )); } - } - if signatures.total_signatures() > max_signatures { - return Err(Error::InvalidSectionSignature( - "too many signatures.".to_string(), - )); - } - - if signatures.total_signatures() < threshold { - return Err(Error::InvalidSectionSignature( - "too few signatures.".to_string(), - )); - } - - for signature_index in &signatures.signatures { - let is_valid_signature = signature_index - .verify( + // Finally verify that the signature itself is valid + let prev_verifieds = verified_pks.len(); + let amt_verifieds = signatures + .verify_signature( + &mut verified_pks, &public_keys_index_map, - &signatures.get_raw_hash(), + signer, ) - .is_ok(); - gas_meter - .consume(VERIFY_TX_SIG_GAS_COST) - .map_err(|_| Error::OutOfGas)?; - if is_valid_signature { - valid_signatures += 1; + .map_err(|_| { + Error::InvalidSectionSignature( + "found invalid signature.".to_string(), + ) + }); + // Compute the cost of the signature verifications + if let Some(x) = gas_meter.as_mut() { + let amt_verified = usize::from(amt_verifieds.is_err()) + + verified_pks.len() + - prev_verifieds; + x.consume(VERIFY_TX_SIG_GAS_COST * amt_verified as u64) + .map_err(|_| Error::OutOfGas)?; } - if valid_signatures >= threshold { - return Ok(()); + // Record the section witnessing these signatures + if amt_verifieds? > 0 { + witnesses.push(signatures); + } + // Short-circuit these checks if the threshold is exceeded + if verified_pks.len() >= threshold.into() { + return Ok(witnesses); } } } } Err(Error::InvalidSectionSignature( - "invalid signatures.".to_string(), + "signature threshold not met.".to_string(), )) } @@ -1419,31 +1453,16 @@ impl Tx { public_key: &common::PublicKey, hashes: &[crate::types::hash::Hash], ) -> Result<&Signature> { - for section in &self.sections { - if let Section::Signature(signature) = section { - // Check that the hashes being - // checked are a subset of those in this section - if hashes.iter().all(|x| { - signature.targets.contains(x) || section.get_hash() == *x - }) { - // Ensure that all the sections the signature signs over are - // present - for target in &signature.targets { - if self.get_section(target).is_none() { - return Err(Error::InvalidSectionSignature( - "Target section is missing.".to_string(), - )); - } - } - // Finally verify that the signature itself is valid - return signature - .verify_signature(public_key) - .map(|_| signature) - .map_err(|_| Error::InvalidWrapperSignature); - } - } - } - Err(Error::InvalidWrapperSignature) + self.verify_signatures( + hashes, + AccountPublicKeysMap::from_iter([public_key.clone()].into_iter()), + &None, + 1, + None, + None, + ) + .map(|x| *x.first().unwrap()) + .map_err(|_| Error::InvalidWrapperSignature) } /// Validate any and all ciphertexts stored in this transaction @@ -1466,10 +1485,38 @@ impl Tx { &self, secret_keys: &[common::SecretKey], public_keys_index_map: &AccountPublicKeysMap, - ) -> BTreeSet { + signer: Option
, + ) -> Vec { let targets = self.inner_section_targets(); - MultiSignature::new(targets, secret_keys, public_keys_index_map) - .signatures + let mut signatures = Vec::new(); + let section = Signature::new( + targets, + public_keys_index_map.index_secret_keys(secret_keys.to_vec()), + signer, + ); + match section.signer { + Signer::Address(addr) => { + for (idx, signature) in section.signatures { + signatures.push(SignatureIndex { + pubkey: public_keys_index_map + .get_public_key_from_index(idx) + .unwrap(), + index: Some((addr.clone(), idx)), + signature, + }); + } + } + Signer::PubKeys(pub_keys) => { + for (idx, signature) in section.signatures { + signatures.push(SignatureIndex { + pubkey: pub_keys[idx as usize].clone(), + index: None, + signature, + }); + } + } + } + signatures } /// Decrypt any and all ciphertexts stored in this transaction use the @@ -1718,7 +1765,8 @@ impl Tx { self.protocol_filter(); self.add_section(Section::Signature(Signature::new( self.sechashes(), - &keypair, + [(0, keypair)].into_iter().collect(), + None, ))); self } @@ -1728,27 +1776,53 @@ impl Tx { &mut self, keypairs: Vec, account_public_keys_map: AccountPublicKeysMap, + signer: Option
, ) -> &mut Self { self.protocol_filter(); let hashes = self.inner_section_targets(); - self.add_section(Section::SectionSignature(MultiSignature::new( + self.add_section(Section::Signature(Signature::new( hashes, - &keypairs, - &account_public_keys_map, + account_public_keys_map.index_secret_keys(keypairs), + signer, ))); self } - /// Add signature + /// Add signatures pub fn add_signatures( &mut self, - signatures: BTreeSet, + signatures: Vec, ) -> &mut Self { self.protocol_filter(); - self.add_section(Section::SectionSignature(MultiSignature { + let mut pk_section = Signature { targets: self.inner_section_targets(), - signatures, - })); + signatures: BTreeMap::new(), + signer: Signer::PubKeys(vec![]), + }; + let mut sections = HashMap::new(); + // Put the supplied signatures into the correct sections + for signature in signatures { + if let Some((addr, idx)) = &signature.index { + // Add the signature under the given multisig address + let section = + sections.entry(addr.clone()).or_insert_with(|| Signature { + targets: self.inner_section_targets(), + signatures: BTreeMap::new(), + signer: Signer::Address(addr.clone()), + }); + section.signatures.insert(*idx, signature.signature); + } else if let Signer::PubKeys(pks) = &mut pk_section.signer { + // Add the signature under its corresponding public key + pk_section + .signatures + .insert(pks.len() as u8, signature.signature); + pks.push(signature.pubkey); + } + } + for section in std::iter::once(pk_section).chain(sections.into_values()) + { + self.add_section(Section::Signature(section)); + } self } } diff --git a/core/src/types/account.rs b/core/src/types/account.rs index d66876ba37b..83f0b0aafea 100644 --- a/core/src/types/account.rs +++ b/core/src/types/account.rs @@ -1,12 +1,12 @@ //! Helper structures to manage accounts -use std::collections::HashMap; +use std::collections::{BTreeMap, HashMap}; use borsh::{BorshDeserialize, BorshSerialize}; use serde::{Deserialize, Serialize}; use super::address::Address; -use super::key::common; +use super::key::{common, RefTo}; #[derive( Debug, Clone, BorshSerialize, BorshDeserialize, Serialize, Deserialize, @@ -89,4 +89,18 @@ impl AccountPublicKeysMap { ) -> Option { self.pk_to_idx.get(public_key).cloned() } + + /// Index the given set of secret keys + pub fn index_secret_keys( + &self, + secret_keys: Vec, + ) -> BTreeMap { + secret_keys + .into_iter() + .filter_map(|secret_key: common::SecretKey| { + self.get_index_from_public_key(&secret_key.ref_to()) + .map(|index| (index, secret_key)) + }) + .collect() + } } diff --git a/core/src/types/transaction/mod.rs b/core/src/types/transaction/mod.rs index 6b00e4dfcc7..ba7f4558ef2 100644 --- a/core/src/types/transaction/mod.rs +++ b/core/src/types/transaction/mod.rs @@ -235,7 +235,8 @@ mod test_process_tx { .clone(); tx.add_section(Section::Signature(Signature::new( vec![*tx.code_sechash(), *tx.data_sechash()], - &gen_keypair(), + [(0, gen_keypair())].into_iter().collect(), + None, ))); tx.validate_tx().expect("Test failed"); @@ -271,7 +272,8 @@ mod test_process_tx { tx.set_data(Data::new("transaction data".as_bytes().to_owned())); tx.add_section(Section::Signature(Signature::new( tx.sechashes(), - &keypair, + [(0, keypair)].into_iter().collect(), + None, ))); tx.validate_tx().expect("Test failed"); @@ -364,9 +366,14 @@ fn test_process_tx_decrypted_signed() { // Invalid signed data let ed_sig = ed25519::Signature::try_from_slice([0u8; 64].as_ref()).unwrap(); - let mut sig_sec = - Signature::new(vec![decrypted.header_hash()], &gen_keypair()); - sig_sec.signature = Some(common::Signature::try_from_sig(&ed_sig).unwrap()); + let mut sig_sec = Signature::new( + vec![decrypted.header_hash()], + [(0, gen_keypair())].into_iter().collect(), + None, + ); + sig_sec + .signatures + .insert(0, common::Signature::try_from_sig(&ed_sig).unwrap()); decrypted.add_section(Section::Signature(sig_sec)); // create the tx with signed decrypted data let code_sec = decrypted diff --git a/core/src/types/transaction/protocol.rs b/core/src/types/transaction/protocol.rs index aa9abe8cec8..1a51434b296 100644 --- a/core/src/types/transaction/protocol.rs +++ b/core/src/types/transaction/protocol.rs @@ -201,7 +201,8 @@ mod protocol_txs { outer_tx.set_data(Data::new(tx_data)); outer_tx.add_section(Section::Signature(Signature::new( outer_tx.sechashes(), - signing_key, + [(0, signing_key.clone())].into_iter().collect(), + None, ))); outer_tx } @@ -339,7 +340,8 @@ mod protocol_txs { *outer_tx.code_sechash(), *outer_tx.data_sechash(), ], - signing_key, + [(0, signing_key.clone())].into_iter().collect(), + None, ))); outer_tx } diff --git a/core/src/types/transaction/wrapper.rs b/core/src/types/transaction/wrapper.rs index bda7142220a..0a764fb80c4 100644 --- a/core/src/types/transaction/wrapper.rs +++ b/core/src/types/transaction/wrapper.rs @@ -452,7 +452,8 @@ pub mod wrapper_tx { encrypted_tx.encrypt(&Default::default()); wrapper.add_section(Section::Signature(Signature::new( vec![wrapper.header_hash(), wrapper.sections[0].get_hash()], - &keypair, + [(0, keypair)].into_iter().collect(), + None, ))); assert!(encrypted_tx.validate_ciphertext()); let privkey = ::G2Affine::prime_subgroup_generator(); @@ -489,7 +490,8 @@ pub mod wrapper_tx { wrapper.encrypt(&Default::default()); wrapper.add_section(Section::Signature(Signature::new( vec![wrapper.header_hash(), wrapper.sections[0].get_hash()], - &keypair, + [(0, keypair)].into_iter().collect(), + None, ))); assert!(wrapper.validate_ciphertext()); let privkey = ::G2Affine::prime_subgroup_generator(); @@ -523,7 +525,8 @@ pub mod wrapper_tx { tx.set_data(Data::new("transaction data".as_bytes().to_owned())); tx.add_section(Section::Signature(Signature::new( tx.sechashes(), - &keypair, + [(0, keypair.clone())].into_iter().collect(), + None, ))); // we now try to alter the inner tx maliciously diff --git a/shared/src/ledger/ibc/vp/mod.rs b/shared/src/ledger/ibc/vp/mod.rs index 4e02cb229a5..2d7ebf18f79 100644 --- a/shared/src/ledger/ibc/vp/mod.rs +++ b/shared/src/ledger/ibc/vp/mod.rs @@ -725,7 +725,8 @@ mod tests { outer_tx.set_data(Data::new(tx_data)); outer_tx.add_section(Section::Signature(Signature::new( vec![*outer_tx.code_sechash(), *outer_tx.data_sechash()], - &keypair_1(), + [(0, keypair_1())].into_iter().collect(), + None, ))); let ctx = Ctx::new( &ADDRESS, @@ -1037,7 +1038,8 @@ mod tests { outer_tx.set_data(Data::new(tx_data)); outer_tx.add_section(Section::Signature(Signature::new( vec![*outer_tx.code_sechash(), *outer_tx.data_sechash()], - &keypair_1(), + [(0, keypair_1())].into_iter().collect(), + None, ))); let gas_meter = VpGasMeter::new_from_tx_meter( &TxGasMeter::new_from_sub_limit(TX_GAS_LIMIT.into()), @@ -1370,7 +1372,8 @@ mod tests { outer_tx.set_data(Data::new(tx_data)); outer_tx.add_section(Section::Signature(Signature::new( vec![*outer_tx.code_sechash(), *outer_tx.data_sechash()], - &keypair_1(), + [(0, keypair_1())].into_iter().collect(), + None, ))); let gas_meter = VpGasMeter::new_from_tx_meter( &TxGasMeter::new_from_sub_limit(TX_GAS_LIMIT.into()), @@ -1457,7 +1460,8 @@ mod tests { outer_tx.set_data(Data::new(tx_data)); outer_tx.add_section(Section::Signature(Signature::new( vec![*outer_tx.code_sechash(), *outer_tx.data_sechash()], - &keypair_1(), + [(0, keypair_1())].into_iter().collect(), + None, ))); let gas_meter = VpGasMeter::new_from_tx_meter( &TxGasMeter::new_from_sub_limit(TX_GAS_LIMIT.into()), @@ -1581,7 +1585,8 @@ mod tests { outer_tx.set_data(Data::new(tx_data)); outer_tx.add_section(Section::Signature(Signature::new( vec![*outer_tx.code_sechash(), *outer_tx.data_sechash()], - &keypair_1(), + [(0, keypair_1())].into_iter().collect(), + None, ))); let gas_meter = VpGasMeter::new_from_tx_meter( &TxGasMeter::new_from_sub_limit(TX_GAS_LIMIT.into()), @@ -1704,7 +1709,8 @@ mod tests { outer_tx.set_data(Data::new(tx_data)); outer_tx.add_section(Section::Signature(Signature::new( vec![*outer_tx.code_sechash(), *outer_tx.data_sechash()], - &keypair_1(), + [(0, keypair_1())].into_iter().collect(), + None, ))); let gas_meter = VpGasMeter::new_from_tx_meter( &TxGasMeter::new_from_sub_limit(TX_GAS_LIMIT.into()), @@ -1812,7 +1818,8 @@ mod tests { outer_tx.set_data(Data::new(tx_data)); outer_tx.add_section(Section::Signature(Signature::new( vec![*outer_tx.code_sechash(), *outer_tx.data_sechash()], - &keypair_1(), + [(0, keypair_1())].into_iter().collect(), + None, ))); let gas_meter = VpGasMeter::new_from_tx_meter( &TxGasMeter::new_from_sub_limit(TX_GAS_LIMIT.into()), diff --git a/shared/src/ledger/native_vp/multitoken.rs b/shared/src/ledger/native_vp/multitoken.rs index 0d42e86eaa7..564024fd8f3 100644 --- a/shared/src/ledger/native_vp/multitoken.rs +++ b/shared/src/ledger/native_vp/multitoken.rs @@ -171,7 +171,8 @@ mod tests { tx.set_data(Data::new(tx_data)); tx.add_section(Section::Signature(Signature::new( tx.sechashes(), - &keypair_1(), + [(0, keypair_1())].into_iter().collect(), + None, ))); tx } diff --git a/shared/src/ledger/signing.rs b/shared/src/ledger/signing.rs index 1753c645d35..fd794d9774b 100644 --- a/shared/src/ledger/signing.rs +++ b/shared/src/ledger/signing.rs @@ -63,6 +63,8 @@ const ENV_VAR_TX_LOG_PATH: &str = "NAMADA_TX_LOG_PATH"; /// A struture holding the signing data to craft a transaction #[derive(Clone)] pub struct SigningTxData { + /// The address owning the transaction + pub owner: Option
, /// The public keys associated to an account pub public_keys: Vec, /// The threshold associated to an account @@ -219,7 +221,11 @@ pub fn sign_tx( } }) .collect::>(); - tx.sign_raw(signing_tx_keypairs, account_public_keys_map); + tx.sign_raw( + signing_tx_keypairs, + account_public_keys_map, + signing_data.owner, + ); } let fee_payer_keypair = @@ -237,7 +243,7 @@ pub async fn aux_signing_data< client: &C, wallet: &mut Wallet, args: &args::Tx, - owner: &Option
, + owner: Option
, default_signer: Option
, ) -> Result { let public_keys = if owner.is_some() || args.wrapper_fee_payer.is_none() { @@ -246,7 +252,7 @@ pub async fn aux_signing_data< vec![] }; - let (account_public_keys_map, threshold) = match owner { + let (account_public_keys_map, threshold) = match &owner { Some(owner @ Address::Established(_)) => { let account = rpc::get_account_info::(client, owner).await?; if let Some(account) = account { @@ -284,6 +290,7 @@ pub async fn aux_signing_data< } Ok(SigningTxData { + owner, public_keys, threshold, account_public_keys_map, diff --git a/shared/src/vm/host_env.rs b/shared/src/vm/host_env.rs index 179472a8906..c53cc73254e 100644 --- a/shared/src/vm/host_env.rs +++ b/shared/src/vm/host_env.rs @@ -1796,6 +1796,8 @@ pub fn vp_verify_tx_section_signature( hash_list_len: u64, public_keys_map_ptr: u64, public_keys_map_len: u64, + signer_ptr: u64, + signer_len: u64, threshold: u8, max_signatures_ptr: u64, max_signatures_len: u64, @@ -1828,6 +1830,14 @@ where ) .map_err(vp_host_fns::RuntimeError::EncodingError)?; + let (signer, gas) = env + .memory + .read_bytes(signer_ptr, signer_len as _) + .map_err(|e| vp_host_fns::RuntimeError::MemoryError(Box::new(e)))?; + vp_host_fns::add_gas(gas_meter, gas)?; + let signer = Address::try_from_slice(&signer) + .map_err(vp_host_fns::RuntimeError::EncodingError)?; + let (max_signatures, gas) = env .memory .read_bytes(max_signatures_ptr, max_signatures_len as _) @@ -1839,12 +1849,13 @@ where let tx = unsafe { env.ctx.tx.get() }; Ok(HostEnvResult::from( - tx.verify_section_signatures( + tx.verify_signatures( &hashes, public_keys_map, + &Some(signer), threshold, max_signatures, - gas_meter, + Some(gas_meter), ) .is_ok(), ) diff --git a/tests/src/vm_host_env/mod.rs b/tests/src/vm_host_env/mod.rs index fe61570fb8b..27545c644e4 100644 --- a/tests/src/vm_host_env/mod.rs +++ b/tests/src/vm_host_env/mod.rs @@ -466,7 +466,7 @@ mod tests { let mut tx = Tx::new(chain_id, expiration); tx.add_code(code.clone()) .add_serialized_data(data.to_vec()) - .sign_raw(keypairs.clone(), pks_map.clone()) + .sign_raw(keypairs.clone(), pks_map.clone(), None) .sign_wrapper(keypair.clone()); env.tx = tx; env.tx.clone() @@ -474,17 +474,18 @@ mod tests { assert_eq!(signed_tx_data.data().as_ref(), Some(data)); assert!( signed_tx_data - .verify_section_signatures( + .verify_signatures( &[ *signed_tx_data.data_sechash(), *signed_tx_data.code_sechash(), ], pks_map, + &None, 1, None, - &mut VpGasMeter::new_from_tx_meter( + Some(&mut VpGasMeter::new_from_tx_meter( &TxGasMeter::new_from_sub_limit(u64::MAX.into()) - ) + )) ) .is_ok() ); @@ -492,7 +493,7 @@ mod tests { let other_keypair = key::testing::keypair_2(); assert!( signed_tx_data - .verify_section_signatures( + .verify_signatures( &[ *signed_tx_data.data_sechash(), *signed_tx_data.code_sechash(), @@ -500,11 +501,12 @@ mod tests { AccountPublicKeysMap::from_iter([ other_keypair.ref_to() ]), + &None, 1, None, - &mut VpGasMeter::new_from_tx_meter( + Some(&mut VpGasMeter::new_from_tx_meter( &TxGasMeter::new_from_sub_limit(u64::MAX.into()) - ) + )) ) .is_err() ); @@ -567,7 +569,7 @@ mod tests { let mut tx = Tx::new(ChainId::default(), None); tx.add_code(vec![]) .add_serialized_data(input_data.clone()) - .sign_raw(keypairs.clone(), pks_map.clone()) + .sign_raw(keypairs.clone(), pks_map.clone(), None) .sign_wrapper(keypair.clone()); let result = vp::CTX.eval(empty_code, tx).unwrap(); assert!(!result); @@ -589,7 +591,7 @@ mod tests { let mut tx = Tx::new(ChainId::default(), None); tx.add_code_from_hash(code_hash) .add_serialized_data(input_data.clone()) - .sign_raw(keypairs.clone(), pks_map.clone()) + .sign_raw(keypairs.clone(), pks_map.clone(), None) .sign_wrapper(keypair.clone()); let result = vp::CTX.eval(code_hash, tx).unwrap(); assert!(result); @@ -612,7 +614,7 @@ mod tests { let mut tx = Tx::new(ChainId::default(), None); tx.add_code_from_hash(code_hash) .add_serialized_data(input_data) - .sign_raw(keypairs, pks_map) + .sign_raw(keypairs, pks_map, None) .sign_wrapper(keypair); let result = vp::CTX.eval(code_hash, tx).unwrap(); assert!(!result); @@ -637,7 +639,7 @@ mod tests { let mut tx = Tx::new(ChainId::default(), None); tx.add_code(vec![]) .add_serialized_data(tx_data.clone()) - .sign_raw(keypairs.clone(), pks_map.clone()) + .sign_raw(keypairs.clone(), pks_map.clone(), None) .sign_wrapper(keypair.clone()); // create a client with the message @@ -671,7 +673,7 @@ mod tests { let mut tx = Tx::new(ChainId::default(), None); tx.add_code(vec![]) .add_serialized_data(tx_data.clone()) - .sign_raw(keypairs, pks_map) + .sign_raw(keypairs, pks_map, None) .sign_wrapper(keypair); // update the client with the message tx_host_env::ibc::ibc_actions(tx::ctx()) @@ -714,7 +716,7 @@ mod tests { let mut tx = Tx::new(ChainId::default(), None); tx.add_code(vec![]) .add_serialized_data(tx_data.clone()) - .sign_raw(keypairs.clone(), pks_map.clone()) + .sign_raw(keypairs.clone(), pks_map.clone(), None) .sign_wrapper(keypair.clone()); // init a connection with the message tx_host_env::ibc::ibc_actions(tx::ctx()) @@ -747,7 +749,7 @@ mod tests { let mut tx = Tx::new(ChainId::default(), None); tx.add_code(vec![]) .add_serialized_data(tx_data.clone()) - .sign_raw(keypairs, pks_map) + .sign_raw(keypairs, pks_map, None) .sign_wrapper(keypair); // open the connection with the message tx_host_env::ibc::ibc_actions(tx::ctx()) @@ -791,7 +793,7 @@ mod tests { let mut tx = Tx::new(ChainId::default(), None); tx.add_code(vec![]) .add_serialized_data(tx_data.clone()) - .sign_raw(keypairs.clone(), pks_map.clone()) + .sign_raw(keypairs.clone(), pks_map.clone(), None) .sign_wrapper(keypair.clone()); // open try a connection with the message tx_host_env::ibc::ibc_actions(tx::ctx()) @@ -824,7 +826,7 @@ mod tests { let mut tx = Tx::new(ChainId::default(), None); tx.add_code(vec![]) .add_serialized_data(tx_data.clone()) - .sign_raw(keypairs, pks_map) + .sign_raw(keypairs, pks_map, None) .sign_wrapper(keypair); // open the connection with the mssage tx_host_env::ibc::ibc_actions(tx::ctx()) @@ -870,7 +872,7 @@ mod tests { let mut tx = Tx::new(ChainId::default(), None); tx.add_code(vec![]) .add_serialized_data(tx_data.clone()) - .sign_raw(keypairs.clone(), pks_map.clone()) + .sign_raw(keypairs.clone(), pks_map.clone(), None) .sign_wrapper(keypair.clone()); // init a channel with the message tx_host_env::ibc::ibc_actions(tx::ctx()) @@ -903,7 +905,7 @@ mod tests { let mut tx = Tx::new(ChainId::default(), None); tx.add_code(vec![]) .add_serialized_data(tx_data.clone()) - .sign_raw(keypairs, pks_map) + .sign_raw(keypairs, pks_map, None) .sign_wrapper(keypair); // open the channle with the message tx_host_env::ibc::ibc_actions(tx::ctx()) @@ -949,7 +951,7 @@ mod tests { let mut tx = Tx::new(ChainId::default(), None); tx.add_code(vec![]) .add_serialized_data(tx_data.clone()) - .sign_raw(keypairs.clone(), pks_map.clone()) + .sign_raw(keypairs.clone(), pks_map.clone(), None) .sign_wrapper(keypair.clone()); // try open a channel with the message tx_host_env::ibc::ibc_actions(tx::ctx()) @@ -983,7 +985,7 @@ mod tests { let mut tx = Tx::new(ChainId::default(), None); tx.add_code(vec![]) .add_serialized_data(tx_data.clone()) - .sign_raw(keypairs, pks_map) + .sign_raw(keypairs, pks_map, None) .sign_wrapper(keypair); // open a channel with the message tx_host_env::ibc::ibc_actions(tx::ctx()) @@ -1032,7 +1034,7 @@ mod tests { let mut tx = Tx::new(ChainId::default(), None); tx.add_code(vec![]) .add_serialized_data(tx_data.clone()) - .sign_raw(keypairs, pks_map) + .sign_raw(keypairs, pks_map, None) .sign_wrapper(keypair); // close the channel with the message let mut actions = tx_host_env::ibc::ibc_actions(tx::ctx()); @@ -1089,7 +1091,7 @@ mod tests { let mut tx = Tx::new(ChainId::default(), None); tx.add_code(vec![]) .add_serialized_data(tx_data.clone()) - .sign_raw(keypairs, pks_map) + .sign_raw(keypairs, pks_map, None) .sign_wrapper(keypair); // close the channel with the message @@ -1143,7 +1145,7 @@ mod tests { let mut tx = Tx::new(ChainId::default(), None); tx.add_code(vec![]) .add_serialized_data(tx_data.clone()) - .sign_raw(keypairs.clone(), pks_map.clone()) + .sign_raw(keypairs.clone(), pks_map.clone(), None) .sign_wrapper(keypair.clone()); // send the token and a packet with the data tx_host_env::ibc::ibc_actions(tx::ctx()) @@ -1190,7 +1192,7 @@ mod tests { let mut tx = Tx::new(ChainId::default(), None); tx.add_code(vec![]) .add_serialized_data(tx_data.clone()) - .sign_raw(keypairs, pks_map) + .sign_raw(keypairs, pks_map, None) .sign_wrapper(keypair); // ack the packet with the message tx_host_env::ibc::ibc_actions(tx::ctx()) @@ -1280,7 +1282,7 @@ mod tests { let mut tx = Tx::new(ChainId::default(), None); tx.add_code(vec![]) .add_serialized_data(tx_data.clone()) - .sign_raw(keypairs, pks_map) + .sign_raw(keypairs, pks_map, None) .sign_wrapper(keypair); // send the token and a packet with the data tx_host_env::ibc::ibc_actions(tx::ctx()) @@ -1353,7 +1355,7 @@ mod tests { let mut tx = Tx::new(ChainId::default(), None); tx.add_code(vec![]) .add_serialized_data(tx_data.clone()) - .sign_raw(keypairs, pks_map) + .sign_raw(keypairs, pks_map, None) .sign_wrapper(keypair); // receive a packet with the message tx_host_env::ibc::ibc_actions(tx::ctx()) @@ -1432,7 +1434,7 @@ mod tests { let mut tx = Tx::new(ChainId::default(), None); tx.add_code(vec![]) .add_serialized_data(tx_data.clone()) - .sign_raw(keypairs, pks_map) + .sign_raw(keypairs, pks_map, None) .sign_wrapper(keypair); // Receive the packet, but no token is received tx_host_env::ibc::ibc_actions(tx::ctx()) @@ -1536,7 +1538,7 @@ mod tests { let mut tx = Tx::new(ChainId::default(), None); tx.add_code(vec![]) .add_serialized_data(tx_data.clone()) - .sign_raw(keypairs, pks_map) + .sign_raw(keypairs, pks_map, None) .sign_wrapper(keypair); // receive a packet with the message tx_host_env::ibc::ibc_actions(tx::ctx()) @@ -1641,7 +1643,7 @@ mod tests { let mut tx = Tx::new(ChainId::default(), None); tx.add_code(vec![]) .add_serialized_data(tx_data.clone()) - .sign_raw(keypairs, pks_map) + .sign_raw(keypairs, pks_map, None) .sign_wrapper(keypair); // receive a packet with the message tx_host_env::ibc::ibc_actions(tx::ctx()) @@ -1741,7 +1743,7 @@ mod tests { let mut tx = Tx::new(ChainId::default(), None); tx.add_code(vec![]) .add_serialized_data(tx_data.clone()) - .sign_raw(keypairs, pks_map) + .sign_raw(keypairs, pks_map, None) .sign_wrapper(keypair); // timeout the packet @@ -1830,7 +1832,7 @@ mod tests { let mut tx = Tx::new(ChainId::default(), None); tx.add_code(vec![]) .add_serialized_data(tx_data.clone()) - .sign_raw(keypairs, pks_map) + .sign_raw(keypairs, pks_map, None) .sign_wrapper(keypair); // timeout the packet diff --git a/tests/src/vm_host_env/vp.rs b/tests/src/vm_host_env/vp.rs index 7324fbd90ec..4bdb1893fdd 100644 --- a/tests/src/vm_host_env/vp.rs +++ b/tests/src/vm_host_env/vp.rs @@ -379,6 +379,8 @@ mod native_vp_host_env { hash_list_len: u64, public_keys_map_ptr: u64, public_keys_map_len: u64, + signer_ptr: u64, + signer_len: u64, threshold: u8, max_signatures_ptr: u64, max_signatures_len: u64,) diff --git a/vm_env/src/lib.rs b/vm_env/src/lib.rs index 099460258b8..33e2a9c0d8e 100644 --- a/vm_env/src/lib.rs +++ b/vm_env/src/lib.rs @@ -202,6 +202,8 @@ pub mod vp { hash_list_len: u64, public_keys_map_ptr: u64, public_keys_map_len: u64, + signer_ptr: u64, + signer_len: u64, threshold: u8, max_signatures_ptr: u64, max_signatures_len: u64, diff --git a/vp_prelude/src/lib.rs b/vp_prelude/src/lib.rs index 32e29df46b7..95239644a63 100644 --- a/vp_prelude/src/lib.rs +++ b/vp_prelude/src/lib.rs @@ -94,6 +94,7 @@ pub fn verify_signatures(ctx: &Ctx, tx: &Tx, owner: &Address) -> VpResult { let max_signatures = max_signatures_per_transaction.try_to_vec().unwrap(); let public_keys_map = public_keys_index_map.try_to_vec().unwrap(); let targets = targets.try_to_vec().unwrap(); + let signer = owner.try_to_vec().unwrap(); let valid = unsafe { namada_vp_verify_tx_section_signature( @@ -101,6 +102,8 @@ pub fn verify_signatures(ctx: &Ctx, tx: &Tx, owner: &Address) -> VpResult { targets.len() as _, public_keys_map.as_ptr() as _, public_keys_map.len() as _, + signer.as_ptr() as _, + signer.len() as _, threshold, max_signatures.as_ptr() as _, max_signatures.len() as _, diff --git a/wasm/checksums.json b/wasm/checksums.json index 9c50dd46dc8..7ffb5759831 100644 --- a/wasm/checksums.json +++ b/wasm/checksums.json @@ -1,23 +1,23 @@ { - "tx_bond.wasm": "tx_bond.8d1ddbeb397209c5efa22dd57fbdb31825d67c2942441cb2612583ec2593831a.wasm", - "tx_bridge_pool.wasm": "tx_bridge_pool.41ada308019a6227a495d996f5d3248e3f8052fcadf8779ee2b2e293aa73ccd0.wasm", - "tx_change_validator_commission.wasm": "tx_change_validator_commission.137f2871848970aa9cf1d3a92a1e1a6e7a48b0537632d838bbb4e69fd301f8c3.wasm", - "tx_ibc.wasm": "tx_ibc.af007e03e8de1f8c34eb928fcfe91fd44b05c0183ca1149c5b262c8f62fcdd36.wasm", - "tx_init_account.wasm": "tx_init_account.d527ea17b417fca1a72d6a26abc34219630efcad4701e629a89e026e06ee06c1.wasm", - "tx_init_proposal.wasm": "tx_init_proposal.e605bb96ff8b6ad1e10491a81590d15ed792f87b0382d1faee9966cb25a09028.wasm", - "tx_init_validator.wasm": "tx_init_validator.91ce97ff0bfa49ce9baa7585ae7e2c0514e91a66c625502b4aced635da5b021a.wasm", - "tx_resign_steward.wasm": "tx_resign_steward.a34a5737653182ecb75f6fcbac5b74ef849eb29b0072a20e90897acc14d8886e.wasm", - "tx_reveal_pk.wasm": "tx_reveal_pk.8ab38f516ac799dcb96ba372cd5e5defd381ddf9d69579ce1556d1721d34f668.wasm", - "tx_transfer.wasm": "tx_transfer.738ac69d4a4f3dfb154aeed6b806ef1042b1a707de98bf8c6cc5ad66d478f6d9.wasm", - "tx_unbond.wasm": "tx_unbond.0c90a1f9a95b7171e0ebdca8318c19ba45f358158aa68370f630f84025635c8f.wasm", - "tx_unjail_validator.wasm": "tx_unjail_validator.310c196cb7b2d371bb74fe37ee1f2f7e233ead59477027891e4e28751b6bb3fe.wasm", - "tx_update_account.wasm": "tx_update_account.8f5934e4fcca4e7d3c58e1c0b8722ce0a948efa6b99e7801dd1c16f8ea22fb59.wasm", - "tx_update_steward_commission.wasm": "tx_update_steward_commission.3deda3d2d0fcce2e14c6a4d72931ea3a3713666c6eed5fd29a78e30d395b3cf5.wasm", - "tx_vote_proposal.wasm": "tx_vote_proposal.33567afd0c59d5f2499a3cf4ebf3c254de1cae1d310d004b8e0e538f2fc8377a.wasm", - "tx_withdraw.wasm": "tx_withdraw.00e0a04e892eb67ac3c3c7a3162b12dc198506c1c466893923911c3ab471dc03.wasm", - "vp_implicit.wasm": "vp_implicit.0fc8114c5d87db4d818b4b38ded664c1ca1d3d42026e6b1328213c00e99f01eb.wasm", - "vp_masp.wasm": "vp_masp.8b01ab3c616342973fb30e37c8b9e4c83615f25b7cc6657f0360146266d36890.wasm", - "vp_testnet_faucet.wasm": "vp_testnet_faucet.720d6808fa225cb3381ac0ff682e1c9136d8ef1193933ce30356ef2252fee001.wasm", - "vp_user.wasm": "vp_user.f93b90d5a0226c79159edd48f2801e7a12525751b937fda58525a8fc8b42d745.wasm", - "vp_validator.wasm": "vp_validator.3decad0fd761b928cdec3f89ed241fc218dd402be300f5edabf511677ae3d37d.wasm" + "tx_bond.wasm": "tx_bond.a45305b1984005309b77d5d7125f15436cc0d6397839bc74210877363a978b3c.wasm", + "tx_bridge_pool.wasm": "tx_bridge_pool.c6a9ee9dc86ab7c25f54c7ffed6324f6cdc59a66acb0b0893a734e18025856f3.wasm", + "tx_change_validator_commission.wasm": "tx_change_validator_commission.9c06096b65713755e3ee90490949497bbf99bb2a3a5b1043bced13acc6034ca9.wasm", + "tx_ibc.wasm": "tx_ibc.7d1d9c34e69eac9069c40d8e20a89894623f4062097417407c4ddde303f40b18.wasm", + "tx_init_account.wasm": "tx_init_account.f13534a21b8afd058e4e64366961bd5864864956cc915a745ad3cc087eb0a6d7.wasm", + "tx_init_proposal.wasm": "tx_init_proposal.46844bfdbb8bfbbf44bd4eafb7cd25466631b2adf19e3ba769fe46fd52f18257.wasm", + "tx_init_validator.wasm": "tx_init_validator.bec486bb8ca3ddc54019ee0b8f65849ec1f886e515c65e85a006233412fd9aac.wasm", + "tx_resign_steward.wasm": "tx_resign_steward.cbc73594470c7d8a7546fddaeb5be2af0f063431c79735fb957c1cf9e9122a02.wasm", + "tx_reveal_pk.wasm": "tx_reveal_pk.55477e7a6c7c8d624206396beb7f3406624460b41a783d299d3c3d5ccc1940c5.wasm", + "tx_transfer.wasm": "tx_transfer.3f22ef22dd8f1fe51bbef73a9750923b364e3c58349dc7e650eecb7ea2b57536.wasm", + "tx_unbond.wasm": "tx_unbond.182682e3a0cd37a005242a801c4775961963cfd9b4e60d03f10a123252585d55.wasm", + "tx_unjail_validator.wasm": "tx_unjail_validator.ac2149f640f06600c4537ebad7fa5c94eb4feb3a57ce6fa39ac43dc2d77f2016.wasm", + "tx_update_account.wasm": "tx_update_account.7b53a6bb499a183eb9e42da2b9a7e3296303706f211c796d60d1476bea706250.wasm", + "tx_update_steward_commission.wasm": "tx_update_steward_commission.fb58be64d742ec709cd7f1751a73158fbc3c0e7e596e6f7ee2b1e2b0e4c1b664.wasm", + "tx_vote_proposal.wasm": "tx_vote_proposal.3afc69680243b68b2b866bdb827a3e901b18afe27bf85bb04019a26dfc1c6109.wasm", + "tx_withdraw.wasm": "tx_withdraw.f838cfa0723c2748369f70125e1317ea6a4604c1f187185eab23151557388740.wasm", + "vp_implicit.wasm": "vp_implicit.16cf20b2caa01a6003ddbe73776b187a4633ba42a4a1881c9d5528c6abe5d7f5.wasm", + "vp_masp.wasm": "vp_masp.15f3d99564bbe3c42f89447448f81f3080adbfc04279faf7b1ddbc1e4160f4d0.wasm", + "vp_testnet_faucet.wasm": "vp_testnet_faucet.5219b9bceebe7fc38370865c6f137a113f51ad7b53c042df3f71e474e026112a.wasm", + "vp_user.wasm": "vp_user.1c05c88ecb42362753e672db473770bb46b5685449d810cf407bde68d906f08c.wasm", + "vp_validator.wasm": "vp_validator.7d51c286b21d36d81a5e972d6a54ab94ee1ffa9e39356931b7dcbc9f9cea4e91.wasm" } \ No newline at end of file diff --git a/wasm/wasm_source/src/vp_implicit.rs b/wasm/wasm_source/src/vp_implicit.rs index a67b40d357b..215dccf421d 100644 --- a/wasm/wasm_source/src/vp_implicit.rs +++ b/wasm/wasm_source/src/vp_implicit.rs @@ -187,7 +187,7 @@ fn validate_tx( mod tests { // Use this as `#[test]` annotation to enable logging use namada::ledger::pos::{GenesisValidator, PosParams}; - use namada::proto::{Code, Data, MultiSignature}; + use namada::proto::{Code, Data, Signature}; use namada::types::dec::Dec; use namada::types::storage::Epoch; use namada::types::transaction::TxType; @@ -535,10 +535,10 @@ mod tests { let mut tx = vp_env.tx.clone(); tx.set_data(Data::new(vec![])); tx.set_code(Code::new(vec![])); - tx.add_section(Section::SectionSignature(MultiSignature::new( + tx.add_section(Section::Signature(Signature::new( vec![*tx.data_sechash(), *tx.code_sechash()], - &[secret_key], - &pks_map, + pks_map.index_secret_keys(vec![secret_key]), + None, ))); let signed_tx = tx.clone(); @@ -671,10 +671,10 @@ mod tests { let mut tx = vp_env.tx.clone(); tx.set_data(Data::new(vec![])); tx.set_code(Code::new(vec![])); - tx.add_section(Section::SectionSignature(MultiSignature::new( + tx.add_section(Section::Signature(Signature::new( vec![*tx.data_sechash(), *tx.code_sechash()], - &[secret_key], - &pks_map, + pks_map.index_secret_keys(vec![secret_key]), + None, ))); let signed_tx = tx.clone(); @@ -839,10 +839,10 @@ mod tests { let mut tx = vp_env.tx.clone(); tx.set_data(Data::new(vec![])); tx.set_code(Code::new(vec![])); - tx.add_section(Section::SectionSignature(MultiSignature::new( + tx.add_section(Section::Signature(Signature::new( vec![*tx.data_sechash(), *tx.code_sechash()], - &[secret_key], - &pks_map, + pks_map.index_secret_keys(vec![secret_key]), + None, ))); let signed_tx = tx.clone(); vp_env.tx = signed_tx.clone(); @@ -932,10 +932,10 @@ mod tests { let mut tx = vp_env.tx.clone(); tx.set_data(Data::new(vec![])); tx.set_code(Code::new(vec![])); - tx.add_section(Section::SectionSignature(MultiSignature::new( + tx.add_section(Section::Signature(Signature::new( vec![*tx.data_sechash(), *tx.code_sechash()], - &[secret_key], - &pks_map, + pks_map.index_secret_keys(vec![secret_key]), + None, ))); let signed_tx = tx.clone(); vp_env.tx = signed_tx.clone(); @@ -987,10 +987,10 @@ mod tests { let mut tx = vp_env.tx.clone(); tx.set_code(Code::new(vec![])); tx.set_data(Data::new(vec![])); - tx.add_section(Section::SectionSignature(MultiSignature::new( + tx.add_section(Section::Signature(Signature::new( vec![*tx.data_sechash(), *tx.code_sechash()], - &[secret_key], - &pks_map, + pks_map.index_secret_keys(vec![secret_key]), + None, ))); let signed_tx = tx.clone(); vp_env.tx = signed_tx.clone(); diff --git a/wasm/wasm_source/src/vp_testnet_faucet.rs b/wasm/wasm_source/src/vp_testnet_faucet.rs index 44b5adfb06e..7298c0b1260 100644 --- a/wasm/wasm_source/src/vp_testnet_faucet.rs +++ b/wasm/wasm_source/src/vp_testnet_faucet.rs @@ -108,7 +108,7 @@ fn validate_tx( #[cfg(test)] mod tests { use address::testing::arb_non_internal_address; - use namada::proto::{Code, Data, MultiSignature, Signature}; + use namada::proto::{Code, Data, Signature}; use namada::types::transaction::TxType; use namada_test_utils::TestWasms; // Use this as `#[test]` annotation to enable logging @@ -266,10 +266,10 @@ mod tests { let mut tx = vp_env.tx.clone(); tx.set_data(Data::new(vec![])); tx.set_code(Code::new(vec![])); - tx.add_section(Section::SectionSignature(MultiSignature::new( + tx.add_section(Section::Signature(Signature::new( vec![*tx.data_sechash(), *tx.code_sechash()], - &[keypair], - &pks_map, + pks_map.index_secret_keys(vec![keypair]), + None, ))); let signed_tx = tx.clone(); vp_env.tx = signed_tx.clone(); @@ -399,7 +399,11 @@ mod tests { let mut tx_data = Tx::from_type(TxType::Raw); tx_data.set_data(Data::new(solution_bytes)); tx_data.set_code(Code::new(vec![])); - tx_data.add_section(Section::Signature(Signature::new(vec![*tx_data.data_sechash(), *tx_data.code_sechash()], &target_key))); + tx_data.add_section(Section::Signature(Signature::new( + vec![*tx_data.data_sechash(), *tx_data.code_sechash()], + [(0, target_key)].into_iter().collect(), + None, + ))); let keys_changed: BTreeSet = vp_env.all_touched_storage_keys(); let verifiers: BTreeSet
= BTreeSet::default(); @@ -449,10 +453,10 @@ mod tests { let mut tx = vp_env.tx.clone(); tx.set_data(Data::new(vec![])); tx.set_code(Code::new(vec![])); - tx.add_section(Section::SectionSignature(MultiSignature::new( + tx.add_section(Section::Signature(Signature::new( vec![*tx.data_sechash(), *tx.code_sechash()], - &[keypair], - &pks_map, + pks_map.index_secret_keys(vec![keypair]), + None, ))); let signed_tx = tx.clone(); vp_env.tx = signed_tx.clone(); diff --git a/wasm/wasm_source/src/vp_user.rs b/wasm/wasm_source/src/vp_user.rs index 5f0b70b506f..a334576b530 100644 --- a/wasm/wasm_source/src/vp_user.rs +++ b/wasm/wasm_source/src/vp_user.rs @@ -185,7 +185,7 @@ fn validate_tx( mod tests { use address::testing::arb_non_internal_address; use namada::ledger::pos::{GenesisValidator, PosParams}; - use namada::proto::{Code, Data, MultiSignature}; + use namada::proto::{Code, Data, Signature}; use namada::types::dec::Dec; use namada::types::storage::Epoch; use namada::types::transaction::TxType; @@ -392,10 +392,10 @@ mod tests { let mut tx = vp_env.tx.clone(); tx.set_data(Data::new(vec![])); tx.set_code(Code::new(vec![])); - tx.add_section(Section::SectionSignature(MultiSignature::new( + tx.add_section(Section::Signature(Signature::new( vec![*tx.data_sechash(), *tx.code_sechash()], - &[keypair], - &pks_map, + pks_map.index_secret_keys(vec![keypair]), + None, ))); let signed_tx = tx.clone(); vp_env.tx = signed_tx.clone(); @@ -561,10 +561,10 @@ mod tests { let mut tx = vp_env.tx.clone(); tx.set_data(Data::new(vec![])); tx.set_code(Code::new(vec![])); - tx.add_section(Section::SectionSignature(MultiSignature::new( + tx.add_section(Section::Signature(Signature::new( vec![*tx.data_sechash(), *tx.code_sechash()], - &[secret_key], - &pks_map, + pks_map.index_secret_keys(vec![secret_key]), + None, ))); let signed_tx = tx.clone(); vp_env.tx = signed_tx.clone(); @@ -723,7 +723,11 @@ mod tests { let mut tx = vp_env.tx.clone(); tx.set_code(Code::new(vec![])); tx.set_data(Data::new(vec![])); - tx.add_section(Section::SectionSignature(MultiSignature::new(vec![*tx.data_sechash(), *tx.code_sechash()], &[keypair], &pks_map))); + tx.add_section(Section::Signature(Signature::new( + vec![*tx.data_sechash(), *tx.code_sechash()], + pks_map.index_secret_keys(vec![keypair]), + None, + ))); let signed_tx = tx.clone(); vp_env.tx = signed_tx.clone(); let keys_changed: BTreeSet = @@ -806,10 +810,10 @@ mod tests { let mut tx = vp_env.tx.clone(); tx.set_data(Data::new(vec![])); tx.set_code(Code::new(vec![])); - tx.add_section(Section::SectionSignature(MultiSignature::new( + tx.add_section(Section::Signature(Signature::new( vec![*tx.data_sechash(), *tx.code_sechash()], - &[keypair], - &pks_map, + pks_map.index_secret_keys(vec![keypair]), + None, ))); let signed_tx = tx.clone(); vp_env.tx = signed_tx.clone(); @@ -861,10 +865,10 @@ mod tests { let mut tx = vp_env.tx.clone(); tx.set_data(Data::new(vec![])); tx.set_code(Code::new(vec![])); - tx.add_section(Section::SectionSignature(MultiSignature::new( + tx.add_section(Section::Signature(Signature::new( vec![*tx.data_sechash(), *tx.code_sechash()], - &[keypair], - &pks_map, + pks_map.index_secret_keys(vec![keypair]), + None, ))); let signed_tx = tx.clone(); vp_env.tx = signed_tx.clone(); @@ -917,10 +921,10 @@ mod tests { let mut tx = vp_env.tx.clone(); tx.set_data(Data::new(vec![])); tx.set_code(Code::new(vec![])); - tx.add_section(Section::SectionSignature(MultiSignature::new( + tx.add_section(Section::Signature(Signature::new( vec![*tx.data_sechash(), *tx.code_sechash()], - &[keypair], - &pks_map, + pks_map.index_secret_keys(vec![keypair]), + None, ))); let signed_tx = tx.clone(); vp_env.tx = signed_tx.clone(); @@ -973,10 +977,10 @@ mod tests { let mut tx = vp_env.tx.clone(); tx.set_data(Data::new(vec![])); tx.set_code(Code::new(vec![])); - tx.add_section(Section::SectionSignature(MultiSignature::new( + tx.add_section(Section::Signature(Signature::new( vec![*tx.data_sechash(), *tx.code_sechash()], - &[keypair], - &pks_map, + pks_map.index_secret_keys(vec![keypair]), + None, ))); let signed_tx = tx.clone(); vp_env.tx = signed_tx.clone(); @@ -1029,10 +1033,10 @@ mod tests { let mut tx = vp_env.tx.clone(); tx.set_code(Code::new(vec![])); tx.set_data(Data::new(vec![])); - tx.add_section(Section::SectionSignature(MultiSignature::new( + tx.add_section(Section::Signature(Signature::new( vec![*tx.data_sechash(), *tx.code_sechash()], - &[keypair], - &pks_map, + pks_map.index_secret_keys(vec![keypair]), + None, ))); let signed_tx = tx.clone(); vp_env.tx = signed_tx.clone(); diff --git a/wasm/wasm_source/src/vp_validator.rs b/wasm/wasm_source/src/vp_validator.rs index f1418e38e11..f929a8a0d1e 100644 --- a/wasm/wasm_source/src/vp_validator.rs +++ b/wasm/wasm_source/src/vp_validator.rs @@ -192,7 +192,7 @@ fn validate_tx( mod tests { use address::testing::arb_non_internal_address; use namada::ledger::pos::{GenesisValidator, PosParams}; - use namada::proto::{Code, Data, MultiSignature}; + use namada::proto::{Code, Data, Signature}; use namada::types::dec::Dec; use namada::types::storage::Epoch; use namada::types::transaction::TxType; @@ -399,10 +399,10 @@ mod tests { let mut tx = vp_env.tx.clone(); tx.set_data(Data::new(vec![])); tx.set_code(Code::new(vec![])); - tx.add_section(Section::SectionSignature(MultiSignature::new( + tx.add_section(Section::Signature(Signature::new( vec![*tx.data_sechash(), *tx.code_sechash()], - &[keypair], - &pks_map, + pks_map.index_secret_keys(vec![keypair]), + None, ))); let signed_tx = tx.clone(); vp_env.tx = signed_tx.clone(); @@ -579,10 +579,10 @@ mod tests { let mut tx = vp_env.tx.clone(); tx.set_data(Data::new(vec![])); tx.set_code(Code::new(vec![])); - tx.add_section(Section::SectionSignature(MultiSignature::new( + tx.add_section(Section::Signature(Signature::new( vec![*tx.data_sechash(), *tx.code_sechash()], - &[secret_key], - &pks_map, + pks_map.index_secret_keys(vec![secret_key]), + None, ))); let signed_tx = tx.clone(); vp_env.tx = signed_tx.clone(); @@ -741,7 +741,11 @@ mod tests { let mut tx = vp_env.tx.clone(); tx.set_data(Data::new(vec![])); tx.set_code(Code::new(vec![])); - tx.add_section(Section::SectionSignature(MultiSignature::new(vec![*tx.data_sechash(), *tx.code_sechash()], &[keypair], &pks_map))); + tx.add_section(Section::Signature(Signature::new( + vec![*tx.data_sechash(), *tx.code_sechash()], + pks_map.index_secret_keys(vec![keypair]), + None, + ))); let signed_tx = tx.clone(); vp_env.tx = signed_tx.clone(); let keys_changed: BTreeSet = @@ -823,10 +827,10 @@ mod tests { let mut tx = vp_env.tx.clone(); tx.set_data(Data::new(vec![])); tx.set_code(Code::new(vec![])); - tx.add_section(Section::SectionSignature(MultiSignature::new( + tx.add_section(Section::Signature(Signature::new( vec![*tx.data_sechash(), *tx.code_sechash()], - &[keypair], - &pks_map, + pks_map.index_secret_keys(vec![keypair]), + None, ))); let signed_tx = tx.clone(); vp_env.tx = signed_tx.clone(); @@ -878,10 +882,10 @@ mod tests { let mut tx = vp_env.tx.clone(); tx.set_data(Data::new(vec![])); tx.set_code(Code::new(vec![])); - tx.add_section(Section::SectionSignature(MultiSignature::new( + tx.add_section(Section::Signature(Signature::new( vec![*tx.data_sechash(), *tx.code_sechash()], - &[keypair], - &pks_map, + pks_map.index_secret_keys(vec![keypair]), + None, ))); let signed_tx = tx.clone(); vp_env.tx = signed_tx.clone(); @@ -934,10 +938,10 @@ mod tests { let mut tx = vp_env.tx.clone(); tx.set_data(Data::new(vec![])); tx.set_code(Code::new(vec![])); - tx.add_section(Section::SectionSignature(MultiSignature::new( + tx.add_section(Section::Signature(Signature::new( vec![*tx.data_sechash(), *tx.code_sechash()], - &[keypair], - &pks_map, + pks_map.index_secret_keys(vec![keypair]), + None, ))); let signed_tx = tx.clone(); vp_env.tx = signed_tx.clone(); @@ -990,10 +994,10 @@ mod tests { let mut tx = vp_env.tx.clone(); tx.set_data(Data::new(vec![])); tx.set_code(Code::new(vec![])); - tx.add_section(Section::SectionSignature(MultiSignature::new( + tx.add_section(Section::Signature(Signature::new( vec![*tx.data_sechash(), *tx.code_sechash()], - &[keypair], - &pks_map, + pks_map.index_secret_keys(vec![keypair]), + None, ))); let signed_tx = tx.clone(); vp_env.tx = signed_tx.clone(); @@ -1046,10 +1050,10 @@ mod tests { let mut tx = vp_env.tx.clone(); tx.set_code(Code::new(vec![])); tx.set_data(Data::new(vec![])); - tx.add_section(Section::SectionSignature(MultiSignature::new( + tx.add_section(Section::Signature(Signature::new( vec![*tx.data_sechash(), *tx.code_sechash()], - &[keypair], - &pks_map, + pks_map.index_secret_keys(vec![keypair]), + None, ))); let signed_tx = tx.clone(); vp_env.tx = signed_tx.clone(); diff --git a/wasm_for_tests/tx_memory_limit.wasm b/wasm_for_tests/tx_memory_limit.wasm index 94ed2403786..8a6a2a0cde3 100755 Binary files a/wasm_for_tests/tx_memory_limit.wasm and b/wasm_for_tests/tx_memory_limit.wasm differ diff --git a/wasm_for_tests/tx_mint_tokens.wasm b/wasm_for_tests/tx_mint_tokens.wasm index 68c67235796..ee848eed089 100755 Binary files a/wasm_for_tests/tx_mint_tokens.wasm and b/wasm_for_tests/tx_mint_tokens.wasm differ diff --git a/wasm_for_tests/tx_no_op.wasm b/wasm_for_tests/tx_no_op.wasm index 0d7b20da7f0..1a0a031b575 100755 Binary files a/wasm_for_tests/tx_no_op.wasm and b/wasm_for_tests/tx_no_op.wasm differ diff --git a/wasm_for_tests/tx_proposal_code.wasm b/wasm_for_tests/tx_proposal_code.wasm index b2cfea8633d..a55d5ca6faa 100755 Binary files a/wasm_for_tests/tx_proposal_code.wasm and b/wasm_for_tests/tx_proposal_code.wasm differ diff --git a/wasm_for_tests/tx_read_storage_key.wasm b/wasm_for_tests/tx_read_storage_key.wasm index fb483a0b846..b49be052e9c 100755 Binary files a/wasm_for_tests/tx_read_storage_key.wasm and b/wasm_for_tests/tx_read_storage_key.wasm differ diff --git a/wasm_for_tests/tx_write.wasm b/wasm_for_tests/tx_write.wasm index 39b20ef813c..78afc0cc2d0 100755 Binary files a/wasm_for_tests/tx_write.wasm and b/wasm_for_tests/tx_write.wasm differ diff --git a/wasm_for_tests/vp_always_false.wasm b/wasm_for_tests/vp_always_false.wasm index 003fc115be9..5cd7b4b0e0a 100755 Binary files a/wasm_for_tests/vp_always_false.wasm and b/wasm_for_tests/vp_always_false.wasm differ diff --git a/wasm_for_tests/vp_always_true.wasm b/wasm_for_tests/vp_always_true.wasm index a18626d71ef..8690590269c 100755 Binary files a/wasm_for_tests/vp_always_true.wasm and b/wasm_for_tests/vp_always_true.wasm differ diff --git a/wasm_for_tests/vp_eval.wasm b/wasm_for_tests/vp_eval.wasm index 98fcac06a28..5b6c94e987e 100755 Binary files a/wasm_for_tests/vp_eval.wasm and b/wasm_for_tests/vp_eval.wasm differ diff --git a/wasm_for_tests/vp_memory_limit.wasm b/wasm_for_tests/vp_memory_limit.wasm index 33b7c719f3e..dcc7c28cfba 100755 Binary files a/wasm_for_tests/vp_memory_limit.wasm and b/wasm_for_tests/vp_memory_limit.wasm differ diff --git a/wasm_for_tests/vp_read_storage_key.wasm b/wasm_for_tests/vp_read_storage_key.wasm index 9867e710095..f8c7a711612 100755 Binary files a/wasm_for_tests/vp_read_storage_key.wasm and b/wasm_for_tests/vp_read_storage_key.wasm differ