Skip to content

Commit

Permalink
Support transaction signing by heterogenous lists of keypairs (solana…
Browse files Browse the repository at this point in the history
…-labs#8342)

automerge
  • Loading branch information
garious authored Feb 20, 2020
1 parent 1720fe6 commit e812432
Show file tree
Hide file tree
Showing 16 changed files with 196 additions and 81 deletions.
4 changes: 2 additions & 2 deletions archiver-lib/src/archiver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ impl Archiver {
);
let message =
Message::new_with_payer(vec![ix], Some(&archiver_keypair.pubkey()));
if let Err(e) = client.send_message(&[&archiver_keypair], message) {
if let Err(e) = client.send_message(&[archiver_keypair.as_ref()], message) {
error!("unable to redeem reward, tx failed: {:?}", e);
} else {
info!(
Expand Down Expand Up @@ -671,7 +671,7 @@ impl Archiver {
blockhash,
);
if let Err(err) = client.send_and_confirm_transaction(
&[&archiver_keypair, &storage_keypair],
&[archiver_keypair.as_ref(), storage_keypair.as_ref()],
&mut transaction,
10,
0,
Expand Down
15 changes: 12 additions & 3 deletions bench-exchange/src/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -701,7 +701,7 @@ fn verify_funding_transfer<T: SyncClient + ?Sized>(
false
}

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

pub fn create_token_accounts(client: &dyn Client, signers: &[Arc<Keypair>], accounts: &[Keypair]) {
pub fn create_token_accounts<T: Client>(
client: &T,
signers: &[Arc<Keypair>],
accounts: &[Keypair],
) {
let mut notfunded: Vec<(&Arc<Keypair>, &Keypair)> = signers.iter().zip(accounts).collect();

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

pub fn airdrop_lamports(client: &dyn Client, faucet_addr: &SocketAddr, id: &Keypair, amount: u64) {
pub fn airdrop_lamports<T: Client>(
client: &T,
faucet_addr: &SocketAddr,
id: &Keypair,
amount: u64,
) {
let balance = client.get_balance_with_commitment(&id.pubkey(), CommitmentConfig::recent());
let balance = balance.unwrap_or(0);
if balance >= amount {
Expand Down
15 changes: 8 additions & 7 deletions client/src/rpc_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ use solana_sdk::{
hash::Hash,
inflation::Inflation,
pubkey::Pubkey,
signature::{KeypairUtil, Signature},
signature::Signature,
signers::Signers,
transaction::{self, Transaction, TransactionError},
};
use std::{
Expand Down Expand Up @@ -405,10 +406,10 @@ impl RpcClient {
})
}

pub fn send_and_confirm_transaction<T: KeypairUtil>(
pub fn send_and_confirm_transaction<T: Signers>(
&self,
transaction: &mut Transaction,
signer_keys: &[&T],
signer_keys: &T,
) -> Result<String, ClientError> {
let mut send_retries = 20;
loop {
Expand Down Expand Up @@ -456,10 +457,10 @@ impl RpcClient {
}
}

pub fn send_and_confirm_transactions<T: KeypairUtil>(
pub fn send_and_confirm_transactions<T: Signers>(
&self,
mut transactions: Vec<Transaction>,
signer_keys: &[&T],
signer_keys: &T,
) -> Result<(), Box<dyn error::Error>> {
let mut send_retries = 5;
loop {
Expand Down Expand Up @@ -526,10 +527,10 @@ impl RpcClient {
}
}

pub fn resign_transaction<T: KeypairUtil>(
pub fn resign_transaction<T: Signers>(
&self,
tx: &mut Transaction,
signer_keys: &[&T],
signer_keys: &T,
) -> Result<(), ClientError> {
let (blockhash, _fee_calculator) =
self.get_new_blockhash(&tx.message().recent_blockhash)?;
Expand Down
19 changes: 12 additions & 7 deletions client/src/thin_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use solana_sdk::{
packet::PACKET_DATA_SIZE,
pubkey::Pubkey,
signature::{Keypair, KeypairUtil, Signature},
signers::Signers,
system_instruction,
timing::duration_as_ms,
transaction::{self, Transaction},
Expand Down Expand Up @@ -202,9 +203,9 @@ impl ThinClient {
}

/// Retry sending a signed Transaction to the server for processing
pub fn send_and_confirm_transaction(
pub fn send_and_confirm_transaction<T: Signers>(
&self,
keypairs: &[&Keypair],
keypairs: &T,
transaction: &mut Transaction,
tries: usize,
pending_confirmations: usize,
Expand Down Expand Up @@ -351,9 +352,13 @@ impl Client for ThinClient {
}

impl SyncClient for ThinClient {
fn send_message(&self, keypairs: &[&Keypair], message: Message) -> TransportResult<Signature> {
fn send_message<T: Signers>(
&self,
keypairs: &T,
message: Message,
) -> TransportResult<Signature> {
let (blockhash, _fee_calculator) = self.get_recent_blockhash()?;
let mut transaction = Transaction::new(&keypairs, message, blockhash);
let mut transaction = Transaction::new(keypairs, message, blockhash);
let signature = self.send_and_confirm_transaction(keypairs, &mut transaction, 5, 0)?;
Ok(signature)
}
Expand Down Expand Up @@ -561,13 +566,13 @@ impl AsyncClient for ThinClient {
.send_to(&buf[..], &self.tpu_addr())?;
Ok(transaction.signatures[0])
}
fn async_send_message(
fn async_send_message<T: Signers>(
&self,
keypairs: &[&Keypair],
keypairs: &T,
message: Message,
recent_blockhash: Hash,
) -> io::Result<Signature> {
let transaction = Transaction::new(&keypairs, message, recent_blockhash);
let transaction = Transaction::new(keypairs, message, recent_blockhash);
self.async_send_transaction(transaction)
}
fn async_send_instruction(
Expand Down
15 changes: 6 additions & 9 deletions ledger/src/staking_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ pub(crate) mod tests {
instruction::Instruction,
pubkey::Pubkey,
signature::{Keypair, KeypairUtil},
signers::Signers,
sysvar::{
stake_history::{self, StakeHistory},
Sysvar,
Expand All @@ -133,18 +134,14 @@ pub(crate) mod tests {
amount: u64,
) {
let vote_pubkey = vote_account.pubkey();
fn process_instructions<T: KeypairUtil>(
bank: &Bank,
keypairs: &[&T],
ixs: Vec<Instruction>,
) {
bank.process_transaction(&Transaction::new_signed_with_payer(
fn process_instructions<T: Signers>(bank: &Bank, keypairs: &T, ixs: Vec<Instruction>) {
let tx = Transaction::new_signed_with_payer(
ixs,
Some(&keypairs[0].pubkey()),
Some(&keypairs.pubkeys()[0]),
keypairs,
bank.last_blockhash(),
))
.unwrap();
);
bank.process_transaction(&tx).unwrap();
}

process_instructions(
Expand Down
4 changes: 2 additions & 2 deletions programs/ownable/src/ownable_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ mod tests {
lamports,
);
let message = Message::new(instructions);
bank_client.send_message(&[&payer_keypair, &account_keypair], message)
bank_client.send_message(&[payer_keypair, account_keypair], message)
}

fn send_set_owner(
Expand All @@ -110,7 +110,7 @@ mod tests {
new_owner_pubkey,
);
let message = Message::new_with_payer(vec![instruction], Some(&payer_keypair.pubkey()));
bank_client.send_message(&[&payer_keypair, &old_owner_keypair], message)
bank_client.send_message(&[payer_keypair, old_owner_keypair], message)
}

#[test]
Expand Down
8 changes: 4 additions & 4 deletions programs/vest/src/vest_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ mod tests {
instructions.push(date_instruction::store(&date_pubkey, date));

let message = Message::new(instructions);
bank_client.send_message(&[&payer_keypair, &date_keypair], message)
bank_client.send_message(&[payer_keypair, date_keypair], message)
}

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

fn create_vest_account(
Expand All @@ -223,7 +223,7 @@ mod tests {
lamports,
);
let message = Message::new(instructions);
bank_client.send_message(&[&payer_keypair, &contract_keypair], message)
bank_client.send_message(&[payer_keypair, contract_keypair], message)
}

fn send_set_terminator(
Expand Down Expand Up @@ -258,7 +258,7 @@ mod tests {
let instruction =
vest_instruction::redeem_tokens(&contract_pubkey, &date_pubkey, &payee_pubkey);
let message = Message::new_with_payer(vec![instruction], Some(&payer_keypair.pubkey()));
bank_client.send_message(&[&payer_keypair], message)
bank_client.send_message(&[payer_keypair], message)
}

#[test]
Expand Down
2 changes: 1 addition & 1 deletion runtime/src/accounts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -744,7 +744,7 @@ mod tests {
let mut error_counters = ErrorCounters::default();

let instructions = vec![CompiledInstruction::new(0, &(), vec![0])];
let tx = Transaction::new_with_compiled_instructions::<Keypair>(
let tx = Transaction::new_with_compiled_instructions::<[&Keypair; 0]>(
&[],
&[],
Hash::default(),
Expand Down
11 changes: 6 additions & 5 deletions runtime/src/bank_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use solana_sdk::{
message::Message,
pubkey::Pubkey,
signature::{Keypair, KeypairUtil, Signature},
signers::Signers,
system_instruction,
transaction::{self, Transaction},
transport::{Result, TransportError},
Expand Down Expand Up @@ -42,13 +43,13 @@ impl AsyncClient for BankClient {
Ok(signature)
}

fn async_send_message(
fn async_send_message<T: Signers>(
&self,
keypairs: &[&Keypair],
keypairs: &T,
message: Message,
recent_blockhash: Hash,
) -> io::Result<Signature> {
let transaction = Transaction::new(&keypairs, message, recent_blockhash);
let transaction = Transaction::new(keypairs, message, recent_blockhash);
self.async_send_transaction(transaction)
}

Expand Down Expand Up @@ -77,9 +78,9 @@ impl AsyncClient for BankClient {
}

impl SyncClient for BankClient {
fn send_message(&self, keypairs: &[&Keypair], message: Message) -> Result<Signature> {
fn send_message<T: Signers>(&self, keypairs: &T, message: Message) -> Result<Signature> {
let blockhash = self.bank.last_blockhash();
let transaction = Transaction::new(&keypairs, message, blockhash);
let transaction = Transaction::new(keypairs, message, blockhash);
self.bank.process_transaction(&transaction)?;
Ok(transaction.signatures.get(0).cloned().unwrap_or_default())
}
Expand Down
2 changes: 1 addition & 1 deletion runtime/tests/stake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ fn fill_epoch_with_votes(
Some(&mint_pubkey),
);
assert!(bank_client
.send_message(&[&mint_keypair, &vote_keypair], message)
.send_message(&[mint_keypair, vote_keypair], message)
.is_ok());
}
bank
Expand Down
2 changes: 1 addition & 1 deletion runtime/tests/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ fn submit_proof(
);

assert_matches!(
bank_client.send_message(&[&mint_keypair, &storage_keypair], message),
bank_client.send_message(&[mint_keypair, storage_keypair], message),
Ok(_)
);
ProofStatus::Valid
Expand Down
10 changes: 7 additions & 3 deletions sdk-c/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ pub unsafe extern "C" fn deserialize_transaction(
/// # Undefined Behavior
///
/// Causes UB if any of the pointers is `NULL`, or if `keypairs` does not point to a valid array of
/// `Keypairs` of length `num_keypairs`
/// `Signers` of length `num_keypairs`
///
/// # Safety
#[no_mangle]
Expand All @@ -453,7 +453,11 @@ pub unsafe extern "C" fn transaction_partial_sign(
};
let keypairs_ref: Vec<&KeypairNative> = keypairs.iter().collect();

let positions = if let Ok(v) = tx_native.get_signing_keypair_positions(&keypairs_ref[..]) {
let pubkeys: Vec<_> = keypairs_ref
.iter()
.map(|keypair| keypair.pubkey())
.collect();
let positions = if let Ok(v) = tx_native.get_signing_keypair_positions(&pubkeys) {
v
} else {
return 2;
Expand All @@ -467,7 +471,7 @@ pub unsafe extern "C" fn transaction_partial_sign(
return 3;
};

tx_native.partial_sign_unchecked(&keypairs_ref[..], positions, *recent_blockhash);
tx_native.partial_sign_unchecked(&keypairs_ref, positions, *recent_blockhash);
*tx = Transaction::from_native(tx_native);
Box::into_raw(tx);
0
Expand Down
7 changes: 4 additions & 3 deletions sdk/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use crate::{
message::Message,
pubkey::Pubkey,
signature::{Keypair, Signature},
signers::Signers,
transaction,
transport::Result,
};
Expand All @@ -29,7 +30,7 @@ pub trait Client: SyncClient + AsyncClient {
pub trait SyncClient {
/// Create a transaction from the given message, and send it to the
/// server, retrying as-needed.
fn send_message(&self, keypairs: &[&Keypair], message: Message) -> Result<Signature>;
fn send_message<T: Signers>(&self, keypairs: &T, message: Message) -> Result<Signature>;

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

/// Create a transaction from the given message, and send it to the
/// server, but don't wait for to see if the server accepted it.
fn async_send_message(
fn async_send_message<T: Signers>(
&self,
keypairs: &[&Keypair],
keypairs: &T,
message: Message,
recent_blockhash: Hash,
) -> io::Result<Signature>;
Expand Down
2 changes: 2 additions & 0 deletions sdk/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ pub mod genesis_config;
#[cfg(not(feature = "program"))]
pub mod signature;
#[cfg(not(feature = "program"))]
pub mod signers;
#[cfg(not(feature = "program"))]
pub mod system_transaction;
#[cfg(not(feature = "program"))]
pub mod transaction;
Expand Down
Loading

0 comments on commit e812432

Please sign in to comment.