fix: sort accountMetas after deduping

This commit is contained in:
sudhir-b 2022-05-30 16:47:56 +01:00 committed by Steven Luscher
parent 4b1dd0f921
commit 20f169c0b0
2 changed files with 40 additions and 11 deletions

View File

@ -376,17 +376,6 @@ export class Transaction {
});
});
// Sort. Prioritizing first by signer, then by writable
accountMetas.sort(function (x, y) {
const pubkeySorting = x.pubkey
.toBase58()
.localeCompare(y.pubkey.toBase58());
const checkSigner = x.isSigner === y.isSigner ? 0 : x.isSigner ? -1 : 1;
const checkWritable =
x.isWritable === y.isWritable ? pubkeySorting : x.isWritable ? -1 : 1;
return checkSigner || checkWritable;
});
// Cull duplicate account metas
const uniqueMetas: AccountMeta[] = [];
accountMetas.forEach(accountMeta => {
@ -397,11 +386,24 @@ export class Transaction {
if (uniqueIndex > -1) {
uniqueMetas[uniqueIndex].isWritable =
uniqueMetas[uniqueIndex].isWritable || accountMeta.isWritable;
uniqueMetas[uniqueIndex].isSigner =
uniqueMetas[uniqueIndex].isSigner || accountMeta.isSigner;
} else {
uniqueMetas.push(accountMeta);
}
});
// Sort. Prioritizing first by signer, then by writable
uniqueMetas.sort(function (x, y) {
const pubkeySorting = x.pubkey
.toBase58()
.localeCompare(y.pubkey.toBase58());
const checkSigner = x.isSigner === y.isSigner ? 0 : x.isSigner ? -1 : 1;
const checkWritable =
x.isWritable === y.isWritable ? pubkeySorting : x.isWritable ? -1 : 1;
return checkSigner || checkWritable;
});
// Move fee payer to the front
const feePayerIndex = uniqueMetas.findIndex(x => {
return x.pubkey.equals(feePayer);

View File

@ -47,6 +47,33 @@ describe('Transaction', () => {
expect(message.accountKeys[2]).to.eql(account3.publicKey);
});
it('accountKeys are sorted & deduplicated correctly', () => {
const payer = Keypair.generate();
const account2 = new PublicKey(2);
const account3 = new PublicKey(1);
const recentBlockhash = Keypair.generate().publicKey.toBase58();
const programId = Keypair.generate().publicKey;
const transaction = new Transaction({
blockhash: recentBlockhash,
lastValidBlockHeight: 9999,
}).add({
keys: [
{pubkey: account3, isSigner: true, isWritable: false},
{pubkey: payer.publicKey, isSigner: true, isWritable: true},
{pubkey: account2, isSigner: false, isWritable: true},
{pubkey: account2, isSigner: true, isWritable: false},
],
programId,
});
transaction.feePayer = payer.publicKey;
const message = transaction.compileMessage();
expect(message.accountKeys[0]).to.eql(payer.publicKey);
expect(message.accountKeys[1].toBase58()).to.eql(account2.toBase58());
expect(message.accountKeys[2].toBase58()).to.eql(account3.toBase58());
});
it('payer is first account meta', () => {
const payer = Keypair.generate();
const other = Keypair.generate();