Fix signInputAsync when SignerAsync rejects
Co-authored-by: Zhang Zengbo <zengbo.zhang@gmail.com>
This commit is contained in:
parent
9e2a8fe45a
commit
65d7603cf7
3 changed files with 91 additions and 40 deletions
|
@ -488,9 +488,9 @@ class Psbt {
|
||||||
keyPair,
|
keyPair,
|
||||||
sighashTypes = [transaction_1.Transaction.SIGHASH_ALL],
|
sighashTypes = [transaction_1.Transaction.SIGHASH_ALL],
|
||||||
) {
|
) {
|
||||||
return new Promise((resolve, reject) => {
|
return Promise.resolve().then(() => {
|
||||||
if (!keyPair || !keyPair.publicKey)
|
if (!keyPair || !keyPair.publicKey)
|
||||||
return reject(new Error('Need Signer to sign input'));
|
throw new Error('Need Signer to sign input');
|
||||||
const { hash, sighashType } = getHashAndSighashType(
|
const { hash, sighashType } = getHashAndSighashType(
|
||||||
this.data.inputs,
|
this.data.inputs,
|
||||||
inputIndex,
|
inputIndex,
|
||||||
|
@ -498,7 +498,7 @@ class Psbt {
|
||||||
this.__CACHE,
|
this.__CACHE,
|
||||||
sighashTypes,
|
sighashTypes,
|
||||||
);
|
);
|
||||||
Promise.resolve(keyPair.sign(hash)).then(signature => {
|
return Promise.resolve(keyPair.sign(hash)).then(signature => {
|
||||||
const partialSig = [
|
const partialSig = [
|
||||||
{
|
{
|
||||||
pubkey: keyPair.publicKey,
|
pubkey: keyPair.publicKey,
|
||||||
|
@ -506,7 +506,6 @@ class Psbt {
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
this.data.updateInput(inputIndex, { partialSig });
|
this.data.updateInput(inputIndex, { partialSig });
|
||||||
resolve();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,14 @@
|
||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import { describe, it } from 'mocha';
|
import { describe, it } from 'mocha';
|
||||||
|
|
||||||
import { bip32, ECPair, networks as NETWORKS, Psbt } from '..';
|
import {
|
||||||
|
bip32,
|
||||||
|
ECPair,
|
||||||
|
networks as NETWORKS,
|
||||||
|
Psbt,
|
||||||
|
Signer,
|
||||||
|
SignerAsync,
|
||||||
|
} from '..';
|
||||||
|
|
||||||
import * as preFixtures from './fixtures/psbt.json';
|
import * as preFixtures from './fixtures/psbt.json';
|
||||||
|
|
||||||
|
@ -22,6 +29,40 @@ const fixtures = initBuffers(preFixtures);
|
||||||
const upperCaseFirstLetter = (str: string): string =>
|
const upperCaseFirstLetter = (str: string): string =>
|
||||||
str.replace(/^./, s => s.toUpperCase());
|
str.replace(/^./, s => s.toUpperCase());
|
||||||
|
|
||||||
|
const toAsyncSigner = (signer: Signer): SignerAsync => {
|
||||||
|
const ret: SignerAsync = {
|
||||||
|
publicKey: signer.publicKey,
|
||||||
|
sign: (hash: Buffer, lowerR: boolean | undefined): Promise<Buffer> => {
|
||||||
|
return new Promise(
|
||||||
|
(resolve, rejects): void => {
|
||||||
|
setTimeout(() => {
|
||||||
|
try {
|
||||||
|
const r = signer.sign(hash, lowerR);
|
||||||
|
resolve(r);
|
||||||
|
} catch (e) {
|
||||||
|
rejects(e);
|
||||||
|
}
|
||||||
|
}, 10);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
const failedAsyncSigner = (publicKey: Buffer): SignerAsync => {
|
||||||
|
return {
|
||||||
|
publicKey,
|
||||||
|
sign: (__: Buffer): Promise<Buffer> => {
|
||||||
|
return new Promise(
|
||||||
|
(_, reject): void => {
|
||||||
|
setTimeout(() => {
|
||||||
|
reject(new Error('sign failed'));
|
||||||
|
}, 10);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
// const b = (hex: string) => Buffer.from(hex, 'hex');
|
// const b = (hex: string) => Buffer.from(hex, 'hex');
|
||||||
|
|
||||||
describe(`Psbt`, () => {
|
describe(`Psbt`, () => {
|
||||||
|
@ -164,25 +205,39 @@ describe(`Psbt`, () => {
|
||||||
it(f.description, async () => {
|
it(f.description, async () => {
|
||||||
if (f.shouldSign) {
|
if (f.shouldSign) {
|
||||||
const psbtThatShouldsign = Psbt.fromBase64(f.shouldSign.psbt);
|
const psbtThatShouldsign = Psbt.fromBase64(f.shouldSign.psbt);
|
||||||
assert.doesNotReject(async () => {
|
await assert.doesNotReject(async () => {
|
||||||
await psbtThatShouldsign.signInputAsync(
|
await psbtThatShouldsign.signInputAsync(
|
||||||
f.shouldSign.inputToCheck,
|
f.shouldSign.inputToCheck,
|
||||||
ECPair.fromWIF(f.shouldSign.WIF),
|
ECPair.fromWIF(f.shouldSign.WIF),
|
||||||
f.shouldSign.sighashTypes || undefined,
|
f.shouldSign.sighashTypes || undefined,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
await assert.rejects(async () => {
|
||||||
|
await psbtThatShouldsign.signInputAsync(
|
||||||
|
f.shouldSign.inputToCheck,
|
||||||
|
failedAsyncSigner(ECPair.fromWIF(f.shouldSign.WIF).publicKey),
|
||||||
|
f.shouldSign.sighashTypes || undefined,
|
||||||
|
);
|
||||||
|
}, /sign failed/);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (f.shouldThrow) {
|
if (f.shouldThrow) {
|
||||||
const psbtThatShouldThrow = Psbt.fromBase64(f.shouldThrow.psbt);
|
const psbtThatShouldThrow = Psbt.fromBase64(f.shouldThrow.psbt);
|
||||||
assert.rejects(async () => {
|
await assert.rejects(async () => {
|
||||||
await psbtThatShouldThrow.signInputAsync(
|
await psbtThatShouldThrow.signInputAsync(
|
||||||
f.shouldThrow.inputToCheck,
|
f.shouldThrow.inputToCheck,
|
||||||
ECPair.fromWIF(f.shouldThrow.WIF),
|
ECPair.fromWIF(f.shouldThrow.WIF),
|
||||||
(f.shouldThrow as any).sighashTypes || undefined,
|
(f.shouldThrow as any).sighashTypes || undefined,
|
||||||
);
|
);
|
||||||
}, new RegExp(f.shouldThrow.errorMessage));
|
}, new RegExp(f.shouldThrow.errorMessage));
|
||||||
assert.rejects(async () => {
|
await assert.rejects(async () => {
|
||||||
|
await psbtThatShouldThrow.signInputAsync(
|
||||||
|
f.shouldThrow.inputToCheck,
|
||||||
|
toAsyncSigner(ECPair.fromWIF(f.shouldThrow.WIF)),
|
||||||
|
(f.shouldThrow as any).sighashTypes || undefined,
|
||||||
|
);
|
||||||
|
}, new RegExp(f.shouldThrow.errorMessage));
|
||||||
|
await assert.rejects(async () => {
|
||||||
await (psbtThatShouldThrow.signInputAsync as any)(
|
await (psbtThatShouldThrow.signInputAsync as any)(
|
||||||
f.shouldThrow.inputToCheck,
|
f.shouldThrow.inputToCheck,
|
||||||
);
|
);
|
||||||
|
@ -229,7 +284,7 @@ describe(`Psbt`, () => {
|
||||||
it(f.description, async () => {
|
it(f.description, async () => {
|
||||||
if (f.shouldSign) {
|
if (f.shouldSign) {
|
||||||
const psbtThatShouldsign = Psbt.fromBase64(f.shouldSign.psbt);
|
const psbtThatShouldsign = Psbt.fromBase64(f.shouldSign.psbt);
|
||||||
assert.doesNotReject(async () => {
|
await assert.doesNotReject(async () => {
|
||||||
await psbtThatShouldsign.signAllInputsAsync(
|
await psbtThatShouldsign.signAllInputsAsync(
|
||||||
ECPair.fromWIF(f.shouldSign.WIF),
|
ECPair.fromWIF(f.shouldSign.WIF),
|
||||||
f.shouldSign.sighashTypes || undefined,
|
f.shouldSign.sighashTypes || undefined,
|
||||||
|
@ -239,13 +294,13 @@ describe(`Psbt`, () => {
|
||||||
|
|
||||||
if (f.shouldThrow) {
|
if (f.shouldThrow) {
|
||||||
const psbtThatShouldThrow = Psbt.fromBase64(f.shouldThrow.psbt);
|
const psbtThatShouldThrow = Psbt.fromBase64(f.shouldThrow.psbt);
|
||||||
assert.rejects(async () => {
|
await assert.rejects(async () => {
|
||||||
await psbtThatShouldThrow.signAllInputsAsync(
|
await psbtThatShouldThrow.signAllInputsAsync(
|
||||||
ECPair.fromWIF(f.shouldThrow.WIF),
|
ECPair.fromWIF(f.shouldThrow.WIF),
|
||||||
(f.shouldThrow as any).sighashTypes || undefined,
|
(f.shouldThrow as any).sighashTypes || undefined,
|
||||||
);
|
);
|
||||||
}, new RegExp('No inputs were signed'));
|
}, new RegExp('No inputs were signed'));
|
||||||
assert.rejects(async () => {
|
await assert.rejects(async () => {
|
||||||
await (psbtThatShouldThrow.signAllInputsAsync as any)();
|
await (psbtThatShouldThrow.signAllInputsAsync as any)();
|
||||||
}, new RegExp('Need Signer to sign input'));
|
}, new RegExp('Need Signer to sign input'));
|
||||||
}
|
}
|
||||||
|
@ -288,7 +343,7 @@ describe(`Psbt`, () => {
|
||||||
it(f.description, async () => {
|
it(f.description, async () => {
|
||||||
if (f.shouldSign) {
|
if (f.shouldSign) {
|
||||||
const psbtThatShouldsign = Psbt.fromBase64(f.shouldSign.psbt);
|
const psbtThatShouldsign = Psbt.fromBase64(f.shouldSign.psbt);
|
||||||
assert.doesNotReject(async () => {
|
await assert.doesNotReject(async () => {
|
||||||
await psbtThatShouldsign.signInputHDAsync(
|
await psbtThatShouldsign.signInputHDAsync(
|
||||||
f.shouldSign.inputToCheck,
|
f.shouldSign.inputToCheck,
|
||||||
bip32.fromBase58(f.shouldSign.xprv),
|
bip32.fromBase58(f.shouldSign.xprv),
|
||||||
|
@ -299,14 +354,14 @@ describe(`Psbt`, () => {
|
||||||
|
|
||||||
if (f.shouldThrow) {
|
if (f.shouldThrow) {
|
||||||
const psbtThatShouldThrow = Psbt.fromBase64(f.shouldThrow.psbt);
|
const psbtThatShouldThrow = Psbt.fromBase64(f.shouldThrow.psbt);
|
||||||
assert.rejects(async () => {
|
await assert.rejects(async () => {
|
||||||
await psbtThatShouldThrow.signInputHDAsync(
|
await psbtThatShouldThrow.signInputHDAsync(
|
||||||
f.shouldThrow.inputToCheck,
|
f.shouldThrow.inputToCheck,
|
||||||
bip32.fromBase58(f.shouldThrow.xprv),
|
bip32.fromBase58(f.shouldThrow.xprv),
|
||||||
(f.shouldThrow as any).sighashTypes || undefined,
|
(f.shouldThrow as any).sighashTypes || undefined,
|
||||||
);
|
);
|
||||||
}, new RegExp(f.shouldThrow.errorMessage));
|
}, new RegExp(f.shouldThrow.errorMessage));
|
||||||
assert.rejects(async () => {
|
await assert.rejects(async () => {
|
||||||
await (psbtThatShouldThrow.signInputHDAsync as any)(
|
await (psbtThatShouldThrow.signInputHDAsync as any)(
|
||||||
f.shouldThrow.inputToCheck,
|
f.shouldThrow.inputToCheck,
|
||||||
);
|
);
|
||||||
|
@ -354,7 +409,7 @@ describe(`Psbt`, () => {
|
||||||
it(f.description, async () => {
|
it(f.description, async () => {
|
||||||
if (f.shouldSign) {
|
if (f.shouldSign) {
|
||||||
const psbtThatShouldsign = Psbt.fromBase64(f.shouldSign.psbt);
|
const psbtThatShouldsign = Psbt.fromBase64(f.shouldSign.psbt);
|
||||||
assert.doesNotReject(async () => {
|
await assert.doesNotReject(async () => {
|
||||||
await psbtThatShouldsign.signAllInputsHDAsync(
|
await psbtThatShouldsign.signAllInputsHDAsync(
|
||||||
bip32.fromBase58(f.shouldSign.xprv),
|
bip32.fromBase58(f.shouldSign.xprv),
|
||||||
(f.shouldSign as any).sighashTypes || undefined,
|
(f.shouldSign as any).sighashTypes || undefined,
|
||||||
|
@ -364,13 +419,13 @@ describe(`Psbt`, () => {
|
||||||
|
|
||||||
if (f.shouldThrow) {
|
if (f.shouldThrow) {
|
||||||
const psbtThatShouldThrow = Psbt.fromBase64(f.shouldThrow.psbt);
|
const psbtThatShouldThrow = Psbt.fromBase64(f.shouldThrow.psbt);
|
||||||
assert.rejects(async () => {
|
await assert.rejects(async () => {
|
||||||
await psbtThatShouldThrow.signAllInputsHDAsync(
|
await psbtThatShouldThrow.signAllInputsHDAsync(
|
||||||
bip32.fromBase58(f.shouldThrow.xprv),
|
bip32.fromBase58(f.shouldThrow.xprv),
|
||||||
(f.shouldThrow as any).sighashTypes || undefined,
|
(f.shouldThrow as any).sighashTypes || undefined,
|
||||||
);
|
);
|
||||||
}, new RegExp('No inputs were signed'));
|
}, new RegExp('No inputs were signed'));
|
||||||
assert.rejects(async () => {
|
await assert.rejects(async () => {
|
||||||
await (psbtThatShouldThrow.signAllInputsHDAsync as any)();
|
await (psbtThatShouldThrow.signAllInputsHDAsync as any)();
|
||||||
}, new RegExp('Need HDSigner to sign input'));
|
}, new RegExp('Need HDSigner to sign input'));
|
||||||
}
|
}
|
||||||
|
|
|
@ -580,31 +580,28 @@ export class Psbt {
|
||||||
keyPair: Signer | SignerAsync,
|
keyPair: Signer | SignerAsync,
|
||||||
sighashTypes: number[] = [Transaction.SIGHASH_ALL],
|
sighashTypes: number[] = [Transaction.SIGHASH_ALL],
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
return new Promise(
|
return Promise.resolve().then(() => {
|
||||||
(resolve, reject): void => {
|
if (!keyPair || !keyPair.publicKey)
|
||||||
if (!keyPair || !keyPair.publicKey)
|
throw new Error('Need Signer to sign input');
|
||||||
return reject(new Error('Need Signer to sign input'));
|
const { hash, sighashType } = getHashAndSighashType(
|
||||||
const { hash, sighashType } = getHashAndSighashType(
|
this.data.inputs,
|
||||||
this.data.inputs,
|
inputIndex,
|
||||||
inputIndex,
|
keyPair.publicKey,
|
||||||
keyPair.publicKey,
|
this.__CACHE,
|
||||||
this.__CACHE,
|
sighashTypes,
|
||||||
sighashTypes,
|
);
|
||||||
);
|
|
||||||
|
|
||||||
Promise.resolve(keyPair.sign(hash)).then(signature => {
|
return Promise.resolve(keyPair.sign(hash)).then(signature => {
|
||||||
const partialSig = [
|
const partialSig = [
|
||||||
{
|
{
|
||||||
pubkey: keyPair.publicKey,
|
pubkey: keyPair.publicKey,
|
||||||
signature: bscript.signature.encode(signature, sighashType),
|
signature: bscript.signature.encode(signature, sighashType),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
this.data.updateInput(inputIndex, { partialSig });
|
this.data.updateInput(inputIndex, { partialSig });
|
||||||
resolve();
|
});
|
||||||
});
|
});
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
toBuffer(): Buffer {
|
toBuffer(): Buffer {
|
||||||
|
|
Loading…
Reference in a new issue