Skip to content

Commit

Permalink
sdk: fix replace_signatures for variable signer ordering (anza-xyz#1608)
Browse files Browse the repository at this point in the history
* Add failing test

* sdk: don't assume input key ordering matches tx when replacing signatures

* Refactor iterators

---------

Co-authored-by: Trent Nelson <[email protected]>
  • Loading branch information
CriesofCarrots and t-nelson authored Jun 5, 2024
1 parent 28242cd commit ad29f68
Showing 1 changed file with 45 additions and 5 deletions.
50 changes: 45 additions & 5 deletions sdk/src/transaction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1060,13 +1060,21 @@ impl Transaction {
return Err(TransactionError::InvalidAccountIndex);
}

signers
for (index, account_key) in self
.message
.account_keys
.iter()
.enumerate()
.for_each(|(i, (pubkey, signature))| {
self.signatures[i] = *signature;
self.message.account_keys[i] = *pubkey;
});
.take(num_required_signatures)
{
if let Some((_pubkey, signature)) =
signers.iter().find(|(key, _signature)| account_key == key)
{
self.signatures[index] = *signature
} else {
return Err(TransactionError::InvalidAccountIndex);
}
}

self.verify()
}
Expand Down Expand Up @@ -1662,4 +1670,36 @@ mod tests {

assert!(tx.is_signed());
}

#[test]
fn test_replace_signatures() {
let program_id = Pubkey::default();
let keypair0 = Keypair::new();
let keypair1 = Keypair::new();
let pubkey0 = keypair0.pubkey();
let pubkey1 = keypair1.pubkey();
let ix = Instruction::new_with_bincode(
program_id,
&0,
vec![
AccountMeta::new(pubkey0, true),
AccountMeta::new(pubkey1, true),
],
);
let message = Message::new(&[ix], Some(&pubkey0));
let expected_account_keys = message.account_keys.clone();
let mut tx = Transaction::new_unsigned(message);
tx.sign(&[&keypair0, &keypair1], Hash::new_unique());

let signature0 = keypair0.sign_message(&tx.message_data());
let signature1 = keypair1.sign_message(&tx.message_data());

// Replace signatures with order swapped
tx.replace_signatures(&[(pubkey1, signature1), (pubkey0, signature0)])
.unwrap();
// Order of account_keys should not change
assert_eq!(tx.message.account_keys, expected_account_keys);
// Order of signatures should match original account_keys list
assert_eq!(tx.signatures, &[signature0, signature1]);
}
}

0 comments on commit ad29f68

Please sign in to comment.