Add offline signing support to CLI (#7104)

This commit is contained in:
Jack May
2019-11-25 21:09:57 -08:00
committed by GitHub
parent 294662a1ce
commit 88cb0c6ae3
8 changed files with 892 additions and 70 deletions

View File

@ -117,7 +117,7 @@ impl Instruction {
pub struct AccountMeta {
/// An account's public key
pub pubkey: Pubkey,
/// True if an Instruciton requires a Transaction signature matching `pubkey`.
/// True if an Instruction requires a Transaction signature matching `pubkey`.
pub is_signer: bool,
/// True if the `pubkey` can be loaded as a read-write account.
pub is_writable: bool,

View File

@ -51,6 +51,9 @@ pub enum TransactionError {
/// Transaction contains an invalid account reference
InvalidAccountIndex,
/// Transaction did not pass signature verification
SignatureFailure,
}
pub type Result<T> = result::Result<T, TransactionError>;
@ -225,6 +228,21 @@ impl Transaction {
}
}
/// Verify the transaction
pub fn verify(&self) -> Result<()> {
if !self
.signatures
.iter()
.zip(&self.message.account_keys)
.map(|(signature, pubkey)| signature.verify(pubkey.as_ref(), &self.message_data()))
.all(|verify_result| verify_result)
{
Err(TransactionError::SignatureFailure)
} else {
Ok(())
}
}
/// Get the positions of the pubkeys in `account_keys` associated with signing keypairs
pub fn get_signing_keypair_positions<T: KeypairUtil>(
&self,
@ -246,6 +264,27 @@ impl Transaction {
.collect())
}
/// Replace all the signatures and pubkeys
pub fn replace_signatures(&mut self, signers: &[(Pubkey, Signature)]) -> Result<()> {
let num_required_signatures = self.message.header.num_required_signatures as usize;
if signers.len() != num_required_signatures
|| self.signatures.len() != num_required_signatures
|| self.message.account_keys.len() < num_required_signatures
{
return Err(TransactionError::InvalidAccountIndex);
}
signers
.iter()
.enumerate()
.for_each(|(i, (pubkey, signature))| {
self.signatures[i] = *signature;
self.message.account_keys[i] = *pubkey;
});
self.verify()
}
pub fn is_signed(&self) -> bool {
self.signatures
.iter()