Support transaction signing by heterogenous lists of keypairs (#8342)
automerge
This commit is contained in:
		@@ -384,7 +384,7 @@ impl Archiver {
 | 
				
			|||||||
                    );
 | 
					                    );
 | 
				
			||||||
                    let message =
 | 
					                    let message =
 | 
				
			||||||
                        Message::new_with_payer(vec![ix], Some(&archiver_keypair.pubkey()));
 | 
					                        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);
 | 
					                        error!("unable to redeem reward, tx failed: {:?}", e);
 | 
				
			||||||
                    } else {
 | 
					                    } else {
 | 
				
			||||||
                        info!(
 | 
					                        info!(
 | 
				
			||||||
@@ -671,7 +671,7 @@ impl Archiver {
 | 
				
			|||||||
            blockhash,
 | 
					            blockhash,
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
        if let Err(err) = client.send_and_confirm_transaction(
 | 
					        if let Err(err) = client.send_and_confirm_transaction(
 | 
				
			||||||
            &[&archiver_keypair, &storage_keypair],
 | 
					            &[archiver_keypair.as_ref(), storage_keypair.as_ref()],
 | 
				
			||||||
            &mut transaction,
 | 
					            &mut transaction,
 | 
				
			||||||
            10,
 | 
					            10,
 | 
				
			||||||
            0,
 | 
					            0,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -701,7 +701,7 @@ fn verify_funding_transfer<T: SyncClient + ?Sized>(
 | 
				
			|||||||
    false
 | 
					    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 total = lamports * (dests.len() as u64 + 1);
 | 
				
			||||||
    let mut funded: Vec<(&Keypair, u64)> = vec![(source, total)];
 | 
					    let mut funded: Vec<(&Keypair, u64)> = vec![(source, total)];
 | 
				
			||||||
    let mut notfunded: Vec<&Arc<Keypair>> = dests.iter().collect();
 | 
					    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>],
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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();
 | 
					    let mut notfunded: Vec<(&Arc<Keypair>, &Keypair)> = signers.iter().zip(accounts).collect();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    while !notfunded.is_empty() {
 | 
					    while !notfunded.is_empty() {
 | 
				
			||||||
@@ -968,7 +972,12 @@ fn generate_keypairs(num: u64) -> Vec<Keypair> {
 | 
				
			|||||||
    rnd.gen_n_keypairs(num)
 | 
					    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 = client.get_balance_with_commitment(&id.pubkey(), CommitmentConfig::recent());
 | 
				
			||||||
    let balance = balance.unwrap_or(0);
 | 
					    let balance = balance.unwrap_or(0);
 | 
				
			||||||
    if balance >= amount {
 | 
					    if balance >= amount {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,7 +22,8 @@ use solana_sdk::{
 | 
				
			|||||||
    hash::Hash,
 | 
					    hash::Hash,
 | 
				
			||||||
    inflation::Inflation,
 | 
					    inflation::Inflation,
 | 
				
			||||||
    pubkey::Pubkey,
 | 
					    pubkey::Pubkey,
 | 
				
			||||||
    signature::{KeypairUtil, Signature},
 | 
					    signature::Signature,
 | 
				
			||||||
 | 
					    signers::Signers,
 | 
				
			||||||
    transaction::{self, Transaction, TransactionError},
 | 
					    transaction::{self, Transaction, TransactionError},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use std::{
 | 
					use std::{
 | 
				
			||||||
@@ -405,10 +406,10 @@ impl RpcClient {
 | 
				
			|||||||
        })
 | 
					        })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn send_and_confirm_transaction<T: KeypairUtil>(
 | 
					    pub fn send_and_confirm_transaction<T: Signers>(
 | 
				
			||||||
        &self,
 | 
					        &self,
 | 
				
			||||||
        transaction: &mut Transaction,
 | 
					        transaction: &mut Transaction,
 | 
				
			||||||
        signer_keys: &[&T],
 | 
					        signer_keys: &T,
 | 
				
			||||||
    ) -> Result<String, ClientError> {
 | 
					    ) -> Result<String, ClientError> {
 | 
				
			||||||
        let mut send_retries = 20;
 | 
					        let mut send_retries = 20;
 | 
				
			||||||
        loop {
 | 
					        loop {
 | 
				
			||||||
@@ -456,10 +457,10 @@ impl RpcClient {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn send_and_confirm_transactions<T: KeypairUtil>(
 | 
					    pub fn send_and_confirm_transactions<T: Signers>(
 | 
				
			||||||
        &self,
 | 
					        &self,
 | 
				
			||||||
        mut transactions: Vec<Transaction>,
 | 
					        mut transactions: Vec<Transaction>,
 | 
				
			||||||
        signer_keys: &[&T],
 | 
					        signer_keys: &T,
 | 
				
			||||||
    ) -> Result<(), Box<dyn error::Error>> {
 | 
					    ) -> Result<(), Box<dyn error::Error>> {
 | 
				
			||||||
        let mut send_retries = 5;
 | 
					        let mut send_retries = 5;
 | 
				
			||||||
        loop {
 | 
					        loop {
 | 
				
			||||||
@@ -526,10 +527,10 @@ impl RpcClient {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn resign_transaction<T: KeypairUtil>(
 | 
					    pub fn resign_transaction<T: Signers>(
 | 
				
			||||||
        &self,
 | 
					        &self,
 | 
				
			||||||
        tx: &mut Transaction,
 | 
					        tx: &mut Transaction,
 | 
				
			||||||
        signer_keys: &[&T],
 | 
					        signer_keys: &T,
 | 
				
			||||||
    ) -> Result<(), ClientError> {
 | 
					    ) -> Result<(), ClientError> {
 | 
				
			||||||
        let (blockhash, _fee_calculator) =
 | 
					        let (blockhash, _fee_calculator) =
 | 
				
			||||||
            self.get_new_blockhash(&tx.message().recent_blockhash)?;
 | 
					            self.get_new_blockhash(&tx.message().recent_blockhash)?;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,6 +18,7 @@ use solana_sdk::{
 | 
				
			|||||||
    packet::PACKET_DATA_SIZE,
 | 
					    packet::PACKET_DATA_SIZE,
 | 
				
			||||||
    pubkey::Pubkey,
 | 
					    pubkey::Pubkey,
 | 
				
			||||||
    signature::{Keypair, KeypairUtil, Signature},
 | 
					    signature::{Keypair, KeypairUtil, Signature},
 | 
				
			||||||
 | 
					    signers::Signers,
 | 
				
			||||||
    system_instruction,
 | 
					    system_instruction,
 | 
				
			||||||
    timing::duration_as_ms,
 | 
					    timing::duration_as_ms,
 | 
				
			||||||
    transaction::{self, Transaction},
 | 
					    transaction::{self, Transaction},
 | 
				
			||||||
@@ -202,9 +203,9 @@ impl ThinClient {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Retry sending a signed Transaction to the server for processing
 | 
					    /// 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,
 | 
					        &self,
 | 
				
			||||||
        keypairs: &[&Keypair],
 | 
					        keypairs: &T,
 | 
				
			||||||
        transaction: &mut Transaction,
 | 
					        transaction: &mut Transaction,
 | 
				
			||||||
        tries: usize,
 | 
					        tries: usize,
 | 
				
			||||||
        pending_confirmations: usize,
 | 
					        pending_confirmations: usize,
 | 
				
			||||||
@@ -351,9 +352,13 @@ impl Client for ThinClient {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl SyncClient 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 (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)?;
 | 
					        let signature = self.send_and_confirm_transaction(keypairs, &mut transaction, 5, 0)?;
 | 
				
			||||||
        Ok(signature)
 | 
					        Ok(signature)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -561,13 +566,13 @@ impl AsyncClient for ThinClient {
 | 
				
			|||||||
            .send_to(&buf[..], &self.tpu_addr())?;
 | 
					            .send_to(&buf[..], &self.tpu_addr())?;
 | 
				
			||||||
        Ok(transaction.signatures[0])
 | 
					        Ok(transaction.signatures[0])
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    fn async_send_message(
 | 
					    fn async_send_message<T: Signers>(
 | 
				
			||||||
        &self,
 | 
					        &self,
 | 
				
			||||||
        keypairs: &[&Keypair],
 | 
					        keypairs: &T,
 | 
				
			||||||
        message: Message,
 | 
					        message: Message,
 | 
				
			||||||
        recent_blockhash: Hash,
 | 
					        recent_blockhash: Hash,
 | 
				
			||||||
    ) -> io::Result<Signature> {
 | 
					    ) -> io::Result<Signature> {
 | 
				
			||||||
        let transaction = Transaction::new(&keypairs, message, recent_blockhash);
 | 
					        let transaction = Transaction::new(keypairs, message, recent_blockhash);
 | 
				
			||||||
        self.async_send_transaction(transaction)
 | 
					        self.async_send_transaction(transaction)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    fn async_send_instruction(
 | 
					    fn async_send_instruction(
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -108,6 +108,7 @@ pub(crate) mod tests {
 | 
				
			|||||||
        instruction::Instruction,
 | 
					        instruction::Instruction,
 | 
				
			||||||
        pubkey::Pubkey,
 | 
					        pubkey::Pubkey,
 | 
				
			||||||
        signature::{Keypair, KeypairUtil},
 | 
					        signature::{Keypair, KeypairUtil},
 | 
				
			||||||
 | 
					        signers::Signers,
 | 
				
			||||||
        sysvar::{
 | 
					        sysvar::{
 | 
				
			||||||
            stake_history::{self, StakeHistory},
 | 
					            stake_history::{self, StakeHistory},
 | 
				
			||||||
            Sysvar,
 | 
					            Sysvar,
 | 
				
			||||||
@@ -133,18 +134,14 @@ pub(crate) mod tests {
 | 
				
			|||||||
        amount: u64,
 | 
					        amount: u64,
 | 
				
			||||||
    ) {
 | 
					    ) {
 | 
				
			||||||
        let vote_pubkey = vote_account.pubkey();
 | 
					        let vote_pubkey = vote_account.pubkey();
 | 
				
			||||||
        fn process_instructions<T: KeypairUtil>(
 | 
					        fn process_instructions<T: Signers>(bank: &Bank, keypairs: &T, ixs: Vec<Instruction>) {
 | 
				
			||||||
            bank: &Bank,
 | 
					            let tx = Transaction::new_signed_with_payer(
 | 
				
			||||||
            keypairs: &[&T],
 | 
					 | 
				
			||||||
            ixs: Vec<Instruction>,
 | 
					 | 
				
			||||||
        ) {
 | 
					 | 
				
			||||||
            bank.process_transaction(&Transaction::new_signed_with_payer(
 | 
					 | 
				
			||||||
                ixs,
 | 
					                ixs,
 | 
				
			||||||
                Some(&keypairs[0].pubkey()),
 | 
					                Some(&keypairs.pubkeys()[0]),
 | 
				
			||||||
                keypairs,
 | 
					                keypairs,
 | 
				
			||||||
                bank.last_blockhash(),
 | 
					                bank.last_blockhash(),
 | 
				
			||||||
            ))
 | 
					            );
 | 
				
			||||||
            .unwrap();
 | 
					            bank.process_transaction(&tx).unwrap();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        process_instructions(
 | 
					        process_instructions(
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -94,7 +94,7 @@ mod tests {
 | 
				
			|||||||
            lamports,
 | 
					            lamports,
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
        let message = Message::new(instructions);
 | 
					        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(
 | 
					    fn send_set_owner(
 | 
				
			||||||
@@ -110,7 +110,7 @@ mod tests {
 | 
				
			|||||||
            new_owner_pubkey,
 | 
					            new_owner_pubkey,
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
        let message = Message::new_with_payer(vec![instruction], Some(&payer_keypair.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]
 | 
					    #[test]
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -188,7 +188,7 @@ mod tests {
 | 
				
			|||||||
        instructions.push(date_instruction::store(&date_pubkey, date));
 | 
					        instructions.push(date_instruction::store(&date_pubkey, date));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let message = Message::new(instructions);
 | 
					        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(
 | 
					    fn store_date(
 | 
				
			||||||
@@ -200,7 +200,7 @@ mod tests {
 | 
				
			|||||||
        let date_pubkey = date_keypair.pubkey();
 | 
					        let date_pubkey = date_keypair.pubkey();
 | 
				
			||||||
        let instruction = date_instruction::store(&date_pubkey, date);
 | 
					        let instruction = date_instruction::store(&date_pubkey, date);
 | 
				
			||||||
        let message = Message::new_with_payer(vec![instruction], Some(&payer_keypair.pubkey()));
 | 
					        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(
 | 
					    fn create_vest_account(
 | 
				
			||||||
@@ -223,7 +223,7 @@ mod tests {
 | 
				
			|||||||
            lamports,
 | 
					            lamports,
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
        let message = Message::new(instructions);
 | 
					        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(
 | 
					    fn send_set_terminator(
 | 
				
			||||||
@@ -258,7 +258,7 @@ mod tests {
 | 
				
			|||||||
        let instruction =
 | 
					        let instruction =
 | 
				
			||||||
            vest_instruction::redeem_tokens(&contract_pubkey, &date_pubkey, &payee_pubkey);
 | 
					            vest_instruction::redeem_tokens(&contract_pubkey, &date_pubkey, &payee_pubkey);
 | 
				
			||||||
        let message = Message::new_with_payer(vec![instruction], Some(&payer_keypair.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]
 | 
					    #[test]
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -744,7 +744,7 @@ mod tests {
 | 
				
			|||||||
        let mut error_counters = ErrorCounters::default();
 | 
					        let mut error_counters = ErrorCounters::default();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let instructions = vec![CompiledInstruction::new(0, &(), vec![0])];
 | 
					        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(),
 | 
					            Hash::default(),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,6 +9,7 @@ use solana_sdk::{
 | 
				
			|||||||
    message::Message,
 | 
					    message::Message,
 | 
				
			||||||
    pubkey::Pubkey,
 | 
					    pubkey::Pubkey,
 | 
				
			||||||
    signature::{Keypair, KeypairUtil, Signature},
 | 
					    signature::{Keypair, KeypairUtil, Signature},
 | 
				
			||||||
 | 
					    signers::Signers,
 | 
				
			||||||
    system_instruction,
 | 
					    system_instruction,
 | 
				
			||||||
    transaction::{self, Transaction},
 | 
					    transaction::{self, Transaction},
 | 
				
			||||||
    transport::{Result, TransportError},
 | 
					    transport::{Result, TransportError},
 | 
				
			||||||
@@ -42,13 +43,13 @@ impl AsyncClient for BankClient {
 | 
				
			|||||||
        Ok(signature)
 | 
					        Ok(signature)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn async_send_message(
 | 
					    fn async_send_message<T: Signers>(
 | 
				
			||||||
        &self,
 | 
					        &self,
 | 
				
			||||||
        keypairs: &[&Keypair],
 | 
					        keypairs: &T,
 | 
				
			||||||
        message: Message,
 | 
					        message: Message,
 | 
				
			||||||
        recent_blockhash: Hash,
 | 
					        recent_blockhash: Hash,
 | 
				
			||||||
    ) -> io::Result<Signature> {
 | 
					    ) -> io::Result<Signature> {
 | 
				
			||||||
        let transaction = Transaction::new(&keypairs, message, recent_blockhash);
 | 
					        let transaction = Transaction::new(keypairs, message, recent_blockhash);
 | 
				
			||||||
        self.async_send_transaction(transaction)
 | 
					        self.async_send_transaction(transaction)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -77,9 +78,9 @@ impl AsyncClient for BankClient {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl SyncClient 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 blockhash = self.bank.last_blockhash();
 | 
				
			||||||
        let transaction = Transaction::new(&keypairs, message, blockhash);
 | 
					        let transaction = Transaction::new(keypairs, message, blockhash);
 | 
				
			||||||
        self.bank.process_transaction(&transaction)?;
 | 
					        self.bank.process_transaction(&transaction)?;
 | 
				
			||||||
        Ok(transaction.signatures.get(0).cloned().unwrap_or_default())
 | 
					        Ok(transaction.signatures.get(0).cloned().unwrap_or_default())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -61,7 +61,7 @@ fn fill_epoch_with_votes(
 | 
				
			|||||||
            Some(&mint_pubkey),
 | 
					            Some(&mint_pubkey),
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
        assert!(bank_client
 | 
					        assert!(bank_client
 | 
				
			||||||
            .send_message(&[&mint_keypair, &vote_keypair], message)
 | 
					            .send_message(&[mint_keypair, vote_keypair], message)
 | 
				
			||||||
            .is_ok());
 | 
					            .is_ok());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    bank
 | 
					    bank
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -371,7 +371,7 @@ fn submit_proof(
 | 
				
			|||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assert_matches!(
 | 
					    assert_matches!(
 | 
				
			||||||
        bank_client.send_message(&[&mint_keypair, &storage_keypair], message),
 | 
					        bank_client.send_message(&[mint_keypair, storage_keypair], message),
 | 
				
			||||||
        Ok(_)
 | 
					        Ok(_)
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
    ProofStatus::Valid
 | 
					    ProofStatus::Valid
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -428,7 +428,7 @@ pub unsafe extern "C" fn deserialize_transaction(
 | 
				
			|||||||
/// # Undefined Behavior
 | 
					/// # Undefined Behavior
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
/// Causes UB if any of the pointers is `NULL`, or if `keypairs` does not point to a valid array of
 | 
					/// 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
 | 
					/// # Safety
 | 
				
			||||||
#[no_mangle]
 | 
					#[no_mangle]
 | 
				
			||||||
@@ -453,7 +453,11 @@ pub unsafe extern "C" fn transaction_partial_sign(
 | 
				
			|||||||
    };
 | 
					    };
 | 
				
			||||||
    let keypairs_ref: Vec<&KeypairNative> = keypairs.iter().collect();
 | 
					    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
 | 
					        v
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        return 2;
 | 
					        return 2;
 | 
				
			||||||
@@ -467,7 +471,7 @@ pub unsafe extern "C" fn transaction_partial_sign(
 | 
				
			|||||||
        return 3;
 | 
					        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);
 | 
					    *tx = Transaction::from_native(tx_native);
 | 
				
			||||||
    Box::into_raw(tx);
 | 
					    Box::into_raw(tx);
 | 
				
			||||||
    0
 | 
					    0
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,6 +17,7 @@ use crate::{
 | 
				
			|||||||
    message::Message,
 | 
					    message::Message,
 | 
				
			||||||
    pubkey::Pubkey,
 | 
					    pubkey::Pubkey,
 | 
				
			||||||
    signature::{Keypair, Signature},
 | 
					    signature::{Keypair, Signature},
 | 
				
			||||||
 | 
					    signers::Signers,
 | 
				
			||||||
    transaction,
 | 
					    transaction,
 | 
				
			||||||
    transport::Result,
 | 
					    transport::Result,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@@ -29,7 +30,7 @@ pub trait Client: SyncClient + AsyncClient {
 | 
				
			|||||||
pub trait SyncClient {
 | 
					pub trait SyncClient {
 | 
				
			||||||
    /// Create a transaction from the given message, and send it to the
 | 
					    /// Create a transaction from the given message, and send it to the
 | 
				
			||||||
    /// server, retrying as-needed.
 | 
					    /// 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
 | 
					    /// Create a transaction from a single instruction that only requires
 | 
				
			||||||
    /// a single signer. Then send it to the server, retrying as-needed.
 | 
					    /// a single signer. Then send it to the server, retrying as-needed.
 | 
				
			||||||
@@ -121,9 +122,9 @@ pub trait AsyncClient {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /// Create a transaction from the given message, and send it to the
 | 
					    /// 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.
 | 
					    /// server, but don't wait for to see if the server accepted it.
 | 
				
			||||||
    fn async_send_message(
 | 
					    fn async_send_message<T: Signers>(
 | 
				
			||||||
        &self,
 | 
					        &self,
 | 
				
			||||||
        keypairs: &[&Keypair],
 | 
					        keypairs: &T,
 | 
				
			||||||
        message: Message,
 | 
					        message: Message,
 | 
				
			||||||
        recent_blockhash: Hash,
 | 
					        recent_blockhash: Hash,
 | 
				
			||||||
    ) -> io::Result<Signature>;
 | 
					    ) -> io::Result<Signature>;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -72,6 +72,8 @@ pub mod genesis_config;
 | 
				
			|||||||
#[cfg(not(feature = "program"))]
 | 
					#[cfg(not(feature = "program"))]
 | 
				
			||||||
pub mod signature;
 | 
					pub mod signature;
 | 
				
			||||||
#[cfg(not(feature = "program"))]
 | 
					#[cfg(not(feature = "program"))]
 | 
				
			||||||
 | 
					pub mod signers;
 | 
				
			||||||
 | 
					#[cfg(not(feature = "program"))]
 | 
				
			||||||
pub mod system_transaction;
 | 
					pub mod system_transaction;
 | 
				
			||||||
#[cfg(not(feature = "program"))]
 | 
					#[cfg(not(feature = "program"))]
 | 
				
			||||||
pub mod transaction;
 | 
					pub mod transaction;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										97
									
								
								sdk/src/signers.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								sdk/src/signers.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,97 @@
 | 
				
			|||||||
 | 
					use crate::{
 | 
				
			||||||
 | 
					    pubkey::Pubkey,
 | 
				
			||||||
 | 
					    signature::{KeypairUtil, Signature},
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub trait Signers {
 | 
				
			||||||
 | 
					    fn pubkeys(&self) -> Vec<Pubkey>;
 | 
				
			||||||
 | 
					    fn sign_message(&self, message: &[u8]) -> Vec<Signature>;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					macro_rules! default_keypairs_impl {
 | 
				
			||||||
 | 
					    () => (
 | 
				
			||||||
 | 
					            fn pubkeys(&self) -> Vec<Pubkey> {
 | 
				
			||||||
 | 
					                self.iter().map(|keypair| keypair.pubkey()).collect()
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            fn sign_message(&self, message: &[u8]) -> Vec<Signature> {
 | 
				
			||||||
 | 
					                self.iter()
 | 
				
			||||||
 | 
					                    .map(|keypair| keypair.sign_message(message))
 | 
				
			||||||
 | 
					                    .collect()
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<T: KeypairUtil> Signers for [&T] {
 | 
				
			||||||
 | 
					    default_keypairs_impl!();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Signers for [Box<dyn KeypairUtil>] {
 | 
				
			||||||
 | 
					    default_keypairs_impl!();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<T: KeypairUtil> Signers for [&T; 0] {
 | 
				
			||||||
 | 
					    default_keypairs_impl!();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<T: KeypairUtil> Signers for [&T; 1] {
 | 
				
			||||||
 | 
					    default_keypairs_impl!();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<T: KeypairUtil> Signers for [&T; 2] {
 | 
				
			||||||
 | 
					    default_keypairs_impl!();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<T: KeypairUtil> Signers for [&T; 3] {
 | 
				
			||||||
 | 
					    default_keypairs_impl!();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<T: KeypairUtil> Signers for [&T; 4] {
 | 
				
			||||||
 | 
					    default_keypairs_impl!();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<T: KeypairUtil> Signers for Vec<&T> {
 | 
				
			||||||
 | 
					    default_keypairs_impl!();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[cfg(test)]
 | 
				
			||||||
 | 
					mod tests {
 | 
				
			||||||
 | 
					    use super::*;
 | 
				
			||||||
 | 
					    use std::error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct Foo;
 | 
				
			||||||
 | 
					    impl KeypairUtil for Foo {
 | 
				
			||||||
 | 
					        fn try_pubkey(&self) -> Result<Pubkey, Box<dyn error::Error>> {
 | 
				
			||||||
 | 
					            Ok(Pubkey::default())
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        fn try_sign_message(&self, _message: &[u8]) -> Result<Signature, Box<dyn error::Error>> {
 | 
				
			||||||
 | 
					            Ok(Signature::default())
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct Bar;
 | 
				
			||||||
 | 
					    impl KeypairUtil for Bar {
 | 
				
			||||||
 | 
					        fn try_pubkey(&self) -> Result<Pubkey, Box<dyn error::Error>> {
 | 
				
			||||||
 | 
					            Ok(Pubkey::default())
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        fn try_sign_message(&self, _message: &[u8]) -> Result<Signature, Box<dyn error::Error>> {
 | 
				
			||||||
 | 
					            Ok(Signature::default())
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[test]
 | 
				
			||||||
 | 
					    fn test_dyn_keypairs_compile() {
 | 
				
			||||||
 | 
					        let xs: Vec<Box<dyn KeypairUtil>> = vec![Box::new(Foo {}), Box::new(Bar {})];
 | 
				
			||||||
 | 
					        assert_eq!(
 | 
				
			||||||
 | 
					            xs.sign_message(b""),
 | 
				
			||||||
 | 
					            vec![Signature::default(), Signature::default()],
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Same as above, but less compiler magic.
 | 
				
			||||||
 | 
					        let xs_ref: &[Box<dyn KeypairUtil>] = &xs;
 | 
				
			||||||
 | 
					        assert_eq!(
 | 
				
			||||||
 | 
					            Signers::sign_message(xs_ref, b""),
 | 
				
			||||||
 | 
					            vec![Signature::default(), Signature::default()],
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -6,7 +6,8 @@ use crate::{
 | 
				
			|||||||
    message::Message,
 | 
					    message::Message,
 | 
				
			||||||
    pubkey::Pubkey,
 | 
					    pubkey::Pubkey,
 | 
				
			||||||
    short_vec,
 | 
					    short_vec,
 | 
				
			||||||
    signature::{KeypairUtil, Signature},
 | 
					    signature::Signature,
 | 
				
			||||||
 | 
					    signers::Signers,
 | 
				
			||||||
    system_instruction,
 | 
					    system_instruction,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use std::result;
 | 
					use std::result;
 | 
				
			||||||
@@ -95,20 +96,20 @@ impl Transaction {
 | 
				
			|||||||
        Self::new_unsigned(message)
 | 
					        Self::new_unsigned(message)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn new_signed_with_payer<T: KeypairUtil>(
 | 
					    pub fn new_signed_with_payer<T: Signers>(
 | 
				
			||||||
        instructions: Vec<Instruction>,
 | 
					        instructions: Vec<Instruction>,
 | 
				
			||||||
        payer: Option<&Pubkey>,
 | 
					        payer: Option<&Pubkey>,
 | 
				
			||||||
        signing_keypairs: &[&T],
 | 
					        signing_keypairs: &T,
 | 
				
			||||||
        recent_blockhash: Hash,
 | 
					        recent_blockhash: Hash,
 | 
				
			||||||
    ) -> Self {
 | 
					    ) -> Self {
 | 
				
			||||||
        let message = Message::new_with_payer(instructions, payer);
 | 
					        let message = Message::new_with_payer(instructions, payer);
 | 
				
			||||||
        Self::new(signing_keypairs, message, recent_blockhash)
 | 
					        Self::new(signing_keypairs, message, recent_blockhash)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn new_signed_with_nonce<T: KeypairUtil>(
 | 
					    pub fn new_signed_with_nonce<T: Signers>(
 | 
				
			||||||
        mut instructions: Vec<Instruction>,
 | 
					        mut instructions: Vec<Instruction>,
 | 
				
			||||||
        payer: Option<&Pubkey>,
 | 
					        payer: Option<&Pubkey>,
 | 
				
			||||||
        signing_keypairs: &[&T],
 | 
					        signing_keypairs: &T,
 | 
				
			||||||
        nonce_account_pubkey: &Pubkey,
 | 
					        nonce_account_pubkey: &Pubkey,
 | 
				
			||||||
        nonce_authority_pubkey: &Pubkey,
 | 
					        nonce_authority_pubkey: &Pubkey,
 | 
				
			||||||
        nonce_hash: Hash,
 | 
					        nonce_hash: Hash,
 | 
				
			||||||
@@ -126,8 +127,8 @@ impl Transaction {
 | 
				
			|||||||
        Self::new_unsigned(message)
 | 
					        Self::new_unsigned(message)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn new<T: KeypairUtil>(
 | 
					    pub fn new<T: Signers>(
 | 
				
			||||||
        from_keypairs: &[&T],
 | 
					        from_keypairs: &T,
 | 
				
			||||||
        message: Message,
 | 
					        message: Message,
 | 
				
			||||||
        recent_blockhash: Hash,
 | 
					        recent_blockhash: Hash,
 | 
				
			||||||
    ) -> Transaction {
 | 
					    ) -> Transaction {
 | 
				
			||||||
@@ -136,8 +137,8 @@ impl Transaction {
 | 
				
			|||||||
        tx
 | 
					        tx
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn new_signed_instructions<T: KeypairUtil>(
 | 
					    pub fn new_signed_instructions<T: Signers>(
 | 
				
			||||||
        from_keypairs: &[&T],
 | 
					        from_keypairs: &T,
 | 
				
			||||||
        instructions: Vec<Instruction>,
 | 
					        instructions: Vec<Instruction>,
 | 
				
			||||||
        recent_blockhash: Hash,
 | 
					        recent_blockhash: Hash,
 | 
				
			||||||
    ) -> Transaction {
 | 
					    ) -> Transaction {
 | 
				
			||||||
@@ -152,21 +153,19 @@ impl Transaction {
 | 
				
			|||||||
    /// * `recent_blockhash` - The PoH hash.
 | 
					    /// * `recent_blockhash` - The PoH hash.
 | 
				
			||||||
    /// * `program_ids` - The keys that identify programs used in the `instruction` vector.
 | 
					    /// * `program_ids` - The keys that identify programs used in the `instruction` vector.
 | 
				
			||||||
    /// * `instructions` - Instructions that will be executed atomically.
 | 
					    /// * `instructions` - Instructions that will be executed atomically.
 | 
				
			||||||
    pub fn new_with_compiled_instructions<T: KeypairUtil>(
 | 
					    pub fn new_with_compiled_instructions<T: Signers>(
 | 
				
			||||||
        from_keypairs: &[&T],
 | 
					        from_keypairs: &T,
 | 
				
			||||||
        keys: &[Pubkey],
 | 
					        keys: &[Pubkey],
 | 
				
			||||||
        recent_blockhash: Hash,
 | 
					        recent_blockhash: Hash,
 | 
				
			||||||
        program_ids: Vec<Pubkey>,
 | 
					        program_ids: Vec<Pubkey>,
 | 
				
			||||||
        instructions: Vec<CompiledInstruction>,
 | 
					        instructions: Vec<CompiledInstruction>,
 | 
				
			||||||
    ) -> Self {
 | 
					    ) -> Self {
 | 
				
			||||||
        let mut account_keys: Vec<_> = from_keypairs
 | 
					        let mut account_keys = from_keypairs.pubkeys();
 | 
				
			||||||
            .iter()
 | 
					        let from_keypairs_len = account_keys.len();
 | 
				
			||||||
            .map(|keypair| (*keypair).pubkey())
 | 
					 | 
				
			||||||
            .collect();
 | 
					 | 
				
			||||||
        account_keys.extend_from_slice(keys);
 | 
					        account_keys.extend_from_slice(keys);
 | 
				
			||||||
        account_keys.extend(&program_ids);
 | 
					        account_keys.extend(&program_ids);
 | 
				
			||||||
        let message = Message::new_with_compiled_instructions(
 | 
					        let message = Message::new_with_compiled_instructions(
 | 
				
			||||||
            from_keypairs.len() as u8,
 | 
					            from_keypairs_len as u8,
 | 
				
			||||||
            0,
 | 
					            0,
 | 
				
			||||||
            program_ids.len() as u8,
 | 
					            program_ids.len() as u8,
 | 
				
			||||||
            account_keys,
 | 
					            account_keys,
 | 
				
			||||||
@@ -214,7 +213,7 @@ impl Transaction {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Check keys and keypair lengths, then sign this transaction.
 | 
					    /// Check keys and keypair lengths, then sign this transaction.
 | 
				
			||||||
    pub fn sign<T: KeypairUtil>(&mut self, keypairs: &[&T], recent_blockhash: Hash) {
 | 
					    pub fn sign<T: Signers>(&mut self, keypairs: &T, recent_blockhash: Hash) {
 | 
				
			||||||
        self.partial_sign(keypairs, recent_blockhash);
 | 
					        self.partial_sign(keypairs, recent_blockhash);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        assert_eq!(self.is_signed(), true, "not enough keypairs");
 | 
					        assert_eq!(self.is_signed(), true, "not enough keypairs");
 | 
				
			||||||
@@ -223,9 +222,9 @@ impl Transaction {
 | 
				
			|||||||
    /// Sign using some subset of required keys
 | 
					    /// Sign using some subset of required keys
 | 
				
			||||||
    ///  if recent_blockhash is not the same as currently in the transaction,
 | 
					    ///  if recent_blockhash is not the same as currently in the transaction,
 | 
				
			||||||
    ///  clear any prior signatures and update recent_blockhash
 | 
					    ///  clear any prior signatures and update recent_blockhash
 | 
				
			||||||
    pub fn partial_sign<T: KeypairUtil>(&mut self, keypairs: &[&T], recent_blockhash: Hash) {
 | 
					    pub fn partial_sign<T: Signers>(&mut self, keypairs: &T, recent_blockhash: Hash) {
 | 
				
			||||||
        let positions = self
 | 
					        let positions = self
 | 
				
			||||||
            .get_signing_keypair_positions(keypairs)
 | 
					            .get_signing_keypair_positions(&keypairs.pubkeys())
 | 
				
			||||||
            .expect("account_keys doesn't contain num_required_signatures keys");
 | 
					            .expect("account_keys doesn't contain num_required_signatures keys");
 | 
				
			||||||
        let positions: Vec<usize> = positions
 | 
					        let positions: Vec<usize> = positions
 | 
				
			||||||
            .iter()
 | 
					            .iter()
 | 
				
			||||||
@@ -236,9 +235,9 @@ impl Transaction {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /// Sign the transaction and place the signatures in their associated positions in `signatures`
 | 
					    /// Sign the transaction and place the signatures in their associated positions in `signatures`
 | 
				
			||||||
    /// without checking that the positions are correct.
 | 
					    /// without checking that the positions are correct.
 | 
				
			||||||
    pub fn partial_sign_unchecked<T: KeypairUtil>(
 | 
					    pub fn partial_sign_unchecked<T: Signers>(
 | 
				
			||||||
        &mut self,
 | 
					        &mut self,
 | 
				
			||||||
        keypairs: &[&T],
 | 
					        keypairs: &T,
 | 
				
			||||||
        positions: Vec<usize>,
 | 
					        positions: Vec<usize>,
 | 
				
			||||||
        recent_blockhash: Hash,
 | 
					        recent_blockhash: Hash,
 | 
				
			||||||
    ) {
 | 
					    ) {
 | 
				
			||||||
@@ -250,8 +249,9 @@ impl Transaction {
 | 
				
			|||||||
                .for_each(|signature| *signature = Signature::default());
 | 
					                .for_each(|signature| *signature = Signature::default());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let signatures = keypairs.sign_message(&self.message_data());
 | 
				
			||||||
        for i in 0..positions.len() {
 | 
					        for i in 0..positions.len() {
 | 
				
			||||||
            self.signatures[positions[i]] = keypairs[i].sign_message(&self.message_data())
 | 
					            self.signatures[positions[i]] = signatures[i];
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -271,23 +271,16 @@ impl Transaction {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Get the positions of the pubkeys in `account_keys` associated with signing keypairs
 | 
					    /// Get the positions of the pubkeys in `account_keys` associated with signing keypairs
 | 
				
			||||||
    pub fn get_signing_keypair_positions<T: KeypairUtil>(
 | 
					    pub fn get_signing_keypair_positions(&self, pubkeys: &[Pubkey]) -> Result<Vec<Option<usize>>> {
 | 
				
			||||||
        &self,
 | 
					 | 
				
			||||||
        keypairs: &[&T],
 | 
					 | 
				
			||||||
    ) -> Result<Vec<Option<usize>>> {
 | 
					 | 
				
			||||||
        if self.message.account_keys.len() < self.message.header.num_required_signatures as usize {
 | 
					        if self.message.account_keys.len() < self.message.header.num_required_signatures as usize {
 | 
				
			||||||
            return Err(TransactionError::InvalidAccountIndex);
 | 
					            return Err(TransactionError::InvalidAccountIndex);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        let signed_keys =
 | 
					        let signed_keys =
 | 
				
			||||||
            &self.message.account_keys[0..self.message.header.num_required_signatures as usize];
 | 
					            &self.message.account_keys[0..self.message.header.num_required_signatures as usize];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Ok(keypairs
 | 
					        Ok(pubkeys
 | 
				
			||||||
            .iter()
 | 
					            .iter()
 | 
				
			||||||
            .map(|keypair| {
 | 
					            .map(|pubkey| signed_keys.iter().position(|x| x == pubkey))
 | 
				
			||||||
                signed_keys
 | 
					 | 
				
			||||||
                    .iter()
 | 
					 | 
				
			||||||
                    .position(|pubkey| pubkey == &keypair.pubkey())
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .collect())
 | 
					            .collect())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -338,7 +331,12 @@ impl Transaction {
 | 
				
			|||||||
#[cfg(test)]
 | 
					#[cfg(test)]
 | 
				
			||||||
mod tests {
 | 
					mod tests {
 | 
				
			||||||
    use super::*;
 | 
					    use super::*;
 | 
				
			||||||
    use crate::{hash::hash, instruction::AccountMeta, signature::Keypair, system_instruction};
 | 
					    use crate::{
 | 
				
			||||||
 | 
					        hash::hash,
 | 
				
			||||||
 | 
					        instruction::AccountMeta,
 | 
				
			||||||
 | 
					        signature::{Keypair, KeypairUtil},
 | 
				
			||||||
 | 
					        system_instruction,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
    use bincode::{deserialize, serialize, serialized_size};
 | 
					    use bincode::{deserialize, serialize, serialized_size};
 | 
				
			||||||
    use std::mem::size_of;
 | 
					    use std::mem::size_of;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user