Skip to content
This repository was archived by the owner on Jan 22, 2025. It is now read-only.

Commit 9dffc3a

Browse files
authored
Support transaction signing by heterogenous lists of keypairs (bp #8342) (#8362)
automerge
1 parent b4eb815 commit 9dffc3a

File tree

16 files changed

+191
-81
lines changed

16 files changed

+191
-81
lines changed

archiver-lib/src/archiver.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ impl Archiver {
384384
);
385385
let message =
386386
Message::new_with_payer(vec![ix], Some(&archiver_keypair.pubkey()));
387-
if let Err(e) = client.send_message(&[&archiver_keypair], message) {
387+
if let Err(e) = client.send_message(&[archiver_keypair.as_ref()], message) {
388388
error!("unable to redeem reward, tx failed: {:?}", e);
389389
} else {
390390
info!(
@@ -671,7 +671,7 @@ impl Archiver {
671671
blockhash,
672672
);
673673
if let Err(err) = client.send_and_confirm_transaction(
674-
&[&archiver_keypair, &storage_keypair],
674+
&[archiver_keypair.as_ref(), storage_keypair.as_ref()],
675675
&mut transaction,
676676
10,
677677
0,

bench-exchange/src/bench.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -701,7 +701,7 @@ fn verify_funding_transfer<T: SyncClient + ?Sized>(
701701
false
702702
}
703703

704-
pub fn fund_keys(client: &dyn Client, source: &Keypair, dests: &[Arc<Keypair>], lamports: u64) {
704+
pub fn fund_keys<T: Client>(client: &T, source: &Keypair, dests: &[Arc<Keypair>], lamports: u64) {
705705
let total = lamports * (dests.len() as u64 + 1);
706706
let mut funded: Vec<(&Keypair, u64)> = vec![(source, total)];
707707
let mut notfunded: Vec<&Arc<Keypair>> = dests.iter().collect();
@@ -824,7 +824,11 @@ pub fn fund_keys(client: &dyn Client, source: &Keypair, dests: &[Arc<Keypair>],
824824
}
825825
}
826826

827-
pub fn create_token_accounts(client: &dyn Client, signers: &[Arc<Keypair>], accounts: &[Keypair]) {
827+
pub fn create_token_accounts<T: Client>(
828+
client: &T,
829+
signers: &[Arc<Keypair>],
830+
accounts: &[Keypair],
831+
) {
828832
let mut notfunded: Vec<(&Arc<Keypair>, &Keypair)> = signers.iter().zip(accounts).collect();
829833

830834
while !notfunded.is_empty() {
@@ -968,7 +972,12 @@ fn generate_keypairs(num: u64) -> Vec<Keypair> {
968972
rnd.gen_n_keypairs(num)
969973
}
970974

971-
pub fn airdrop_lamports(client: &dyn Client, faucet_addr: &SocketAddr, id: &Keypair, amount: u64) {
975+
pub fn airdrop_lamports<T: Client>(
976+
client: &T,
977+
faucet_addr: &SocketAddr,
978+
id: &Keypair,
979+
amount: u64,
980+
) {
972981
let balance = client.get_balance_with_commitment(&id.pubkey(), CommitmentConfig::recent());
973982
let balance = balance.unwrap_or(0);
974983
if balance >= amount {

client/src/rpc_client.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ use solana_sdk::{
2222
hash::Hash,
2323
inflation::Inflation,
2424
pubkey::Pubkey,
25-
signature::{KeypairUtil, Signature},
25+
signature::Signature,
26+
signers::Signers,
2627
transaction::{self, Transaction, TransactionError},
2728
};
2829
use std::{
@@ -405,10 +406,10 @@ impl RpcClient {
405406
})
406407
}
407408

408-
pub fn send_and_confirm_transaction<T: KeypairUtil>(
409+
pub fn send_and_confirm_transaction<T: Signers>(
409410
&self,
410411
transaction: &mut Transaction,
411-
signer_keys: &[&T],
412+
signer_keys: &T,
412413
) -> Result<String, ClientError> {
413414
let mut send_retries = 20;
414415
loop {
@@ -456,10 +457,10 @@ impl RpcClient {
456457
}
457458
}
458459

459-
pub fn send_and_confirm_transactions<T: KeypairUtil>(
460+
pub fn send_and_confirm_transactions<T: Signers>(
460461
&self,
461462
mut transactions: Vec<Transaction>,
462-
signer_keys: &[&T],
463+
signer_keys: &T,
463464
) -> Result<(), Box<dyn error::Error>> {
464465
let mut send_retries = 5;
465466
loop {
@@ -526,10 +527,10 @@ impl RpcClient {
526527
}
527528
}
528529

529-
pub fn resign_transaction<T: KeypairUtil>(
530+
pub fn resign_transaction<T: Signers>(
530531
&self,
531532
tx: &mut Transaction,
532-
signer_keys: &[&T],
533+
signer_keys: &T,
533534
) -> Result<(), ClientError> {
534535
let (blockhash, _fee_calculator) =
535536
self.get_new_blockhash(&tx.message().recent_blockhash)?;

client/src/thin_client.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use solana_sdk::{
1818
packet::PACKET_DATA_SIZE,
1919
pubkey::Pubkey,
2020
signature::{Keypair, KeypairUtil, Signature},
21+
signers::Signers,
2122
system_instruction,
2223
timing::duration_as_ms,
2324
transaction::{self, Transaction},
@@ -202,9 +203,9 @@ impl ThinClient {
202203
}
203204

204205
/// Retry sending a signed Transaction to the server for processing
205-
pub fn send_and_confirm_transaction(
206+
pub fn send_and_confirm_transaction<T: Signers>(
206207
&self,
207-
keypairs: &[&Keypair],
208+
keypairs: &T,
208209
transaction: &mut Transaction,
209210
tries: usize,
210211
pending_confirmations: usize,
@@ -351,9 +352,13 @@ impl Client for ThinClient {
351352
}
352353

353354
impl SyncClient for ThinClient {
354-
fn send_message(&self, keypairs: &[&Keypair], message: Message) -> TransportResult<Signature> {
355+
fn send_message<T: Signers>(
356+
&self,
357+
keypairs: &T,
358+
message: Message,
359+
) -> TransportResult<Signature> {
355360
let (blockhash, _fee_calculator) = self.get_recent_blockhash()?;
356-
let mut transaction = Transaction::new(&keypairs, message, blockhash);
361+
let mut transaction = Transaction::new(keypairs, message, blockhash);
357362
let signature = self.send_and_confirm_transaction(keypairs, &mut transaction, 5, 0)?;
358363
Ok(signature)
359364
}
@@ -561,13 +566,13 @@ impl AsyncClient for ThinClient {
561566
.send_to(&buf[..], &self.tpu_addr())?;
562567
Ok(transaction.signatures[0])
563568
}
564-
fn async_send_message(
569+
fn async_send_message<T: Signers>(
565570
&self,
566-
keypairs: &[&Keypair],
571+
keypairs: &T,
567572
message: Message,
568573
recent_blockhash: Hash,
569574
) -> io::Result<Signature> {
570-
let transaction = Transaction::new(&keypairs, message, recent_blockhash);
575+
let transaction = Transaction::new(keypairs, message, recent_blockhash);
571576
self.async_send_transaction(transaction)
572577
}
573578
fn async_send_instruction(

ledger/src/staking_utils.rs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ pub(crate) mod tests {
108108
instruction::Instruction,
109109
pubkey::Pubkey,
110110
signature::{Keypair, KeypairUtil},
111+
signers::Signers,
111112
sysvar::{
112113
stake_history::{self, StakeHistory},
113114
Sysvar,
@@ -133,18 +134,14 @@ pub(crate) mod tests {
133134
amount: u64,
134135
) {
135136
let vote_pubkey = vote_account.pubkey();
136-
fn process_instructions<T: KeypairUtil>(
137-
bank: &Bank,
138-
keypairs: &[&T],
139-
ixs: Vec<Instruction>,
140-
) {
141-
bank.process_transaction(&Transaction::new_signed_with_payer(
137+
fn process_instructions<T: Signers>(bank: &Bank, keypairs: &T, ixs: Vec<Instruction>) {
138+
let tx = Transaction::new_signed_with_payer(
142139
ixs,
143-
Some(&keypairs[0].pubkey()),
140+
Some(&keypairs.pubkeys()[0]),
144141
keypairs,
145142
bank.last_blockhash(),
146-
))
147-
.unwrap();
143+
);
144+
bank.process_transaction(&tx).unwrap();
148145
}
149146

150147
process_instructions(

programs/ownable/src/ownable_processor.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ mod tests {
9494
lamports,
9595
);
9696
let message = Message::new(instructions);
97-
bank_client.send_message(&[&payer_keypair, &account_keypair], message)
97+
bank_client.send_message(&[payer_keypair, account_keypair], message)
9898
}
9999

100100
fn send_set_owner(
@@ -110,7 +110,7 @@ mod tests {
110110
new_owner_pubkey,
111111
);
112112
let message = Message::new_with_payer(vec![instruction], Some(&payer_keypair.pubkey()));
113-
bank_client.send_message(&[&payer_keypair, &old_owner_keypair], message)
113+
bank_client.send_message(&[payer_keypair, old_owner_keypair], message)
114114
}
115115

116116
#[test]

programs/vest/src/vest_processor.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ mod tests {
188188
instructions.push(date_instruction::store(&date_pubkey, date));
189189

190190
let message = Message::new(instructions);
191-
bank_client.send_message(&[&payer_keypair, &date_keypair], message)
191+
bank_client.send_message(&[payer_keypair, date_keypair], message)
192192
}
193193

194194
fn store_date(
@@ -200,7 +200,7 @@ mod tests {
200200
let date_pubkey = date_keypair.pubkey();
201201
let instruction = date_instruction::store(&date_pubkey, date);
202202
let message = Message::new_with_payer(vec![instruction], Some(&payer_keypair.pubkey()));
203-
bank_client.send_message(&[&payer_keypair, &date_keypair], message)
203+
bank_client.send_message(&[payer_keypair, date_keypair], message)
204204
}
205205

206206
fn create_vest_account(
@@ -223,7 +223,7 @@ mod tests {
223223
lamports,
224224
);
225225
let message = Message::new(instructions);
226-
bank_client.send_message(&[&payer_keypair, &contract_keypair], message)
226+
bank_client.send_message(&[payer_keypair, contract_keypair], message)
227227
}
228228

229229
fn send_set_terminator(
@@ -258,7 +258,7 @@ mod tests {
258258
let instruction =
259259
vest_instruction::redeem_tokens(&contract_pubkey, &date_pubkey, &payee_pubkey);
260260
let message = Message::new_with_payer(vec![instruction], Some(&payer_keypair.pubkey()));
261-
bank_client.send_message(&[&payer_keypair], message)
261+
bank_client.send_message(&[payer_keypair], message)
262262
}
263263

264264
#[test]

runtime/src/accounts.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -730,7 +730,7 @@ mod tests {
730730
let mut error_counters = ErrorCounters::default();
731731

732732
let instructions = vec![CompiledInstruction::new(0, &(), vec![0])];
733-
let tx = Transaction::new_with_compiled_instructions::<Keypair>(
733+
let tx = Transaction::new_with_compiled_instructions::<[&Keypair; 0]>(
734734
&[],
735735
&[],
736736
Hash::default(),

runtime/src/bank_client.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use solana_sdk::{
99
message::Message,
1010
pubkey::Pubkey,
1111
signature::{Keypair, KeypairUtil, Signature},
12+
signers::Signers,
1213
system_instruction,
1314
transaction::{self, Transaction},
1415
transport::{Result, TransportError},
@@ -42,13 +43,13 @@ impl AsyncClient for BankClient {
4243
Ok(signature)
4344
}
4445

45-
fn async_send_message(
46+
fn async_send_message<T: Signers>(
4647
&self,
47-
keypairs: &[&Keypair],
48+
keypairs: &T,
4849
message: Message,
4950
recent_blockhash: Hash,
5051
) -> io::Result<Signature> {
51-
let transaction = Transaction::new(&keypairs, message, recent_blockhash);
52+
let transaction = Transaction::new(keypairs, message, recent_blockhash);
5253
self.async_send_transaction(transaction)
5354
}
5455

@@ -77,9 +78,9 @@ impl AsyncClient for BankClient {
7778
}
7879

7980
impl SyncClient for BankClient {
80-
fn send_message(&self, keypairs: &[&Keypair], message: Message) -> Result<Signature> {
81+
fn send_message<T: Signers>(&self, keypairs: &T, message: Message) -> Result<Signature> {
8182
let blockhash = self.bank.last_blockhash();
82-
let transaction = Transaction::new(&keypairs, message, blockhash);
83+
let transaction = Transaction::new(keypairs, message, blockhash);
8384
self.bank.process_transaction(&transaction)?;
8485
Ok(transaction.signatures.get(0).cloned().unwrap_or_default())
8586
}

runtime/tests/stake.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ fn fill_epoch_with_votes(
6161
Some(&mint_pubkey),
6262
);
6363
assert!(bank_client
64-
.send_message(&[&mint_keypair, &vote_keypair], message)
64+
.send_message(&[mint_keypair, vote_keypair], message)
6565
.is_ok());
6666
}
6767
bank

runtime/tests/storage.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ fn submit_proof(
372372
);
373373

374374
assert_matches!(
375-
bank_client.send_message(&[&mint_keypair, &storage_keypair], message),
375+
bank_client.send_message(&[mint_keypair, storage_keypair], message),
376376
Ok(_)
377377
);
378378
ProofStatus::Valid

sdk-c/src/lib.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,7 @@ pub unsafe extern "C" fn deserialize_transaction(
428428
/// # Undefined Behavior
429429
///
430430
/// Causes UB if any of the pointers is `NULL`, or if `keypairs` does not point to a valid array of
431-
/// `Keypairs` of length `num_keypairs`
431+
/// `Signers` of length `num_keypairs`
432432
///
433433
/// # Safety
434434
#[no_mangle]
@@ -453,7 +453,11 @@ pub unsafe extern "C" fn transaction_partial_sign(
453453
};
454454
let keypairs_ref: Vec<&KeypairNative> = keypairs.iter().collect();
455455

456-
let positions = if let Ok(v) = tx_native.get_signing_keypair_positions(&keypairs_ref[..]) {
456+
let pubkeys: Vec<_> = keypairs_ref
457+
.iter()
458+
.map(|keypair| keypair.pubkey())
459+
.collect();
460+
let positions = if let Ok(v) = tx_native.get_signing_keypair_positions(&pubkeys) {
457461
v
458462
} else {
459463
return 2;
@@ -467,7 +471,7 @@ pub unsafe extern "C" fn transaction_partial_sign(
467471
return 3;
468472
};
469473

470-
tx_native.partial_sign_unchecked(&keypairs_ref[..], positions, *recent_blockhash);
474+
tx_native.partial_sign_unchecked(&keypairs_ref, positions, *recent_blockhash);
471475
*tx = Transaction::from_native(tx_native);
472476
Box::into_raw(tx);
473477
0

sdk/src/client.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use crate::{
1717
message::Message,
1818
pubkey::Pubkey,
1919
signature::{Keypair, Signature},
20+
signers::Signers,
2021
transaction,
2122
transport::Result,
2223
};
@@ -29,7 +30,7 @@ pub trait Client: SyncClient + AsyncClient {
2930
pub trait SyncClient {
3031
/// Create a transaction from the given message, and send it to the
3132
/// server, retrying as-needed.
32-
fn send_message(&self, keypairs: &[&Keypair], message: Message) -> Result<Signature>;
33+
fn send_message<T: Signers>(&self, keypairs: &T, message: Message) -> Result<Signature>;
3334

3435
/// Create a transaction from a single instruction that only requires
3536
/// a single signer. Then send it to the server, retrying as-needed.
@@ -121,9 +122,9 @@ pub trait AsyncClient {
121122

122123
/// Create a transaction from the given message, and send it to the
123124
/// server, but don't wait for to see if the server accepted it.
124-
fn async_send_message(
125+
fn async_send_message<T: Signers>(
125126
&self,
126-
keypairs: &[&Keypair],
127+
keypairs: &T,
127128
message: Message,
128129
recent_blockhash: Hash,
129130
) -> io::Result<Signature>;

sdk/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ pub mod genesis_config;
7070
#[cfg(not(feature = "program"))]
7171
pub mod signature;
7272
#[cfg(not(feature = "program"))]
73+
pub mod signers;
74+
#[cfg(not(feature = "program"))]
7375
pub mod system_transaction;
7476
#[cfg(not(feature = "program"))]
7577
pub mod transaction;

0 commit comments

Comments
 (0)