Add discouraged unsafe nonsegwit signing
This commit is contained in:
parent
7d09fe5dcb
commit
0c52803ba1
2 changed files with 68 additions and 3 deletions
35
src/psbt.js
35
src/psbt.js
|
@ -69,6 +69,14 @@ class Psbt {
|
|||
__NON_WITNESS_UTXO_BUF_CACHE: [],
|
||||
__TX_IN_CACHE: {},
|
||||
__TX: this.data.globalMap.unsignedTx.tx,
|
||||
// Old TransactionBuilder behavior was to not confirm input values
|
||||
// before signing. Even though we highly encourage people to get
|
||||
// the full parent transaction to verify values, the ability to
|
||||
// sign non-segwit inputs without the full transaction was often
|
||||
// requested. So the only way to activate is to use @ts-ignore.
|
||||
// We will disable exporting the Psbt when unsafe sign is active.
|
||||
// because it is not BIP174 compliant.
|
||||
__UNSAFE_SIGN_NONSEGWIT: false,
|
||||
};
|
||||
if (this.data.inputs.length === 0) this.setVersion(2);
|
||||
// Make data hidden when enumerating
|
||||
|
@ -313,6 +321,7 @@ class Psbt {
|
|||
inputIndex,
|
||||
Object.assign({}, input, { sighashType: sig.hashType }),
|
||||
this.__CACHE,
|
||||
true,
|
||||
)
|
||||
: { hash: hashCache, script: scriptCache };
|
||||
sighashCache = sig.hashType;
|
||||
|
@ -513,12 +522,15 @@ class Psbt {
|
|||
});
|
||||
}
|
||||
toBuffer() {
|
||||
checkCache(this.__CACHE);
|
||||
return this.data.toBuffer();
|
||||
}
|
||||
toHex() {
|
||||
checkCache(this.__CACHE);
|
||||
return this.data.toHex();
|
||||
}
|
||||
toBase64() {
|
||||
checkCache(this.__CACHE);
|
||||
return this.data.toBase64();
|
||||
}
|
||||
updateGlobal(updateData) {
|
||||
|
@ -626,6 +638,11 @@ function canFinalize(input, script, scriptType) {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
function checkCache(cache) {
|
||||
if (cache.__UNSAFE_SIGN_NONSEGWIT !== false) {
|
||||
throw new Error('Not BIP174 compliant, can not export');
|
||||
}
|
||||
}
|
||||
function hasSigs(neededSigs, partialSig, pubkeys) {
|
||||
if (!partialSig) return false;
|
||||
let sigs;
|
||||
|
@ -857,6 +874,7 @@ function getHashAndSighashType(
|
|||
inputIndex,
|
||||
input,
|
||||
cache,
|
||||
false,
|
||||
sighashTypes,
|
||||
);
|
||||
checkScriptForPubkey(pubkey, script, 'sign');
|
||||
|
@ -865,7 +883,7 @@ function getHashAndSighashType(
|
|||
sighashType,
|
||||
};
|
||||
}
|
||||
function getHashForSig(inputIndex, input, cache, sighashTypes) {
|
||||
function getHashForSig(inputIndex, input, cache, forValidate, sighashTypes) {
|
||||
const unsignedTx = cache.__TX;
|
||||
const sighashType =
|
||||
input.sighashType || transaction_1.Transaction.SIGHASH_ALL;
|
||||
|
@ -925,11 +943,24 @@ function getHashForSig(inputIndex, input, cache, sighashTypes) {
|
|||
);
|
||||
} else {
|
||||
// non-segwit
|
||||
if (input.nonWitnessUtxo === undefined)
|
||||
if (
|
||||
input.nonWitnessUtxo === undefined &&
|
||||
cache.__UNSAFE_SIGN_NONSEGWIT === false
|
||||
)
|
||||
throw new Error(
|
||||
`Input #${inputIndex} has witnessUtxo but non-segwit script: ` +
|
||||
`${meaningfulScript.toString('hex')}`,
|
||||
);
|
||||
if (!forValidate && cache.__UNSAFE_SIGN_NONSEGWIT !== false)
|
||||
console.warn(
|
||||
'Warning: Signing non-segwit inputs without the full parent transaction ' +
|
||||
'means there is a chance that a miner could feed you incorrect information ' +
|
||||
'to trick you into paying large fees. This behavior is the same as the old ' +
|
||||
'TransactionBuilder class when signing non-segwit scripts. You are not ' +
|
||||
'able to export this Psbt with toBuffer|toBase64|toHex since it is not ' +
|
||||
'BIP174 compliant.\n*********************\nPROCEED WITH CAUTION!\n' +
|
||||
'*********************',
|
||||
);
|
||||
hash = unsignedTx.hashForSignature(
|
||||
inputIndex,
|
||||
meaningfulScript,
|
||||
|
|
|
@ -115,6 +115,14 @@ export class Psbt {
|
|||
__NON_WITNESS_UTXO_BUF_CACHE: [],
|
||||
__TX_IN_CACHE: {},
|
||||
__TX: (this.data.globalMap.unsignedTx as PsbtTransaction).tx,
|
||||
// Old TransactionBuilder behavior was to not confirm input values
|
||||
// before signing. Even though we highly encourage people to get
|
||||
// the full parent transaction to verify values, the ability to
|
||||
// sign non-segwit inputs without the full transaction was often
|
||||
// requested. So the only way to activate is to use @ts-ignore.
|
||||
// We will disable exporting the Psbt when unsafe sign is active.
|
||||
// because it is not BIP174 compliant.
|
||||
__UNSAFE_SIGN_NONSEGWIT: false,
|
||||
};
|
||||
if (this.data.inputs.length === 0) this.setVersion(2);
|
||||
|
||||
|
@ -386,6 +394,7 @@ export class Psbt {
|
|||
inputIndex,
|
||||
Object.assign({}, input, { sighashType: sig.hashType }),
|
||||
this.__CACHE,
|
||||
true,
|
||||
)
|
||||
: { hash: hashCache!, script: scriptCache! };
|
||||
sighashCache = sig.hashType;
|
||||
|
@ -619,14 +628,17 @@ export class Psbt {
|
|||
}
|
||||
|
||||
toBuffer(): Buffer {
|
||||
checkCache(this.__CACHE);
|
||||
return this.data.toBuffer();
|
||||
}
|
||||
|
||||
toHex(): string {
|
||||
checkCache(this.__CACHE);
|
||||
return this.data.toHex();
|
||||
}
|
||||
|
||||
toBase64(): string {
|
||||
checkCache(this.__CACHE);
|
||||
return this.data.toBase64();
|
||||
}
|
||||
|
||||
|
@ -681,6 +693,7 @@ interface PsbtCache {
|
|||
__FEE_RATE?: number;
|
||||
__FEE?: number;
|
||||
__EXTRACTED_TX?: Transaction;
|
||||
__UNSAFE_SIGN_NONSEGWIT: boolean;
|
||||
}
|
||||
|
||||
interface PsbtOptsOptional {
|
||||
|
@ -825,6 +838,12 @@ function canFinalize(
|
|||
}
|
||||
}
|
||||
|
||||
function checkCache(cache: PsbtCache): void {
|
||||
if (cache.__UNSAFE_SIGN_NONSEGWIT !== false) {
|
||||
throw new Error('Not BIP174 compliant, can not export');
|
||||
}
|
||||
}
|
||||
|
||||
function hasSigs(
|
||||
neededSigs: number,
|
||||
partialSig?: any[],
|
||||
|
@ -1130,6 +1149,7 @@ function getHashAndSighashType(
|
|||
inputIndex,
|
||||
input,
|
||||
cache,
|
||||
false,
|
||||
sighashTypes,
|
||||
);
|
||||
checkScriptForPubkey(pubkey, script, 'sign');
|
||||
|
@ -1143,6 +1163,7 @@ function getHashForSig(
|
|||
inputIndex: number,
|
||||
input: PsbtInput,
|
||||
cache: PsbtCache,
|
||||
forValidate: boolean,
|
||||
sighashTypes?: number[],
|
||||
): {
|
||||
script: Buffer;
|
||||
|
@ -1213,11 +1234,24 @@ function getHashForSig(
|
|||
);
|
||||
} else {
|
||||
// non-segwit
|
||||
if (input.nonWitnessUtxo === undefined)
|
||||
if (
|
||||
input.nonWitnessUtxo === undefined &&
|
||||
cache.__UNSAFE_SIGN_NONSEGWIT === false
|
||||
)
|
||||
throw new Error(
|
||||
`Input #${inputIndex} has witnessUtxo but non-segwit script: ` +
|
||||
`${meaningfulScript.toString('hex')}`,
|
||||
);
|
||||
if (!forValidate && cache.__UNSAFE_SIGN_NONSEGWIT !== false)
|
||||
console.warn(
|
||||
'Warning: Signing non-segwit inputs without the full parent transaction ' +
|
||||
'means there is a chance that a miner could feed you incorrect information ' +
|
||||
'to trick you into paying large fees. This behavior is the same as the old ' +
|
||||
'TransactionBuilder class when signing non-segwit scripts. You are not ' +
|
||||
'able to export this Psbt with toBuffer|toBase64|toHex since it is not ' +
|
||||
'BIP174 compliant.\n*********************\nPROCEED WITH CAUTION!\n' +
|
||||
'*********************',
|
||||
);
|
||||
hash = unsignedTx.hashForSignature(
|
||||
inputIndex,
|
||||
meaningfulScript,
|
||||
|
|
Loading…
Reference in a new issue