@ -30,7 +30,7 @@ declare print_free_tree=(
|
|||||||
'programs/stake_program/src'
|
'programs/stake_program/src'
|
||||||
)
|
)
|
||||||
|
|
||||||
if _ git grep -n --max-depth=0 "${prints[@]/#/-e }" -- "${print_free_tree[@]}"; then
|
if _ git --no-pager grep -n --max-depth=0 "${prints[@]/#/-e }" -- "${print_free_tree[@]}"; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -39,14 +39,14 @@ fi
|
|||||||
# Default::default()
|
# Default::default()
|
||||||
#
|
#
|
||||||
# Ref: https://github.com/solana-labs/solana/issues/2630
|
# Ref: https://github.com/solana-labs/solana/issues/2630
|
||||||
if _ git grep -n 'Default::default()' -- '*.rs'; then
|
if _ git --no-pager grep -n 'Default::default()' -- '*.rs'; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Let's keep a .gitignore for every crate, ensure it's got
|
# Let's keep a .gitignore for every crate, ensure it's got
|
||||||
# /target/ in it
|
# /target/ in it
|
||||||
declare gitignores_ok=true
|
declare gitignores_ok=true
|
||||||
for i in $(git ls-files \*/Cargo.toml ); do
|
for i in $(git --no-pager ls-files \*/Cargo.toml ); do
|
||||||
dir=$(dirname "$i")
|
dir=$(dirname "$i")
|
||||||
if [[ ! -f $dir/.gitignore ]]; then
|
if [[ ! -f $dir/.gitignore ]]; then
|
||||||
echo 'error: nits.sh .gitnore missing for crate '"$dir" >&2
|
echo 'error: nits.sh .gitnore missing for crate '"$dir" >&2
|
||||||
|
@ -67,7 +67,7 @@ pub struct Transaction {
|
|||||||
impl Transaction {
|
impl Transaction {
|
||||||
pub fn new_unsigned(message: Message) -> Self {
|
pub fn new_unsigned(message: Message) -> Self {
|
||||||
Self {
|
Self {
|
||||||
signatures: Vec::with_capacity(message.num_required_signatures as usize),
|
signatures: vec![Signature::default(); message.num_required_signatures as usize],
|
||||||
message,
|
message,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -180,10 +180,40 @@ impl Transaction {
|
|||||||
assert_eq!(keypair.pubkey(), signed_keys[i], "keypair-pubkey mismatch");
|
assert_eq!(keypair.pubkey(), signed_keys[i], "keypair-pubkey mismatch");
|
||||||
}
|
}
|
||||||
assert_eq!(keypairs.len(), signed_keys.len(), "not enough keypairs");
|
assert_eq!(keypairs.len(), signed_keys.len(), "not enough keypairs");
|
||||||
|
|
||||||
self.sign_unchecked(keypairs, recent_blockhash);
|
self.sign_unchecked(keypairs, recent_blockhash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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: KeypairUtil>(&mut self, keypairs: &[&T], recent_blockhash: Hash) {
|
||||||
|
let signed_keys =
|
||||||
|
&self.message.account_keys[0..self.message.num_required_signatures as usize];
|
||||||
|
|
||||||
|
// if you change the blockhash, you're re-signing...
|
||||||
|
if recent_blockhash != self.message.recent_blockhash {
|
||||||
|
self.message.recent_blockhash = recent_blockhash;
|
||||||
|
self.signatures
|
||||||
|
.iter_mut()
|
||||||
|
.for_each(|signature| *signature = Signature::default());
|
||||||
|
}
|
||||||
|
|
||||||
|
for keypair in keypairs {
|
||||||
|
let i = signed_keys
|
||||||
|
.iter()
|
||||||
|
.position(|pubkey| pubkey == &keypair.pubkey())
|
||||||
|
.expect("keypair-pubkey mismatch");
|
||||||
|
|
||||||
|
self.signatures[i] = keypair.sign_message(&self.message_data())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_signed(&self) -> bool {
|
||||||
|
self.signatures
|
||||||
|
.iter()
|
||||||
|
.all(|signature| *signature != Signature::default())
|
||||||
|
}
|
||||||
|
|
||||||
/// Verify that references in the instructions are valid
|
/// Verify that references in the instructions are valid
|
||||||
pub fn verify_refs(&self) -> bool {
|
pub fn verify_refs(&self) -> bool {
|
||||||
let message = self.message();
|
let message = self.message();
|
||||||
@ -204,6 +234,7 @@ impl Transaction {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::hash::hash;
|
||||||
use crate::instruction::AccountMeta;
|
use crate::instruction::AccountMeta;
|
||||||
use crate::signature::Keypair;
|
use crate::signature::Keypair;
|
||||||
use crate::system_instruction;
|
use crate::system_instruction;
|
||||||
@ -397,6 +428,45 @@ mod tests {
|
|||||||
Transaction::new_unsigned_instructions(vec![]).sign(&[&keypair], Hash::default());
|
Transaction::new_unsigned_instructions(vec![]).sign(&[&keypair], Hash::default());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn test_partial_sign_mismatched_key() {
|
||||||
|
let keypair = Keypair::new();
|
||||||
|
Transaction::new_unsigned_instructions(vec![Instruction::new(
|
||||||
|
Pubkey::default(),
|
||||||
|
&0,
|
||||||
|
vec![AccountMeta::new(Pubkey::new_rand(), true)],
|
||||||
|
)])
|
||||||
|
.partial_sign(&[&keypair], Hash::default());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_partial_sign() {
|
||||||
|
let keypair0 = Keypair::new();
|
||||||
|
let keypair1 = Keypair::new();
|
||||||
|
let keypair2 = Keypair::new();
|
||||||
|
let mut tx = Transaction::new_unsigned_instructions(vec![Instruction::new(
|
||||||
|
Pubkey::default(),
|
||||||
|
&0,
|
||||||
|
vec![
|
||||||
|
AccountMeta::new(keypair0.pubkey(), true),
|
||||||
|
AccountMeta::new(keypair1.pubkey(), true),
|
||||||
|
AccountMeta::new(keypair2.pubkey(), true),
|
||||||
|
],
|
||||||
|
)]);
|
||||||
|
|
||||||
|
tx.partial_sign(&[&keypair0, &keypair2], Hash::default());
|
||||||
|
assert!(!tx.is_signed());
|
||||||
|
tx.partial_sign(&[&keypair1], Hash::default());
|
||||||
|
assert!(tx.is_signed());
|
||||||
|
|
||||||
|
let hash = hash(&[1]);
|
||||||
|
tx.partial_sign(&[&keypair1], hash);
|
||||||
|
assert!(!tx.is_signed());
|
||||||
|
tx.partial_sign(&[&keypair0, &keypair2], hash);
|
||||||
|
assert!(tx.is_signed());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[should_panic]
|
#[should_panic]
|
||||||
fn test_transaction_missing_keypair() {
|
fn test_transaction_missing_keypair() {
|
||||||
@ -430,5 +500,6 @@ mod tests {
|
|||||||
tx.message.instructions[0],
|
tx.message.instructions[0],
|
||||||
CompiledInstruction::new(0, &0, vec![0])
|
CompiledInstruction::new(0, &0, vec![0])
|
||||||
);
|
);
|
||||||
|
assert!(tx.is_signed());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user