Merge pull request #1519 from bitcoinjs/doubleMSSamekey
PSBT Bugfix for multiple of same pubkey in p2ms
This commit is contained in:
commit
879d49033c
3 changed files with 66 additions and 8 deletions
20
src/psbt.js
20
src/psbt.js
|
@ -590,15 +590,27 @@ function canFinalize(input, script, scriptType) {
|
|||
return hasSigs(1, input.partialSig);
|
||||
case 'multisig':
|
||||
const p2ms = payments.p2ms({ output: script });
|
||||
return hasSigs(p2ms.m, input.partialSig);
|
||||
return hasSigs(p2ms.m, input.partialSig, p2ms.pubkeys);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
function hasSigs(neededSigs, partialSig) {
|
||||
function hasSigs(neededSigs, partialSig, pubkeys) {
|
||||
if (!partialSig) return false;
|
||||
if (partialSig.length > neededSigs) throw new Error('Too many signatures');
|
||||
return partialSig.length === neededSigs;
|
||||
let sigs;
|
||||
if (pubkeys) {
|
||||
sigs = pubkeys
|
||||
.map(pkey => {
|
||||
const pubkey = ecpair_1.fromPublicKey(pkey, { compressed: true })
|
||||
.publicKey;
|
||||
return partialSig.find(pSig => pSig.pubkey.equals(pubkey));
|
||||
})
|
||||
.filter(v => !!v);
|
||||
} else {
|
||||
sigs = partialSig;
|
||||
}
|
||||
if (sigs.length > neededSigs) throw new Error('Too many signatures');
|
||||
return sigs.length === neededSigs;
|
||||
}
|
||||
function isFinalized(input) {
|
||||
return !!input.finalScriptSig || !!input.finalScriptWitness;
|
||||
|
|
|
@ -530,6 +530,36 @@ describe('bitcoinjs-lib (transactions with psbt)', () => {
|
|||
},
|
||||
);
|
||||
|
||||
it(
|
||||
'can create (and broadcast via 3PBP) a Transaction, w/ a ' +
|
||||
'P2SH(P2MS(2 of 2)) input with nonWitnessUtxo',
|
||||
async () => {
|
||||
const myKey = bitcoin.ECPair.makeRandom({ network: regtest });
|
||||
const myKeys = [
|
||||
myKey,
|
||||
bitcoin.ECPair.fromPrivateKey(myKey.privateKey!, { network: regtest }),
|
||||
];
|
||||
const p2sh = createPayment('p2sh-p2ms(2 of 2)', myKeys);
|
||||
const inputData = await getInputData(5e4, p2sh.payment, false, 'p2sh');
|
||||
const psbt = new bitcoin.Psbt({ network: regtest })
|
||||
.addInput(inputData)
|
||||
.addOutput({
|
||||
address: regtestUtils.RANDOM_ADDRESS,
|
||||
value: 2e4,
|
||||
})
|
||||
.signInput(0, p2sh.keys[0]);
|
||||
psbt.finalizeAllInputs();
|
||||
const tx = psbt.extractTransaction();
|
||||
await regtestUtils.broadcast(tx.toHex());
|
||||
await regtestUtils.verify({
|
||||
txId: tx.getId(),
|
||||
address: regtestUtils.RANDOM_ADDRESS,
|
||||
vout: 0,
|
||||
value: 2e4,
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
it('can create (and broadcast via 3PBP) a Transaction, w/ a P2WPKH input using HD', async () => {
|
||||
const hdRoot = bip32.fromSeed(rng(64));
|
||||
const masterFingerprint = hdRoot.fingerprint;
|
||||
|
|
|
@ -770,16 +770,32 @@ function canFinalize(
|
|||
return hasSigs(1, input.partialSig);
|
||||
case 'multisig':
|
||||
const p2ms = payments.p2ms({ output: script });
|
||||
return hasSigs(p2ms.m!, input.partialSig);
|
||||
return hasSigs(p2ms.m!, input.partialSig, p2ms.pubkeys);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function hasSigs(neededSigs: number, partialSig?: any[]): boolean {
|
||||
function hasSigs(
|
||||
neededSigs: number,
|
||||
partialSig?: any[],
|
||||
pubkeys?: Buffer[],
|
||||
): boolean {
|
||||
if (!partialSig) return false;
|
||||
if (partialSig.length > neededSigs) throw new Error('Too many signatures');
|
||||
return partialSig.length === neededSigs;
|
||||
let sigs: any;
|
||||
if (pubkeys) {
|
||||
sigs = pubkeys
|
||||
.map(pkey => {
|
||||
const pubkey = ecPairFromPublicKey(pkey, { compressed: true })
|
||||
.publicKey;
|
||||
return partialSig.find(pSig => pSig.pubkey.equals(pubkey));
|
||||
})
|
||||
.filter(v => !!v);
|
||||
} else {
|
||||
sigs = partialSig;
|
||||
}
|
||||
if (sigs.length > neededSigs) throw new Error('Too many signatures');
|
||||
return sigs.length === neededSigs;
|
||||
}
|
||||
|
||||
function isFinalized(input: PsbtInput): boolean {
|
||||
|
|
Loading…
Reference in a new issue