mirror of
https://github.com/mempool/mempool.git
synced 2025-09-25 18:11:46 +02:00
PSBT support for script and signature pre-filling in P2TR inputs
This commit is contained in:
@@ -1052,7 +1052,10 @@ function fromBuffer(buffer: Uint8Array, network: string, inputs?: { key: Uint8Ar
|
||||
finalScriptWitness: null,
|
||||
redeemScript: null,
|
||||
witnessScript: null,
|
||||
partialSigs: []
|
||||
partialSigs: [],
|
||||
tapLeafScripts: [],
|
||||
tapScriptSigs: [],
|
||||
tapInternalKey: null,
|
||||
};
|
||||
|
||||
for (const record of inputRecords) {
|
||||
@@ -1078,6 +1081,14 @@ function fromBuffer(buffer: Uint8Array, network: string, inputs?: { key: Uint8Ar
|
||||
case 0x02:
|
||||
groups.partialSigs.push(record);
|
||||
break;
|
||||
case 0x14:
|
||||
groups.tapScriptSigs.push(record);
|
||||
break;
|
||||
case 0x15:
|
||||
groups.tapLeafScripts.push(record);
|
||||
break;
|
||||
case 0x17:
|
||||
groups.tapInternalKey = record;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1175,6 +1186,61 @@ function fromBuffer(buffer: Uint8Array, network: string, inputs?: { key: Uint8Ar
|
||||
vin.witness.unshift(uint8ArrayToHexString(signature));
|
||||
}
|
||||
}
|
||||
|
||||
if (groups.tapLeafScripts.length && groups.tapInternalKey && !finalizedWitness) {
|
||||
// If no signature is present, assume key spend *except* if internal key is provably unspendable
|
||||
if (!groups.tapScriptSigs.length) {
|
||||
if (uint8ArrayToHexString(groups.tapInternalKey.value) === '50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0') {
|
||||
// unspendable internal key, use the first tap leaf script provided
|
||||
const record = groups.tapLeafScripts[0];
|
||||
const controlBlock = uint8ArrayToHexString(record.key.slice(1));
|
||||
const tapLeaf = uint8ArrayToHexString(record.value.slice(0, -1));
|
||||
vin.witness = vin.witness || [];
|
||||
vin.witness.unshift(tapLeaf, controlBlock);
|
||||
vin.inner_witnessscript_asm = convertScriptSigAsm(tapLeaf);
|
||||
}
|
||||
} else {
|
||||
// get the hash with the most signatures
|
||||
const leafScriptSignatures: { [leafHash: string]: number } = {};
|
||||
let maxSignatures = 0;
|
||||
let scriptMostSigs = '';
|
||||
|
||||
for (const record of groups.tapScriptSigs) {
|
||||
const leafHash = uint8ArrayToHexString(record.key.slice(33));
|
||||
if (!leafScriptSignatures[leafHash]) {
|
||||
leafScriptSignatures[leafHash] = 0;
|
||||
}
|
||||
leafScriptSignatures[leafHash]++;
|
||||
if (leafScriptSignatures[leafHash] > maxSignatures) {
|
||||
maxSignatures = leafScriptSignatures[leafHash];
|
||||
scriptMostSigs = leafHash;
|
||||
}
|
||||
}
|
||||
|
||||
// find the script with most signatures
|
||||
for (const record of groups.tapLeafScripts) {
|
||||
const leafVersion = uint8ArrayToHexString(record.value.slice(-1));
|
||||
const script = uint8ArrayToHexString(record.value.slice(0, -1));
|
||||
const scriptSize = uint8ArrayToHexString(compactSize(record.value.length - 1));
|
||||
if (taggedHash('TapLeaf', leafVersion + scriptSize + script) === scriptMostSigs) {
|
||||
// add the script
|
||||
const controlBlock = uint8ArrayToHexString(record.key.slice(1));
|
||||
const tapLeaf = uint8ArrayToHexString(record.value.slice(0, -1));
|
||||
vin.witness = vin.witness || [];
|
||||
vin.witness.unshift(tapLeaf, controlBlock);
|
||||
vin.inner_witnessscript_asm = convertScriptSigAsm(tapLeaf);
|
||||
// add the signatures that are part of this script
|
||||
for (const sigRecord of groups.tapScriptSigs) {
|
||||
const sigLeafHash = uint8ArrayToHexString(sigRecord.key.slice(33));
|
||||
if (sigLeafHash === scriptMostSigs) {
|
||||
vin.witness.unshift(uint8ArrayToHexString(sigRecord.value));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user