mirror of
https://github.com/mempool/mempool.git
synced 2025-03-26 17:51:45 +01:00
Merge pull request #5237 from vostrnad/p2tr-without-witness
Fix errors caused by P2TR inputs without witness data
This commit is contained in:
commit
8fc5fdbde6
@ -460,11 +460,10 @@ export class Common {
|
||||
case 'v0_p2wpkh': flags |= TransactionFlags.p2wpkh; break;
|
||||
case 'v0_p2wsh': flags |= TransactionFlags.p2wsh; break;
|
||||
case 'v1_p2tr': {
|
||||
if (!vin.witness?.length) {
|
||||
throw new Error('Taproot input missing witness data');
|
||||
}
|
||||
flags |= TransactionFlags.p2tr;
|
||||
flags = Common.isInscription(vin, flags);
|
||||
if (vin.witness?.length) {
|
||||
flags = Common.isInscription(vin, flags);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
} else {
|
||||
|
@ -71,19 +71,24 @@ export function calcSegwitFeeGains(tx: Transaction) {
|
||||
}
|
||||
|
||||
if (isP2tr) {
|
||||
if (vin.witness.length === 1) {
|
||||
// key path spend
|
||||
// we don't know if this was a multisig or single sig (the goal of taproot :)),
|
||||
// so calculate fee savings by comparing to the cheapest single sig input type: P2WPKH and say "saved at least ...%"
|
||||
// the witness size of P2WPKH is 1 (stack size) + 1 (size) + 72 (low s signature) + 1 (size) + 33 (pubkey) = 108 WU
|
||||
// the witness size of key path P2TR is 1 (stack size) + 1 (size) + 64 (signature) = 66 WU
|
||||
realizedTaprootGains += 42;
|
||||
} else {
|
||||
// script path spend
|
||||
// complex scripts with multiple spending paths can often be made around 2x to 3x smaller with the Taproot script tree
|
||||
// because only the hash of the alternative spending path has the be in the witness data, not the entire script,
|
||||
// but only assumptions can be made because the scripts themselves are unknown (again, the goal of taproot :))
|
||||
// TODO maybe add some complex scripts that are specified somewhere, so that size is known, such as lightning scripts
|
||||
// every valid taproot input has at least one witness item, however transactions
|
||||
// created before taproot activation don't need to have any witness data
|
||||
// (see https://mempool.space/tx/b10c007c60e14f9d087e0291d4d0c7869697c6681d979c6639dbd960792b4d41)
|
||||
if (vin.witness?.length) {
|
||||
if (vin.witness.length === 1) {
|
||||
// key path spend
|
||||
// we don't know if this was a multisig or single sig (the goal of taproot :)),
|
||||
// so calculate fee savings by comparing to the cheapest single sig input type: P2WPKH and say "saved at least ...%"
|
||||
// the witness size of P2WPKH is 1 (stack size) + 1 (size) + 72 (low s signature) + 1 (size) + 33 (pubkey) = 108 WU
|
||||
// the witness size of key path P2TR is 1 (stack size) + 1 (size) + 64 (signature) = 66 WU
|
||||
realizedTaprootGains += 42;
|
||||
} else {
|
||||
// script path spend
|
||||
// complex scripts with multiple spending paths can often be made around 2x to 3x smaller with the Taproot script tree
|
||||
// because only the hash of the alternative spending path has the be in the witness data, not the entire script,
|
||||
// but only assumptions can be made because the scripts themselves are unknown (again, the goal of taproot :))
|
||||
// TODO maybe add some complex scripts that are specified somewhere, so that size is known, such as lightning scripts
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const script = isP2shP2Wsh || isP2wsh ? vin.inner_witnessscript_asm : vin.inner_redeemscript_asm;
|
||||
|
@ -335,19 +335,21 @@ export function getTransactionFlags(tx: Transaction, cpfpInfo?: CpfpInfo, replac
|
||||
case 'v0_p2wpkh': flags |= TransactionFlags.p2wpkh; break;
|
||||
case 'v0_p2wsh': flags |= TransactionFlags.p2wsh; break;
|
||||
case 'v1_p2tr': {
|
||||
if (!vin.witness?.length) {
|
||||
throw new Error('Taproot input missing witness data');
|
||||
}
|
||||
flags |= TransactionFlags.p2tr;
|
||||
// in taproot, if the last witness item begins with 0x50, it's an annex
|
||||
const hasAnnex = vin.witness?.[vin.witness.length - 1].startsWith('50');
|
||||
// script spends have more than one witness item, not counting the annex (if present)
|
||||
if (vin.witness.length > (hasAnnex ? 2 : 1)) {
|
||||
// the script itself is the second-to-last witness item, not counting the annex
|
||||
const asm = vin.inner_witnessscript_asm;
|
||||
// inscriptions smuggle data within an 'OP_0 OP_IF ... OP_ENDIF' envelope
|
||||
if (asm?.includes('OP_0 OP_IF')) {
|
||||
flags |= TransactionFlags.inscription;
|
||||
// every valid taproot input has at least one witness item, however transactions
|
||||
// created before taproot activation don't need to have any witness data
|
||||
// (see https://mempool.space/tx/b10c007c60e14f9d087e0291d4d0c7869697c6681d979c6639dbd960792b4d41)
|
||||
if (vin.witness?.length) {
|
||||
// in taproot, if the last witness item begins with 0x50, it's an annex
|
||||
const hasAnnex = vin.witness?.[vin.witness.length - 1].startsWith('50');
|
||||
// script spends have more than one witness item, not counting the annex (if present)
|
||||
if (vin.witness.length > (hasAnnex ? 2 : 1)) {
|
||||
// the script itself is the second-to-last witness item, not counting the annex
|
||||
const asm = vin.inner_witnessscript_asm;
|
||||
// inscriptions smuggle data within an 'OP_0 OP_IF ... OP_ENDIF' envelope
|
||||
if (asm?.includes('OP_0 OP_IF')) {
|
||||
flags |= TransactionFlags.inscription;
|
||||
}
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
Loading…
x
Reference in New Issue
Block a user