feat: Allow for verifying the sigs of partially signed txs in web3.js (#29249)
* feat: allow for verifying the sigs of partially signed txs * fix: make comment ab verifying sigs more specific Co-authored-by: Steven Luscher <steveluscher@users.noreply.github.com> * feat: add tests for partial signed tx verification * fix: revert lockfile changes * fix: make tests more modular * fix: run linter Co-authored-by: Steven Luscher <steveluscher@users.noreply.github.com>
This commit is contained in:
parent
1cc8917b9f
commit
5f4752a29e
|
@ -726,10 +726,15 @@ export class Transaction {
|
|||
}
|
||||
|
||||
/**
|
||||
* Verify signatures of a complete, signed Transaction
|
||||
* Verify signatures of a Transaction
|
||||
* Optional parameter specifies if we're expecting a fully signed Transaction or a partially signed one.
|
||||
* If no boolean is provided, we expect a fully signed Transaction by default.
|
||||
*/
|
||||
verifySignatures(): boolean {
|
||||
return this._verifySignatures(this.serializeMessage(), true);
|
||||
verifySignatures(requireAllSignatures?: boolean): boolean {
|
||||
return this._verifySignatures(
|
||||
this.serializeMessage(),
|
||||
requireAllSignatures === undefined ? true : requireAllSignatures,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -845,6 +845,127 @@ describe('Transaction', () => {
|
|||
expect(expectedTransaction.signatures).to.have.length(1);
|
||||
});
|
||||
|
||||
describe('partially signed transaction signature verification tests', () => {
|
||||
const sender = Keypair.fromSeed(Uint8Array.from(Array(32).fill(8))); // Arbitrary known account
|
||||
const feePayer = Keypair.fromSeed(Uint8Array.from(Array(32).fill(9))); // Arbitrary known account
|
||||
const fakeKey = Keypair.fromSeed(Uint8Array.from(Array(32).fill(10))); // Arbitrary known account
|
||||
const recentBlockhash = 'EETubP5AKHgjPAhzPAFcb8BAY1hMH639CWCFTqi3hq1k'; // Arbitrary known recentBlockhash
|
||||
const recipient = new PublicKey(
|
||||
'J3dxNj7nDRRqRRXuEMynDG57DkZK4jYRuv3Garmb1i99',
|
||||
); // Arbitrary known public key
|
||||
const transfer = SystemProgram.transfer({
|
||||
fromPubkey: sender.publicKey,
|
||||
toPubkey: recipient,
|
||||
lamports: 49,
|
||||
});
|
||||
let expectedTransaction: Transaction;
|
||||
beforeEach(() => {
|
||||
expectedTransaction = new Transaction({
|
||||
blockhash: recentBlockhash,
|
||||
lastValidBlockHeight: 9999,
|
||||
}).add(transfer);
|
||||
// To have 2 required signers we add a feepayer
|
||||
expectedTransaction.feePayer = feePayer.publicKey;
|
||||
});
|
||||
|
||||
it('verifies for no sigs', () => {
|
||||
expect(expectedTransaction.signatures).to.have.length(0);
|
||||
|
||||
// No extra param should require all sigs, should be false for no sigs
|
||||
expect(expectedTransaction.verifySignatures()).to.be.false;
|
||||
|
||||
// True should require all sigs, should be false for no sigs
|
||||
expect(expectedTransaction.verifySignatures(true)).to.be.false;
|
||||
|
||||
// False should verify only the available sigs, should be true for no sigs
|
||||
expect(expectedTransaction.verifySignatures(false)).to.be.true;
|
||||
});
|
||||
|
||||
it('verifies for one sig', () => {
|
||||
// Add one required sig
|
||||
expectedTransaction.partialSign(sender);
|
||||
|
||||
expect(
|
||||
expectedTransaction.signatures.filter(sig => sig.signature !== null),
|
||||
).to.have.length(1);
|
||||
|
||||
// No extra param should require all sigs, should be false for one missing sig
|
||||
expect(expectedTransaction.verifySignatures()).to.be.false;
|
||||
|
||||
// True should require all sigs, should be false one missing sigs
|
||||
expect(expectedTransaction.verifySignatures(true)).to.be.false;
|
||||
|
||||
// False should verify only the available sigs, should be true one valid sig
|
||||
expect(expectedTransaction.verifySignatures(false)).to.be.true;
|
||||
});
|
||||
|
||||
it('verifies for all sigs', () => {
|
||||
// Add all required sigs
|
||||
expectedTransaction.partialSign(sender);
|
||||
expectedTransaction.partialSign(feePayer);
|
||||
|
||||
expect(
|
||||
expectedTransaction.signatures.filter(sig => sig.signature !== null),
|
||||
).to.have.length(2);
|
||||
|
||||
// No extra param should require all sigs, should be true for no missing sig
|
||||
expect(expectedTransaction.verifySignatures()).to.be.true;
|
||||
|
||||
// True should require all sigs, should be true for no missing sig
|
||||
expect(expectedTransaction.verifySignatures(true)).to.be.true;
|
||||
|
||||
// False should verify only the available sigs, should be true for no missing sig
|
||||
expect(expectedTransaction.verifySignatures(false)).to.be.true;
|
||||
});
|
||||
|
||||
it('throws for wrong sig with only one sig present', () => {
|
||||
// Add one required sigs
|
||||
expectedTransaction.partialSign(feePayer);
|
||||
|
||||
// Add a wrong signature
|
||||
expectedTransaction.signatures[0].publicKey = fakeKey.publicKey;
|
||||
|
||||
// No extra param should require all sigs, should throw for wrong sig
|
||||
expect(() => expectedTransaction.verifySignatures()).to.throw(
|
||||
'unknown signer: ' + fakeKey.publicKey.toBase58(),
|
||||
);
|
||||
|
||||
// True should require all sigs, should throw for wrong sig
|
||||
expect(() => expectedTransaction.verifySignatures(true)).to.throw(
|
||||
'unknown signer: ' + fakeKey.publicKey.toBase58(),
|
||||
);
|
||||
|
||||
// False should verify only the available sigs, should throw for wrong sig
|
||||
expect(() => expectedTransaction.verifySignatures(false)).to.throw(
|
||||
'unknown signer: ' + fakeKey.publicKey.toBase58(),
|
||||
);
|
||||
});
|
||||
|
||||
it('throws for wrong sig with all sigs present', () => {
|
||||
// Add all required sigs
|
||||
expectedTransaction.partialSign(sender);
|
||||
expectedTransaction.partialSign(feePayer);
|
||||
|
||||
// Add a wrong signature
|
||||
expectedTransaction.signatures[0].publicKey = fakeKey.publicKey;
|
||||
|
||||
// No extra param should require all sigs, should throw for wrong sig
|
||||
expect(() => expectedTransaction.verifySignatures()).to.throw(
|
||||
'unknown signer: ' + fakeKey.publicKey.toBase58(),
|
||||
);
|
||||
|
||||
// True should require all sigs, should throw for wrong sig
|
||||
expect(() => expectedTransaction.verifySignatures(true)).to.throw(
|
||||
'unknown signer: ' + fakeKey.publicKey.toBase58(),
|
||||
);
|
||||
|
||||
// False should verify only the available sigs, should throw for wrong sig
|
||||
expect(() => expectedTransaction.verifySignatures(false)).to.throw(
|
||||
'unknown signer: ' + fakeKey.publicKey.toBase58(),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('deprecated - externally signed stake delegate', () => {
|
||||
const authority = Keypair.fromSeed(Uint8Array.from(Array(32).fill(1)));
|
||||
const stake = new PublicKey(2);
|
||||
|
|
Loading…
Reference in New Issue