* sdk: Add accessor for signer pubkeys of a tx message (cherry picked from commitbf33ce8906
) * clap-utils: Add helper to `CliSignerInfo` for getting signers for a message (cherry picked from commit4e99f1e634
) Co-authored-by: Trent Nelson <trent@solana.com>
This commit is contained in:
@ -12,6 +12,7 @@ use solana_remote_wallet::{
|
|||||||
};
|
};
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
hash::Hash,
|
hash::Hash,
|
||||||
|
message::Message,
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
signature::{
|
signature::{
|
||||||
keypair_from_seed, keypair_from_seed_phrase_and_passphrase, read_keypair,
|
keypair_from_seed, keypair_from_seed_phrase_and_passphrase, read_keypair,
|
||||||
@ -68,6 +69,18 @@ impl CliSignerInfo {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn signers_for_message(&self, message: &Message) -> Vec<&dyn Signer> {
|
||||||
|
self.signers
|
||||||
|
.iter()
|
||||||
|
.filter_map(|k| {
|
||||||
|
if message.signer_keys().contains(&&k.pubkey()) {
|
||||||
|
Some(k.as_ref())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DefaultSigner {
|
pub struct DefaultSigner {
|
||||||
@ -356,6 +369,7 @@ fn sanitize_seed_phrase(seed_phrase: &str) -> String {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use solana_sdk::system_instruction;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_sanitize_seed_phrase() {
|
fn test_sanitize_seed_phrase() {
|
||||||
@ -365,4 +379,35 @@ mod tests {
|
|||||||
sanitize_seed_phrase(seed_phrase)
|
sanitize_seed_phrase(seed_phrase)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_signer_info_signers_for_message() {
|
||||||
|
let source = Keypair::new();
|
||||||
|
let fee_payer = Keypair::new();
|
||||||
|
let nonsigner1 = Keypair::new();
|
||||||
|
let nonsigner2 = Keypair::new();
|
||||||
|
let recipient = Pubkey::new_unique();
|
||||||
|
let message = Message::new(
|
||||||
|
&[system_instruction::transfer(
|
||||||
|
&source.pubkey(),
|
||||||
|
&recipient,
|
||||||
|
42,
|
||||||
|
)],
|
||||||
|
Some(&fee_payer.pubkey()),
|
||||||
|
);
|
||||||
|
let signers = vec![
|
||||||
|
Box::new(fee_payer) as Box<dyn Signer>,
|
||||||
|
Box::new(source) as Box<dyn Signer>,
|
||||||
|
Box::new(nonsigner1) as Box<dyn Signer>,
|
||||||
|
Box::new(nonsigner2) as Box<dyn Signer>,
|
||||||
|
];
|
||||||
|
let signer_info = CliSignerInfo { signers };
|
||||||
|
let msg_signers = signer_info.signers_for_message(&message);
|
||||||
|
let signer_pubkeys = msg_signers.iter().map(|s| s.pubkey()).collect::<Vec<_>>();
|
||||||
|
let expect = vec![
|
||||||
|
signer_info.signers[0].pubkey(),
|
||||||
|
signer_info.signers[1].pubkey(),
|
||||||
|
];
|
||||||
|
assert_eq!(signer_pubkeys, expect);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -435,6 +435,15 @@ impl Message {
|
|||||||
accounts,
|
accounts,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn signer_keys(&self) -> Vec<&Pubkey> {
|
||||||
|
// Clamp in case we're working on un-`sanitize()`ed input
|
||||||
|
let last_key = self
|
||||||
|
.account_keys
|
||||||
|
.len()
|
||||||
|
.max(self.header.num_required_signatures as usize);
|
||||||
|
self.account_keys[..last_key].iter().collect()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
Reference in New Issue
Block a user