Add offline signing support to CLI (#7104)
This commit is contained in:
@ -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,
|
||||
|
@ -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()
|
||||
|
Reference in New Issue
Block a user