@@ -6,7 +6,7 @@ use crate::{
|
||||
message::Message,
|
||||
pubkey::Pubkey,
|
||||
short_vec,
|
||||
signature::Signature,
|
||||
signature::{Signature, SignerError},
|
||||
signers::Signers,
|
||||
system_instruction,
|
||||
};
|
||||
@@ -214,23 +214,18 @@ impl Transaction {
|
||||
|
||||
/// Check keys and keypair lengths, then sign this transaction.
|
||||
pub fn sign<T: Signers>(&mut self, keypairs: &T, recent_blockhash: Hash) {
|
||||
self.partial_sign(keypairs, recent_blockhash);
|
||||
|
||||
assert_eq!(self.is_signed(), true, "not enough keypairs");
|
||||
if let Err(e) = self.try_sign(keypairs, recent_blockhash) {
|
||||
panic!("Transaction::sign failed with error {:?}", e);
|
||||
}
|
||||
}
|
||||
|
||||
/// Sign using some subset of required keys
|
||||
/// if recent_blockhash is not the same as currently in the transaction,
|
||||
/// clear any prior signatures and update recent_blockhash
|
||||
pub fn partial_sign<T: Signers>(&mut self, keypairs: &T, recent_blockhash: Hash) {
|
||||
let positions = self
|
||||
.get_signing_keypair_positions(&keypairs.pubkeys())
|
||||
.expect("account_keys doesn't contain num_required_signatures keys");
|
||||
let positions: Vec<usize> = positions
|
||||
.iter()
|
||||
.map(|pos| pos.expect("keypair-pubkey mismatch"))
|
||||
.collect();
|
||||
self.partial_sign_unchecked(keypairs, positions, recent_blockhash)
|
||||
if let Err(e) = self.try_partial_sign(keypairs, recent_blockhash) {
|
||||
panic!("Transaction::partial_sign failed with error {:?}", e);
|
||||
}
|
||||
}
|
||||
|
||||
/// Sign the transaction and place the signatures in their associated positions in `signatures`
|
||||
@@ -241,6 +236,55 @@ impl Transaction {
|
||||
positions: Vec<usize>,
|
||||
recent_blockhash: Hash,
|
||||
) {
|
||||
if let Err(e) = self.try_partial_sign_unchecked(keypairs, positions, recent_blockhash) {
|
||||
panic!(
|
||||
"Transaction::partial_sign_unchecked failed with error {:?}",
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Check keys and keypair lengths, then sign this transaction, returning any signing errors
|
||||
/// encountered
|
||||
pub fn try_sign<T: Signers>(
|
||||
&mut self,
|
||||
keypairs: &T,
|
||||
recent_blockhash: Hash,
|
||||
) -> result::Result<(), SignerError> {
|
||||
self.try_partial_sign(keypairs, recent_blockhash)?;
|
||||
|
||||
if !self.is_signed() {
|
||||
Err(SignerError::NotEnoughSigners)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Sign using some subset of required keys, returning any signing errors encountered. If
|
||||
/// recent_blockhash is not the same as currently in the transaction, clear any prior
|
||||
/// signatures and update recent_blockhash
|
||||
pub fn try_partial_sign<T: Signers>(
|
||||
&mut self,
|
||||
keypairs: &T,
|
||||
recent_blockhash: Hash,
|
||||
) -> result::Result<(), SignerError> {
|
||||
let positions = self.get_signing_keypair_positions(&keypairs.pubkeys())?;
|
||||
if positions.iter().any(|pos| pos.is_none()) {
|
||||
return Err(SignerError::KeypairPubkeyMismatch);
|
||||
}
|
||||
let positions: Vec<usize> = positions.iter().map(|pos| pos.unwrap()).collect();
|
||||
self.try_partial_sign_unchecked(keypairs, positions, recent_blockhash)
|
||||
}
|
||||
|
||||
/// Sign the transaction, returning any signing errors encountered, and place the
|
||||
/// signatures in their associated positions in `signatures` without checking that the
|
||||
/// positions are correct.
|
||||
pub fn try_partial_sign_unchecked<T: Signers>(
|
||||
&mut self,
|
||||
keypairs: &T,
|
||||
positions: Vec<usize>,
|
||||
recent_blockhash: Hash,
|
||||
) -> result::Result<(), SignerError> {
|
||||
// if you change the blockhash, you're re-signing...
|
||||
if recent_blockhash != self.message.recent_blockhash {
|
||||
self.message.recent_blockhash = recent_blockhash;
|
||||
@@ -249,10 +293,11 @@ impl Transaction {
|
||||
.for_each(|signature| *signature = Signature::default());
|
||||
}
|
||||
|
||||
let signatures = keypairs.sign_message(&self.message_data());
|
||||
let signatures = keypairs.try_sign_message(&self.message_data())?;
|
||||
for i in 0..positions.len() {
|
||||
self.signatures[positions[i]] = signatures[i];
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Verify the transaction
|
||||
|
||||
Reference in New Issue
Block a user