From 81981cac317755cf78980eb082e527248041c954 Mon Sep 17 00:00:00 2001 From: Jasper van Gelder Date: Tue, 24 Mar 2026 14:12:36 +0100 Subject: [PATCH 01/26] chore(psbt): Add silent payment fields --- packages/caravan-psbt/src/psbtv2/types.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/caravan-psbt/src/psbtv2/types.ts b/packages/caravan-psbt/src/psbtv2/types.ts index da33e250e0..9c3f21c5d8 100644 --- a/packages/caravan-psbt/src/psbtv2/types.ts +++ b/packages/caravan-psbt/src/psbtv2/types.ts @@ -25,6 +25,8 @@ export enum KeyType { PSBT_GLOBAL_INPUT_COUNT = "04", PSBT_GLOBAL_OUTPUT_COUNT = "05", PSBT_GLOBAL_TX_MODIFIABLE = "06", + PSBT_GLOBAL_SP_ECDH_SHARE = "07", + PSBT_GLOBAL_SP_DLEQ = "08", PSBT_GLOBAL_VERSION = "fb", PSBT_GLOBAL_PROPRIETARY = "fc", @@ -53,6 +55,8 @@ export enum KeyType { PSBT_IN_TAP_BIP32_DERIVATION = "16", PSBT_IN_TAP_INTERNAL_KEY = "17", PSBT_IN_TAP_MERKLE_ROOT = "18", + PSBT_IN_SP_ECDH_SHARE = "1d", + PSBT_IN_SP_DLEQ = "1e", PSBT_IN_PROPRIETARY = "fc", PSBT_OUT_REDEEM_SCRIPT = "00", @@ -63,6 +67,8 @@ export enum KeyType { PSBT_OUT_TAP_INTERNAL_KEY = "05", PSBT_OUT_TAP_TREE = "06", PSBT_OUT_TAP_BIP32_DERIVATION = "07", + PSBT_OUT_SP_V0_INFO = "09", + PSBT_OUT_SP_V0_LABEL = "0a", PSBT_OUT_PROPRIETARY = "fc", } From dcfc2a97ccc22e5bff99a86f11362ded3886f074 Mon Sep 17 00:00:00 2001 From: Jasper van Gelder Date: Tue, 24 Mar 2026 19:29:06 +0100 Subject: [PATCH 02/26] chore(psbt): Add silent payment fields Added encoders and decoders for the given silent payment fields. Since we add new fields that are not allowed by v0 we also need to delete them when converting to v0. --- packages/caravan-psbt/src/psbtv2/psbtv2.ts | 181 ++++++++++++++++++ .../caravan-psbt/src/psbtv2/psbtv2maps.ts | 6 + 2 files changed, 187 insertions(+) diff --git a/packages/caravan-psbt/src/psbtv2/psbtv2.ts b/packages/caravan-psbt/src/psbtv2/psbtv2.ts index 5ddb8470dc..ea8a217d91 100644 --- a/packages/caravan-psbt/src/psbtv2/psbtv2.ts +++ b/packages/caravan-psbt/src/psbtv2/psbtv2.ts @@ -157,6 +157,20 @@ export class PsbtV2 extends PsbtV2Maps { this.globalMap.set(KeyType.PSBT_GLOBAL_TX_MODIFIABLE, br.render()); } + get PSBT_GLOBAL_SP_ECDH_SHARE(): NonUniqueKeyTypeValue[] { + return getNonUniqueKeyTypeValues( + this.globalMap, + KeyType.PSBT_GLOBAL_SP_ECDH_SHARE, + ) as NonUniqueKeyTypeValue[]; + } + + get PSBT_GLOBAL_SP_DLEQ(): NonUniqueKeyTypeValue[] { + return getNonUniqueKeyTypeValues( + this.globalMap, + KeyType.PSBT_GLOBAL_SP_DLEQ, + ) as NonUniqueKeyTypeValue[]; + } + get PSBT_GLOBAL_VERSION() { const version = this.globalMap .get(KeyType.PSBT_GLOBAL_VERSION) @@ -379,6 +393,20 @@ export class PsbtV2 extends PsbtV2Maps { ); } + get PSBT_IN_SP_ECDH_SHARE(): NonUniqueKeyTypeValue[][] { + return getNonUniqueKeyTypeValues( + this.inputMaps, + KeyType.PSBT_IN_SP_ECDH_SHARE, + ) as NonUniqueKeyTypeValue[][]; + } + + get PSBT_IN_SP_DLEQ(): NonUniqueKeyTypeValue[][] { + return getNonUniqueKeyTypeValues( + this.inputMaps, + KeyType.PSBT_IN_SP_DLEQ, + ) as NonUniqueKeyTypeValue[][]; + } + get PSBT_IN_PROPRIETARY() { return getNonUniqueKeyTypeValues( this.inputMaps, @@ -458,6 +486,20 @@ export class PsbtV2 extends PsbtV2Maps { ); } + get PSBT_OUT_SP_V0_INFO(): (string | null)[] { + return getOptionalMappedBytesAsHex( + this.outputMaps, + KeyType.PSBT_OUT_SP_V0_INFO, + ); + } + + get PSBT_OUT_SP_V0_LABEL(): (number | null)[] { + return getOptionalMappedBytesAsUInt( + this.outputMaps, + KeyType.PSBT_OUT_SP_V0_LABEL, + ); + } + get PSBT_OUT_PROPRIETARY() { return getNonUniqueKeyTypeValues( this.outputMaps, @@ -1198,6 +1240,145 @@ export class PsbtV2 extends PsbtV2Maps { } } + // ── Global SP methods ───────────────────────────────────────────────────── + + public addGlobalSPECDHShare(bscan: Buffer, share: Buffer): void { + if (bscan.length !== 33) { + throw new Error( + `bscan must be a 33-byte compressed pubkey, got ${bscan.length}`, + ); + } + if (share.length !== 33) { + throw new Error( + `ECDH share must be a 33-byte compressed EC point, got ${share.length}`, + ); + } + const key = KeyType.PSBT_GLOBAL_SP_ECDH_SHARE + bscan.toString("hex"); + this.globalMap.set(key, share); + } + + public addGlobalSPDLEQProof(bscan: Buffer, proof: Buffer): void { + if (bscan.length !== 33) { + throw new Error( + `bscan must be a 33-byte compressed pubkey, got ${bscan.length}`, + ); + } + if (proof.length !== 64) { + throw new Error(`DLEQ proof must be 64 bytes, got ${proof.length}`); + } + const shareKey = KeyType.PSBT_GLOBAL_SP_ECDH_SHARE + bscan.toString("hex"); + if (!this.globalMap.has(shareKey)) { + throw new Error( + "Cannot add global SP DLEQ proof: no matching ECDH share for this " + + "bscan. Call addGlobalSPECDHShare first.", + ); + } + const key = KeyType.PSBT_GLOBAL_SP_DLEQ + bscan.toString("hex"); + this.globalMap.set(key, proof); + } + + // ── Per-input SP methods ────────────────────────────────────────────────── + + public addInputSPECDHShare( + inputIndex: number, + bscan: Buffer, + share: Buffer, + ): void { + if (inputIndex < 0 || inputIndex >= this.inputMaps.length) { + throw new Error( + `inputIndex ${inputIndex} out of range (${this.inputMaps.length} inputs)`, + ); + } + if (bscan.length !== 33) { + throw new Error( + `bscan must be a 33-byte compressed pubkey, got ${bscan.length}`, + ); + } + if (share.length !== 33) { + throw new Error( + `ECDH share must be a 33-byte compressed EC point, got ${share.length}`, + ); + } + const key = KeyType.PSBT_IN_SP_ECDH_SHARE + bscan.toString("hex"); + this.inputMaps[inputIndex].set(key, share); + } + + public addInputSPDLEQProof( + inputIndex: number, + bscan: Buffer, + proof: Buffer, + ): void { + if (inputIndex < 0 || inputIndex >= this.inputMaps.length) { + throw new Error( + `inputIndex ${inputIndex} out of range (${this.inputMaps.length} inputs)`, + ); + } + if (bscan.length !== 33) { + throw new Error( + `bscan must be a 33-byte compressed pubkey, got ${bscan.length}`, + ); + } + if (proof.length !== 64) { + throw new Error(`DLEQ proof must be 64 bytes, got ${proof.length}`); + } + const shareKey = KeyType.PSBT_IN_SP_ECDH_SHARE + bscan.toString("hex"); + if (!this.inputMaps[inputIndex].has(shareKey)) { + throw new Error( + `Cannot add SP DLEQ proof on input ${inputIndex}: no matching ECDH ` + + "share for this bscan. Call addInputSPECDHShare first.", + ); + } + const key = KeyType.PSBT_IN_SP_DLEQ + bscan.toString("hex"); + this.inputMaps[inputIndex].set(key, proof); + } + + // ── Per-output SP methods ───────────────────────────────────────────────── + + public addOutputSPInfo( + outputIndex: number, + bscan: Buffer, + bspend: Buffer, + ): void { + if (outputIndex < 0 || outputIndex >= this.outputMaps.length) { + throw new Error( + `outputIndex ${outputIndex} out of range (${this.outputMaps.length} outputs)`, + ); + } + if (bscan.length !== 33) { + throw new Error( + `bscan must be a 33-byte compressed pubkey, got ${bscan.length}`, + ); + } + if (bspend.length !== 33) { + throw new Error( + `bspend must be a 33-byte compressed pubkey, got ${bspend.length}`, + ); + } + const bw = new BufferWriter(); + bw.writeBytes(bscan); + bw.writeBytes(bspend); + this.outputMaps[outputIndex].set(KeyType.PSBT_OUT_SP_V0_INFO, bw.render()); + } + + public addOutputSPLabel(outputIndex: number, label: number): void { + if (outputIndex < 0 || outputIndex >= this.outputMaps.length) { + throw new Error( + `outputIndex ${outputIndex} out of range (${this.outputMaps.length} outputs)`, + ); + } + if (!this.outputMaps[outputIndex].has(KeyType.PSBT_OUT_SP_V0_INFO)) { + throw new Error( + `Output ${outputIndex} has no SP info. Call addOutputSPInfo first.`, + ); + } + if (!Number.isInteger(label) || label < 0 || label > 0xffffffff) { + throw new Error(`label must be a uint32 (0–${0xffffffff}), got ${label}`); + } + const bw = new BufferWriter(); + bw.writeU32(label); + this.outputMaps[outputIndex].set(KeyType.PSBT_OUT_SP_V0_LABEL, bw.render()); + } + /** * Sets values on the proprietary keytype for a global, input, or output map. * BIP 174 allows for proprietary values to be set on all maps with the diff --git a/packages/caravan-psbt/src/psbtv2/psbtv2maps.ts b/packages/caravan-psbt/src/psbtv2/psbtv2maps.ts index 0d5b5ec9a1..19d25bc9b2 100644 --- a/packages/caravan-psbt/src/psbtv2/psbtv2maps.ts +++ b/packages/caravan-psbt/src/psbtv2/psbtv2maps.ts @@ -277,6 +277,8 @@ export class PsbtConversionMaps extends PsbtV2Maps { this.v0delete(this.globalMap, KeyType.PSBT_GLOBAL_INPUT_COUNT); this.v0delete(this.globalMap, KeyType.PSBT_GLOBAL_OUTPUT_COUNT); this.v0delete(this.globalMap, KeyType.PSBT_GLOBAL_TX_MODIFIABLE); + this.v0delete(this.globalMap, KeyType.PSBT_GLOBAL_SP_ECDH_SHARE); + this.v0delete(this.globalMap, KeyType.PSBT_GLOBAL_SP_DLEQ); this.v0delete(this.globalMap, KeyType.PSBT_GLOBAL_VERSION); for (const inputMap of this.inputMaps) { @@ -285,11 +287,15 @@ export class PsbtConversionMaps extends PsbtV2Maps { this.v0delete(inputMap, KeyType.PSBT_IN_SEQUENCE); this.v0delete(inputMap, KeyType.PSBT_IN_REQUIRED_TIME_LOCKTIME); this.v0delete(inputMap, KeyType.PSBT_IN_REQUIRED_HEIGHT_LOCKTIME); + this.v0delete(inputMap, KeyType.PSBT_IN_SP_ECDH_SHARE); + this.v0delete(inputMap, KeyType.PSBT_IN_SP_DLEQ); } for (const outputMap of this.outputMaps) { this.v0delete(outputMap, KeyType.PSBT_OUT_AMOUNT); this.v0delete(outputMap, KeyType.PSBT_OUT_SCRIPT); + this.v0delete(outputMap, KeyType.PSBT_OUT_SP_V0_INFO); + this.v0delete(outputMap, KeyType.PSBT_OUT_SP_V0_LABEL); } }; From 8b2a8abe0569a2c87a4fcf8f9e58ad61cc0b92cf Mon Sep 17 00:00:00 2001 From: Jasper van Gelder Date: Tue, 24 Mar 2026 17:16:05 +0100 Subject: [PATCH 03/26] chore(psbt): Add output functionality Allow the user to set and get a silentpayment object instead of a script. As per BIP375 we need to make sure there is either an OUPUT_SCRIPT or PSBT_OUT_SP_V0_INFO updated getter, validation and unsignedtx accordingly. --- packages/caravan-psbt/src/psbtv2/psbtv2.ts | 128 +++++++++++++++--- .../caravan-psbt/src/psbtv2/psbtv2maps.ts | 15 +- 2 files changed, 120 insertions(+), 23 deletions(-) diff --git a/packages/caravan-psbt/src/psbtv2/psbtv2.ts b/packages/caravan-psbt/src/psbtv2/psbtv2.ts index ea8a217d91..dba80b12cb 100644 --- a/packages/caravan-psbt/src/psbtv2/psbtv2.ts +++ b/packages/caravan-psbt/src/psbtv2/psbtv2.ts @@ -452,17 +452,12 @@ export class PsbtV2 extends PsbtV2Maps { return indices; } - get PSBT_OUT_SCRIPT() { - const indices: string[] = []; - for (const map of this.outputMaps) { + get PSBT_OUT_SCRIPT(): (string | null)[] { + return this.outputMaps.map((map) => { const value = map.get(KeyType.PSBT_OUT_SCRIPT); - if (!value) { - // This should never happen, but it can't be gracefully handled. - throw Error("PSBT_OUT_SCRIPT not set for an output"); - } - indices.push(value.toString("hex")); - } - return indices; + if (!value) return null; + return value.toString("hex"); + }); } get PSBT_OUT_TAP_INTERNAL_KEY() { @@ -575,7 +570,11 @@ export class PsbtV2 extends PsbtV2Maps { if (this.isReadyForTransactionExtractor) { return false; } - + // Per BIP375: if SP outputs are present, all must have a computed + // PSBT_OUT_SCRIPT before signing is permitted. + if (this.hasSilentPaymentOutputs && !this.hasAllSPOutputScripts) { + return false; + } return true; } @@ -800,9 +799,12 @@ export class PsbtV2 extends PsbtV2Maps { throw Error("PsbtV2 input is missing PSBT_OUT_AMOUNT"); } } - for (const script of this.PSBT_OUT_SCRIPT) { - if (!script) { - throw Error("PsbtV2 input is missing PSBT_OUT_SCRIPT"); + for (const [i, script] of this.PSBT_OUT_SCRIPT.entries()) { + if (!script && !this.outputMaps[i].has(KeyType.PSBT_OUT_SP_V0_INFO)) { + throw Error( + `PsbtV2 output ${i} is missing PSBT_OUT_SCRIPT and has no ` + + "PSBT_OUT_SP_V0_INFO. An output must have one or both per BIP375.", + ); } } for (const locktime of this.PSBT_IN_REQUIRED_TIME_LOCKTIME) { @@ -1034,12 +1036,18 @@ export class PsbtV2 extends PsbtV2Maps { public addOutput({ amount, script, + silentPayment, redeemScript, witnessScript, bip32Derivation, }: { amount: number; - script: Buffer; + script?: Buffer; + silentPayment?: { + bscan: Buffer; + bspend: Buffer; + label?: number; + }; redeemScript?: Buffer; witnessScript?: Buffer; bip32Derivation?: { @@ -1058,12 +1066,49 @@ export class PsbtV2 extends PsbtV2Maps { "PsbtV2.PSBT_GLOBAL_TX_MODIFIABLE outputs cannot be modified.", ); } + // Per BIP375: every output must have PSBT_OUT_SCRIPT, PSBT_OUT_SP_V0_INFO, + // or both. A regular output with no script and no SP info is invalid. + if (!script && !silentPayment) { + throw Error( + "addOutput requires either a script (regular output) or " + + "silentPayment { bscan, bspend } (SP output).", + ); + } + const map = new Map(); const bw = new BufferWriter(); + bw.writeI64(amount); map.set(KeyType.PSBT_OUT_AMOUNT, bw.render()); - bw.writeBytes(script); - map.set(KeyType.PSBT_OUT_SCRIPT, bw.render()); + + if (script) { + bw.writeBytes(script); + map.set(KeyType.PSBT_OUT_SCRIPT, bw.render()); + } + + if (silentPayment) { + const { bscan, bspend, label } = silentPayment; + if (bscan.length !== 33) { + throw Error(`bscan must be 33 bytes, got ${bscan.length}`); + } + if (bspend.length !== 33) { + throw Error(`bspend must be 33 bytes, got ${bspend.length}`); + } + // Value: bscan || bspend, 66 bytes — no version prefix in field value. + const spBw = new BufferWriter(); + spBw.writeBytes(bscan); + spBw.writeBytes(bspend); + map.set(KeyType.PSBT_OUT_SP_V0_INFO, spBw.render()); + + if (label !== undefined) { + if (!Number.isInteger(label) || label < 0 || label > 0xffffffff) { + throw Error(`label must be a uint32 (0–${0xffffffff}), got ${label}`); + } + const labelBw = new BufferWriter(); + labelBw.writeU32(label); + map.set(KeyType.PSBT_OUT_SP_V0_LABEL, labelBw.render()); + } + } if (redeemScript) { bw.writeBytes(redeemScript); @@ -1694,4 +1739,53 @@ export class PsbtV2 extends PsbtV2Maps { throw Error("Failed to combine PSBTs."); } } + + /** + * Returns `true` if any output has `PSBT_OUT_SP_V0_INFO` set. + * Used by the Signer to determine whether SP rules apply. + */ + get hasSilentPaymentOutputs(): boolean { + return this.outputMaps.some((map) => map.has(KeyType.PSBT_OUT_SP_V0_INFO)); + } + + /** + * Returns `true` if every output that has `PSBT_OUT_SP_V0_INFO` also has + * `PSBT_OUT_SCRIPT` set. Non-SP outputs are excluded from this check since + * `validate()` already guarantees they have a script. + * + * Per BIP375: the Signer must not add a signature until this is true. + */ + get hasAllSPOutputScripts(): boolean { + return this.outputMaps.every( + (map) => + !map.has(KeyType.PSBT_OUT_SP_V0_INFO) || + map.has(KeyType.PSBT_OUT_SCRIPT), + ); + } + + /** + * Splits the raw 66-byte `PSBT_OUT_SP_V0_INFO` value for a given output + * into its typed `bscan` and `bspend` components. + * + * @param outputIndex - Zero-based index of the output. + * @returns `{ bscan, bspend }` or `null` if the output is not an SP output. + * @throws {Error} If the stored value is not exactly 66 bytes. + */ + getSilentPaymentOutputInfo(outputIndex: number): { + bscan: Buffer; + bspend: Buffer; + } | null { + const raw = this.outputMaps[outputIndex]?.get(KeyType.PSBT_OUT_SP_V0_INFO); + if (!raw) return null; + if (raw.length !== 66) { + throw new Error( + `PSBT_OUT_SP_V0_INFO at output ${outputIndex}: ` + + `expected 66 bytes, got ${raw.length}`, + ); + } + return { + bscan: raw.slice(0, 33), + bspend: raw.slice(33, 66), + }; + } } diff --git a/packages/caravan-psbt/src/psbtv2/psbtv2maps.ts b/packages/caravan-psbt/src/psbtv2/psbtv2maps.ts index 19d25bc9b2..8dbf91f46e 100644 --- a/packages/caravan-psbt/src/psbtv2/psbtv2maps.ts +++ b/packages/caravan-psbt/src/psbtv2/psbtv2maps.ts @@ -224,12 +224,15 @@ export class PsbtConversionMaps extends PsbtV2Maps { } for (let i = 0; i < numOutputs; i++) { + const spInfo = this.outputMaps[i].get(KeyType.PSBT_OUT_SP_V0_INFO); + const script = this.outputMaps[i].get(KeyType.PSBT_OUT_SCRIPT); + if ( - !this.outputMaps[i].has(KeyType.PSBT_OUT_SCRIPT) || + (!spInfo && !script) || !this.outputMaps[i].has(KeyType.PSBT_OUT_AMOUNT) ) { console.warn( - `Output ${i} is missing previous out script or amount. Skipping.`, + `Output ${i} is missing SP_INFO, script or amount. Skipping.`, ); continue; } @@ -237,10 +240,10 @@ export class PsbtConversionMaps extends PsbtV2Maps { this.outputMaps[i].get(KeyType.PSBT_OUT_AMOUNT) as Buffer ).readBigInt64LE(); const numberAmount = parseInt(bigintAmount.toString()); - tx.addOutput( - this.outputMaps[i].get(KeyType.PSBT_OUT_SCRIPT) as Buffer, - numberAmount, - ); + + // BIP375: prefer PSBT_OUT_SP_V0_INFO for unique identification so the + // ID is stable whether or not the output script has been computed yet. + tx.addOutput((spInfo ?? script) as Buffer, numberAmount); } return tx.toBuffer(); From ed8b289e0046e08cb2ae72faf889b71be63d033d Mon Sep 17 00:00:00 2001 From: Jasper van Gelder Date: Tue, 24 Mar 2026 21:46:50 +0100 Subject: [PATCH 04/26] feat(psbt): Add BIP352 silent payment output script computation - Add silentpayment.ts with pure BIP352 crypto primitives: eligibleIndices, sumECDHShares, computeInputHash, deriveSilentPaymentOutput, bip352TaggedHash - Add computeSilentPaymentOutputScripts() to PsbtV2 (Signer role) implementing BIP375 output script derivation from ECDH shares --- .changeset/ripe-turkeys-dance.md | 15 ++ packages/caravan-psbt/src/psbtv2/psbtv2.ts | 197 ++++++++++++++ .../caravan-psbt/src/psbtv2/silentpayment.ts | 246 ++++++++++++++++++ 3 files changed, 458 insertions(+) create mode 100644 .changeset/ripe-turkeys-dance.md create mode 100644 packages/caravan-psbt/src/psbtv2/silentpayment.ts diff --git a/.changeset/ripe-turkeys-dance.md b/.changeset/ripe-turkeys-dance.md new file mode 100644 index 0000000000..b76568c0f7 --- /dev/null +++ b/.changeset/ripe-turkeys-dance.md @@ -0,0 +1,15 @@ +--- +"@caravan/psbt": minor +--- + +Add BIP375 silent payment sending support to PsbtV2 + +- Add PSBT_OUT_SP_V0_INFO and PSBT_OUT_SP_V0_LABEL getters and methods +- Add PSBT_GLOBAL_SP_ECDH_SHARE, PSBT_GLOBAL_SP_DLEQ getters and methods +- Add PSBT_IN_SP_ECDH_SHARE, PSBT_IN_SP_DLEQ getters and methods +- Add silentPayment option to addOutput() for SP output construction +- Add computeSilentPaymentOutputScripts() implementing BIP352 derivation +- Add hasSilentPaymentOutputs, hasAllSPOutputScripts, hasCompleteECDHCoverage predicates +- Add eligibleIndices, sumECDHShares, computeInputHash, deriveSilentPaymentOutput to silentpayment.ts +- Update isReadyForSigner to enforce BIP375 signing rules +- Update getTransactionId() for BIP375 unique identification diff --git a/packages/caravan-psbt/src/psbtv2/psbtv2.ts b/packages/caravan-psbt/src/psbtv2/psbtv2.ts index dba80b12cb..49d1764b96 100644 --- a/packages/caravan-psbt/src/psbtv2/psbtv2.ts +++ b/packages/caravan-psbt/src/psbtv2/psbtv2.ts @@ -1,3 +1,4 @@ +import { secp256k1 } from "@noble/curves/secp256k1"; import { BufferReader, BufferWriter } from "bufio"; import { Psbt } from "bitcoinjs-lib-v6"; @@ -18,6 +19,14 @@ import { } from "./functions"; import { PsbtConversionMaps, PsbtV2Maps } from "./psbtv2maps"; import { bufferize } from "../functions"; +import { + computeInputHash, + deriveSilentPaymentOutput, + eligibleIndices, + ProjectivePoint, + SPOutputEntry, + sumECDHShares, +} from "src/psbtv2/silentpayment"; /** * The PsbtV2 class is intended to represent an easily modifiable and * serializable psbt of version 2 conforming to BIP0174. Getters exist for all @@ -1788,4 +1797,192 @@ export class PsbtV2 extends PsbtV2Maps { bspend: raw.slice(33, 66), }; } + + /** + * Returns the indices of inputs eligible for SP ECDH derivation per BIP352. + * + * Delegates to {@link eligibleIndices} in `silentpayment.ts`, passing the + * raw `PSBT_IN_WITNESS_UTXO` buffer for each input (or `null` if absent). + * + * @returns Array of eligible input indices. + */ + getEligibleInputsForSilentPayments(): number[] { + return eligibleIndices( + this.inputMaps.map((map) => ({ + witnessUtxo: map.get(KeyType.PSBT_IN_WITNESS_UTXO) ?? null, + })), + ); + } + + /** + * Returns `true` when all eligible inputs have an ECDH share, or when a + * global ECDH share exists for every unique scan key in the SP outputs. + * + * Must return `true` before {@link computeSilentPaymentOutputScripts} can run. + */ + hasCompleteECDHCoverage(): boolean { + if (!this.hasSilentPaymentOutputs) return false; + + // Collect unique scan keys from SP outputs + const scanKeys = new Set(); + for (const map of this.outputMaps) { + const raw = map.get(KeyType.PSBT_OUT_SP_V0_INFO); + if (raw) scanKeys.add(raw.slice(0, 33).toString("hex")); + } + + // Check if global shares cover all scan keys + const globalShareKeys = new Set( + this.PSBT_GLOBAL_SP_ECDH_SHARE.map((entry) => entry.key.slice(2)), + ); + if ([...scanKeys].every((k) => globalShareKeys.has(k))) { + return true; + } + + // Fall back: all eligible inputs must have per-input shares + const eligible = this.getEligibleInputsForSilentPayments(); + return eligible.every((i) => this.PSBT_IN_SP_ECDH_SHARE[i].length > 0); + } + + /** + * Signer role: derives taproot output scripts for all silent payment outputs + * and writes them to `PSBT_OUT_SCRIPT` on each SP output map. + * + * Implements the BIP352 output derivation algorithm: + * ``` + * ecdhSecret = inputHash · ecdhShare + * Pk = Bspend + taggedHash("BIP0352/SharedSecret", ecdhSecret || k) · G + * script = OP_1 <0x20> + * ``` + * + * After setting all output scripts, locks `PSBT_GLOBAL_TX_MODIFIABLE` by + * clearing the Inputs and Outputs Modifiable flags per BIP375. + * + * @throws {Error} If there are no SP outputs. + * @throws {Error} If {@link hasCompleteECDHCoverage} returns `false`. + * @throws {Error} If eligible input public keys cannot be extracted. + * @throws {Error} If no ECDH share is found for a scan key group. + */ + public computeSilentPaymentOutputScripts(): void { + if (!this.hasSilentPaymentOutputs) { + throw new Error("No silent payment outputs found."); + } + if (!this.hasCompleteECDHCoverage()) { + throw new Error( + "Incomplete ECDH coverage — call addGlobalSPECDHShare or " + + "addInputSPECDHShare for all eligible inputs first.", + ); + } + + // ── Step 1: Build outpoints + combined pubkey for inputHash ───────────── + const eligible = this.getEligibleInputsForSilentPayments(); + + const outpoints: Buffer[] = eligible.map((i) => { + const txid = this.inputMaps[i].get(KeyType.PSBT_IN_PREVIOUS_TXID)!; + const vout = this.inputMaps[i].get(KeyType.PSBT_IN_OUTPUT_INDEX)!; + return Buffer.concat([txid, vout]); // txid(32 LE) || vout(4 LE) + }); + + let combinedPubkey: ProjectivePoint | null = null; + + for (const i of eligible) { + const witnessUtxo = this.inputMaps[i].get(KeyType.PSBT_IN_WITNESS_UTXO); + if (!witnessUtxo) continue; + + const scriptLen = witnessUtxo[8]; + const inputScript = witnessUtxo.slice(9, 9 + scriptLen); + let pubkeyBytes: Buffer | null = null; + + if (inputScript[0] === 0x51 && inputScript.length === 34) { + // P2TR — use tap internal key, prefixed with 0x02 (even y per BIP352) + const tapKey = this.inputMaps[i].get(KeyType.PSBT_IN_TAP_INTERNAL_KEY); + if (tapKey) { + pubkeyBytes = Buffer.concat([Buffer.from([0x02]), tapKey]); + } + } else if (inputScript[0] === 0x00 && inputScript.length === 22) { + // P2WPKH — pubkey from BIP32 derivation field + // key format: keytype(1) || pubkey(33) — strip keytype byte + const entries = this.PSBT_IN_BIP32_DERIVATION[i]; + if (entries.length > 0) { + pubkeyBytes = Buffer.from(entries[0].key.slice(2), "hex"); + } + } + + if (!pubkeyBytes) continue; + const point = secp256k1.ProjectivePoint.fromHex(pubkeyBytes); + combinedPubkey = combinedPubkey ? combinedPubkey.add(point) : point; + } + + if (!combinedPubkey) { + throw new Error("Could not extract public keys from eligible inputs."); + } + + const inputHash = computeInputHash( + outpoints, + Buffer.from(combinedPubkey.toRawBytes(true)), + ); + + // ── Step 2: Group SP outputs by Bscan, sort within groups ─────────────── + // BIP375: recipients with the same Bscan sorted lexicographically ascending + // by Bspend to determine k-value ordering. Same Bspend → by output index. + const scanKeyGroups = new Map(); + for (let i = 0; i < this.outputMaps.length; i++) { + const info = this.getSilentPaymentOutputInfo(i); + if (!info) continue; + const key = info.bscan.toString("hex"); + if (!scanKeyGroups.has(key)) scanKeyGroups.set(key, []); + scanKeyGroups.get(key)!.push({ outputIndex: i, ...info }); + } + + for (const group of scanKeyGroups.values()) { + group.sort((a, b) => { + const cmp = a.bspend.compare(b.bspend); + return cmp !== 0 ? cmp : a.outputIndex - b.outputIndex; + }); + } + + // ── Step 3: Resolve ECDH share and derive output scripts ──────────────── + for (const [bscanHex, group] of scanKeyGroups) { + // Prefer global share — read directly from map to avoid hex round-trip + const globalShareKey = KeyType.PSBT_GLOBAL_SP_ECDH_SHARE + bscanHex; + let ecdhShare: Buffer; + + if (this.globalMap.has(globalShareKey)) { + ecdhShare = this.globalMap.get(globalShareKey) as Buffer; + } else { + // Sum per-input shares for this scan key — read directly from input maps + const perInputBuffers = eligible.flatMap((i) => { + const val = this.inputMaps[i].get( + KeyType.PSBT_IN_SP_ECDH_SHARE + bscanHex, + ); + return val ? [val] : []; + }); + if (perInputBuffers.length === 0) { + throw new Error(`No ECDH share found for scan key ${bscanHex}`); + } + ecdhShare = Buffer.from( + sumECDHShares(perInputBuffers).toRawBytes(true), + ); + } + + for (let k = 0; k < group.length; k++) { + const { outputIndex, bspend } = group[k]; + const script = deriveSilentPaymentOutput( + ecdhShare, + inputHash, + bspend, + k, + ); + this.outputMaps[outputIndex].set(KeyType.PSBT_OUT_SCRIPT, script); + } + } + + // ── Step 4: Lock modifiable flags per BIP375 ──────────────────────────── + // Signer must set Inputs and Outputs Modifiable to False after setting + // missing PSBT_OUT_SCRIPTs. + this.PSBT_GLOBAL_TX_MODIFIABLE = this.PSBT_GLOBAL_TX_MODIFIABLE.filter( + (f) => + f !== PsbtGlobalTxModifiableBits.INPUTS && + f !== PsbtGlobalTxModifiableBits.OUTPUTS, + ); + } } diff --git a/packages/caravan-psbt/src/psbtv2/silentpayment.ts b/packages/caravan-psbt/src/psbtv2/silentpayment.ts new file mode 100644 index 0000000000..55a84664a3 --- /dev/null +++ b/packages/caravan-psbt/src/psbtv2/silentpayment.ts @@ -0,0 +1,246 @@ +/** + * @file BIP352 / BIP375 Silent Payment cryptographic primitives. + * + * Pure functions with no PSBT state. Imported by {@link PsbtV2} for use in + * {@link PsbtV2.computeSilentPaymentOutputScripts}. + * + * @see {@link https://github.com/bitcoin/bips/blob/master/bip-0352.mediawiki BIP352} + * @see {@link https://github.com/bitcoin/bips/blob/master/bip-0375.mediawiki BIP375} + */ + +import { secp256k1 } from "@noble/curves/secp256k1"; +import { createHash } from "crypto"; +import { script } from "bitcoinjs-lib-v6"; +import { xOnlyPointAddTweak } from "src/noble-ecc"; + +const { OPS } = script; + +export type ProjectivePoint = InstanceType; + +// ── Public types ─────────────────────────────────────────────────────────── + +/** + * A single silent payment output entry within a scan-key group, used to + * determine recipient ordering and k-value assignment per BIP375. + */ +export interface SPOutputEntry { + /** Index of this output in the PSBT output maps. */ + outputIndex: number; + /** 33-byte compressed scan public key. */ + bscan: Buffer; + /** 33-byte compressed spend public key. */ + bspend: Buffer; +} + +/** + * Input descriptor passed to {@link eligibleIndices}. One entry per input, + * in original index order. + */ +export interface SPInputDescriptor { + /** + * Raw `PSBT_IN_WITNESS_UTXO` value for this input, or `null` if the field + * is absent (legacy P2PKH / P2SH-P2WPKH inputs). + * + * Format: `amount(8) || scriptLen(varint) || script`. + */ + witnessUtxo: Buffer | null; +} + +// ── Tagged hash ──────────────────────────────────────────────────────────── + +/** + * Computes a BIP340 tagged hash. + * + * ``` + * taggedHash(tag, data) = SHA256(SHA256(tag) || SHA256(tag) || data) + * ``` + * + * @param tag - ASCII tag string, e.g. `"BIP0352/Inputs"`. + * @param data - Arbitrary data to hash. + * @returns 32-byte hash buffer. + */ +export function bip352TaggedHash(tag: string, data: Buffer): Buffer { + const tagHash = createHash("sha256").update(tag).digest(); + return createHash("sha256") + .update(tagHash) + .update(tagHash) + .update(data) + .digest(); +} + +// ── Eligible input indices ───────────────────────────────────────────────── + +/** + * Determines which transaction inputs are eligible for silent payment ECDH + * derivation per BIP352. + * + * Eligible input types: + * - P2TR (Taproot keypath) — `OP_1 <32-byte x-only key>` + * - P2WPKH — `OP_0 <20-byte hash>` + * - P2SH-P2WPKH / P2PKH — no witness UTXO present + * + * Ineligible input types: + * - P2WSH — `OP_0 <32-byte hash>` (multisig, multiple keys) + * - Segwit v2+ — not permitted alongside SP outputs per BIP375 + * + * @param inputs - One entry per input, in original index order. The array + * must be complete and unfiltered so that returned indices correctly + * correspond to positions in the original input list. + * @returns Array of input indices eligible for SP ECDH derivation. + */ +export function eligibleIndices(inputs: SPInputDescriptor[]): number[] { + const eligible: number[] = []; + + for (let i = 0; i < inputs.length; i++) { + const { witnessUtxo } = inputs[i]; + + if (!witnessUtxo) { + // No witness UTXO — legacy input (P2PKH / P2SH-P2WPKH), eligible + eligible.push(i); + continue; + } + + // witnessUtxo format: 8-byte amount || varint scriptLen || script + const scriptLen = witnessUtxo[8]; + const inputScript = witnessUtxo.slice(9, 9 + scriptLen); + const version = inputScript[0]; + + if (version === OPS.OP_1 && inputScript.length === 34) { + // P2TR (OP_1 + 32-byte x-only key) — eligible + eligible.push(i); + } else if (version === OPS.OP_0 && inputScript.length === 22) { + // P2WPKH (OP_0 + 20-byte hash) — eligible + eligible.push(i); + } else if (version === OPS.OP_0 && inputScript.length === 34) { + // P2WSH (OP_0 + 32-byte hash) — NOT eligible (multisig) + continue; + } else if (version >= OPS.OP_2) { + // Segwit v2+ — NOT eligible per BIP375 + continue; + } else { + // Anything else (P2SH-P2WPKH wrapped, P2PKH) — eligible + eligible.push(i); + } + } + + return eligible; +} + +// ── ECDH share accumulation ──────────────────────────────────────────────── + +/** + * Sums a list of 33-byte compressed EC points (per-input ECDH shares) into a + * single point. Used when a global ECDH share is not available and per-input + * shares must be combined before output script derivation. + * + * @param shares - Array of 33-byte compressed EC point buffers. + * @returns The accumulated projective point. + * @throws {Error} If `shares` is empty. + */ +export function sumECDHShares(shares: Buffer[]): ProjectivePoint { + if (shares.length === 0) { + throw new Error("Cannot sum zero ECDH shares."); + } + let sum: ProjectivePoint | null = null; + for (const buf of shares) { + const point = secp256k1.ProjectivePoint.fromHex(buf); + sum = sum ? sum.add(point) : point; + } + return sum!; +} + +// ── Input hash ──────────────────────────────────────────────────────────── + +/** + * Computes the BIP352 input hash used to bind the silent payment derivation + * to the specific set of transaction inputs. + * + * ``` + * inputHash = taggedHash("BIP0352/Inputs", outpointL || A) + * ``` + * + * Where `outpointL` is the lexicographically smallest outpoint and `A` is + * the sum of compressed public keys of all eligible inputs. + * + * @param outpoints - Array of 36-byte buffers, each `txid(32 LE) || vout(4 LE)`. + * @param combinedPubkey - 33-byte compressed sum of eligible input public keys. + * @returns 32-byte input hash buffer. + * @throws {Error} If `outpoints` is empty. + */ +export function computeInputHash( + outpoints: Buffer[], + combinedPubkey: Buffer, +): Buffer { + if (outpoints.length === 0) { + throw new Error("At least one outpoint is required to compute inputHash."); + } + const sorted = [...outpoints].sort(Buffer.compare); + const data = Buffer.concat([sorted[0], combinedPubkey]); + return bip352TaggedHash("BIP0352/Inputs", data); +} + +// ── Output script derivation ─────────────────────────────────────────────── + +/** + * Derives the taproot (P2TR) output script for a single silent payment + * recipient within a scan-key group. + * + * Per BIP352: + * ``` + * ecdhSecret = inputHash · ecdhShare + * tweak_k = taggedHash("BIP0352/SharedSecret", ecdhSecret_compressed || k_be32) + * Pk = Bspend + tweak_k · G + * outputScript = OP_1 <0x20> + * ``` + * + * @param ecdhShare - 33-byte compressed EC point `C = a·Bscan`, where `a` is + * the sum of eligible input private keys (global share) or a single input's + * private key (per-input share). + * @param inputHash - 32-byte scalar produced by {@link computeInputHash}. + * @param bspend - 33-byte compressed spend public key from the recipient's + * silent payment address. + * @param k - Zero-based recipient index within the scan-key group. Increments + * for each recipient sharing the same `Bscan`. + * @returns 34-byte P2TR output script: `OP_1 <0x20> <32-byte x-only pubkey>`. + * @throws {Error} If the tweak produces an invalid point. + */ +export function deriveSilentPaymentOutput( + ecdhShare: Buffer, + inputHash: Buffer, + bspend: Buffer, + k: number, +): Buffer { + // ecdhSecret = inputHash · ecdhShare + // Fn.fromBytes handles modular reduction internally — no manual BigInt needed. + const inputHashScalar = secp256k1.ProjectivePoint.Fn.fromBytes(inputHash); + const ecdhSecretPoint = + secp256k1.ProjectivePoint.fromHex(ecdhShare).multiply(inputHashScalar); + const ecdhSecretBytes = Buffer.from(ecdhSecretPoint.toRawBytes(true)); + + // tweak_k = taggedHash("BIP0352/SharedSecret", ecdhSecret_compressed || k_be32) + const kBuf = Buffer.allocUnsafe(4); + kBuf.writeUInt32BE(k, 0); + const tweak = bip352TaggedHash( + "BIP0352/SharedSecret", + Buffer.concat([ecdhSecretBytes, kBuf]), + ); + + // Pk = Bspend + tweak·G + // xOnlyPointAddTweak expects an x-only (32-byte) pubkey — strip the 02/03 prefix. + // It is already tested against BIP341 vectors in noble-ecc.test.ts. + const bspendXOnly = bspend.slice(1); + const tweakResult = xOnlyPointAddTweak(bspendXOnly, tweak); + if (!tweakResult) { + throw new Error( + "Silent payment output derivation failed: invalid tweak result.", + ); + } + + // P2TR output script: OP_1 + // THIRTY_TWO_BYTE_PUSH_LENGTH is a raw data push length, not an opcode. + const THIRTY_TWO_BYTE_PUSH_LENGTH = 0x20; + return Buffer.concat([ + Buffer.from([OPS.OP_1, THIRTY_TWO_BYTE_PUSH_LENGTH]), + Buffer.from(tweakResult.xOnlyPubkey), + ]); +} From 296fa75e0c4572580b089ac10bd1f55951343d68 Mon Sep 17 00:00:00 2001 From: Jasper van Gelder Date: Tue, 24 Mar 2026 22:44:31 +0100 Subject: [PATCH 05/26] fix(psbt): Prevent creating breaking change with PSBT_OUT_SCRIPT Return empty string instead of changing the signature, feels vary shaky. --- packages/caravan-psbt/src/psbtv2/psbtv2.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/caravan-psbt/src/psbtv2/psbtv2.ts b/packages/caravan-psbt/src/psbtv2/psbtv2.ts index 49d1764b96..18c47f3933 100644 --- a/packages/caravan-psbt/src/psbtv2/psbtv2.ts +++ b/packages/caravan-psbt/src/psbtv2/psbtv2.ts @@ -461,10 +461,10 @@ export class PsbtV2 extends PsbtV2Maps { return indices; } - get PSBT_OUT_SCRIPT(): (string | null)[] { + get PSBT_OUT_SCRIPT(): string[] { return this.outputMaps.map((map) => { const value = map.get(KeyType.PSBT_OUT_SCRIPT); - if (!value) return null; + if (!value) return ""; return value.toString("hex"); }); } From 80e7c117b97f440064cd5137adde560172044ef3 Mon Sep 17 00:00:00 2001 From: Jasper van Gelder Date: Mon, 30 Mar 2026 12:06:04 +0200 Subject: [PATCH 06/26] chore(psbtv2): Added test vectors from BIP375 Credits to @macgyver13 taken from https://github.com/bitcoin/bips/pull/2046 --- .../src/fixtures/bip375_vectors.json | 1717 +++++++++++++++++ .../src/psbtv2/psbtv2-bip375.test.ts | 120 ++ .../caravan-psbt/src/psbtv2/psbtv2.test.ts | 6 +- 3 files changed, 1838 insertions(+), 5 deletions(-) create mode 100644 packages/caravan-psbt/src/fixtures/bip375_vectors.json create mode 100644 packages/caravan-psbt/src/psbtv2/psbtv2-bip375.test.ts diff --git a/packages/caravan-psbt/src/fixtures/bip375_vectors.json b/packages/caravan-psbt/src/fixtures/bip375_vectors.json new file mode 100644 index 0000000000..a3d2ec0c10 --- /dev/null +++ b/packages/caravan-psbt/src/fixtures/bip375_vectors.json @@ -0,0 +1,1717 @@ +{ + "description": "BIP-375 Test Vectors", + "version": "1.1", + "notes": [ + "Generated by https://github.com/macgyver13/bip375-test-generator/", + "Each vector includes: base64-encoded psbt and description", + "Supplementary material (inputs, outputs, sp_proofs) is included for diagnostics and should not be used for validation", + "'checks' overrides the validation sequence, e.g. skip structure checks to test input eligibility" + ], + "invalid": [ + { + "description": "psbt structure: missing PSBT_OUT_SP_V0_INFO field when PSBT_OUT_SP_V0_LABEL set", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEgfCTD+UpVH5TLj1wOA8yaFwh/sU1xSl0vTp/Ux4nT02YBCgQBAAAAAA==", + "supplementary": {} + }, + { + "description": "psbt structure: incorrect byte length for PSBT_OUT_SP_V0_INFO field", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEgMm31D+Cge3rLcgcL6ztjLrmtFbppXMHlqmqgB7YUb9gBCUECekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84AA=", + "supplementary": {} + }, + { + "description": "psbt structure: incorrect byte length for PSBT_IN_SP_ECDH_SHARE field", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GggA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QoiHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaECKE7OYVUX3K9bolxSuuQmz41SoQqm7i1bNDt7SHfihmVmLMSKKSeC9fpXOEFP3xbKKy1Q6aHB2AOPOiYIu4yAhAAEDCBhzAQAAAAAAAQQiUSAybfUP4KB7estyBwvrO2Muua0VumlcweWqaqAHthRv2AEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "supplementary": {} + }, + { + "description": "psbt structure: incorrect byte length for PSBT_IN_SP_DLEQ field", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4Gg/ihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgAAEDCBhzAQAAAAAAAQQiUSAybfUP4KB7estyBwvrO2Muua0VumlcweWqaqAHthRv2AEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "supplementary": {} + }, + { + "description": "psbt structure: PSBT_GLOBAL_TX_MODIFIABLE field is non-zero when PSBT_OUT_SCRIPT set for sp output", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAQABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEgMm31D+Cge3rLcgcL6ztjLrmtFbppXMHlqmqgB7YUb9gBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "supplementary": {} + }, + { + "description": "psbt structure: missing PSBT_OUT_SCRIPT field when sending to non-sp output", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAA=", + "supplementary": {} + }, + { + "description": "psbt structure: empty PSBT_OUT_SCRIPT field when sending to non-sp output", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEAAA=", + "supplementary": {} + }, + { + "description": "ecdh coverage: only one ineligible P2MS input when PSBT_OUT_SCRIPT set for sp output", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiBPa2xI91PQstsuV3qY9lLMD4wBpxZ0Jhhhb5ag+ezmZwEPBAAAAAABASughgEAAAAAACIAIOr39e5jDu+omlGHtlFF4GmTiHzQv1oD8JZFgXkxw/hiAQVHUiEDaGidhEg6mw9BaLYu3+hU5d5PRyw42+0S4nN0susnfjohArPI8nEqzmYLPLqq/KShgFDY2qzp8YMkjzj0SWjwUgPjUq4BEAT+////AAEDCJBfAQAAAAAAAQQiUSDN452LBbSW+PGPILJ9CvmjIzMJ4EciGeCBP/O103h+KQEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "", + "public_key": "", + "prevout_txid": "4f6b6c48f753d0b2db2e577a98f652cc0f8c01a716742618616f96a0f9ece667", + "prevout_index": 0, + "prevout_scriptpubkey": "52210368689d84483a9b0f4168b62edfe854e5de4f472c38dbed12e27374b2eb277e3a2102b3c8f2712ace660b3cbaaafca4a18050d8daace9f183248f38f44968f05203e352ae", + "amount": 100000, + "witness_utxo": "a086010000000000220020eaf7f5ee630eefa89a5187b65145e06993887cd0bf5a03f09645817931c3f862", + "sequence": 4294967294, + "signed": false + } + ] + } + }, + { + "description": "ecdh coverage: missing PSBT_IN_SP_ECDH_SHARE field for input 0 when PSBT_OUT_SCRIPT set for sp output", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////AAEOIL6dZcg5FfsJJIq738qMo+7mzjUMVU9l6NUm5d9SerUiAQ8EAAAAAAEBHxAnAAAAAAAAFgAURjPVnK0TQ0eZcuDJlpIdCl2ttl0BAwQBAAAAIgYCQ6DUDp3giCeUFhdSuuQrqQlSeEIJ8GNDDwryVjVKhbsIAAAAgAEAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghAuV6etywGNj7MVToDBS5elCZS0I1aEHqn8ExcGFEAOY3Ih4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhA9/o4HeILO0WcbkJsYhPUF1MI8kgqROMyhCMmJNTa/Vcymb868WqzAsViY2OjfUSHB/fnoevqBke8zUhiA7srpgABAwgYcwEAAAAAAAEEIlEgzeOdiwW0lvjxjyCyfQr5oyMzCeBHIhnggT/ztdN4fikBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 100000, + "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": false + }, + { + "input_index": 1, + "private_key": "586b0810bbc3c7266971aeb7f8778b41707e092a1aeaf0d953b211f956e35541", + "public_key": "0243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb", + "prevout_txid": "be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab522", + "prevout_index": 0, + "prevout_scriptpubkey": "00144633d59cad1343479972e0c996921d0a5dadb65d", + "amount": 10000, + "witness_utxo": "10270000000000001600144633d59cad1343479972e0c996921d0a5dadb65d", + "sequence": 4294967294, + "signed": false + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "02e57a7adcb018d8fb3154e80c14b97a50994b42356841ea9fc13170614400e637", + "dleq_proof": "f7fa381de20b3b459c6e426c6213d4175308f2482a44e33284232624d4dafd573299bf3af16ab302c5626363a37d448707f7e7a1ebea0647bccd486203bb2ba6", + "input_index": 1 + } + ] + } + }, + { + "description": "ecdh coverage: missing PSBT_IN_SP_DLEQ field for input when PSBT_IN_SP_ECDH_SHARE set", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbAAEDCBhzAQAAAAAAAQQiUSAybfUP4KB7estyBwvrO2Muua0VumlcweWqaqAHthRv2AEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 100000, + "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": null, + "input_index": 0 + } + ] + } + }, + { + "description": "ecdh coverage: missing PSBT_GLOBAL_SP_DLEQ field when PSBT_GLOBAL_SP_ECDH_SHARE set", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBACIHAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWwABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEiBgLIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvwgAAACAAAAAAAEQBP7///8AAQMIGHMBAAAAAAABBCJRIDJt9Q/goHt6y3IHC+s7Yy65rRW6aVzB5apqoAe2FG/YAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 100000, + "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b" + } + ] + } + }, + { + "description": "ecdh coverage: invalid proof in PSBT_IN_SP_DLEQ field", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAbvHreDwFl9ZoVl4787j95b7SgVKV9D4XAVEk1EXcy9rdKkne51lhePEhbl1NuRdP/dpjNON8kDEQjAjOE3TeDwABAwgYcwEAAAAAAAEEIlEgMm31D+Cge3rLcgcL6ztjLrmtFbppXMHlqmqgB7YUb9gBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 100000, + "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "6ef1eb783c0597d668565e3bf3b8fde5bed2815295f43e17015124d445dccbdadd2a49dee7596178f1216e5d4db9174ffdda6334e37c9031108c08ce1374de0f", + "input_index": 0 + } + ] + } + }, + { + "description": "ecdh coverage: invalid proof in PSBT_GLOBAL_SP_DLEQ field", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBACIHAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIIAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQOfI/UQrlNiKKmoskrQ0ZI+gB8n+CARyozeA0LUjKETQm9iLP+6G0S1DhsRlf7t4Xi0vFL/PkYV0P+EqyCUPldkAAQ4gGKcXZjsLqxSxKhp3EyP/HkB53VMuXdE+KOoQgccAmEoBDwQAAAAAAQEfoIYBAAAAAAAWABQimnLTSmRb00lru/ULu4HJBj9PlCICAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/RzBEAiAJB3pqpkrBSuehqk/mjAKs4gbJ6scjSQYa52A5ALkibgIgbxQypXj44zCvC5ACVnRryfTlKqLozHkCncjnajwpSwYBIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////AAEDCBhzAQAAAAAAAQQiUSAybfUP4KB7estyBwvrO2Muua0VumlcweWqaqAHthRv2AEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 100000, + "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "2430479d2da1310a024d2aab8e4c7b49d76cd51f45ee8127c159b0393a675b6f75c581ebe3d0817ddaf3bb598cfd7a022f1a87ed479664f6b947a47db5941cb2" + } + ] + } + }, + { + "description": "ecdh coverage: missing PSBT_IN_BIP32_DERIVATION field for input when PSBT_IN_SP_DLEQ set", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEBAwQBAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIGHMBAAAAAAABBCJRIDJt9Q/goHt6y3IHC+s7Yy65rRW6aVzB5apqoAe2FG/YAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 100000, + "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", + "input_index": 0 + } + ] + } + }, + { + "description": "ecdh coverage: output 1 missing ECDH share for scan key with one input / three sp outputs (different scan keys)", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEDAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR9ADQMAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdArlFYVfpRu8H90tU+gm+Sn6Tjcr7+ye0s3LFc8BZ8SqwIQLChkR0sISqyB9uMKxe30ZnOTzmBNgI0/SZoJhOi1JJdCIdA2UdLAc/ywKk2C3aU/HVAdd6A1BmZ5hUZHOyEmts0afeIQN2iSMnxOeAru7UzhvJK7ASK3t5ENlvCtUUi0lvnD6S+yIeArlFYVfpRu8H90tU+gm+Sn6Tjcr7+ye0s3LFc8BZ8SqwQPCxHVHD/ROzjgpsjvwu4Mpxdzr2dLMVHmiSFJJcS1fIFojJ4Hi3UIhabKsoa1d+k6JJfrSWNrGvG2vILnyRElEiHgNlHSwHP8sCpNgt2lPx1QHXegNQZmeYVGRzshJrbNGn3kCY8UrEWvZFmrDITUfaU2TPsUT/kL2scy+cq8bbAA3PGpXjsx97cKBCmKUbb9RRbIHXFsmVT4rxDD1ZgJruK704AAEDCJBfAQAAAAAAAQQiUSDTlxRqgoZbVOsSuepx1oJP6rD5KkgTf3p5OmhZazNnpAEJQgNlHSwHP8sCpNgt2lPx1QHXegNQZmeYVGRzshJrbNGn3gPycOClYyGDtqsBB06HfmgA2wD1x8XS+vu2j5wo1IVFJAABAwgQJwAAAAAAAAEEIlEgzeOdiwW0lvjxjyCyfQr5oyMzCeBHIhnggT/ztdN4fikBCUIDUteMQTkAMq2RgWppf8dA2OuQnPBNcIhSZLBR8jheJewC4MTBh7chX5l8hIWnW0WRtsKEd7laESO5lpItMVSGC/gAAQMIIE4AAAAAAAABBCJRINLSQezkGFFKoY45kuyVPE1K1exwSmk+IQa6IsOwWnqDAQlCArlFYVfpRu8H90tU+gm+Sn6Tjcr7+ye0s3LFc8BZ8SqwAhJoHj8J6uOKjy8/7NfdVvxYbPoCjoqzP3KpD4QKbSJcAA==", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 200000, + "witness_utxo": "400d030000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": false + } + ], + "sp_proofs": [ + { + "scan_key": "03651d2c073fcb02a4d82dda53f1d501d77a0350666798546473b2126b6cd1a7de", + "ecdh_share": "0376892327c4e780aeeed4ce1bc92bb0122b7b7910d96f0ad5148b496f9c3e92fb", + "dleq_proof": "98f14ac45af6459ab0c84d47da5364cfb144ff90bdac732f9cabc6db000dcf1a95e3b31f7b70a04298a51b6fd4516c81d716c9954f8af10c3d59809aee2bbd38", + "input_index": 0 + }, + { + "scan_key": "02b9456157e946ef07f74b54fa09be4a7e938dcafbfb27b4b372c573c059f12ab0", + "ecdh_share": "02c2864474b084aac81f6e30ac5edf4667393ce604d808d3f499a0984e8b524974", + "dleq_proof": "f0b11d51c3fd13b38e0a6c8efc2ee0ca71773af674b3151e689214925c4b57c81688c9e078b750885a6cab286b577e93a2497eb49636b1af1b6bc82e7c911251", + "input_index": 0 + } + ] + } + }, + { + "description": "ecdh coverage: input 1 missing ECDH share for output 1 with two inputs / two sp outputs (different scan keys)", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQECAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsIQMJH9SAORd/RNe3npYWiEnGLrP4eADEZ2fFCo84+Y79FSIdA2UdLAc/ywKk2C3aU/HVAdd6A1BmZ5hUZHOyEmts0afeIQN2iSMnxOeAru7UzhvJK7ASK3t5ENlvCtUUi0lvnD6S+yIeA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsQL4acjrvVeiYG5lZmpvBKzj4froBWMxwZokPImnK3kY7dzQal9KScZZNAcAkHMMi/VOQwpuZFg+CbzKTZYmMvwIiHgNlHSwHP8sCpNgt2lPx1QHXegNQZmeYVGRzshJrbNGn3kCY8UrEWvZFmrDITUfaU2TPsUT/kL2scy+cq8bbAA3PGpXjsx97cKBCmKUbb9RRbIHXFsmVT4rxDD1ZgJruK704AAEOIL6dZcg5FfsJJIq738qMo+7mzjUMVU9l6NUm5d9SerUiAQ8EAAAAAAEBH6CGAQAAAAAAFgAURjPVnK0TQ0eZcuDJlpIdCl2ttl0BAwQBAAAAIgYCQ6DUDp3giCeUFhdSuuQrqQlSeEIJ8GNDDwryVjVKhbsIAAAAgAEAAAABEAT+////Ih0DZR0sBz/LAqTYLdpT8dUB13oDUGZnmFRkc7ISa2zRp94hAnUEQAf+LQMNV3wymRzyo+deU1BCRbPL5bMFOufF8iBaIh4DZR0sBz/LAqTYLdpT8dUB13oDUGZnmFRkc7ISa2zRp95AOLnjgGtJvr7vxs7gZcKwZv2wCuzs8ei1sqr0fPBBeyma4KJW7Xy2yCcC63E31zv1eSccQoTQBuO1nXCpuWfYiQABAwiQXwEAAAAAAAEEIlEg9Jwu8ZtnBhG4bd7+iQzvlCaKgq4zHkb+GVHWxuNyPLEBCUIDZR0sBz/LAqTYLdpT8dUB13oDUGZnmFRkc7ISa2zRp94D8nDgpWMhg7arAQdOh35oANsA9cfF0vr7to+cKNSFRSQAAQMIkF8BAAAAAAABBCJRID2h4XbGT7RZU+xG4FA2NLx+jjQ6do2+77sKPojMSkyaAQlCA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsAuDEwYe3IV+ZfISFp1tFkbbChHe5WhEjuZaSLTFUhgv4AA==", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 100000, + "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": false + }, + { + "input_index": 1, + "private_key": "586b0810bbc3c7266971aeb7f8778b41707e092a1aeaf0d953b211f956e35541", + "public_key": "0243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb", + "prevout_txid": "be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab522", + "prevout_index": 0, + "prevout_scriptpubkey": "00144633d59cad1343479972e0c996921d0a5dadb65d", + "amount": 100000, + "witness_utxo": "a0860100000000001600144633d59cad1343479972e0c996921d0a5dadb65d", + "sequence": 4294967294, + "signed": false + } + ], + "sp_proofs": [ + { + "scan_key": "03651d2c073fcb02a4d82dda53f1d501d77a0350666798546473b2126b6cd1a7de", + "ecdh_share": "0376892327c4e780aeeed4ce1bc92bb0122b7b7910d96f0ad5148b496f9c3e92fb", + "dleq_proof": "98f14ac45af6459ab0c84d47da5364cfb144ff90bdac732f9cabc6db000dcf1a95e3b31f7b70a04298a51b6fd4516c81d716c9954f8af10c3d59809aee2bbd38", + "input_index": 0 + }, + { + "scan_key": "0352d78c41390032ad91816a697fc740d8eb909cf04d70885264b051f2385e25ec", + "ecdh_share": "03091fd48039177f44d7b79e96168849c62eb3f87800c46767c50a8f38f98efd15", + "dleq_proof": "be1a723aef55e8981b99599a9bc12b38f87eba0158cc7066890f2269cade463b77341a97d29271964d01c0241cc322fd5390c29b99160f826f329365898cbf02", + "input_index": 0 + }, + { + "scan_key": "03651d2c073fcb02a4d82dda53f1d501d77a0350666798546473b2126b6cd1a7de", + "ecdh_share": "0275044007fe2d030d577c32991cf2a3e75e53504245b3cbe5b3053ae7c5f2205a", + "dleq_proof": "38b9e3806b49bebeefc6cee065c2b066fdb00aececf1e8b5b2aaf47cf0417b299ae0a256ed7cb6c82702eb7137d73bf579271c4284d006e3b59d70a9b967d889", + "input_index": 1 + } + ] + } + }, + { + "description": "ecdh coverage: input 1 missing ECDH share for scan key with two inputs / one sp output", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR9QwwAAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQ4gvp1lyDkV+wkkirvfyoyj7ubONQxVT2Xo1Sbl31J6tSIBDwQAAAAAAQEfUMMAAAAAAAAWABRGM9WcrRNDR5ly4MmWkh0KXa22XSIGAkOg1A6d4IgnlBYXUrrkK6kJUnhCCfBjQw8K8lY1SoW7CAAAAIABAAAAARAE/v///wABAwgYcwEAAAAAAAEEIlEgzeOdiwW0lvjxjyCyfQr5oyMzCeBHIhnggT/ztdN4fikBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 50000, + "witness_utxo": "50c3000000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": false + }, + { + "input_index": 1, + "private_key": "586b0810bbc3c7266971aeb7f8778b41707e092a1aeaf0d953b211f956e35541", + "public_key": "0243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb", + "prevout_txid": "be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab522", + "prevout_index": 0, + "prevout_scriptpubkey": "00144633d59cad1343479972e0c996921d0a5dadb65d", + "amount": 50000, + "witness_utxo": "50c30000000000001600144633d59cad1343479972e0c996921d0a5dadb65d", + "sequence": 4294967294, + "signed": false + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", + "input_index": 0 + } + ] + } + }, + { + "description": "input eligibility: segwit version greater than 1 in transaction inputs with sp output", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABZSFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIHLzeIUvuENyYHLyUHbw53Vg7UwuBHFm7mpibHW/2znWAiAhKq5fCVdONB9YhvX/8y9XFuq5AwpKU3nmAWtqTULcJAEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEgMm31D+Cge3rLcgcL6ztjLrmtFbppXMHlqmqgB7YUb9gBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "5214229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 100000, + "witness_utxo": "a086010000000000165214229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + } + ] + }, + "checks": [ + "input_eligibility" + ] + }, + { + "description": "input eligibility: non-SIGHASH_ALL signature on input with sp output", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIHLzeIUvuENyYHLyUHbw53Vg7UwuBHFm7mpibHW/2znWAiAhKq5fCVdONB9YhvX/8y9XFuq5AwpKU3nmAWtqTULcJAEBAwQCAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEgMm31D+Cge3rLcgcL6ztjLrmtFbppXMHlqmqgB7YUb9gBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 100000, + "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + } + ] + } + }, + { + "description": "output scripts: P2TR input with NUMS internal key cannot derive sp output", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAT8Qa2S1e1sTdvn2xHGQ9AzAazvty4qrqXhQqz1/Z9AgEPBAAAAAABASsQJwAAAAAAACJRIFCSm3TBoElUt4tLYDXpel4HiloPKOyW1Ue/7prOgDrAAQMEAQAAAAEQBP7///8BFyBQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wCIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIHCUAAAAAAAABBCJRICdoyIruoiMiW6OthOeGNS+YKdLT6TeKOToL/1mvh83QAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "13f106b64b57b5b1376f9f6c47190f40cc06b3bedcb8aaba97850ab3d7f67d02", + "prevout_index": 0, + "prevout_scriptpubkey": "512050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "amount": 10000, + "witness_utxo": "102700000000000022512050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "sequence": 4294967294, + "signed": false + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", + "input_index": 0 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 9500, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "51202768c88aeea223225ba3ad84e786352f9829d2d3e9378a393a0bff59af87cdd0" + } + ] + } + }, + { + "description": "output scripts: PSBT_OUT_SCRIPT does not match derived sp output", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIGHMBAAAAAAABBCJRIM3jnYsFtJb48Y8gsn0K+aMjMwngRyIZ4IE/87XTeH4pAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 100000, + "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": false + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", + "input_index": 0 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 95000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "5120cde39d8b05b496f8f18f20b27d0af9a3233309e0472219e0813ff3b5d3787e29" + } + ] + } + }, + { + "description": "output scripts: two sp outputs (same scan / different spend keys) not sorted lexicographically by spend key", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQECAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCID9iBcRocGpGJF8XE6u4uLmjp7/YOsdF98ByDUQxtM38AiBxWKv7gg8r9a1nRfVvwHCcmVzMrP4XCY2KobYfjJ/y/wEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwiQXwEAAAAAAAEEIlEgdUe4Fj1bvFSYQL5MwUaq0JUgc2e565RwbeZwjUCPk/kBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgCi4D5lDNIleEbx2x1q254/iwluzMvIXshHEAXvx9nfYYAAQMIECcAAAAAAAABBCJRIGziw1OV8XDyS20tgNCkDEb0a6S0hD9qsxGpNLMcXYTcAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA6r4Yq7amM+SU5r33DN10dpfsGsSHvCh8DGp9zgv1T27AA==", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 100000, + "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", + "input_index": 0 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 90000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068028b80f994334895e11bc76c75ab6e78fe2c25bb332f217b211c4017bf1f677d86", + "script": "51207547b8163d5bbc549840be4cc146aad095207367b9eb94706de6708d408f93f9" + }, + { + "output_index": 1, + "amount": 10000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe06803aaf862aeda98cf92539af7dc3375d1da5fb06b121ef0a1f031a9f7382fd53dbb", + "script": "51206ce2c35395f170f24b6d2d80d0a40c46f46ba4b4843f6ab311a934b31c5d84dc" + } + ] + } + }, + { + "description": "output scripts: k values assigned to wrong output indices with three sp outputs (same scan / spend keys)", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEDAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIFg36hg2U7tRrGNQq+bDhHvokGogZdwwSNbSCOp8DkyCAiAQ+0/6sv7Vqmy2KAqTxHnPsE5Gyp7fF6owXNFnSiQsSQEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwiQXwEAAAAAAAEEIlEgMm31D+Cge3rLcgcL6ztjLrmtFbppXMHlqmqgB7YUb9gBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkAAQMIECcAAAAAAAABBCJRIJcUQsifBHhuCCcorhFu6rgC8/qelf2w03U6aEAgIAbeAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AAEDCBAnAAAAAAAAAQQiUSA/y66kkIf44D2d79Ory9bejAMrWD+Fpl0FeIHExEPNwAEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 100000, + "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", + "input_index": 0 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 90000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "5120326df50fe0a07b7acb72070beb3b632eb9ad15ba695cc1e5aa6aa007b6146fd8" + }, + { + "output_index": 1, + "amount": 10000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "5120971442c89f04786e082728ae116eeab802f3fa9e95fdb0d3753a6840202006de" + }, + { + "output_index": 2, + "amount": 10000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "51203fcbaea49087f8e03d9defd3abcbd6de8c032b583f85a65d057881c4c443cdc0" + } + ] + } + } + ], + "valid": [ + { + "description": "can finalize: one input single-signer", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEgMm31D+Cge3rLcgcL6ztjLrmtFbppXMHlqmqgB7YUb9gBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 100000, + "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", + "input_index": 0 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 95000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "5120326df50fe0a07b7acb72070beb3b632eb9ad15ba695cc1e5aa6aa007b6146fd8" + } + ] + } + }, + { + "description": "can finalize: two inputs single-signer using global ECDH share", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEBAQYBACIHAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQLTJicjNSYH6E/K92UfjS1jfgIK6obfrYDTBs1PSM/MYiIIAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQMZTtx+UaBipW9w58JGERbyQOgh2tzgGDp5dsdzsMKvfVOC18XhXP1EZ3nGqY60ZtEnjvLZUY5Nsi67qTZFzkrkAAQ4gGKcXZjsLqxSxKhp3EyP/HkB53VMuXdE+KOoQgccAmEoBDwQAAAAAAQEfoIYBAAAAAAAWABQimnLTSmRb00lru/ULu4HJBj9PlCICAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/RzBEAiAXBfzaBiZu2zKxaYZ3s39nu25F1JLr/OZWqIDufxOOtgIgPc3jI53ZBjavZPskEspB45fJWKAwd3z/nIlAucd310wBIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////AAEOIL6dZcg5FfsJJIq738qMo+7mzjUMVU9l6NUm5d9SerUiAQ8EAAAAAAEBH6CGAQAAAAAAFgAUE5NQEXxXeUGphYArue3vwROTK8ciAgL1tZ+l5JIiHr9VunitRCYFvq6VFmuh66MlDQu6rH4u3EcwRAIgA4mx4K7v1/q2Ce+rAYv7AWrP8hu4EPPEjDi6ckQYDpUCIBUP7GDiVvQMR1dN/RKaCOr3rB2Xq+4x9AaZ+Hk1RhnzASIGAvW1n6XkkiIev1W6eK1EJgW+rpUWa6HroyUNC7qsfi7cCAAAAIABAAAAARAE/v///wABAwgYcwEAAAAAAAEEIlEgEz1qT1CQlbV5T3SR+8PxLDxFvC2bYK8luLunBMgHKq8BCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 100000, + "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + }, + { + "input_index": 1, + "private_key": "295c2eedddd8331d20b5d4cf9e69bb523ed85cb0bf35ab12e04fea66fe6d4a4a", + "public_key": "02f5b59fa5e492221ebf55ba78ad442605beae95166ba1eba3250d0bbaac7e2edc", + "prevout_txid": "be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab522", + "prevout_index": 0, + "prevout_scriptpubkey": "0014139350117c577941a985802bb9edefc113932bc7", + "amount": 100000, + "witness_utxo": "a086010000000000160014139350117c577941a985802bb9edefc113932bc7", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "02d3262723352607e84fcaf7651f8d2d637e020aea86dfad80d306cd4f48cfcc62", + "dleq_proof": "c653b71f946818a95bdc39f0918445bc903a0876b738060e9e5db1dcec30abdf54e0b5f178573f5119de71aa63ad19b449e3bcb65463936c8baeea4d917392b9" + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 95000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "5120133d6a4f509095b5794f7491fbc3f12c3c45bc2d9b60af25b8bba704c8072aaf" + } + ] + } + }, + { + "description": "can finalize: two inputs single-signer using per-input ECDH shares", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIBcF/NoGJm7bMrFphnezf2e7bkXUkuv85laogO5/E462AiA9zeMjndkGNq9k+yQSykHjl8lYoDB3fP+ciUC5x3fXTAEiBgLIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvwgAAACAAAAAAAEQBP7///8iHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCED7KT/Ebco4uD2DOYiKUOm/1W52V9ie/mpnQhLyHLVClsiHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaECKE7OYVUX3K9bolxSuuQmz41SoQqm7i1bNDt7SHfihmVmLMSKKSeC9fpXOEFP3xbKKy1Q6aHB2AOPOiYIu4yAhAAEOIL6dZcg5FfsJJIq738qMo+7mzjUMVU9l6NUm5d9SerUiAQ8EAAAAAAEBH6CGAQAAAAAAFgAUE5NQEXxXeUGphYArue3vwROTK8ciAgL1tZ+l5JIiHr9VunitRCYFvq6VFmuh66MlDQu6rH4u3EcwRAIgA4mx4K7v1/q2Ce+rAYv7AWrP8hu4EPPEjDi6ckQYDpUCIBUP7GDiVvQMR1dN/RKaCOr3rB2Xq+4x9AaZ+Hk1RhnzAQEDBAEAAAAiBgL1tZ+l5JIiHr9VunitRCYFvq6VFmuh66MlDQu6rH4u3AgAAACAAQAAAAEQBP7///8iHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCEDNNLO907e1EZCJ2B/xZrB3oDBKiQzpWJxUo7cz1D6bCsiHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaEA3wAwLQqBz9rZfDEtuVuBndLOAwd894otkCxIe4LO0z3hQ30VuC12OGXXd/yUmLIOB4g+FLNhwveP2qDKmMlvMAAEDCBhzAQAAAAAAAQQiUSATPWpPUJCVtXlPdJH7w/EsPEW8LZtgryW4u6cEyAcqrwEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 100000, + "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + }, + { + "input_index": 1, + "private_key": "295c2eedddd8331d20b5d4cf9e69bb523ed85cb0bf35ab12e04fea66fe6d4a4a", + "public_key": "02f5b59fa5e492221ebf55ba78ad442605beae95166ba1eba3250d0bbaac7e2edc", + "prevout_txid": "be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab522", + "prevout_index": 0, + "prevout_scriptpubkey": "0014139350117c577941a985802bb9edefc113932bc7", + "amount": 100000, + "witness_utxo": "a086010000000000160014139350117c577941a985802bb9edefc113932bc7", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", + "input_index": 0 + }, + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "0334d2cef74eded4464227607fc59ac1de80c12a2433a56271528edccf50fa6c2b", + "dleq_proof": "37c00c0b42a073f6b65f0c4b6e56e06774b380c1df3de28b640b121ee0b3b4cf7850df456e0b5d8e1975ddff25262c8381e20f852cd870bde3f6a832a6325bcc", + "input_index": 1 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 95000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "5120133d6a4f509095b5794f7491fbc3f12c3c45bc2d9b60af25b8bba704c8072aaf" + } + ] + } + }, + { + "description": "can finalize: two inputs / two sp outputs with mixed global and per-input ECDH shares", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQECAQYBACIHAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oIQNmz8f9zgbgjtSbGzlSuNFRqPfgdf5fbdWN1o+dre7KlCIIAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oQF6riwhtSFD+nRyflhqR+Ze2HKjQhQr8BqeL3zx0nvVAUOaStT+1sIbl54eT8B5203R/ieMXen/v9vjBYX8bBuMAAQ4gGKcXZjsLqxSxKhp3EyP/HkB53VMuXdE+KOoQgccAmEoBDwQAAAAAAQEfQA0DAAAAAAAWABQimnLTSmRb00lru/ULu4HJBj9PlCICAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/SDBFAiEA1k6e8CREAEbpyjkwLrh7LfYN/FHJwKkX1oLzz4EFkIwCIB6+EqXx/SGW8u+11Tr+V850W5Af6ImXitWa7+FKT1A3AQEDBAEAAAAiBgLIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvwgAAACAAAAAAAEQBP7///8iHQKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVECED+9Fz2cSNWMUCJCbQUni8oXuajiKCZmkBobALngS3mUkiHgKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVEEDAXaQQSHz67DeP6+avUAXjrmyGI2gYsOVbIUAX61Bz7e9AF5V1tdzaqQY0kayLg/0GJNQXek0t1JlMRkDWuMzeAAEOIL6dZcg5FfsJJIq738qMo+7mzjUMVU9l6NUm5d9SerUiAQ8EAAAAAAEBH0ANAwAAAAAAFgAUE5NQEXxXeUGphYArue3vwROTK8ciAgL1tZ+l5JIiHr9VunitRCYFvq6VFmuh66MlDQu6rH4u3EcwRAIgWoJ5pshwRPECyFkwyJ7C/wGUKGJBraOMeFTy6DZR1fICICvMZkqflwTVcxLbwryDaGcIDyLEdYuR27ktF6HkEeqpAQEDBAEAAAAiBgL1tZ+l5JIiHr9VunitRCYFvq6VFmuh66MlDQu6rH4u3AgAAACAAQAAAAEQBP7///8iHQKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVECEDpqibG5hqmVUz4XvtZFALVBuw1zkHHv4q4rfvsKDKa88iHgKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVEEDDSmopQLvppzVsHMb/41jdREHbWIl8upnCEut1KF59oeyhHHksl6OASTNFqyJN6dlMKzbuhSauI1KBcaMjHeczAAEDCJBfAQAAAAAAAQQiUSCA65gxi89t1hGsF6lksJFzbATK6t8ubodOXO+Gx8YFFwEJQgMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKAMSZlgePoQcu5TeYupzVYOiMsTIiPpu3vLsL4cHifwd1AABAwiQXwEAAAAAAAEEIlEgELYvxakKvKAWeWHb/0zq6aoyTvssfyRmJ+i1oz3jfIQBCUICqfH6wsxFdoTzPekAc/4g0iyUfJIWO4YrFNCrod9HFRACSkjXbiDUC89fLhpcP/6z3CqLO4jXmkhtVMnZ6qj6GI4A", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 200000, + "witness_utxo": "400d030000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + }, + { + "input_index": 1, + "private_key": "295c2eedddd8331d20b5d4cf9e69bb523ed85cb0bf35ab12e04fea66fe6d4a4a", + "public_key": "02f5b59fa5e492221ebf55ba78ad442605beae95166ba1eba3250d0bbaac7e2edc", + "prevout_txid": "be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab522", + "prevout_index": 0, + "prevout_scriptpubkey": "0014139350117c577941a985802bb9edefc113932bc7", + "amount": 200000, + "witness_utxo": "400d030000000000160014139350117c577941a985802bb9edefc113932bc7", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28", + "ecdh_share": "0366cfc7fdce06e08ed49b1b3952b8d151a8f7e075fe5f6dd58dd68f9dadeeca94", + "dleq_proof": "5eab8b086d4850fe9d1c9f961a91f997b61ca8d0850afc06a78bdf3c749ef54050e692b53fb5b086e5e78793f01e76d3747f89e3177a7feff6f8c1617f1b06e3" + }, + { + "scan_key": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510", + "ecdh_share": "03fbd173d9c48d58c5022426d05278bca17b9a8e2282666901a1b00b9e04b79949", + "dleq_proof": "c05da410487cfaec378febe6af5005e3ae6c86236818b0e55b214017eb5073edef40179575b5dcdaa9063491ac8b83fd0624d4177a4d2dd4994c4640d6b8ccde", + "input_index": 0 + }, + { + "scan_key": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510", + "ecdh_share": "03a6a89b1b986a995533e17bed64500b541bb0d739071efe2ae2b7efb0a0ca6bcf", + "dleq_proof": "c34a6a2940bbe9a7356c1cc6ffe358dd4441db58897cba99c212eb75285e7da1eca11c792c97a380493345ab224de9d94c2b36ee8526ae23528171a3231de733", + "input_index": 1 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 90000, + "sp_v0_info": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28031266581e3e841cbb94de62ea735583a232c4c888fa6edef2ec2f870789fc1dd4", + "script": "512080eb98318bcf6dd611ac17a964b091736c04caeadf2e6e874e5cef86c7c60517" + }, + { + "output_index": 1, + "amount": 90000, + "sp_v0_info": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510024a48d76e20d40bcf5f2e1a5c3ffeb3dc2a8b3b88d79a486d54c9d9eaa8fa188e", + "script": "512010b62fc5a90abca0167961dbff4ceae9aa324efb2c7f246627e8b5a33de37c84" + } + ] + } + }, + { + "description": "can finalize: one input / one sp output with both global and per-input ECDH shares", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBACIHAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oIQMKGLm7QZm4kzDrF/juWseG4IU9zS88zfF0S5fOTt4FPiIIAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oQCf7kMXWHHjjEVIA/9GD0o0KtIOAYslUGTTGQW1CZ84xvUKH6TWUUsCBevDvTVDP9XhDaw0o+e2PIbeaRHZAgI4AAQ4gGKcXZjsLqxSxKhp3EyP/HkB53VMuXdE+KOoQgccAmEoBDwQAAAAAAQEfQA0DAAAAAAAWABQimnLTSmRb00lru/ULu4HJBj9PlCICAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/RzBEAiA3eo+fWjPY+iVcM7OSJtO88CKd+tlgRw74AWpxQvIzWAIgCBvWlIh63us2Ia9aLeTw05yxNpLQQb99vM00oysFQekBAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oIQMKGLm7QZm4kzDrF/juWseG4IU9zS88zfF0S5fOTt4FPiIeAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oQAATg9RmG+hyXvKQSPSMkR+J9fNDF9fAwKzGDvZfG1K//3qW2DObYl34Orq1eqJz7c2aNceU2suxyGEXG7JnB18AAQMIkF8BAAAAAAABBCJRINxNRNnjYeXnQ2V5x44lklVB4in9wVOtWYmtiuawYkx4AQlCAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oAxJmWB4+hBy7lN5i6nNVg6IyxMiI+m7e8uwvhweJ/B3UAA==", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 200000, + "witness_utxo": "400d030000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28", + "ecdh_share": "030a18b9bb4199b89330eb17f8ee5ac786e0853dcd2f3ccdf1744b97ce4ede053e", + "dleq_proof": "27fb90c5d61c78e3115200ffd183d28d0ab4838062c9541934c6416d4267ce31bd4287e9359452c0817af0ef4d50cff578436b0d28f9ed8f21b79a447640808e" + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 90000, + "sp_v0_info": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28031266581e3e841cbb94de62ea735583a232c4c888fa6edef2ec2f870789fc1dd4", + "script": "5120dc4d44d9e361e5e7436579c78e25925541e229fdc153ad5989ad8ae6b0624c78" + } + ] + } + }, + { + "description": "can finalize: three sp outputs (different scan keys) with multiple global ECDH shares", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEDAQYBACIHAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQIQLC2d9g7mmlqGYE3ZpigsIu+OLJJ22m5ZWlRj83Gq3uJCIHAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oIQLcfS7KxWiwEVF1ujzVSW/0xLbZCUItvMrrjyUvpU+L0CIHA47TIg5zNE+R4tMzkePhaR2zna8G5CN+GX7Q0Ae/JyhsIQJwvvXAapqFX8Y7/yvQvi1wAzyCC2FTQTyNbtpR8lobKSIIAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQQOyCQr97WIHO4GBWbH8TzEfkcQyJomRYwgMBswMeSBc7wL6gFoDTN1616AYRqw1Qix5Jq7VxsYeAMqrknwsC99IiCAMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKEDqQ0cOXhvjKRtIoLy1P1WVLGSGDnY177pQA8yt7XfdEo4hZpew9SO+IX7Gh1B3l8zOvFzZQ2KvG0bYA2Qr1flAIggDjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGxAG9/lTtSioG//mwAJrk49gPxHYWR1r98hJEz+PG0QTfJHQah1UU14ZU+5yhEY5tPlUvOPjKujVS6DM8UBvwy9PwABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR8goQcAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQCLg3ekbsHGTj/QlvLhIwW7hrrfzKDP2b9X3JYim55whAIgfn3H3eyoVVwXfr7/yUnqTDNSD+W+7Hun4nJ+NPvUjf0BIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////AAEOIL6dZcg5FfsJJIq738qMo+7mzjUMVU9l6NUm5d9SerUiAQ8EAAAAAAEBH6CGAQAAAAAAFgAURjPVnK0TQ0eZcuDJlpIdCl2ttl0iAgJDoNQOneCIJ5QWF1K65CupCVJ4QgnwY0MPCvJWNUqFu0gwRQIhAPmSLe+tUsYSCQS6pacAUymDbsHD2uFsoGjAFrJrBNLYAiBw+V8k+cklbkGWlGnDUqz6yOiUMjUC6s0WPJSi42nuHwEiBgJDoNQOneCIJ5QWF1K65CupCVJ4QgnwY0MPCvJWNUqFuwgAAACAAQAAAAEQBP7///8AAQMIkF8BAAAAAAABBCJRIKFPr9x+36QEQnF0sSasoOmZMTP+F+JCCurtIO9U/DjcAQlCAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oAxJmWB4+hBy7lN5i6nNVg6IyxMiI+m7e8uwvhweJ/B3UAAEDCJBfAQAAAAAAAQQiUSB99fJJWUQ0FLvv6J0tqJSGSlYotoAzuSPoaGvcw96dlAEJQgKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVEAJKSNduINQLz18uGlw//rPcKos7iNeaSG1UydnqqPoYjgABAwiQXwEAAAAAAAEEIlEgsvEqf1cMxQV4QPpjk/cfBpABQgiBgYEMNLuIdh2SlQ0BCUIDjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGwD+BRzhEyddMkh/xelr0ELYzc0jXr7/3OJG8XLDLJMsMAA", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 500000, + "witness_utxo": "20a1070000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + }, + { + "input_index": 1, + "private_key": "586b0810bbc3c7266971aeb7f8778b41707e092a1aeaf0d953b211f956e35541", + "public_key": "0243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb", + "prevout_txid": "be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab522", + "prevout_index": 0, + "prevout_scriptpubkey": "00144633d59cad1343479972e0c996921d0a5dadb65d", + "amount": 100000, + "witness_utxo": "a0860100000000001600144633d59cad1343479972e0c996921d0a5dadb65d", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28", + "ecdh_share": "02dc7d2ecac568b0115175ba3cd5496ff4c4b6d909422dbccaeb8f252fa54f8bd0", + "dleq_proof": "ea43470e5e1be3291b48a0bcb53f55952c64860e7635efba5003ccaded77dd128e216697b0f523be217ec687507797cccebc5cd94362af1b46d803642bd5f940" + }, + { + "scan_key": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510", + "ecdh_share": "02c2d9df60ee69a5a86604dd9a6282c22ef8e2c9276da6e595a5463f371aadee24", + "dleq_proof": "ec8242bf7b5881cee060566c7f13cc47e4710c89a26458c20301b3031e48173bc0bea01680d3375eb5e80611ab0d508b1e49abb571b1878032aae49f0b02f7d2" + }, + { + "scan_key": "038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c", + "ecdh_share": "0270bef5c06a9a855fc63bff2bd0be2d70033c820b6153413c8d6eda51f25a1b29", + "dleq_proof": "1bdfe54ed4a2a06fff9b0009ae4e3d80fc47616475afdf21244cfe3c6d104df24741a875514d78654fb9ca1118e6d3e552f38f8caba3552e8333c501bf0cbd3f" + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 90000, + "sp_v0_info": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28031266581e3e841cbb94de62ea735583a232c4c888fa6edef2ec2f870789fc1dd4", + "script": "5120a14fafdc7edfa404427174b126aca0e9993133fe17e2420aeaed20ef54fc38dc" + }, + { + "output_index": 1, + "amount": 90000, + "sp_v0_info": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510024a48d76e20d40bcf5f2e1a5c3ffeb3dc2a8b3b88d79a486d54c9d9eaa8fa188e", + "script": "51207df5f24959443414bbefe89d2da894864a5628b68033b923e8686bdcc3de9d94" + }, + { + "output_index": 2, + "amount": 90000, + "sp_v0_info": "038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c03f81473844c9d74c921ff17a5af410b6337348d7afbff73891bc5cb0cb24cb0c0", + "script": "5120b2f12a7f570cc5057840fa6393f71f06900142088181810c34bb88761d92950d" + } + ] + } + }, + { + "description": "can finalize: one P2WPKH input / two mixed outputs - labeled sp output and BIP 32 change", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQECAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR8goQcAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQCspcmETsmSLIHmcIF+My2i3RXSxdOpRiq21l5TtoKJXgIgTfMs6jgucsQ8BYQE/a5wWVHmuj3jPYM8g6lbsBg4CscBAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIoIYBAAAAAAABBCJRIHwkw/lKVR+Uy49cDgPMmhcIf7FNcUpdL06f1MeJ09NmAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoAuJBKtaGGMwJH8G/tuRd4l0b3BZXsljCbRYdEtLosDafAQoEAQAAAAABAwhw8wUAAAAAAAEEFgAUOMGPNd2AY+OApw/+tPmP9O80gXciAgLIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvwwAAAAAAAAAAAAAAAEA", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 500000, + "witness_utxo": "20a1070000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", + "input_index": 0 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 100000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "sp_v0_label": 1, + "script": "51207c24c3f94a551f94cb8f5c0e03cc9a17087fb14d714a5d2f4e9fd4c789d3d366" + }, + { + "output_index": 1, + "amount": 390000, + "script": "001438c18f35dd8063e380a70ffeb4f98ff4ef348177" + } + ] + } + }, + { + "description": "can finalize: one input / two sp outputs - output 0 has no label / output 1 uses label=0 convention for sp change", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQECAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR/gkwQAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCICJa45kPVF365uoUKpN0arSqgSfjyBNY63wha08anrtiAiBl42BSGRArJQdeOVXz80zjvPKjXR4QFd1dw7/tPs81qQEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0CXw7Bs42ZhKfrYvFb5AMCBBDxQu301p42P1YVr9Kmts0hA84eNnXZDZkmSfqd2xH5AlSbs7AvVvbonMCgTIuMN92UIh0Ci3kOCYf96fDRI5jra+MMc3Z5PGR4ZaKgLy78lg2WZWghAlWBv6pzMVb2uY5xom9w/XazZ4ZJ9isfxed7jpq45hBQIh4CXw7Bs42ZhKfrYvFb5AMCBBDxQu301p42P1YVr9Kmts1ADolhPR9rJTbbj6kkIA2zpvjvyhciVWTVaxEuUIZbTTAuBY+m9hwp4jZqSnJp1FVaXGHWVVnb+/rJ4urf5TY31SIeAot5DgmH/enw0SOY62vjDHN2eTxkeGWioC8u/JYNlmVoQHlAgZ626fJYwVg4fApkzBb1F8fvRAkSLM6qlPTi/1N2xCR7/BcNmyY7Dj0ga2aMh+lLNN7q+gCheSsEeteIdbsAAQMIoIYBAAAAAAABBCJRIKBIDZZnnBk25au9SLqw4B/6yx7n0cnhaC8VQBaZZYXZAQlCAot5DgmH/enw0SOY62vjDHN2eTxkeGWioC8u/JYNlmVoA7RDRzNcY/UF5V4mirKA8xi0pqoUSS/zecNmih9U74ybAAEDCDDmAgAAAAAAAQQiUSB2Hb00kpiEpmcp69zbrPFnSC32LBTwmOTvGNcP4Grv0AEJQgJfDsGzjZmEp+ti8VvkAwIEEPFC7fTWnjY/VhWv0qa2zQK+EFEqlVNkHkB62OUJo0GEUqkC6FVqDboumD9eAPe8UQEKBAAAAAAA", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 300000, + "witness_utxo": "e093040000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "025f0ec1b38d9984a7eb62f15be403020410f142edf4d69e363f5615afd2a6b6cd", + "ecdh_share": "03ce1e3675d90d992649fa9ddb11f902549bb3b02f56f6e89cc0a04c8b8c37dd94", + "dleq_proof": "0e89613d1f6b2536db8fa924200db3a6f8efca17225564d56b112e50865b4d302e058fa6f61c29e2366a4a7269d4555a5c61d65559dbfbfac9e2eadfe53637d5", + "input_index": 0 + }, + { + "scan_key": "028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d966568", + "ecdh_share": "025581bfaa733156f6b98e71a26f70fd76b3678649f62b1fc5e77b8e9ab8e61050", + "dleq_proof": "7940819eb6e9f258c158387c0a64cc16f517c7ef4409122cceaa94f4e2ff5376c4247bfc170d9b263b0e3d206b668c87e94b34deeafa00a1792b047ad78875bb", + "input_index": 0 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 100000, + "sp_v0_info": "028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d96656803b44347335c63f505e55e268ab280f318b4a6aa14492ff379c3668a1f54ef8c9b", + "script": "5120a0480d96679c1936e5abbd48bab0e01ffacb1ee7d1c9e1682f154016996585d9" + }, + { + "output_index": 1, + "amount": 190000, + "sp_v0_info": "025f0ec1b38d9984a7eb62f15be403020410f142edf4d69e363f5615afd2a6b6cd037cd462358c69c40525247a8793944d9e67484b248fd84a1e7ee4f920b4da41b5", + "sp_v0_label": 0, + "script": "5120761dbd34929884a66729ebdcdbacf167482df62c14f098e4ef18d70fe06aefd0" + } + ] + } + }, + { + "description": "can finalize: two sp outputs - output 0 uses label=3 / output 1 uses label=1", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQECAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR/gkwQAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCICJa45kPVF365uoUKpN0arSqgSfjyBNY63wha08anrtiAiBl42BSGRArJQdeOVXz80zjvPKjXR4QFd1dw7/tPs81qQEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Ci3kOCYf96fDRI5jra+MMc3Z5PGR4ZaKgLy78lg2WZWghAlWBv6pzMVb2uY5xom9w/XazZ4ZJ9isfxed7jpq45hBQIh4Ci3kOCYf96fDRI5jra+MMc3Z5PGR4ZaKgLy78lg2WZWhAeUCBnrbp8ljBWDh8CmTMFvUXx+9ECRIszqqU9OL/U3bEJHv8Fw2bJjsOPSBrZoyH6Us03ur6AKF5KwR614h1uwABAwighgEAAAAAAAEEIlEgjkFVhZ37qH3uVCd4eSDGlYuRbXrHP02lCyzrTAnwYY8BCUICi3kOCYf96fDRI5jra+MMc3Z5PGR4ZaKgLy78lg2WZWgD8+Tq+VWJ7fdfgshaz/nQvOSCnhaA85Xsfq1iaXfwhRMBCgQDAAAAAAEDCDDmAgAAAAAAAQQiUSDj5vwH7Pa/a1m0ubaqUxM11laKeL6AjUVOAg1+jH/aUwEJQgKLeQ4Jh/3p8NEjmOtr4wxzdnk8ZHhloqAvLvyWDZZlaALcqxqjkFTkguCjoiOo8Sgs1xGXZTHGeaoggF9/X6TxawEKBAEAAAAA", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 300000, + "witness_utxo": "e093040000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d966568", + "ecdh_share": "025581bfaa733156f6b98e71a26f70fd76b3678649f62b1fc5e77b8e9ab8e61050", + "dleq_proof": "7940819eb6e9f258c158387c0a64cc16f517c7ef4409122cceaa94f4e2ff5376c4247bfc170d9b263b0e3d206b668c87e94b34deeafa00a1792b047ad78875bb", + "input_index": 0 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 100000, + "sp_v0_info": "028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d96656803b44347335c63f505e55e268ab280f318b4a6aa14492ff379c3668a1f54ef8c9b", + "sp_v0_label": 3, + "script": "51208e4155859dfba87dee5427787920c6958b916d7ac73f4da50b2ceb4c09f0618f" + }, + { + "output_index": 1, + "amount": 190000, + "sp_v0_info": "028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d96656803b44347335c63f505e55e268ab280f318b4a6aa14492ff379c3668a1f54ef8c9b", + "sp_v0_label": 1, + "script": "5120e3e6fc07ecf6bf6b59b4b9b6aa531335d6568a78be808d454e020d7e8c7fda53" + } + ] + } + }, + { + "description": "can finalize: two mixed input types - only eligible inputs contribute ECDH shares (P2SH excluded)", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQCLTLcGPIp7P5Ia4ABZbNd4jlRA4dY+8e4bzsjCrJQMogIgNw2OmoWgzI3SWwuwgfMaotzFugoiSOqGCoFlHKNKDGgBAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQ4g0iImLyaHKbt8hMVYEppdaYYYXO9TXsFJwN9g3UqSwgQBDwQAAAAAAQBTAgAAAAFA5vqmEmjxehAQHWJVNYKIKuSFi+4TNj24D98oH4Jf/AAAAAAA/////wHwSQIAAAAAABepFPRfjMomjsJuS76JkXDxOCUNfPVehwAAAAABBEdSIQKHfKAvFEBZvYLQDhs5muN094pSzvehyjfyjXiLNA0veSEDTIekSHL14fAG002IoAlZKCvUU150d8PWjDFlmR6hs5ZSrgEQBP7///8AAQMIkF8BAAAAAAABBCJRIDJt9Q/goHt6y3IHC+s7Yy65rRW6aVzB5apqoAe2FG/YAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 100000, + "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + }, + { + "input_index": 1, + "private_key": "", + "public_key": "", + "prevout_txid": "d222262f268729bb7c84c558129a5d6986185cef535ec149c0df60dd4a92c204", + "prevout_index": 0, + "prevout_scriptpubkey": "a914f45f8cca268ec26e4bbe899170f138250d7cf55e87", + "amount": 150000, + "witness_utxo": "020000000140e6faa61268f17a10101d62553582882ae4858bee13363db80fdf281f825ffc0000000000ffffffff01f04902000000000017a914f45f8cca268ec26e4bbe899170f138250d7cf55e8700000000", + "sequence": 4294967294, + "signed": false + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", + "input_index": 0 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 90000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "5120326df50fe0a07b7acb72070beb3b632eb9ad15ba695cc1e5aa6aa007b6146fd8" + } + ] + } + }, + { + "description": "can finalize: two mixed input types - only eligible inputs contribute ECDH shares (NUMS internal key excluded)", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEBAQYBAAABDiAT8Qa2S1e1sTdvn2xHGQ9AzAazvty4qrqXhQqz1/Z9AgEPBAAAAAABASsQJwAAAAAAACJRIFCSm3TBoElUt4tLYDXpel4HiloPKOyW1Ue/7prOgDrAARAE/v///wEXIFCSm3TBoElUt4tLYDXpel4HiloPKOyW1Ue/7prOgDrAAAEOIL6dZcg5FfsJJIq738qMo+7mzjUMVU9l6NUm5d9SerUiAQ8EAAAAAAEBH6CGAQAAAAAAFgAURjPVnK0TQ0eZcuDJlpIdCl2ttl0iAgJDoNQOneCIJ5QWF1K65CupCVJ4QgnwY0MPCvJWNUqFu0gwRQIhAPRhsN/2Q/wKVsFSIUU2OBYiEkh+UGpZ4GnXXtHwq4T2AiBSxx6U6TEuqKkAH80mNyvnCZfdwqpinFqBFtxR9bfpogEBAwQBAAAAIgYCQ6DUDp3giCeUFhdSuuQrqQlSeEIJ8GNDDwryVjVKhbsIAAAAgAEAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghAuV6etywGNj7MVToDBS5elCZS0I1aEHqn8ExcGFEAOY3Ih4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhA9/o4HeILO0WcbkJsYhPUF1MI8kgqROMyhCMmJNTa/Vcymb868WqzAsViY2OjfUSHB/fnoevqBke8zUhiA7srpgABAwgcJQAAAAAAAAEEIlEgBXZyJSSDmoybydLZc46Yu0DdLsUCO9x9p/cGI818hfsBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "13f106b64b57b5b1376f9f6c47190f40cc06b3bedcb8aaba97850ab3d7f67d02", + "prevout_index": 0, + "prevout_scriptpubkey": "512050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "amount": 10000, + "witness_utxo": "102700000000000022512050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "sequence": 4294967294, + "signed": false + }, + { + "input_index": 1, + "private_key": "586b0810bbc3c7266971aeb7f8778b41707e092a1aeaf0d953b211f956e35541", + "public_key": "0243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb", + "prevout_txid": "be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab522", + "prevout_index": 0, + "prevout_scriptpubkey": "00144633d59cad1343479972e0c996921d0a5dadb65d", + "amount": 100000, + "witness_utxo": "a0860100000000001600144633d59cad1343479972e0c996921d0a5dadb65d", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "02e57a7adcb018d8fb3154e80c14b97a50994b42356841ea9fc13170614400e637", + "dleq_proof": "f7fa381de20b3b459c6e426c6213d4175308f2482a44e33284232624d4dafd573299bf3af16ab302c5626363a37d448707f7e7a1ebea0647bccd486203bb2ba6", + "input_index": 1 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 9500, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "51200576722524839a8c9bc9d2d9738e98bb40dd2ec5023bdc7da7f70623cd7c85fb" + } + ] + } + }, + { + "description": "can finalize: three sp outputs (same scan key) - each output has distinct k value", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEEAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+AGgYAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIA3+9XB4r8pV2yK0ze42yxF/h2HkeAgptCHRBkisr62PAiBk5vWJD0/QW3emSnGDHJiGTZyYTJ7x/r6afFC08VkHIQEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwighgEAAAAAAAEEIlEgMm31D+Cge3rLcgcL6ztjLrmtFbppXMHlqmqgB7YUb9gBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkAAQMIoIYBAAAAAAABBCJRID/LrqSQh/jgPZ3v06vL1t6MAytYP4WmXQV4gcTEQ83AAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AAEDCKCGAQAAAAAAAQQiUSCXFELInwR4bggnKK4Rbuq4AvP6npX9sNN1OmhAICAG3gEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQABAwiQXwEAAAAAAAEEIlEgee9WiKP6f+/DkidFWx8cLwjHAIdCTWoA+EwxQhrKjaQA", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 400000, + "witness_utxo": "801a060000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", + "input_index": 0 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 100000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "5120326df50fe0a07b7acb72070beb3b632eb9ad15ba695cc1e5aa6aa007b6146fd8" + }, + { + "output_index": 1, + "amount": 100000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "51203fcbaea49087f8e03d9defd3abcbd6de8c032b583f85a65d057881c4c443cdc0" + }, + { + "output_index": 2, + "amount": 100000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "5120971442c89f04786e082728ae116eeab802f3fa9e95fdb0d3753a6840202006de" + }, + { + "output_index": 3, + "amount": 90000, + "script": "512079ef5688a3fa7fefc39227455b1f1c2f08c70087424d6a00f84c31421aca8da4" + } + ] + } + }, + { + "description": "can finalize: three sp outputs (same scan key) / two regular outputs - k values assigned independently of output index", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEGAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR8goQcAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQD333KAYwDd2+SyTNcz9TsypkayNsKUYFfeR65QOyqxaAIgTGlAW3e+2vOyB+3ll0m7o9VMRhWoi7025Ugkr3fJ5zEBAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIoIYBAAAAAAABBCJRIDJt9Q/goHt6y3IHC+s7Yy65rRW6aVzB5apqoAe2FG/YAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AAEDCFDDAAAAAAAAAQQiUSCcaj0jgY6CDtHQz965Y2V8jsMne32bhlx411V/Xe3WogABAwighgEAAAAAAAEEIlEgP8uupJCH+OA9ne/Tq8vW3owDK1g/haZdBXiBxMRDzcABCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkAAQMIUMMAAAAAAAABBCJRIHnvVoij+n/vw5InRVsfHC8IxwCHQk1qAPhMMUIayo2kAAEDCKCGAQAAAAAAAQQiUSCXFELInwR4bggnKK4Rbuq4AvP6npX9sNN1OmhAICAG3gEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQABAwjILAEAAAAAAAEEIlEgb8UG+AUqn1qKqbmQ1emU9JXd7W1HusRMqs2t2NiZHNAA", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 500000, + "witness_utxo": "20a1070000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", + "input_index": 0 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 100000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "5120326df50fe0a07b7acb72070beb3b632eb9ad15ba695cc1e5aa6aa007b6146fd8" + }, + { + "output_index": 1, + "amount": 50000, + "script": "51209c6a3d23818e820ed1d0cfdeb963657c8ec3277b7d9b865c78d7557f5dedd6a2" + }, + { + "output_index": 2, + "amount": 100000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "51203fcbaea49087f8e03d9defd3abcbd6de8c032b583f85a65d057881c4c443cdc0" + }, + { + "output_index": 3, + "amount": 50000, + "script": "512079ef5688a3fa7fefc39227455b1f1c2f08c70087424d6a00f84c31421aca8da4" + }, + { + "output_index": 4, + "amount": 100000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "5120971442c89f04786e082728ae116eeab802f3fa9e95fdb0d3753a6840202006de" + }, + { + "output_index": 5, + "amount": 77000, + "script": "51206fc506f8052a9f5a8aa9b990d5e994f495dded6d47bac44caacdadd8d8991cd0" + } + ] + } + }, + { + "description": "in progress: two P2TR inputs, neither is signed", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEBAQYBAAABDiAT8Qa2S1e1sTdvn2xHGQ9AzAazvty4qrqXhQqz1/Z9AgEPBAAAAAABASughgEAAAAAACJRIMgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/AQMEAQAAAAEQBP7///8BFyDIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvyIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQ4gK5A3/0HdF05VIvD0BFw/QENiMq8mANTaXJ6hPMPKtLUBDwQAAAAAAQErECcAAAAAAAAiUSBDoNQOneCIJ5QWF1K65CupCVJ4QgnwY0MPCvJWNUqFuwEDBAEAAAABEAT+////ARcgQ6DUDp3giCeUFhdSuuQrqQlSeEIJ8GNDDwryVjVKhbsiHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCEC5Xp63LAY2PsxVOgMFLl6UJlLQjVoQeqfwTFwYUQA5jciHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaED3+jgd4gs7RZxuQmxiE9QXUwjySCpE4zKEIyYk1Nr9VzKZvzrxarMCxWJjY6N9RIcH9+eh6+oGR7zNSGIDuyumAAEDCLj5AgAAAAAAAQQiUSDLH766UNBuv/tpC9qdX/Oc4vrbT87clmMu/xukHMDAewEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "13f106b64b57b5b1376f9f6c47190f40cc06b3bedcb8aaba97850ab3d7f67d02", + "prevout_index": 0, + "prevout_scriptpubkey": "5120c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "amount": 100000, + "witness_utxo": "a086010000000000225120c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "sequence": 4294967294, + "signed": false + }, + { + "input_index": 1, + "private_key": "586b0810bbc3c7266971aeb7f8778b41707e092a1aeaf0d953b211f956e35541", + "public_key": "0243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb", + "prevout_txid": "2b9037ff41dd174e5522f0f4045c3f40436232af2600d4da5c9ea13cc3cab4b5", + "prevout_index": 0, + "prevout_scriptpubkey": "512043a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb", + "amount": 10000, + "witness_utxo": "102700000000000022512043a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb", + "sequence": 4294967294, + "signed": false + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", + "input_index": 0 + }, + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "02e57a7adcb018d8fb3154e80c14b97a50994b42356841ea9fc13170614400e637", + "dleq_proof": "f7fa381de20b3b459c6e426c6213d4175308f2482a44e33284232624d4dafd573299bf3af16ab302c5626363a37d448707f7e7a1ebea0647bccd486203bb2ba6", + "input_index": 1 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 195000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "5120cb1fbeba50d06ebffb690bda9d5ff39ce2fadb4fcedc96632eff1ba41cc0c07b" + } + ] + } + }, + { + "description": "in progress: one P2TR input / one sp output with no ECDH shares when PSBT_OUT_SCRIPT field is not set", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAT8Qa2S1e1sTdvn2xHGQ9AzAazvty4qrqXhQqz1/Z9AgEPBAAAAAABASughgEAAAAAACJRIMgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/ARAE/v///wEXIMgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/AAEDCBhzAQAAAAAAAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "13f106b64b57b5b1376f9f6c47190f40cc06b3bedcb8aaba97850ab3d7f67d02", + "prevout_index": 0, + "prevout_scriptpubkey": "5120c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "amount": 100000, + "witness_utxo": "a086010000000000225120c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "sequence": 4294967294, + "signed": false + } + ], + "sp_proofs": [], + "outputs": [ + { + "output_index": 0, + "amount": 95000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039" + } + ] + } + }, + { + "description": "in progress: two inputs / one sp output, input 1 missing ECDH share when PSBT_OUT_SCRIPT field is not set", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQ4gvp1lyDkV+wkkirvfyoyj7ubONQxVT2Xo1Sbl31J6tSIBDwQAAAAAAQEf8EkCAAAAAAAWABRGM9WcrRNDR5ly4MmWkh0KXa22XSIGAkOg1A6d4IgnlBYXUrrkK6kJUnhCCfBjQw8K8lY1SoW7CAAAAIABAAAAARAE/v///wABAwhADQMAAAAAAAEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 100000, + "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": false + }, + { + "input_index": 1, + "private_key": "586b0810bbc3c7266971aeb7f8778b41707e092a1aeaf0d953b211f956e35541", + "public_key": "0243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb", + "prevout_txid": "be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab522", + "prevout_index": 0, + "prevout_scriptpubkey": "00144633d59cad1343479972e0c996921d0a5dadb65d", + "amount": 150000, + "witness_utxo": "f0490200000000001600144633d59cad1343479972e0c996921d0a5dadb65d", + "sequence": 4294967294, + "signed": false + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", + "input_index": 0 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 200000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039" + } + ] + } + }, + { + "description": "in progress: one input / two sp outputs, input 0 missing ECDH share for output 0 when PSBT_OUT_SCRIPT field is not set", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQECAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR9ADQMAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsIQMJH9SAORd/RNe3npYWiEnGLrP4eADEZ2fFCo84+Y79FSIeA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsQL4acjrvVeiYG5lZmpvBKzj4froBWMxwZokPImnK3kY7dzQal9KScZZNAcAkHMMi/VOQwpuZFg+CbzKTZYmMvwIAAQMIkF8BAAAAAAABCUIDZR0sBz/LAqTYLdpT8dUB13oDUGZnmFRkc7ISa2zRp94D8nDgpWMhg7arAQdOh35oANsA9cfF0vr7to+cKNSFRSQAAQMIkF8BAAAAAAABBCJRIENYHfbIefmqrcU2YN6xVrnxIr0a7KczIDvOh/zx84buAQlCA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsAuDEwYe3IV+ZfISFp1tFkbbChHe5WhEjuZaSLTFUhgv4AA==", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 200000, + "witness_utxo": "400d030000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": false + } + ], + "sp_proofs": [ + { + "scan_key": "0352d78c41390032ad91816a697fc740d8eb909cf04d70885264b051f2385e25ec", + "ecdh_share": "03091fd48039177f44d7b79e96168849c62eb3f87800c46767c50a8f38f98efd15", + "dleq_proof": "be1a723aef55e8981b99599a9bc12b38f87eba0158cc7066890f2269cade463b77341a97d29271964d01c0241cc322fd5390c29b99160f826f329365898cbf02", + "input_index": 0 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 90000, + "sp_v0_info": "03651d2c073fcb02a4d82dda53f1d501d77a0350666798546473b2126b6cd1a7de03f270e0a5632183b6ab01074e877e6800db00f5c7c5d2fafbb68f9c28d4854524" + }, + { + "output_index": 1, + "amount": 90000, + "sp_v0_info": "0352d78c41390032ad91816a697fc740d8eb909cf04d70885264b051f2385e25ec02e0c4c187b7215f997c8485a75b4591b6c28477b95a1123b996922d3154860bf8", + "script": "512043581df6c879f9aaadc53660deb156b9f122bd1aeca733203bce87fcf1f386ee" + } + ] + } + }, + { + "description": "in progress: large PSBT with nine mixed inputs / six outputs - some inputs signed", + "psbt": "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", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 100000, + "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + }, + { + "input_index": 1, + "private_key": "295c2eedddd8331d20b5d4cf9e69bb523ed85cb0bf35ab12e04fea66fe6d4a4a", + "public_key": "02f5b59fa5e492221ebf55ba78ad442605beae95166ba1eba3250d0bbaac7e2edc", + "prevout_txid": "be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab522", + "prevout_index": 0, + "prevout_scriptpubkey": "0014139350117c577941a985802bb9edefc113932bc7", + "amount": 100000, + "witness_utxo": "a086010000000000160014139350117c577941a985802bb9edefc113932bc7", + "sequence": 4294967294, + "signed": true + }, + { + "input_index": 2, + "private_key": "e6db4a04e2fc29745ea1a9dcf1fed7449c8228ffe0503d8171e64126d5399800", + "public_key": "02655ef5daf05d28d1ca73ba8e211300db2b70416737183e0fa8c355ee4c1cbac6", + "prevout_txid": "d041c742ca364472d1a18c7a8eae07e6e904a9ea1b85f198525fb83ef276e343", + "prevout_index": 0, + "prevout_scriptpubkey": "00142307fc774ca174b42ada814bc2e6e444ff3d830c", + "amount": 100000, + "witness_utxo": "a0860100000000001600142307fc774ca174b42ada814bc2e6e444ff3d830c", + "sequence": 4294967294, + "signed": true + }, + { + "input_index": 3, + "private_key": "f5208ed67b0019ba4e306aff029d247931e0dfacd1fe6e69091bc6bc70a42619", + "public_key": "0303a0f4528d264e8e95256634b94414e2748f72962704fe57e8b0a2cc44d2383d", + "prevout_txid": "52262cd5d402bf32616d07fc03286a8f7fe78af7ac411dfff41655ddc1011e6f", + "prevout_index": 0, + "prevout_scriptpubkey": "00147018bce965288d8bf0ccf3e0ec48b6f1dbbfe548", + "amount": 100000, + "witness_utxo": "a0860100000000001600147018bce965288d8bf0ccf3e0ec48b6f1dbbfe548", + "sequence": 4294967294, + "signed": true + }, + { + "input_index": 4, + "private_key": "0c19c34dc1005feb5ca60104d20472f7f2f97bd4d521264618196bf71155b20a", + "public_key": "03a8911beb5a48fe119cb015088cf0c3a118cf026772448972d1b70c764ac59412", + "prevout_txid": "e298eaf24fe1ca68b41e4b6b83cc3d91ced99c6e78d5b992cfb15771b5457064", + "prevout_index": 0, + "prevout_scriptpubkey": "00149332bb020cb03d49eb4d04712c1cc08e2b06d8d8", + "amount": 100000, + "witness_utxo": "a0860100000000001600149332bb020cb03d49eb4d04712c1cc08e2b06d8d8", + "sequence": 4294967294, + "signed": true + }, + { + "input_index": 5, + "private_key": "5aaa151cbdeb566911784d166b01ce57f35993b98f96846efec1cfefcc0d8f56", + "public_key": "02d155713c520ce2d8276164215d659ab623c5f7306f8652c1756e26833e886e01", + "prevout_txid": "1730833ecb5be01362d7149522604484216e1c7b18cf313d1cf1543ef85df3b6", + "prevout_index": 0, + "prevout_scriptpubkey": "5120d155713c520ce2d8276164215d659ab623c5f7306f8652c1756e26833e886e01", + "amount": 100000, + "witness_utxo": "a086010000000000225120d155713c520ce2d8276164215d659ab623c5f7306f8652c1756e26833e886e01", + "sequence": 4294967294, + "signed": false + }, + { + "input_index": 6, + "private_key": "d92c1506167b3a00a21f4d90d7b5ccb4713c00194aa66f9c7deb162c467f9643", + "public_key": "02d00e15fb626a7efee85c5bce676d636b6048914e9a34ace0b4cbc44bc948077a", + "prevout_txid": "e93532e0eda39c4d39da2d3f91d14529bc435fc2efb9196e25fbaac4b4e89b81", + "prevout_index": 0, + "prevout_scriptpubkey": "5120d00e15fb626a7efee85c5bce676d636b6048914e9a34ace0b4cbc44bc948077a", + "amount": 100000, + "witness_utxo": "a086010000000000225120d00e15fb626a7efee85c5bce676d636b6048914e9a34ace0b4cbc44bc948077a", + "sequence": 4294967294, + "signed": false + }, + { + "input_index": 7, + "private_key": "d8bc8d0e1233a97133f3573d6dceb6736e8b6d2e4839925145022ea3efdad8f8", + "public_key": "020500f167cf669e7dac39e6aecda1f28c66b78ec7097eefef25d54f7be785e7f6", + "prevout_txid": "b6368bbc330cddfe9e2550edb7dfc15ae74cac9bcc7d967fe81e6f27f8597b1d", + "prevout_index": 0, + "prevout_scriptpubkey": "a9140df101357f73e6658500cf56f3a132d7bb8afbdd87", + "amount": 100000, + "witness_utxo": "a08601000000000017a9140df101357f73e6658500cf56f3a132d7bb8afbdd87", + "sequence": 4294967294, + "signed": true + }, + { + "input_index": 8, + "private_key": "81e30f5b5d049bdf5c5bea9c3329bf57cc8b473240182a9f2a6eee07435bd54a", + "public_key": "03199d2f155f32ebb167aeb0ccca6e5afb7340898df1b7ab9936500f6d4391902a", + "prevout_txid": "03bceba5379d73daeafe677972b03dcf7ef30b7f10eaa83ad04bc0bf00d8b2f7", + "prevout_index": 0, + "prevout_scriptpubkey": "76a914569bf311e68a383767b43f83042dfabe60093ede88ac", + "amount": 100000, + "witness_utxo": "02000000012a34ac1b0db77a8198c1e29002cc47bbfcd6ed830960304d2c9a3ab548486b5d0000000000ffffffff01a0860100000000001976a914569bf311e68a383767b43f83042dfabe60093ede88ac00000000", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28", + "ecdh_share": "030a18b9bb4199b89330eb17f8ee5ac786e0853dcd2f3ccdf1744b97ce4ede053e", + "dleq_proof": "001383d4661be8725ef29048f48c911f89f5f34317d7c0c0acc60ef65f1b52bfff7a96d8339b625df83abab57aa273edcd9a35c794dacbb1c861171bb267075f", + "input_index": 0 + }, + { + "scan_key": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510", + "ecdh_share": "03fbd173d9c48d58c5022426d05278bca17b9a8e2282666901a1b00b9e04b79949", + "dleq_proof": "c05da410487cfaec378febe6af5005e3ae6c86236818b0e55b214017eb5073edef40179575b5dcdaa9063491ac8b83fd0624d4177a4d2dd4994c4640d6b8ccde", + "input_index": 0 + }, + { + "scan_key": "038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c", + "ecdh_share": "037372d179f4f628da82ccbd4e4217bdb0809f1417c9abeaa35fa805d48ad6554c", + "dleq_proof": "a6872d4eb119fe2af70953f752a22236b54a3b57f70e511f10bd8b42ff56b5acf6365093c480ea9f13776784945b59318ac2927d915aae244cfb683f4188a3a7", + "input_index": 0 + }, + { + "scan_key": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28", + "ecdh_share": "02f6ae7b8aac9a0f9c9f04eab484062172df2e38d9f2f6ec31b404bb5a286aabf0", + "dleq_proof": "334aced8106ebaa4287daca56cca26795f2d2a739784cf6b734da3370757f499e120c0e40be40436cd74c4ef26905706f52fa7fa6e8e76451e8583783051a843", + "input_index": 1 + }, + { + "scan_key": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510", + "ecdh_share": "03a6a89b1b986a995533e17bed64500b541bb0d739071efe2ae2b7efb0a0ca6bcf", + "dleq_proof": "c34a6a2940bbe9a7356c1cc6ffe358dd4441db58897cba99c212eb75285e7da1eca11c792c97a380493345ab224de9d94c2b36ee8526ae23528171a3231de733", + "input_index": 1 + }, + { + "scan_key": "038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c", + "ecdh_share": "02b1d3ed2fa4bc316a08eb1485fa75ed7dd54ca7a9ae18d0c4a17da93f30c385d5", + "dleq_proof": "d841a373ad2896b972b8cfea1634ff14a30f80d84cfd6ef18893397b8f346c80519c9b161a72244d0e9b64e5436c98ce9dd4e17a0728fc997b5c7bcf39cecb68", + "input_index": 1 + }, + { + "scan_key": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28", + "ecdh_share": "03bfb86253beb96f58b8c469e442cfcf9f78a5413a95423be8e686764f2fa7bd3f", + "dleq_proof": "52dffbf0095f29b1de24c9d68d549d1c54bce6900454fe37fd10f5c903dfee85f7bad8a72ada8e52cd9092f51d9e90b5a7e4f36ca04df98e77fbad1347305bc7", + "input_index": 2 + }, + { + "scan_key": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510", + "ecdh_share": "03df706ff26d672fe50c6f56a2ca1e7174e75055c920bbd337e1a7d6bf2826f6dc", + "dleq_proof": "fd2e8c22b9b672d3bb9e26d4b6da2dc3f125455a969fd8e2b2c1ba791076ad71b38c01f9218c3d6776fd895d2f3067484996d85e268390c2b433e6c4b21891f1", + "input_index": 2 + }, + { + "scan_key": "038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c", + "ecdh_share": "038604aa8cff309dddf49b1f366f89c269616587fc41db608540f9431536f6646f", + "dleq_proof": "93e1e5d4888bc1cfe02eecfa9dea144ead84f23a10fc1a301103c1e56393527b63417c6c4a5af45359ff8b6e179af73978e4d62e862eedd2a286f5278e4cb340", + "input_index": 2 + }, + { + "scan_key": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28", + "ecdh_share": "02980bac7264e14bf820cc435b69a78df726c177eb026f1b81b52de811272f58eb", + "dleq_proof": "38e03463b6450dbd051065a812a6f2631087f7951e46ac84e66da811755717c093180e4d49827b8c097ca7093fe92d393f95a5d7ad849a41802dc4e4558abde9", + "input_index": 3 + }, + { + "scan_key": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510", + "ecdh_share": "038029998c73c2b139db75557ec3011ec65ecd212447963006571852a3e92289cc", + "dleq_proof": "381ce3c1ac9fc7f6a51536456252984768e8fbd014070239f4cb13b16793c74cc5ed677c8a7eacc173e988d353a3f289c7e2141db7a4b4145c5499ec837f36ae", + "input_index": 3 + }, + { + "scan_key": "038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c", + "ecdh_share": "03a27d9f1fa53e43f70835a6990954b78a35f747066f7b82b4a9ea82e8bb5e06a6", + "dleq_proof": "732aa0957a9db2c759e39aca5d0167ef13d2a34a43c812e9cc9d712d458f7b2285da7511eb16f61f9600d20be4e94dfdd2bc3ae37fd943fc34947dfc3fdc6797", + "input_index": 3 + }, + { + "scan_key": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28", + "ecdh_share": "027eb7c1c4afcd7e62ab6ad3d2ba2733a3745220641f91903ebfe7bcc5dbdc6b5d", + "dleq_proof": "77b1572336d9bd4e2f73411eb8f6a96235a130f444cbeb07a489f447921e37489d71fd3db28a0bbaa35b88c37b7579ecdbf6ce1638700db81dfc86bf79cd1be7", + "input_index": 4 + }, + { + "scan_key": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510", + "ecdh_share": "02bef4738c6f327f1724b1407988959cdf2bd19210894bfd043535b61138270818", + "dleq_proof": "0a584927102820b7b6cad6bcfb031a23a37312ad87d23f1cb5a8359be2d5ff39b6a2a2fe37cd0d53ee347f13e6b3525769b2e789f0699cb985588eac2daf10dd", + "input_index": 4 + }, + { + "scan_key": "038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c", + "ecdh_share": "03ca88bcdb6d1f5291e90c75d3da601a8bd29991eabbf7f94b2f39483e3858c9a1", + "dleq_proof": "5d0de8a27f0d528802cf3354a1af507bcf0fed419da641c9c0807cd754e07af8790b511c705d5fbf63305ab22afe0497facf070b5afeafcee3a6900547767756", + "input_index": 4 + }, + { + "scan_key": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28", + "ecdh_share": "03802b69b360da4585512b1cf967b184010226d75ce5b762e77a0128bcb068ccbb", + "dleq_proof": "103ae05c10e43298376c3fee1dc5f0d04389f4f20af49346d48ead324d615d6f28fca0a318445130ea56a862019b2de0c2637db3c418c0b074b58548ae8b20c9", + "input_index": 5 + }, + { + "scan_key": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510", + "ecdh_share": "024f2a15a4b15a6b78f0a632fc7fdf112929f64bd4dd14f67a63cf4fb8f325a204", + "dleq_proof": "8f223de27986dd8792a03d9d5b662323e8697830ebabb67363881fe72c86482ae61a09268d083b8354cfc2bad35c148eeb291af622dd460634606332af1b8297", + "input_index": 5 + }, + { + "scan_key": "038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c", + "ecdh_share": "02407615505ecbdea881312504eef6f4681a26316ef73d33537a7fd793f4658ea9", + "dleq_proof": "f055990738544d099b159290e7f5442cb91226260174aa9d8c1c8310b7cb01ce2b94cc5d2b8fdf81667e02fb796db0e5c27877de0d41a2a0e709b01445baf296", + "input_index": 5 + }, + { + "scan_key": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28", + "ecdh_share": "020faa3a0c31ae7695e769546e30aa782abd31fb681b970a13aa35cc21dfd13800", + "dleq_proof": "e4074a6ec893eab806d5df9a74ed257e785ff378643dbaa7933c7813a7b5f6c90ca82b62539f39b38c2c72fe5cf81c22a5e641f673644f6c486b3db577464463", + "input_index": 6 + }, + { + "scan_key": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510", + "ecdh_share": "02153fcdfe96ae70363fd1542646d309c2132b8325540e3dd7f88e37f9796079a6", + "dleq_proof": "4320e9f60fd3c2a6f737aace546c23b0c7d76e84159c0ad289c1df4c0f8a500e51209f296f9d7d223a1d292bd41d266faacb1be843becf4b706eb15dba702806", + "input_index": 6 + }, + { + "scan_key": "038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c", + "ecdh_share": "03f313f8f475eb01e3cecbc0eaac2f726d29032c6ff7c3ad6cc3bf8bb10186527c", + "dleq_proof": "3b29e12cf693f272139f74452f2bccc2bcd07432dce8fb107354c1458a12a47c8544d2d6ca1e33bce0578b6508cf8a5934673f9fc435a5f84a22a54b5adcbcfc", + "input_index": 6 + }, + { + "scan_key": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28", + "ecdh_share": "026f027b235a7593ca8943c6d7b7e37d92eab339617f7f0c344106c58dd0cbc6aa", + "dleq_proof": "16b58148f7baff783e4310f185503fe92417dba43b966c83a2184322cb1f20424cb9d040ae6a1aea4e7444bdc786258a975644ce1a0195564c2b9fc3c606a292", + "input_index": 7 + }, + { + "scan_key": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510", + "ecdh_share": "02fe7841cddfb46fdb2ca9bde56c9558c2d1b36121665659080224e24031438408", + "dleq_proof": "88072551662c3eebee545f188b8dafc682973a2f218e7ca07fc8e42ff57a1134630449fd703177d7a12d0c9ced024844dc1b9e0ecad67587dd5c479431b36a1a", + "input_index": 7 + }, + { + "scan_key": "038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c", + "ecdh_share": "020611450c6c1944ecdecb78f61816c767fba4368f21f7e9b169779c76f23cf4cc", + "dleq_proof": "4ab36bdd69eb1cd0d4b0aeae403dce4db5228c5ba3a291dc725de23382d1736d265d7bc33f83690a5ca5609719f19e81952d4c8d5e288fd0cb8c6411104b80a3", + "input_index": 7 + }, + { + "scan_key": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28", + "ecdh_share": "02fa1ced932598a27fa28410b955ea67479b5a4033b69f2c99e4e26767bba0a556", + "dleq_proof": "a0948c517d70976c0e39ca67abf19e7217040dbe172bb96534133e6ffa3941c1659416f540662b7561efb70064b4d71a9b17b63bc563f630db4422f273e0df12", + "input_index": 8 + }, + { + "scan_key": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510", + "ecdh_share": "02f3c175b08b207637616aa74e67baac1a1807c94bce70800f76f5b17b52c0082d", + "dleq_proof": "99225658fede7a8c2437eb3821bdc9d3700abc896e8b6dcef84e29347b78bc2b03e6da33836e4f40767390c36644ce016b36b1d546963540fa51d0b0407db6d7", + "input_index": 8 + }, + { + "scan_key": "038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c", + "ecdh_share": "0300e0fd1710dc56ad7c173aa9141d731577009bc3dffcba8576a48e77ab34d970", + "dleq_proof": "ee0aaa65ca73ccc547b31c2b7ed2ae31a4f4ccdaea73f2add24630d608ede9aea5d808688186ebca42b877efab13f35e60f210d4f620602f850fc0731c201e91", + "input_index": 8 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 30000, + "sp_v0_info": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28031266581e3e841cbb94de62ea735583a232c4c888fa6edef2ec2f870789fc1dd4", + "script": "51201afa5d88188cef9b91b3f1002b11e0f9e94ad3981978c4d12a0605564c081233" + }, + { + "output_index": 1, + "amount": 30000, + "sp_v0_info": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28031266581e3e841cbb94de62ea735583a232c4c888fa6edef2ec2f870789fc1dd4", + "script": "5120cabf7e4a0de424ec9bbadd7f7242cce7673e1701f49d6a19a97055da332b1324" + }, + { + "output_index": 2, + "amount": 20000, + "sp_v0_info": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510024a48d76e20d40bcf5f2e1a5c3ffeb3dc2a8b3b88d79a486d54c9d9eaa8fa188e", + "script": "51204aadc9e0a590d21e0c19cb2024f27140f9b19c2a1282d50ea7c5f45eb03fd4a2" + }, + { + "output_index": 3, + "amount": 20000, + "sp_v0_info": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510024a48d76e20d40bcf5f2e1a5c3ffeb3dc2a8b3b88d79a486d54c9d9eaa8fa188e", + "script": "51202fa43700ea1d28fd7ad4dcb332b3e5e5a0d8cb54258f6661c4de0377d72804e5" + }, + { + "output_index": 4, + "amount": 10000, + "sp_v0_info": "038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c03f81473844c9d74c921ff17a5af410b6337348d7afbff73891bc5cb0cb24cb0c0", + "script": "512051986faee319436b51b38409c1b300f4396e2b32e3cc9a12ae2a4be135da6f6e" + }, + { + "output_index": 5, + "amount": 50000, + "script": "51206fc506f8052a9f5a8aa9b990d5e994f495dded6d47bac44caacdadd8d8991cd0" + } + ] + } + } + ] +} \ No newline at end of file diff --git a/packages/caravan-psbt/src/psbtv2/psbtv2-bip375.test.ts b/packages/caravan-psbt/src/psbtv2/psbtv2-bip375.test.ts new file mode 100644 index 0000000000..6c1df78317 --- /dev/null +++ b/packages/caravan-psbt/src/psbtv2/psbtv2-bip375.test.ts @@ -0,0 +1,120 @@ +/** + * BIP375 test vectors for PsbtV2 silent payment PSBT validation. + */ + +import { describe, expect, test } from "vitest"; +import { PsbtV2 } from "./psbtv2"; +import bip375Vectors from "../fixtures/bip375_vectors.json"; +import { KeyType } from "src/psbtv2/types"; + +const SKIP_DESCRIPTIONS = new Set([ + "ecdh coverage: invalid proof in PSBT_IN_SP_DLEQ field", + "ecdh coverage: invalid proof in PSBT_GLOBAL_SP_DLEQ field", +]); + +// ── Invalid vectors ──────────────────────────────────────────────────────── + +describe("BIP375 invalid vectors", () => { + test.each( + bip375Vectors.invalid.filter((v) => !SKIP_DESCRIPTIONS.has(v.description)), + )("$description", ({ psbt }) => { + expect(() => { + const p = new PsbtV2(psbt); + p.validate(); + }).toThrow(); + }); +}); + +// ── Valid vectors ────────────────────────────────────────────────────────── + +describe("BIP375 valid vectors", () => { + test.each( + bip375Vectors.valid.filter((v) => !SKIP_DESCRIPTIONS.has(v.description)), + )("$description", ({ psbt, supplementary }) => { + const p = new PsbtV2(psbt); + + expect(() => p.validate()).not.toThrow(); + + // ── Output checks ────────────────────────────────────────────────────── + + for (const output of supplementary.outputs ?? []) { + // Output script + if (output.script) { + expect( + p.PSBT_OUT_SCRIPT[output.output_index], + `output ${output.output_index} script`, + ).toBe(output.script); + } + + // SP V0 info (bscan || bspend): only check unlabeled outputs. + // For labeled outputs, the supplementary bspend is the label-tweaked key + // (B_spend + label·G), but PSBT_OUT_SP_V0_INFO stores the raw bspend. + // The label relationship is verified separately via PSBT_OUT_SP_V0_LABEL. + const hasLabel = "sp_v0_label" in output && output.sp_v0_label !== null; + if (output.sp_v0_info && !hasLabel) { + const info = p.getSilentPaymentOutputInfo(output.output_index); + expect(info, `output ${output.output_index} sp_v0_info`).not.toBeNull(); + const combined = + info!.bscan.toString("hex") + info!.bspend.toString("hex"); + expect(combined, `output ${output.output_index} sp_v0_info`).toBe( + output.sp_v0_info, + ); + } + + // SP V0 label + if (hasLabel) { + expect( + p.PSBT_OUT_SP_V0_LABEL[output.output_index], + `output ${output.output_index} sp_v0_label`, + ).toBe(output.sp_v0_label); + } + } + + // ── Input / proof checks ─────────────────────────────────────────────── + + for (const proof of supplementary.sp_proofs ?? []) { + const isGlobal = + proof.input_index === undefined || proof.input_index === null; + + if (isGlobal) { + if (proof.ecdh_share) { + const entry = p.PSBT_GLOBAL_SP_ECDH_SHARE.find( + (s) => s.key === KeyType.PSBT_GLOBAL_SP_ECDH_SHARE + proof.scan_key, + ); + expect( + entry?.value, + `global ECDH share for scan key ${proof.scan_key}`, + ).toBe(proof.ecdh_share); + } + if (proof.dleq_proof) { + const entry = p.PSBT_GLOBAL_SP_DLEQ.find( + (s) => s.key === KeyType.PSBT_GLOBAL_SP_DLEQ + proof.scan_key, + ); + expect( + entry?.value, + `global DLEQ proof for scan key ${proof.scan_key}`, + ).toBe(proof.dleq_proof); + } + } else { + if (proof.ecdh_share) { + const entry = p.PSBT_IN_SP_ECDH_SHARE[proof.input_index].find( + (s) => s.key === KeyType.PSBT_IN_SP_ECDH_SHARE + proof.scan_key, + ); + expect( + entry?.value, + `input ${proof.input_index} ECDH share for scan key ${proof.scan_key}`, + ).toBe(proof.ecdh_share); + } + if (proof.dleq_proof) { + const entry = p.PSBT_IN_SP_DLEQ[proof.input_index].find( + (s) => s.key === KeyType.PSBT_IN_SP_DLEQ + proof.scan_key, + ); + expect( + entry?.value, + `input ${proof.input_index} DLEQ proof for scan key ${proof.scan_key}`, + ).toBe(proof.dleq_proof); + } + } + } + }); +}); diff --git a/packages/caravan-psbt/src/psbtv2/psbtv2.test.ts b/packages/caravan-psbt/src/psbtv2/psbtv2.test.ts index 08a65cb97c..5218304468 100644 --- a/packages/caravan-psbt/src/psbtv2/psbtv2.test.ts +++ b/packages/caravan-psbt/src/psbtv2/psbtv2.test.ts @@ -2325,11 +2325,7 @@ describe("PsbtV2.combine", () => { // Stub handleSighashType so addPartialSig doesn't throw on sighash // validation. thisPsbt.handleSighashType = vi.fn(); - thisPsbt.addPartialSig( - 0, - Buffer.from([0x01]), - Buffer.from([0x02]), - ); + thisPsbt.addPartialSig(0, Buffer.from([0x01]), Buffer.from([0x02])); } return { thisPsbt, otherPsbt }; From 8f0df4bab6d2b2a530a6ddaee5b00cf5dd19e301 Mon Sep 17 00:00:00 2001 From: Jasper van Gelder Date: Mon, 30 Mar 2026 12:55:58 +0200 Subject: [PATCH 07/26] chore(psbtv2): Add validation --- packages/caravan-psbt/src/psbtv2/psbtv2.ts | 377 +++++++++++++++++- .../caravan-psbt/src/psbtv2/silentpayment.ts | 77 ++++ 2 files changed, 439 insertions(+), 15 deletions(-) diff --git a/packages/caravan-psbt/src/psbtv2/psbtv2.ts b/packages/caravan-psbt/src/psbtv2/psbtv2.ts index 18c47f3933..2d00d8cc89 100644 --- a/packages/caravan-psbt/src/psbtv2/psbtv2.ts +++ b/packages/caravan-psbt/src/psbtv2/psbtv2.ts @@ -1,6 +1,6 @@ import { secp256k1 } from "@noble/curves/secp256k1"; import { BufferReader, BufferWriter } from "bufio"; -import { Psbt } from "bitcoinjs-lib-v6"; +import { Psbt, script } from "bitcoinjs-lib-v6"; import { Key, @@ -20,6 +20,11 @@ import { import { PsbtConversionMaps, PsbtV2Maps } from "./psbtv2maps"; import { bufferize } from "../functions"; import { + assertValidBscan, + assertValidDLEQProof, + assertValidECDHShare, + assertValidKLabel, + assertValidSPV0Info, computeInputHash, deriveSilentPaymentOutput, eligibleIndices, @@ -27,6 +32,9 @@ import { SPOutputEntry, sumECDHShares, } from "src/psbtv2/silentpayment"; + +const { OPS } = script; + /** * The PsbtV2 class is intended to represent an easily modifiable and * serializable psbt of version 2 conforming to BIP0174. Getters exist for all @@ -826,6 +834,332 @@ export class PsbtV2 extends PsbtV2Maps { throw Error("PsbtV2 input hight locktime is gte 500000000."); } } + this.validateSilentPayments(); + } + + /** + * Validates all BIP375 silent payment constraints. + * + * Three phases: + * 1. Output map structural checks — always run + * 2. Input eligibility checks — only when SP outputs present + * 3. ECDH coverage checks — only when SP outputs have PSBT_OUT_SCRIPT set + */ + private validateSilentPayments() { + // ── Output map structural checks ─────────────────────────────────────── + for (const [i, outputMap] of this.outputMaps.entries()) { + const spInfo = outputMap.get(KeyType.PSBT_OUT_SP_V0_INFO); + const spLabel = outputMap.get(KeyType.PSBT_OUT_SP_V0_LABEL); + const script = outputMap.get(KeyType.PSBT_OUT_SCRIPT); + + if (spLabel && !spInfo) { + throw Error( + `PsbtV2 output ${i} has PSBT_OUT_SP_V0_LABEL but no PSBT_OUT_SP_V0_INFO.`, + ); + } + if (spInfo) { + assertValidSPV0Info(spInfo, i); + } + if (!spInfo && !script) { + throw Error( + `PsbtV2 output ${i} is missing PSBT_OUT_SCRIPT and has no ` + + "PSBT_OUT_SP_V0_INFO. An output must have one or both per BIP375.", + ); + } + if (spInfo && script && script.length > 0) { + if (this.PSBT_GLOBAL_TX_MODIFIABLE.length > 0) { + throw Error( + "PSBT_OUT_SCRIPT set for silent payment output but PSBT_GLOBAL_TX_MODIFIABLE is not zeroed.", + ); + } + } + } + + // ── Global map: byte length + pairing checks ─────────────────────────── + for (const [key, value] of this.globalMap.entries()) { + if (key.startsWith(KeyType.PSBT_GLOBAL_SP_ECDH_SHARE)) { + assertValidECDHShare(value); + const scanKey = key.slice(2); + if (!this.globalMap.has(KeyType.PSBT_GLOBAL_SP_DLEQ + scanKey)) { + throw Error( + `Global ECDH share missing PSBT_GLOBAL_SP_DLEQ for scan key ${scanKey}.`, + ); + } + } + if (key.startsWith(KeyType.PSBT_GLOBAL_SP_DLEQ)) { + assertValidDLEQProof(value); + const scanKey = key.slice(2); + if (!this.globalMap.has(KeyType.PSBT_GLOBAL_SP_ECDH_SHARE + scanKey)) { + throw Error( + `Global DLEQ proof missing PSBT_GLOBAL_SP_ECDH_SHARE for scan key ${scanKey}.`, + ); + } + } + } + + // ── Input map: byte length + pairing checks ──────────────────────────── + for (const [i, inputMap] of this.inputMaps.entries()) { + for (const [key, value] of inputMap.entries()) { + if (key.startsWith(KeyType.PSBT_IN_SP_ECDH_SHARE)) { + assertValidECDHShare(value); + const scanKey = key.slice(2); + if (!inputMap.has(KeyType.PSBT_IN_SP_DLEQ + scanKey)) { + throw Error( + `Input ${i} ECDH share missing PSBT_IN_SP_DLEQ for scan key ${scanKey}.`, + ); + } + } + if (key.startsWith(KeyType.PSBT_IN_SP_DLEQ)) { + assertValidDLEQProof(value); + const scanKey = key.slice(2); + if (!inputMap.has(KeyType.PSBT_IN_SP_ECDH_SHARE + scanKey)) { + throw Error( + `Input ${i} DLEQ proof missing PSBT_IN_SP_ECDH_SHARE for scan key ${scanKey}.`, + ); + } + } + } + } + + // ── Sighash restriction when SP outputs exist ────────────────────────── + if (this.hasSilentPaymentOutputs) { + for (const [i, inputMap] of this.inputMaps.entries()) { + const sighash = inputMap.get(KeyType.PSBT_IN_SIGHASH_TYPE); + if (sighash && sighash.length >= 4) { + const sighashType = sighash.readUInt32LE(0); + if (sighashType !== SighashType.SIGHASH_ALL) { + throw Error( + `PsbtV2 input ${i} uses non-SIGHASH_ALL (${sighashType}) with silent payments.`, + ); + } + } + } + } + + // ── Output script correctness (only when scripts are already set) ────── + const hasComputedSPOutputs = this.outputMaps.some((map) => { + const spInfo = map.get(KeyType.PSBT_OUT_SP_V0_INFO); + const script = map.get(KeyType.PSBT_OUT_SCRIPT); + return !!spInfo && !!script && script.length > 0; + }); + + if (!hasComputedSPOutputs) return; + + const eligible = this.getEligibleInputsForSilentPayments(); + + // ── Eligibility and coverage checks ───────────────────────────────────── + // These run whenever scripts are set and throw on violations. + + if (eligible.length === 0) { + throw Error( + "No eligible inputs for silent payment ECDH derivation — " + + "all inputs are ineligible.", + ); + } + + for (const i of eligible) { + const witnessUtxo = this.inputMaps[i].get(KeyType.PSBT_IN_WITNESS_UTXO); + if (witnessUtxo) { + const scriptLen = witnessUtxo[8]; + const inputScript = witnessUtxo.slice(9, 9 + scriptLen); + if (inputScript[0] >= OPS.OP_2 && inputScript[0] <= OPS.OP_16) { + throw Error( + `PsbtV2 input ${i} has a segwit version > 1 alongside silent payment outputs.`, + ); + } + } + } + + // Collect scan keys from computed SP outputs + const spScanKeys = new Set(); + for (const map of this.outputMaps) { + const spInfo = map.get(KeyType.PSBT_OUT_SP_V0_INFO); + const script = map.get(KeyType.PSBT_OUT_SCRIPT); + if (spInfo && script && script.length > 0) { + spScanKeys.add(spInfo.slice(0, 33).toString("hex")); + } + } + + const globalShareKeys = new Set( + this.PSBT_GLOBAL_SP_ECDH_SHARE.map((e) => e.key.slice(2)), + ); + + for (const bscanHex of spScanKeys) { + if (globalShareKeys.has(bscanHex)) continue; + for (const i of eligible) { + const witnessUtxo = this.inputMaps[i].get(KeyType.PSBT_IN_WITNESS_UTXO); + if (!witnessUtxo) continue; + + const scriptLen = witnessUtxo[8]; + const inputScript = witnessUtxo.subarray(9, 9 + scriptLen); + + if (inputScript[0] === 0x51 && inputScript.length === 34) { + const tapKey = this.inputMaps[i].get( + KeyType.PSBT_IN_TAP_INTERNAL_KEY, + ); + const isNums = + tapKey?.toString("hex") === + "50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0"; + // NUMS P2TR must NOT have a share + if ( + isNums && + this.inputMaps[i].has(KeyType.PSBT_IN_SP_ECDH_SHARE + bscanHex) + ) { + throw Error( + `Input ${i}: NUMS P2TR input must not have PSBT_IN_SP_ECDH_SHARE`, + ); + } + if (isNums) continue; + // Non-NUMS P2TR must have a share + if ( + !this.inputMaps[i].has(KeyType.PSBT_IN_SP_ECDH_SHARE + bscanHex) + ) { + throw Error( + `Output script set but eligible input ${i} missing ECDH share`, + ); + } + if (!this.inputMaps[i].has(KeyType.PSBT_IN_SP_DLEQ + bscanHex)) { + throw Error( + `Input ${i} ECDH share missing PSBT_IN_SP_DLEQ for scan key ${bscanHex}`, + ); + } + } else if (inputScript[0] === 0x00 && inputScript.length === 22) { + // P2WPKH must have a share + if ( + !this.inputMaps[i].has(KeyType.PSBT_IN_SP_ECDH_SHARE + bscanHex) + ) { + throw Error( + `Output script set but eligible input ${i} missing ECDH share`, + ); + } + if (!this.inputMaps[i].has(KeyType.PSBT_IN_SP_DLEQ + bscanHex)) { + throw Error( + `Input ${i} ECDH share missing PSBT_IN_SP_DLEQ for scan key ${bscanHex}`, + ); + } + if (this.PSBT_IN_BIP32_DERIVATION[i].length === 0) { + throw Error( + `Input ${i}: PSBT_IN_SP_DLEQ is set but PSBT_IN_BIP32_DERIVATION is missing.`, + ); + } + } + // P2SH and other scripts — share optional, skip + } + } + + // ── Script verification ────────────────────────────────────────────────── + // Per BIP375 reference validate_output_scripts: + // outpoints = ALL inputs (reference collects before eligibility check) + // pubkeys = eligible inputs with witnessUtxo and extractable pubkeys + // ecdh shares = eligible inputs with a share for this scan key + const outpoints: Buffer[] = []; + for (let i = 0; i < this.inputMaps.length; i++) { + const txid = this.inputMaps[i].get(KeyType.PSBT_IN_PREVIOUS_TXID); + const vout = this.inputMaps[i].get(KeyType.PSBT_IN_OUTPUT_INDEX); + if (txid && vout) outpoints.push(Buffer.concat([txid, vout])); + } + + let combinedPubkey: ProjectivePoint | null = null; + + for (const i of eligible) { + const witnessUtxo = this.inputMaps[i].get(KeyType.PSBT_IN_WITNESS_UTXO); + let pubkeyBytes: Buffer | null = null; + + if (!witnessUtxo) { + // P2PKH — no witnessUtxo, pubkey from BIP32 derivation + const entries = this.PSBT_IN_BIP32_DERIVATION[i]; + if (entries.length > 0) + pubkeyBytes = Buffer.from(entries[0].key.slice(2), "hex"); + } else { + const sLen = witnessUtxo[8]; + const iScript = witnessUtxo.subarray(9, 9 + sLen); + + if (iScript[0] === 0x51 && iScript.length === 34) { + // P2TR — use tap internal key, prefixed 0x02 (even y per BIP352) + const tapKey = this.inputMaps[i].get( + KeyType.PSBT_IN_TAP_INTERNAL_KEY, + ); + const NUMS_H = + "50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0"; + const isNums = tapKey?.toString("hex") === NUMS_H; + if (!isNums && tapKey) + pubkeyBytes = Buffer.concat([Buffer.from([0x02]), tapKey]); + } else { + // P2WPKH, P2SH, others — pubkey from BIP32 derivation + const entries = this.PSBT_IN_BIP32_DERIVATION[i]; + if (entries.length > 0) + pubkeyBytes = Buffer.from(entries[0].key.slice(2), "hex"); + } + } + + if (!pubkeyBytes) continue; + const point = secp256k1.ProjectivePoint.fromHex(pubkeyBytes); + combinedPubkey = combinedPubkey ? combinedPubkey.add(point) : point; + } + + if (!combinedPubkey || outpoints.length === 0) return; + + const inputHash = computeInputHash( + outpoints, + Buffer.from(combinedPubkey.toRawBytes(true)), + ); + + const scanKeyKValues = new Map(); + + for ( + let outputIndex = 0; + outputIndex < this.outputMaps.length; + outputIndex++ + ) { + const map = this.outputMaps[outputIndex]; + const spInfo = map.get(KeyType.PSBT_OUT_SP_V0_INFO); + const actualScript = map.get(KeyType.PSBT_OUT_SCRIPT); + if (!spInfo || !actualScript || actualScript.length === 0) continue; + assertValidSPV0Info(spInfo, outputIndex); + + const bscanHex = spInfo.subarray(0, 33).toString("hex"); + const bspend = spInfo.subarray(33, 66); + const k = scanKeyKValues.get(bscanHex) ?? 0; + assertValidKLabel(k, outputIndex); + const globalShareKey = KeyType.PSBT_GLOBAL_SP_ECDH_SHARE + bscanHex; + let ecdhShare: Buffer; + + if (this.globalMap.has(globalShareKey)) { + ecdhShare = this.globalMap.get(globalShareKey) as Buffer; + } else { + // Collect shares from eligible inputs only — P2SH is ineligible per + // BIP352 so its share must be excluded even if present in the PSBT. + const perInputBuffers: Buffer[] = []; + for (const j of eligible) { + const val = this.inputMaps[j].get( + KeyType.PSBT_IN_SP_ECDH_SHARE + bscanHex, + ); + if (val) perInputBuffers.push(val); + } + if (perInputBuffers.length === 0) { + scanKeyKValues.set(bscanHex, k + 1); + continue; + } + ecdhShare = Buffer.from( + sumECDHShares(perInputBuffers).toRawBytes(true), + ); + } + + const expectedScript = deriveSilentPaymentOutput( + ecdhShare, + inputHash, + bspend, + k, + ); + + if (!actualScript.equals(expectedScript)) { + throw Error( + `PsbtV2 output ${outputIndex} PSBT_OUT_SCRIPT does not match silent payment derivation.`, + ); + } + + scanKeyKValues.set(bscanHex, k + 1); + } } /** @@ -1886,24 +2220,37 @@ export class PsbtV2 extends PsbtV2Maps { for (const i of eligible) { const witnessUtxo = this.inputMaps[i].get(KeyType.PSBT_IN_WITNESS_UTXO); - if (!witnessUtxo) continue; - - const scriptLen = witnessUtxo[8]; - const inputScript = witnessUtxo.slice(9, 9 + scriptLen); let pubkeyBytes: Buffer | null = null; - if (inputScript[0] === 0x51 && inputScript.length === 34) { - // P2TR — use tap internal key, prefixed with 0x02 (even y per BIP352) - const tapKey = this.inputMaps[i].get(KeyType.PSBT_IN_TAP_INTERNAL_KEY); - if (tapKey) { - pubkeyBytes = Buffer.concat([Buffer.from([0x02]), tapKey]); - } - } else if (inputScript[0] === 0x00 && inputScript.length === 22) { - // P2WPKH — pubkey from BIP32 derivation field - // key format: keytype(1) || pubkey(33) — strip keytype byte + if (!witnessUtxo) { + // P2PKH — no witnessUtxo, pubkey from BIP32 derivation const entries = this.PSBT_IN_BIP32_DERIVATION[i]; - if (entries.length > 0) { + if (entries.length > 0) pubkeyBytes = Buffer.from(entries[0].key.slice(2), "hex"); + } else { + const scriptLen = witnessUtxo[8]; + const inputScript = witnessUtxo.slice(9, 9 + scriptLen); + + if (inputScript[0] === 0x51 && inputScript.length === 34) { + // P2TR — use tap internal key, prefixed with 0x02 (even y per BIP352) + const tapKey = this.inputMaps[i].get( + KeyType.PSBT_IN_TAP_INTERNAL_KEY, + ); + if (tapKey) { + pubkeyBytes = Buffer.concat([Buffer.from([0x02]), tapKey]); + } + } else if (inputScript[0] === 0x00 && inputScript.length === 22) { + // P2WPKH — pubkey from BIP32 derivation field + // key format: keytype(1) || pubkey(33) — strip keytype byte + const entries = this.PSBT_IN_BIP32_DERIVATION[i]; + if (entries.length > 0) { + pubkeyBytes = Buffer.from(entries[0].key.slice(2), "hex"); + } + } else { + // P2SH — pubkey from BIP32 derivation + const entries = this.PSBT_IN_BIP32_DERIVATION[i]; + if (entries.length > 0) + pubkeyBytes = Buffer.from(entries[0].key.slice(2), "hex"); } } diff --git a/packages/caravan-psbt/src/psbtv2/silentpayment.ts b/packages/caravan-psbt/src/psbtv2/silentpayment.ts index 55a84664a3..6551050dff 100644 --- a/packages/caravan-psbt/src/psbtv2/silentpayment.ts +++ b/packages/caravan-psbt/src/psbtv2/silentpayment.ts @@ -13,8 +13,11 @@ import { createHash } from "crypto"; import { script } from "bitcoinjs-lib-v6"; import { xOnlyPointAddTweak } from "src/noble-ecc"; +const CURVE_ORDER = secp256k1.CURVE.n; const { OPS } = script; +// ── Internal types ───────────────────────────────────────────────────────── + export type ProjectivePoint = InstanceType; // ── Public types ─────────────────────────────────────────────────────────── @@ -46,6 +49,80 @@ export interface SPInputDescriptor { witnessUtxo: Buffer | null; } +// ── Field validators ─────────────────────────────────────────────────────── +// Called from both field setters in PsbtV2 and validateSilentPayments(). + +/** + * Asserts that a scan public key is a valid 33-byte compressed point. + * + * @param bscan - Candidate scan public key buffer. + * @throws {Error} If `bscan` is not exactly 33 bytes. + */ +export function assertValidBscan(bscan: Buffer): void { + if (bscan.length !== 33) { + throw new Error( + `bscan must be a 33-byte compressed pubkey, got ${bscan.length}`, + ); + } +} + +/** + * Asserts that an ECDH share is a valid 33-byte compressed EC point. + * + * @param share - Candidate ECDH share buffer. + * @throws {Error} If `share` is not exactly 33 bytes. + */ +export function assertValidECDHShare(share: Buffer): void { + if (share.length !== 33) { + throw new Error( + `ECDH share must be a 33-byte compressed EC point, got ${share.length}`, + ); + } +} + +/** + * Asserts that a DLEQ proof is exactly 64 bytes. + * + * @param proof - Candidate DLEQ proof buffer. + * @throws {Error} If `proof` is not exactly 64 bytes. + */ +export function assertValidDLEQProof(proof: Buffer): void { + if (proof.length !== 64) { + throw new Error(`DLEQ proof must be 64 bytes, got ${proof.length}`); + } +} + +/** + * Asserts that a `PSBT_OUT_SP_V0_INFO` value is exactly 66 bytes + * (`bscan(33) || bspend(33)`). + * + * @param raw - Candidate SP V0 info buffer. + * @param outputIndex - Output index for error context. + * @throws {Error} If `raw` is not exactly 66 bytes. + */ +export function assertValidSPV0Info(raw: Buffer, outputIndex: number): void { + if (raw.length !== 66) { + throw new Error( + `PSBT_OUT_SP_V0_INFO at output ${outputIndex}: ` + + `expected 66 bytes, got ${raw.length}`, + ); + } +} + +export function assertValidKLabel(k: number, outputIndex: number): void { + if (!Number.isInteger(k) || k < 0 || k > 0xffffffff) { + throw new Error( + `Silent payment recipient index k is invalid at output ${outputIndex}: ${k}`, + ); + } +} + +function assertValidScalar(value: bigint, name: string): void { + if (value === 0n || value >= CURVE_ORDER) { + throw new Error(`${name} is not a valid secp256k1 scalar`); + } +} + // ── Tagged hash ──────────────────────────────────────────────────────────── /** From 0e57be027162b31570c34fba87794ddb2a635b44 Mon Sep 17 00:00:00 2001 From: Jasper van Gelder Date: Mon, 30 Mar 2026 15:19:42 +0200 Subject: [PATCH 08/26] fix(psbtv2): correct silent payment output derivation - validate SegWit version range - use full compressed spend keys in derivation - enforce BIP352 scalar validity checks --- .../caravan-psbt/src/psbtv2/silentpayment.ts | 48 +++++++++---------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/packages/caravan-psbt/src/psbtv2/silentpayment.ts b/packages/caravan-psbt/src/psbtv2/silentpayment.ts index 6551050dff..85d695ecd5 100644 --- a/packages/caravan-psbt/src/psbtv2/silentpayment.ts +++ b/packages/caravan-psbt/src/psbtv2/silentpayment.ts @@ -8,12 +8,12 @@ * @see {@link https://github.com/bitcoin/bips/blob/master/bip-0375.mediawiki BIP375} */ -import { secp256k1 } from "@noble/curves/secp256k1"; +import { secp256k1, schnorr } from "@noble/curves/secp256k1"; import { createHash } from "crypto"; import { script } from "bitcoinjs-lib-v6"; -import { xOnlyPointAddTweak } from "src/noble-ecc"; const CURVE_ORDER = secp256k1.CURVE.n; +const { bytesToNumberBE } = schnorr.utils; const { OPS } = script; // ── Internal types ───────────────────────────────────────────────────────── @@ -191,8 +191,8 @@ export function eligibleIndices(inputs: SPInputDescriptor[]): number[] { } else if (version === OPS.OP_0 && inputScript.length === 34) { // P2WSH (OP_0 + 32-byte hash) — NOT eligible (multisig) continue; - } else if (version >= OPS.OP_2) { - // Segwit v2+ — NOT eligible per BIP375 + } else if (version >= OPS.OP_2 && version <= OPS.OP_16) { + // Segwit v2–v16 (OP_2–OP_16 range 0x52–0x60) — NOT eligible per BIP375 continue; } else { // Anything else (P2SH-P2WPKH wrapped, P2PKH) — eligible @@ -270,6 +270,9 @@ export function computeInputHash( * outputScript = OP_1 <0x20> * ``` * + * Uses full compressed point arithmetic for `Bspend` to correctly handle + * both even-y (0x02) and odd-y (0x03) spend keys. + * * @param ecdhShare - 33-byte compressed EC point `C = a·Bscan`, where `a` is * the sum of eligible input private keys (global share) or a single input's * private key (per-input share). @@ -279,7 +282,6 @@ export function computeInputHash( * @param k - Zero-based recipient index within the scan-key group. Increments * for each recipient sharing the same `Bscan`. * @returns 34-byte P2TR output script: `OP_1 <0x20> <32-byte x-only pubkey>`. - * @throws {Error} If the tweak produces an invalid point. */ export function deriveSilentPaymentOutput( ecdhShare: Buffer, @@ -287,12 +289,13 @@ export function deriveSilentPaymentOutput( bspend: Buffer, k: number, ): Buffer { + const inputScalar = bytesToNumberBE(inputHash); + assertValidScalar(inputScalar, "Silent payment input hash"); + // ecdhSecret = inputHash · ecdhShare - // Fn.fromBytes handles modular reduction internally — no manual BigInt needed. - const inputHashScalar = secp256k1.ProjectivePoint.Fn.fromBytes(inputHash); const ecdhSecretPoint = - secp256k1.ProjectivePoint.fromHex(ecdhShare).multiply(inputHashScalar); - const ecdhSecretBytes = Buffer.from(ecdhSecretPoint.toRawBytes(true)); + secp256k1.ProjectivePoint.fromHex(ecdhShare).multiply(inputScalar); + const ecdhSecretBytes = ecdhSecretPoint.toRawBytes(true); // tweak_k = taggedHash("BIP0352/SharedSecret", ecdhSecret_compressed || k_be32) const kBuf = Buffer.allocUnsafe(4); @@ -302,22 +305,15 @@ export function deriveSilentPaymentOutput( Buffer.concat([ecdhSecretBytes, kBuf]), ); - // Pk = Bspend + tweak·G - // xOnlyPointAddTweak expects an x-only (32-byte) pubkey — strip the 02/03 prefix. - // It is already tested against BIP341 vectors in noble-ecc.test.ts. - const bspendXOnly = bspend.slice(1); - const tweakResult = xOnlyPointAddTweak(bspendXOnly, tweak); - if (!tweakResult) { - throw new Error( - "Silent payment output derivation failed: invalid tweak result.", - ); - } + const tweakScalar = bytesToNumberBE(tweak); + assertValidScalar(tweakScalar, "Silent payment shared-secret tweak"); + + // Pk = Bspend + tweak_k·G + const Pk = secp256k1.ProjectivePoint.fromHex(bspend).add( + secp256k1.ProjectivePoint.BASE.multiply(tweakScalar), + ); - // P2TR output script: OP_1 - // THIRTY_TWO_BYTE_PUSH_LENGTH is a raw data push length, not an opcode. - const THIRTY_TWO_BYTE_PUSH_LENGTH = 0x20; - return Buffer.concat([ - Buffer.from([OPS.OP_1, THIRTY_TWO_BYTE_PUSH_LENGTH]), - Buffer.from(tweakResult.xOnlyPubkey), - ]); + // P2TR output script: OP_1 <0x20> + const xOnlyPk = Pk.toRawBytes(true).subarray(1); + return Buffer.concat([Buffer.from([OPS.OP_1, 0x20]), xOnlyPk]); } From 23cff6875e5344bd2849056d5528e75695765d79 Mon Sep 17 00:00:00 2001 From: Jasper van Gelder Date: Mon, 30 Mar 2026 15:43:30 +0200 Subject: [PATCH 09/26] chore(psbtv2): Replace checks with assert calls Instead of having multiple places where we define checks call the proper assert functions. Also added a missing Bspend check. --- packages/caravan-psbt/src/psbtv2/psbtv2.ts | 17 ++++------------- .../caravan-psbt/src/psbtv2/silentpayment.ts | 14 ++++++++++++++ 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/packages/caravan-psbt/src/psbtv2/psbtv2.ts b/packages/caravan-psbt/src/psbtv2/psbtv2.ts index 2d00d8cc89..19bd15ac00 100644 --- a/packages/caravan-psbt/src/psbtv2/psbtv2.ts +++ b/packages/caravan-psbt/src/psbtv2/psbtv2.ts @@ -21,6 +21,7 @@ import { PsbtConversionMaps, PsbtV2Maps } from "./psbtv2maps"; import { bufferize } from "../functions"; import { assertValidBscan, + assertValidBspend, assertValidDLEQProof, assertValidECDHShare, assertValidKLabel, @@ -1732,16 +1733,8 @@ export class PsbtV2 extends PsbtV2Maps { `outputIndex ${outputIndex} out of range (${this.outputMaps.length} outputs)`, ); } - if (bscan.length !== 33) { - throw new Error( - `bscan must be a 33-byte compressed pubkey, got ${bscan.length}`, - ); - } - if (bspend.length !== 33) { - throw new Error( - `bspend must be a 33-byte compressed pubkey, got ${bspend.length}`, - ); - } + assertValidBscan(bscan); + assertValidBspend(bspend); const bw = new BufferWriter(); bw.writeBytes(bscan); bw.writeBytes(bspend); @@ -1759,9 +1752,7 @@ export class PsbtV2 extends PsbtV2Maps { `Output ${outputIndex} has no SP info. Call addOutputSPInfo first.`, ); } - if (!Number.isInteger(label) || label < 0 || label > 0xffffffff) { - throw new Error(`label must be a uint32 (0–${0xffffffff}), got ${label}`); - } + assertValidKLabel(label, outputIndex); const bw = new BufferWriter(); bw.writeU32(label); this.outputMaps[outputIndex].set(KeyType.PSBT_OUT_SP_V0_LABEL, bw.render()); diff --git a/packages/caravan-psbt/src/psbtv2/silentpayment.ts b/packages/caravan-psbt/src/psbtv2/silentpayment.ts index 85d695ecd5..40fe73946c 100644 --- a/packages/caravan-psbt/src/psbtv2/silentpayment.ts +++ b/packages/caravan-psbt/src/psbtv2/silentpayment.ts @@ -66,6 +66,20 @@ export function assertValidBscan(bscan: Buffer): void { } } +/** + * Asserts that a scan public key is a valid 33-byte compressed point. + * + * @param bspend - Candidate scan public key buffer. + * @throws {Error} If `bscan` is not exactly 33 bytes. + */ +export function assertValidBspend(bspend: Buffer): void { + if (bspend.length !== 33) { + throw new Error( + `bspend must be a 33-byte compressed pubkey, got ${bspend.length}`, + ); + } +} + /** * Asserts that an ECDH share is a valid 33-byte compressed EC point. * From ea819775f31771c34e4e81ee9ac40c9468fa1845 Mon Sep 17 00:00:00 2001 From: Jasper van Gelder Date: Tue, 31 Mar 2026 11:42:53 +0200 Subject: [PATCH 10/26] chore(psbtv2): Proper label and k checking Our assert was contained the wrong message (mentioned k instead of m). Also added a separate assert for 0 < k < Kmax (2323) output index check. --- packages/caravan-psbt/src/psbtv2/psbtv2.ts | 8 +++++--- .../caravan-psbt/src/psbtv2/silentpayment.ts | 18 +++++++++++++----- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/packages/caravan-psbt/src/psbtv2/psbtv2.ts b/packages/caravan-psbt/src/psbtv2/psbtv2.ts index 19bd15ac00..efebd6bb8d 100644 --- a/packages/caravan-psbt/src/psbtv2/psbtv2.ts +++ b/packages/caravan-psbt/src/psbtv2/psbtv2.ts @@ -24,7 +24,8 @@ import { assertValidBspend, assertValidDLEQProof, assertValidECDHShare, - assertValidKLabel, + assertValidLabel, + assertValidOutputK, assertValidSPV0Info, computeInputHash, deriveSilentPaymentOutput, @@ -1121,7 +1122,7 @@ export class PsbtV2 extends PsbtV2Maps { const bscanHex = spInfo.subarray(0, 33).toString("hex"); const bspend = spInfo.subarray(33, 66); const k = scanKeyKValues.get(bscanHex) ?? 0; - assertValidKLabel(k, outputIndex); + assertValidOutputK(k, outputIndex); const globalShareKey = KeyType.PSBT_GLOBAL_SP_ECDH_SHARE + bscanHex; let ecdhShare: Buffer; @@ -1752,7 +1753,7 @@ export class PsbtV2 extends PsbtV2Maps { `Output ${outputIndex} has no SP info. Call addOutputSPInfo first.`, ); } - assertValidKLabel(label, outputIndex); + assertValidLabel(label, outputIndex); const bw = new BufferWriter(); bw.writeU32(label); this.outputMaps[outputIndex].set(KeyType.PSBT_OUT_SP_V0_LABEL, bw.render()); @@ -2304,6 +2305,7 @@ export class PsbtV2 extends PsbtV2Maps { for (let k = 0; k < group.length; k++) { const { outputIndex, bspend } = group[k]; + assertValidOutputK(k, outputIndex); const script = deriveSilentPaymentOutput( ecdhShare, inputHash, diff --git a/packages/caravan-psbt/src/psbtv2/silentpayment.ts b/packages/caravan-psbt/src/psbtv2/silentpayment.ts index 40fe73946c..8ddeba6133 100644 --- a/packages/caravan-psbt/src/psbtv2/silentpayment.ts +++ b/packages/caravan-psbt/src/psbtv2/silentpayment.ts @@ -67,10 +67,10 @@ export function assertValidBscan(bscan: Buffer): void { } /** - * Asserts that a scan public key is a valid 33-byte compressed point. + * Asserts that a spend public key is a valid 33-byte compressed point. * * @param bspend - Candidate scan public key buffer. - * @throws {Error} If `bscan` is not exactly 33 bytes. + * @throws {Error} If `bspend` is not exactly 33 bytes. */ export function assertValidBspend(bspend: Buffer): void { if (bspend.length !== 33) { @@ -123,10 +123,18 @@ export function assertValidSPV0Info(raw: Buffer, outputIndex: number): void { } } -export function assertValidKLabel(k: number, outputIndex: number): void { - if (!Number.isInteger(k) || k < 0 || k > 0xffffffff) { +export function assertValidLabel(m: number, outputIndex: number): void { + if (!Number.isInteger(m) || m < 0 || m > 0xffffffff) { + throw new Error( + `Silent payment label m is invalid at output ${outputIndex}: ${m}`, + ); + } +} + +export function assertValidOutputK(k: number, outputIndex: number): void { + if (!Number.isInteger(k) || k < 0 || k > 2323) { throw new Error( - `Silent payment recipient index k is invalid at output ${outputIndex}: ${k}`, + `Silent payment recipient index should be 0 < k < 2323 (Kmax) but was at output ${outputIndex}: ${k}`, ); } } From 1408cc29e4989ac790e08ef979bef1305b217362 Mon Sep 17 00:00:00 2001 From: Jasper van Gelder Date: Wed, 20 May 2026 12:01:40 +0200 Subject: [PATCH 11/26] fix(caravan-psbt): harden BIP375 silent payment validation --- packages/caravan-psbt/src/psbtv2/psbtv2.ts | 763 ++++++++++-------- .../caravan-psbt/src/psbtv2/psbtv2maps.ts | 16 +- .../caravan-psbt/src/psbtv2/silentpayment.ts | 246 ++++-- 3 files changed, 657 insertions(+), 368 deletions(-) diff --git a/packages/caravan-psbt/src/psbtv2/psbtv2.ts b/packages/caravan-psbt/src/psbtv2/psbtv2.ts index efebd6bb8d..dcee1efd93 100644 --- a/packages/caravan-psbt/src/psbtv2/psbtv2.ts +++ b/packages/caravan-psbt/src/psbtv2/psbtv2.ts @@ -1,6 +1,6 @@ import { secp256k1 } from "@noble/curves/secp256k1"; import { BufferReader, BufferWriter } from "bufio"; -import { Psbt, script } from "bitcoinjs-lib-v6"; +import { Psbt } from "bitcoinjs-lib-v6"; import { Key, @@ -27,16 +27,20 @@ import { assertValidLabel, assertValidOutputK, assertValidSPV0Info, + scanKeyHexFromBIP375Key, computeInputHash, deriveSilentPaymentOutput, eligibleIndices, + getTaprootOutputKeyFromWitnessUtxo, + groupSilentPaymentOutputs, + hasSegwitV2PlusInput, + BIP352_NUMS_H, ProjectivePoint, + SPInputDescriptor, SPOutputEntry, sumECDHShares, } from "src/psbtv2/silentpayment"; -const { OPS } = script; - /** * The PsbtV2 class is intended to represent an easily modifiable and * serializable psbt of version 2 conforming to BIP0174. Getters exist for all @@ -839,6 +843,112 @@ export class PsbtV2 extends PsbtV2Maps { this.validateSilentPayments(); } + private getSilentPaymentInputDescriptors(): SPInputDescriptor[] { + return this.inputMaps.map((map) => { + const outputIndex = map.get(KeyType.PSBT_IN_OUTPUT_INDEX); + + return { + witnessUtxo: map.get(KeyType.PSBT_IN_WITNESS_UTXO) ?? null, + nonWitnessUtxo: map.get(KeyType.PSBT_IN_NON_WITNESS_UTXO) ?? null, + outputIndex: outputIndex ? outputIndex.readUInt32LE(0) : null, + redeemScript: map.get(KeyType.PSBT_IN_REDEEM_SCRIPT) ?? null, + }; + }); + } + + private getAllOutpoints(): Buffer[] { + return this.inputMaps.flatMap((map) => { + const txid = map.get(KeyType.PSBT_IN_PREVIOUS_TXID); + const vout = map.get(KeyType.PSBT_IN_OUTPUT_INDEX); + return txid && vout ? [Buffer.concat([txid, vout])] : []; + }); + } + + private getSilentPaymentOutputGroups( + onlyWithScripts = false, + skipLabeled = false, + ): Map { + const entries: SPOutputEntry[] = []; + + for (let i = 0; i < this.outputMaps.length; i++) { + const info = this.getSilentPaymentOutputInfo(i); + if (!info) continue; + + if (skipLabeled && this.outputMaps[i].has(KeyType.PSBT_OUT_SP_V0_LABEL)) { + continue; + } + + if (onlyWithScripts) { + const script = this.outputMaps[i].get(KeyType.PSBT_OUT_SCRIPT); + if (!script || script.length === 0) continue; + } + + entries.push({ outputIndex: i, ...info }); + } + + return groupSilentPaymentOutputs(entries); + } + + private getInputAggregatePubkey( + eligible: number[], + requirePubkeysForDleqVerification = false, + ): ProjectivePoint | null { + let combinedPubkey: ProjectivePoint | null = null; + + for (const i of eligible) { + if (this.hasNumsTaprootScriptPathSpend(i)) { + continue; + } + + const witnessUtxo = this.inputMaps[i].get(KeyType.PSBT_IN_WITNESS_UTXO); + let pubkeyBytes: Buffer | null = null; + + if (witnessUtxo) { + pubkeyBytes = getTaprootOutputKeyFromWitnessUtxo(witnessUtxo); + } + + if (!pubkeyBytes) { + const entries = this.PSBT_IN_BIP32_DERIVATION[i]; + if (entries.length > 0) { + pubkeyBytes = Buffer.from(entries[0].key.slice(2), "hex"); + } + } + + if (!pubkeyBytes) { + if (requirePubkeysForDleqVerification) { + throw Error( + `Input ${i} missing public key for silent payment DLEQ verification.`, + ); + } + + continue; + } + + const point = secp256k1.ProjectivePoint.fromHex(pubkeyBytes); + combinedPubkey = combinedPubkey ? combinedPubkey.add(point) : point; + } + + return combinedPubkey; + } + + private hasNumsTaprootScriptPathSpend(inputIndex: number): boolean { + const internalKey = this.PSBT_IN_TAP_INTERNAL_KEY[inputIndex]; + + if (internalKey?.toString("hex") === BIP352_NUMS_H) { + return true; + } + + return this.PSBT_IN_TAP_LEAF_SCRIPT[inputIndex].some((entry) => { + const keydata = Buffer.from(entry.key.slice(2), "hex"); + + if (keydata.length < 33) { + return false; + } + + return keydata.subarray(1, 33).toString("hex") === BIP352_NUMS_H; + }); + } + /** * Validates all BIP375 silent payment constraints. * @@ -859,15 +969,22 @@ export class PsbtV2 extends PsbtV2Maps { `PsbtV2 output ${i} has PSBT_OUT_SP_V0_LABEL but no PSBT_OUT_SP_V0_INFO.`, ); } + if (spInfo) { assertValidSPV0Info(spInfo, i); } + if (!spInfo && !script) { throw Error( `PsbtV2 output ${i} is missing PSBT_OUT_SCRIPT and has no ` + "PSBT_OUT_SP_V0_INFO. An output must have one or both per BIP375.", ); } + + if (spInfo && script && script.length === 0) { + throw Error(`PsbtV2 output ${i} has empty PSBT_OUT_SCRIPT.`); + } + if (spInfo && script && script.length > 0) { if (this.PSBT_GLOBAL_TX_MODIFIABLE.length > 0) { throw Error( @@ -877,20 +994,33 @@ export class PsbtV2 extends PsbtV2Maps { } } - // ── Global map: byte length + pairing checks ─────────────────────────── + // ── Global map: keydata/valuedata + pairing checks ──────────────────── for (const [key, value] of this.globalMap.entries()) { if (key.startsWith(KeyType.PSBT_GLOBAL_SP_ECDH_SHARE)) { + const scanKey = scanKeyHexFromBIP375Key( + key, + KeyType.PSBT_GLOBAL_SP_ECDH_SHARE, + "Global ECDH share", + ); + assertValidECDHShare(value); - const scanKey = key.slice(2); + if (!this.globalMap.has(KeyType.PSBT_GLOBAL_SP_DLEQ + scanKey)) { throw Error( `Global ECDH share missing PSBT_GLOBAL_SP_DLEQ for scan key ${scanKey}.`, ); } } + if (key.startsWith(KeyType.PSBT_GLOBAL_SP_DLEQ)) { + const scanKey = scanKeyHexFromBIP375Key( + key, + KeyType.PSBT_GLOBAL_SP_DLEQ, + "Global DLEQ proof", + ); + assertValidDLEQProof(value); - const scanKey = key.slice(2); + if (!this.globalMap.has(KeyType.PSBT_GLOBAL_SP_ECDH_SHARE + scanKey)) { throw Error( `Global DLEQ proof missing PSBT_GLOBAL_SP_ECDH_SHARE for scan key ${scanKey}.`, @@ -899,21 +1029,34 @@ export class PsbtV2 extends PsbtV2Maps { } } - // ── Input map: byte length + pairing checks ──────────────────────────── + // ── Input map: keydata/valuedata + pairing checks ───────────────────── for (const [i, inputMap] of this.inputMaps.entries()) { for (const [key, value] of inputMap.entries()) { if (key.startsWith(KeyType.PSBT_IN_SP_ECDH_SHARE)) { + const scanKey = scanKeyHexFromBIP375Key( + key, + KeyType.PSBT_IN_SP_ECDH_SHARE, + `Input ${i} ECDH share`, + ); + assertValidECDHShare(value); - const scanKey = key.slice(2); + if (!inputMap.has(KeyType.PSBT_IN_SP_DLEQ + scanKey)) { throw Error( `Input ${i} ECDH share missing PSBT_IN_SP_DLEQ for scan key ${scanKey}.`, ); } } + if (key.startsWith(KeyType.PSBT_IN_SP_DLEQ)) { + const scanKey = scanKeyHexFromBIP375Key( + key, + KeyType.PSBT_IN_SP_DLEQ, + `Input ${i} DLEQ proof`, + ); + assertValidDLEQProof(value); - const scanKey = key.slice(2); + if (!inputMap.has(KeyType.PSBT_IN_SP_ECDH_SHARE + scanKey)) { throw Error( `Input ${i} DLEQ proof missing PSBT_IN_SP_ECDH_SHARE for scan key ${scanKey}.`, @@ -923,247 +1066,286 @@ export class PsbtV2 extends PsbtV2Maps { } } - // ── Sighash restriction when SP outputs exist ────────────────────────── - if (this.hasSilentPaymentOutputs) { - for (const [i, inputMap] of this.inputMaps.entries()) { - const sighash = inputMap.get(KeyType.PSBT_IN_SIGHASH_TYPE); - if (sighash && sighash.length >= 4) { - const sighashType = sighash.readUInt32LE(0); - if (sighashType !== SighashType.SIGHASH_ALL) { - throw Error( - `PsbtV2 input ${i} uses non-SIGHASH_ALL (${sighashType}) with silent payments.`, - ); - } + if (!this.hasSilentPaymentOutputs) { + return; + } + + // ── SP-wide restrictions that apply whenever SP outputs exist ────────── + if (hasSegwitV2PlusInput(this.getSilentPaymentInputDescriptors())) { + throw Error( + "A PSBT with PSBT_OUT_SP_V0_INFO must not contain SegWit v2+ inputs.", + ); + } + + for (const [i, inputMap] of this.inputMaps.entries()) { + const sighash = inputMap.get(KeyType.PSBT_IN_SIGHASH_TYPE); + + if (sighash && sighash.length >= 4) { + const sighashType = sighash.readUInt32LE(0); + + if (sighashType !== SighashType.SIGHASH_ALL) { + throw Error( + `PsbtV2 input ${i} uses non-SIGHASH_ALL (${sighashType}) with silent payments.`, + ); } } } - // ── Output script correctness (only when scripts are already set) ────── - const hasComputedSPOutputs = this.outputMaps.some((map) => { - const spInfo = map.get(KeyType.PSBT_OUT_SP_V0_INFO); - const script = map.get(KeyType.PSBT_OUT_SCRIPT); - return !!spInfo && !!script && script.length > 0; - }); + // Only non-labeled SP outputs can be recomputed from public PSBT data. + // Labeled outputs require recipient-side label state / scan private key. + const computedSPScanKeys = new Set(); - if (!hasComputedSPOutputs) return; + for (let i = 0; i < this.outputMaps.length; i++) { + const outputMap = this.outputMaps[i]; - const eligible = this.getEligibleInputsForSilentPayments(); + if (!outputMap.has(KeyType.PSBT_OUT_SP_V0_INFO)) { + continue; + } + + if (outputMap.has(KeyType.PSBT_OUT_SP_V0_LABEL)) { + continue; + } + + const script = outputMap.get(KeyType.PSBT_OUT_SCRIPT); + + if (!script || script.length === 0) { + continue; + } - // ── Eligibility and coverage checks ───────────────────────────────────── - // These run whenever scripts are set and throw on violations. + const info = this.getSilentPaymentOutputInfo(i); + + if (info) { + computedSPScanKeys.add(info.bscan.toString("hex")); + } + } + + // No non-labeled SP output script has been computed yet. Structural checks + // above are enough for an in-progress PSBT. + if (computedSPScanKeys.size === 0) { + return; + } + + const eligible = this.getEligibleInputsForSilentPayments(); if (eligible.length === 0) { throw Error( - "No eligible inputs for silent payment ECDH derivation — " + - "all inputs are ineligible.", + "No eligible inputs for silent payment ECDH derivation — all inputs are ineligible.", ); } + // NUMS P2TR script-path inputs are skipped for SP derivation, but must not + // carry SP ECDH/DLEQ fields. for (const i of eligible) { - const witnessUtxo = this.inputMaps[i].get(KeyType.PSBT_IN_WITNESS_UTXO); - if (witnessUtxo) { - const scriptLen = witnessUtxo[8]; - const inputScript = witnessUtxo.slice(9, 9 + scriptLen); - if (inputScript[0] >= OPS.OP_2 && inputScript[0] <= OPS.OP_16) { + if (!this.hasNumsTaprootScriptPathSpend(i)) { + continue; + } + + for (const key of this.inputMaps[i].keys()) { + if ( + key.startsWith(KeyType.PSBT_IN_SP_ECDH_SHARE) || + key.startsWith(KeyType.PSBT_IN_SP_DLEQ) + ) { throw Error( - `PsbtV2 input ${i} has a segwit version > 1 alongside silent payment outputs.`, + `Input ${i}: NUMS P2TR script-path input must not have silent payment ECDH/DLEQ data.`, ); } } } - // Collect scan keys from computed SP outputs - const spScanKeys = new Set(); - for (const map of this.outputMaps) { - const spInfo = map.get(KeyType.PSBT_OUT_SP_V0_INFO); - const script = map.get(KeyType.PSBT_OUT_SCRIPT); - if (spInfo && script && script.length > 0) { - spScanKeys.add(spInfo.slice(0, 33).toString("hex")); - } - } + // ECDH coverage is required per scan key that has at least one computed, + // non-labeled SP output script. Do not require coverage for outputs that are + // still in progress. + for (const bscanHex of computedSPScanKeys) { + const globalShareKey = KeyType.PSBT_GLOBAL_SP_ECDH_SHARE + bscanHex; - const globalShareKeys = new Set( - this.PSBT_GLOBAL_SP_ECDH_SHARE.map((e) => e.key.slice(2)), - ); + if (this.globalMap.has(globalShareKey)) { + const proofKey = KeyType.PSBT_GLOBAL_SP_DLEQ + bscanHex; + const ecdhShare = this.globalMap.get(globalShareKey) as Buffer; + const proof = this.globalMap.get(proofKey); + + if (!proof) { + throw Error( + `Global ECDH share missing PSBT_GLOBAL_SP_DLEQ for scan key ${bscanHex}.`, + ); + } - for (const bscanHex of spScanKeys) { - if (globalShareKeys.has(bscanHex)) continue; - for (const i of eligible) { - const witnessUtxo = this.inputMaps[i].get(KeyType.PSBT_IN_WITNESS_UTXO); - if (!witnessUtxo) continue; + const nonNumsEligible = eligible.filter( + (i) => !this.hasNumsTaprootScriptPathSpend(i), + ); - const scriptLen = witnessUtxo[8]; - const inputScript = witnessUtxo.subarray(9, 9 + scriptLen); + const aggregatePubkey = this.getInputAggregatePubkey( + nonNumsEligible, + true, + ); - if (inputScript[0] === 0x51 && inputScript.length === 34) { - const tapKey = this.inputMaps[i].get( - KeyType.PSBT_IN_TAP_INTERNAL_KEY, + if (!aggregatePubkey) { + throw Error( + `Could not compute aggregate public key for global DLEQ verification for scan key ${bscanHex}.`, ); - const isNums = - tapKey?.toString("hex") === - "50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0"; - // NUMS P2TR must NOT have a share - if ( - isNums && - this.inputMaps[i].has(KeyType.PSBT_IN_SP_ECDH_SHARE + bscanHex) - ) { - throw Error( - `Input ${i}: NUMS P2TR input must not have PSBT_IN_SP_ECDH_SHARE`, - ); - } - if (isNums) continue; - // Non-NUMS P2TR must have a share - if ( - !this.inputMaps[i].has(KeyType.PSBT_IN_SP_ECDH_SHARE + bscanHex) - ) { - throw Error( - `Output script set but eligible input ${i} missing ECDH share`, - ); - } - if (!this.inputMaps[i].has(KeyType.PSBT_IN_SP_DLEQ + bscanHex)) { - throw Error( - `Input ${i} ECDH share missing PSBT_IN_SP_DLEQ for scan key ${bscanHex}`, - ); - } - } else if (inputScript[0] === 0x00 && inputScript.length === 22) { - // P2WPKH must have a share - if ( - !this.inputMaps[i].has(KeyType.PSBT_IN_SP_ECDH_SHARE + bscanHex) - ) { - throw Error( - `Output script set but eligible input ${i} missing ECDH share`, - ); - } - if (!this.inputMaps[i].has(KeyType.PSBT_IN_SP_DLEQ + bscanHex)) { - throw Error( - `Input ${i} ECDH share missing PSBT_IN_SP_DLEQ for scan key ${bscanHex}`, - ); - } - if (this.PSBT_IN_BIP32_DERIVATION[i].length === 0) { - throw Error( - `Input ${i}: PSBT_IN_SP_DLEQ is set but PSBT_IN_BIP32_DERIVATION is missing.`, - ); - } } - // P2SH and other scripts — share optional, skip + continue; } - } - // ── Script verification ────────────────────────────────────────────────── - // Per BIP375 reference validate_output_scripts: - // outpoints = ALL inputs (reference collects before eligibility check) - // pubkeys = eligible inputs with witnessUtxo and extractable pubkeys - // ecdh shares = eligible inputs with a share for this scan key - const outpoints: Buffer[] = []; - for (let i = 0; i < this.inputMaps.length; i++) { - const txid = this.inputMaps[i].get(KeyType.PSBT_IN_PREVIOUS_TXID); - const vout = this.inputMaps[i].get(KeyType.PSBT_IN_OUTPUT_INDEX); - if (txid && vout) outpoints.push(Buffer.concat([txid, vout])); - } + const nonNumsEligible = eligible.filter( + (i) => !this.hasNumsTaprootScriptPathSpend(i), + ); - let combinedPubkey: ProjectivePoint | null = null; + const hasAnyInputShare = nonNumsEligible.some((i) => + this.inputMaps[i].has(KeyType.PSBT_IN_SP_ECDH_SHARE + bscanHex), + ); - for (const i of eligible) { - const witnessUtxo = this.inputMaps[i].get(KeyType.PSBT_IN_WITNESS_UTXO); - let pubkeyBytes: Buffer | null = null; + if (!hasAnyInputShare) { + throw Error( + `Silent payment output present but no ECDH share for scan key ${bscanHex}.`, + ); + } - if (!witnessUtxo) { - // P2PKH — no witnessUtxo, pubkey from BIP32 derivation - const entries = this.PSBT_IN_BIP32_DERIVATION[i]; - if (entries.length > 0) - pubkeyBytes = Buffer.from(entries[0].key.slice(2), "hex"); - } else { - const sLen = witnessUtxo[8]; - const iScript = witnessUtxo.subarray(9, 9 + sLen); + for (const i of nonNumsEligible) { + const shareKey = KeyType.PSBT_IN_SP_ECDH_SHARE + bscanHex; + const proofKey = KeyType.PSBT_IN_SP_DLEQ + bscanHex; + + if (!this.inputMaps[i].has(shareKey)) { + throw Error( + `Output script set but eligible input ${i} missing ECDH share for scan key ${bscanHex}`, + ); + } - if (iScript[0] === 0x51 && iScript.length === 34) { - // P2TR — use tap internal key, prefixed 0x02 (even y per BIP352) - const tapKey = this.inputMaps[i].get( - KeyType.PSBT_IN_TAP_INTERNAL_KEY, + const inputPubkey = this.getInputAggregatePubkey([i], true); + const ecdhShare = this.inputMaps[i].get(shareKey) as Buffer; + const proof = this.inputMaps[i].get(proofKey) as Buffer; + + if (!inputPubkey) { + throw Error( + `Input ${i} missing public key for silent payment DLEQ verification.`, ); - const NUMS_H = - "50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0"; - const isNums = tapKey?.toString("hex") === NUMS_H; - if (!isNums && tapKey) - pubkeyBytes = Buffer.concat([Buffer.from([0x02]), tapKey]); - } else { - // P2WPKH, P2SH, others — pubkey from BIP32 derivation - const entries = this.PSBT_IN_BIP32_DERIVATION[i]; - if (entries.length > 0) - pubkeyBytes = Buffer.from(entries[0].key.slice(2), "hex"); } + // A per-input SP DLEQ proof requires the input public key as A. + // Even before semantic BIP374 verification, reject proof-bearing + // eligible inputs whose public key cannot be recovered from the PSBT. + this.getInputAggregatePubkey([i], true); } + } - if (!pubkeyBytes) continue; - const point = secp256k1.ProjectivePoint.fromHex(pubkeyBytes); - combinedPubkey = combinedPubkey ? combinedPubkey.add(point) : point; + const allComparableSPOutputsHaveScripts = this.outputMaps.every((map) => { + if (!map.has(KeyType.PSBT_OUT_SP_V0_INFO)) { + return true; + } + + if (map.has(KeyType.PSBT_OUT_SP_V0_LABEL)) { + return true; + } + + const script = map.get(KeyType.PSBT_OUT_SCRIPT); + return !!script && script.length > 0; + }); + + if (!allComparableSPOutputsHaveScripts) { + return; } - if (!combinedPubkey || outpoints.length === 0) return; + const hasPartialSPComputation = this.outputMaps.some((map) => { + if (!map.has(KeyType.PSBT_OUT_SP_V0_INFO)) { + return false; + } + + if (map.has(KeyType.PSBT_OUT_SP_V0_LABEL)) { + return false; + } + + const script = map.get(KeyType.PSBT_OUT_SCRIPT); + return !script || script.length === 0; + }); + + if (hasPartialSPComputation) { + return; + } + + const allOutpoints = this.getAllOutpoints(); + + if (allOutpoints.length === 0) { + return; + } + + const combinedPubkey = this.getInputAggregatePubkey(eligible); + + if (!combinedPubkey) { + return; + } const inputHash = computeInputHash( - outpoints, + allOutpoints, Buffer.from(combinedPubkey.toRawBytes(true)), ); - const scanKeyKValues = new Map(); + const outputGroups = this.getSilentPaymentOutputGroups(true, true); + + for (const [bscanHex, group] of outputGroups) { + if (!computedSPScanKeys.has(bscanHex)) { + continue; + } - for ( - let outputIndex = 0; - outputIndex < this.outputMaps.length; - outputIndex++ - ) { - const map = this.outputMaps[outputIndex]; - const spInfo = map.get(KeyType.PSBT_OUT_SP_V0_INFO); - const actualScript = map.get(KeyType.PSBT_OUT_SCRIPT); - if (!spInfo || !actualScript || actualScript.length === 0) continue; - assertValidSPV0Info(spInfo, outputIndex); - - const bscanHex = spInfo.subarray(0, 33).toString("hex"); - const bspend = spInfo.subarray(33, 66); - const k = scanKeyKValues.get(bscanHex) ?? 0; - assertValidOutputK(k, outputIndex); - const globalShareKey = KeyType.PSBT_GLOBAL_SP_ECDH_SHARE + bscanHex; let ecdhShare: Buffer; + const globalShareKey = KeyType.PSBT_GLOBAL_SP_ECDH_SHARE + bscanHex; if (this.globalMap.has(globalShareKey)) { ecdhShare = this.globalMap.get(globalShareKey) as Buffer; } else { - // Collect shares from eligible inputs only — P2SH is ineligible per - // BIP352 so its share must be excluded even if present in the PSBT. const perInputBuffers: Buffer[] = []; - for (const j of eligible) { - const val = this.inputMaps[j].get( + + for (const i of eligible) { + if (this.hasNumsTaprootScriptPathSpend(i)) { + continue; + } + + const share = this.inputMaps[i].get( KeyType.PSBT_IN_SP_ECDH_SHARE + bscanHex, ); - if (val) perInputBuffers.push(val); + + if (!share) { + throw Error( + `Output script set but eligible input ${i} missing ECDH share for scan key ${bscanHex}`, + ); + } + + perInputBuffers.push(share); } + if (perInputBuffers.length === 0) { - scanKeyKValues.set(bscanHex, k + 1); continue; } + ecdhShare = Buffer.from( sumECDHShares(perInputBuffers).toRawBytes(true), ); } - const expectedScript = deriveSilentPaymentOutput( - ecdhShare, - inputHash, - bspend, - k, - ); + for (let k = 0; k < group.length; k++) { + const { outputIndex, bspend } = group[k]; + const actualScript = this.outputMaps[outputIndex].get( + KeyType.PSBT_OUT_SCRIPT, + ); - if (!actualScript.equals(expectedScript)) { - throw Error( - `PsbtV2 output ${outputIndex} PSBT_OUT_SCRIPT does not match silent payment derivation.`, + if (!actualScript || actualScript.length === 0) { + continue; + } + + assertValidOutputK(k, outputIndex); + + const expectedScript = deriveSilentPaymentOutput( + ecdhShare, + inputHash, + bspend, + k, ); - } - scanKeyKValues.set(bscanHex, k + 1); + if (!actualScript.equals(expectedScript)) { + throw Error( + `PsbtV2 output ${outputIndex} PSBT_OUT_SCRIPT does not match silent payment derivation.`, + ); + } + } } } - /** * Sets the sequence number for a specific input in the transaction. * @@ -1433,12 +1615,8 @@ export class PsbtV2 extends PsbtV2Maps { if (silentPayment) { const { bscan, bspend, label } = silentPayment; - if (bscan.length !== 33) { - throw Error(`bscan must be 33 bytes, got ${bscan.length}`); - } - if (bspend.length !== 33) { - throw Error(`bspend must be 33 bytes, got ${bspend.length}`); - } + assertValidBscan(bscan); + assertValidBspend(bspend); // Value: bscan || bspend, 66 bytes — no version prefix in field value. const spBw = new BufferWriter(); spBw.writeBytes(bscan); @@ -1633,41 +1811,30 @@ export class PsbtV2 extends PsbtV2Maps { // ── Global SP methods ───────────────────────────────────────────────────── public addGlobalSPECDHShare(bscan: Buffer, share: Buffer): void { - if (bscan.length !== 33) { - throw new Error( - `bscan must be a 33-byte compressed pubkey, got ${bscan.length}`, - ); - } - if (share.length !== 33) { - throw new Error( - `ECDH share must be a 33-byte compressed EC point, got ${share.length}`, - ); - } + assertValidBscan(bscan); + assertValidECDHShare(share); + const key = KeyType.PSBT_GLOBAL_SP_ECDH_SHARE + bscan.toString("hex"); this.globalMap.set(key, share); } public addGlobalSPDLEQProof(bscan: Buffer, proof: Buffer): void { - if (bscan.length !== 33) { - throw new Error( - `bscan must be a 33-byte compressed pubkey, got ${bscan.length}`, - ); - } - if (proof.length !== 64) { - throw new Error(`DLEQ proof must be 64 bytes, got ${proof.length}`); - } + assertValidBscan(bscan); + assertValidDLEQProof(proof); + const shareKey = KeyType.PSBT_GLOBAL_SP_ECDH_SHARE + bscan.toString("hex"); + if (!this.globalMap.has(shareKey)) { throw new Error( "Cannot add global SP DLEQ proof: no matching ECDH share for this " + "bscan. Call addGlobalSPECDHShare first.", ); } + const key = KeyType.PSBT_GLOBAL_SP_DLEQ + bscan.toString("hex"); this.globalMap.set(key, proof); } - // ── Per-input SP methods ────────────────────────────────────────────────── public addInputSPECDHShare( inputIndex: number, @@ -1685,10 +1852,20 @@ export class PsbtV2 extends PsbtV2Maps { ); } if (share.length !== 33) { + // ── Per-input SP methods ────────────────────────────────────────────────── + + public addInputSPECDHShare( + inputIndex: number, + bscan: Buffer, + share: Buffer, + ): void { + if (inputIndex < 0 || inputIndex >= this.inputMaps.length) { throw new Error( - `ECDH share must be a 33-byte compressed EC point, got ${share.length}`, + `inputIndex ${inputIndex} out of range (${this.inputMaps.length} inputs)`, ); } + assertValidBscan(bscan); + assertValidECDHShare(share); const key = KeyType.PSBT_IN_SP_ECDH_SHARE + bscan.toString("hex"); this.inputMaps[inputIndex].set(key, share); } @@ -1703,14 +1880,8 @@ export class PsbtV2 extends PsbtV2Maps { `inputIndex ${inputIndex} out of range (${this.inputMaps.length} inputs)`, ); } - if (bscan.length !== 33) { - throw new Error( - `bscan must be a 33-byte compressed pubkey, got ${bscan.length}`, - ); - } - if (proof.length !== 64) { - throw new Error(`DLEQ proof must be 64 bytes, got ${proof.length}`); - } + assertValidBscan(bscan); + assertValidDLEQProof(proof); const shareKey = KeyType.PSBT_IN_SP_ECDH_SHARE + bscan.toString("hex"); if (!this.inputMaps[inputIndex].has(shareKey)) { throw new Error( @@ -2133,11 +2304,7 @@ export class PsbtV2 extends PsbtV2Maps { * @returns Array of eligible input indices. */ getEligibleInputsForSilentPayments(): number[] { - return eligibleIndices( - this.inputMaps.map((map) => ({ - witnessUtxo: map.get(KeyType.PSBT_IN_WITNESS_UTXO) ?? null, - })), - ); + return eligibleIndices(this.getSilentPaymentInputDescriptors()); } /** @@ -2149,24 +2316,22 @@ export class PsbtV2 extends PsbtV2Maps { hasCompleteECDHCoverage(): boolean { if (!this.hasSilentPaymentOutputs) return false; - // Collect unique scan keys from SP outputs - const scanKeys = new Set(); - for (const map of this.outputMaps) { - const raw = map.get(KeyType.PSBT_OUT_SP_V0_INFO); - if (raw) scanKeys.add(raw.slice(0, 33).toString("hex")); - } + const scanKeys = [...this.getSilentPaymentOutputGroups().keys()]; + const eligible = this.getEligibleInputsForSilentPayments(); - // Check if global shares cover all scan keys - const globalShareKeys = new Set( - this.PSBT_GLOBAL_SP_ECDH_SHARE.map((entry) => entry.key.slice(2)), - ); - if ([...scanKeys].every((k) => globalShareKeys.has(k))) { - return true; + for (const bscanHex of scanKeys) { + if (this.globalMap.has(KeyType.PSBT_GLOBAL_SP_ECDH_SHARE + bscanHex)) { + continue; + } + const allEligibleInputsCovered = eligible.every( + (i) => + this.hasNumsTaprootScriptPathSpend(i) || + this.inputMaps[i].has(KeyType.PSBT_IN_SP_ECDH_SHARE + bscanHex), + ); + if (!allEligibleInputsCovered) return false; } - // Fall back: all eligible inputs must have per-input shares - const eligible = this.getEligibleInputsForSilentPayments(); - return eligible.every((i) => this.PSBT_IN_SP_ECDH_SHARE[i].length > 0); + return scanKeys.length > 0; } /** @@ -2192,6 +2357,19 @@ export class PsbtV2 extends PsbtV2Maps { if (!this.hasSilentPaymentOutputs) { throw new Error("No silent payment outputs found."); } + + const hasLabeledSilentPaymentOutput = this.outputMaps.some( + (map) => + map.has(KeyType.PSBT_OUT_SP_V0_INFO) && + map.has(KeyType.PSBT_OUT_SP_V0_LABEL), + ); + + if (hasLabeledSilentPaymentOutput) { + throw new Error( + "Cannot compute labeled silent payment output scripts without label tweak derivation.", + ); + } + if (!this.hasCompleteECDHCoverage()) { throw new Error( "Incomplete ECDH coverage — call addGlobalSPECDHShare or " + @@ -2199,58 +2377,17 @@ export class PsbtV2 extends PsbtV2Maps { ); } - // ── Step 1: Build outpoints + combined pubkey for inputHash ───────────── - const eligible = this.getEligibleInputsForSilentPayments(); - - const outpoints: Buffer[] = eligible.map((i) => { - const txid = this.inputMaps[i].get(KeyType.PSBT_IN_PREVIOUS_TXID)!; - const vout = this.inputMaps[i].get(KeyType.PSBT_IN_OUTPUT_INDEX)!; - return Buffer.concat([txid, vout]); // txid(32 LE) || vout(4 LE) - }); - - let combinedPubkey: ProjectivePoint | null = null; - - for (const i of eligible) { - const witnessUtxo = this.inputMaps[i].get(KeyType.PSBT_IN_WITNESS_UTXO); - let pubkeyBytes: Buffer | null = null; - - if (!witnessUtxo) { - // P2PKH — no witnessUtxo, pubkey from BIP32 derivation - const entries = this.PSBT_IN_BIP32_DERIVATION[i]; - if (entries.length > 0) - pubkeyBytes = Buffer.from(entries[0].key.slice(2), "hex"); - } else { - const scriptLen = witnessUtxo[8]; - const inputScript = witnessUtxo.slice(9, 9 + scriptLen); - - if (inputScript[0] === 0x51 && inputScript.length === 34) { - // P2TR — use tap internal key, prefixed with 0x02 (even y per BIP352) - const tapKey = this.inputMaps[i].get( - KeyType.PSBT_IN_TAP_INTERNAL_KEY, - ); - if (tapKey) { - pubkeyBytes = Buffer.concat([Buffer.from([0x02]), tapKey]); - } - } else if (inputScript[0] === 0x00 && inputScript.length === 22) { - // P2WPKH — pubkey from BIP32 derivation field - // key format: keytype(1) || pubkey(33) — strip keytype byte - const entries = this.PSBT_IN_BIP32_DERIVATION[i]; - if (entries.length > 0) { - pubkeyBytes = Buffer.from(entries[0].key.slice(2), "hex"); - } - } else { - // P2SH — pubkey from BIP32 derivation - const entries = this.PSBT_IN_BIP32_DERIVATION[i]; - if (entries.length > 0) - pubkeyBytes = Buffer.from(entries[0].key.slice(2), "hex"); - } - } - - if (!pubkeyBytes) continue; - const point = secp256k1.ProjectivePoint.fromHex(pubkeyBytes); - combinedPubkey = combinedPubkey ? combinedPubkey.add(point) : point; + if (hasSegwitV2PlusInput(this.getSilentPaymentInputDescriptors())) { + throw new Error( + "A PSBT with PSBT_OUT_SP_V0_INFO must not contain SegWit v2+ inputs.", + ); } + // ── Step 1: Build all outpoints + combined pubkey for inputHash ──────── + const eligible = this.getEligibleInputsForSilentPayments(); + const outpoints = this.getAllOutpoints(); + const combinedPubkey = this.getInputAggregatePubkey(eligible); + if (!combinedPubkey) { throw new Error("Could not extract public keys from eligible inputs."); } @@ -2260,44 +2397,37 @@ export class PsbtV2 extends PsbtV2Maps { Buffer.from(combinedPubkey.toRawBytes(true)), ); - // ── Step 2: Group SP outputs by Bscan, sort within groups ─────────────── - // BIP375: recipients with the same Bscan sorted lexicographically ascending - // by Bspend to determine k-value ordering. Same Bspend → by output index. - const scanKeyGroups = new Map(); - for (let i = 0; i < this.outputMaps.length; i++) { - const info = this.getSilentPaymentOutputInfo(i); - if (!info) continue; - const key = info.bscan.toString("hex"); - if (!scanKeyGroups.has(key)) scanKeyGroups.set(key, []); - scanKeyGroups.get(key)!.push({ outputIndex: i, ...info }); - } + // ── Step 2: Group SP outputs by Bscan, sort within groups ────────────── + const scanKeyGroups = this.getSilentPaymentOutputGroups(false); - for (const group of scanKeyGroups.values()) { - group.sort((a, b) => { - const cmp = a.bspend.compare(b.bspend); - return cmp !== 0 ? cmp : a.outputIndex - b.outputIndex; - }); - } - - // ── Step 3: Resolve ECDH share and derive output scripts ──────────────── + // ── Step 3: Resolve ECDH share and derive output scripts ─────────────── for (const [bscanHex, group] of scanKeyGroups) { - // Prefer global share — read directly from map to avoid hex round-trip const globalShareKey = KeyType.PSBT_GLOBAL_SP_ECDH_SHARE + bscanHex; let ecdhShare: Buffer; if (this.globalMap.has(globalShareKey)) { ecdhShare = this.globalMap.get(globalShareKey) as Buffer; } else { - // Sum per-input shares for this scan key — read directly from input maps - const perInputBuffers = eligible.flatMap((i) => { - const val = this.inputMaps[i].get( + const perInputBuffers: Buffer[] = []; + + for (const i of eligible) { + if (this.hasNumsTaprootScriptPathSpend(i)) { + continue; + } + + const share = this.inputMaps[i].get( KeyType.PSBT_IN_SP_ECDH_SHARE + bscanHex, ); - return val ? [val] : []; - }); + + if (share) { + perInputBuffers.push(share); + } + } + if (perInputBuffers.length === 0) { throw new Error(`No ECDH share found for scan key ${bscanHex}`); } + ecdhShare = Buffer.from( sumECDHShares(perInputBuffers).toRawBytes(true), ); @@ -2305,20 +2435,21 @@ export class PsbtV2 extends PsbtV2Maps { for (let k = 0; k < group.length; k++) { const { outputIndex, bspend } = group[k]; + assertValidOutputK(k, outputIndex); + const script = deriveSilentPaymentOutput( ecdhShare, inputHash, bspend, k, ); + this.outputMaps[outputIndex].set(KeyType.PSBT_OUT_SCRIPT, script); } } - // ── Step 4: Lock modifiable flags per BIP375 ──────────────────────────── - // Signer must set Inputs and Outputs Modifiable to False after setting - // missing PSBT_OUT_SCRIPTs. + // ── Step 4: Lock modifiable flags per BIP375 ─────────────────────────── this.PSBT_GLOBAL_TX_MODIFIABLE = this.PSBT_GLOBAL_TX_MODIFIABLE.filter( (f) => f !== PsbtGlobalTxModifiableBits.INPUTS && diff --git a/packages/caravan-psbt/src/psbtv2/psbtv2maps.ts b/packages/caravan-psbt/src/psbtv2/psbtv2maps.ts index 8dbf91f46e..5ccbda2933 100644 --- a/packages/caravan-psbt/src/psbtv2/psbtv2maps.ts +++ b/packages/caravan-psbt/src/psbtv2/psbtv2maps.ts @@ -128,13 +128,13 @@ export abstract class PsbtV2Maps { if (from.inputMaps.length !== this.inputMaps.length) { throw new Error( `Cannot combine PSBTs with different input counts: ` + - `this has ${this.inputMaps.length}, other has ${from.inputMaps.length}` + `this has ${this.inputMaps.length}, other has ${from.inputMaps.length}`, ); } if (from.outputMaps.length !== this.outputMaps.length) { throw new Error( `Cannot combine PSBTs with different output counts: ` + - `this has ${this.outputMaps.length}, other has ${from.outputMaps.length}` + `this has ${this.outputMaps.length}, other has ${from.outputMaps.length}`, ); } } @@ -241,9 +241,13 @@ export class PsbtConversionMaps extends PsbtV2Maps { ).readBigInt64LE(); const numberAmount = parseInt(bigintAmount.toString()); - // BIP375: prefer PSBT_OUT_SP_V0_INFO for unique identification so the - // ID is stable whether or not the output script has been computed yet. - tx.addOutput((spInfo ?? script) as Buffer, numberAmount); + // BIP375 unique identification uses v0 || Bscan || Bspend when + // PSBT_OUT_SP_V0_INFO is present, so the txid is stable before and after + // the real output script has been computed. + const outputScript = spInfo + ? Buffer.concat([Buffer.from([0x00]), spInfo]) + : (script as Buffer); + tx.addOutput(outputScript, numberAmount); } return tx.toBuffer(); @@ -320,7 +324,7 @@ export class PsbtConversionMaps extends PsbtV2Maps { ); throw new Error( "Cannot compute transaction ID: PSBT has 0 inputs and 1 output, " + - "which produces an ambiguous transaction format. " + "which produces an ambiguous transaction format. ", ); } diff --git a/packages/caravan-psbt/src/psbtv2/silentpayment.ts b/packages/caravan-psbt/src/psbtv2/silentpayment.ts index 8ddeba6133..3a17cd80f3 100644 --- a/packages/caravan-psbt/src/psbtv2/silentpayment.ts +++ b/packages/caravan-psbt/src/psbtv2/silentpayment.ts @@ -15,7 +15,7 @@ import { script } from "bitcoinjs-lib-v6"; const CURVE_ORDER = secp256k1.CURVE.n; const { bytesToNumberBE } = schnorr.utils; const { OPS } = script; - +import { Transaction } from "bitcoinjs-lib-v6"; // ── Internal types ───────────────────────────────────────────────────────── export type ProjectivePoint = InstanceType; @@ -40,15 +40,24 @@ export interface SPOutputEntry { * in original index order. */ export interface SPInputDescriptor { - /** - * Raw `PSBT_IN_WITNESS_UTXO` value for this input, or `null` if the field - * is absent (legacy P2PKH / P2SH-P2WPKH inputs). - * - * Format: `amount(8) || scriptLen(varint) || script`. - */ witnessUtxo: Buffer | null; + nonWitnessUtxo?: Buffer | null; + outputIndex?: number | null; + redeemScript?: Buffer | null; } +export type SPInputScriptType = + | "p2tr" + | "p2wpkh" + | "p2wsh" + | "segwit_v2plus" + | "p2pkh_or_unknown_legacy" + | "p2sh_p2wpkh" + | "ineligible"; + +export const BIP352_NUMS_H = + "50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0"; + // ── Field validators ─────────────────────────────────────────────────────── // Called from both field setters in PsbtV2 and validateSilentPayments(). @@ -58,12 +67,44 @@ export interface SPInputDescriptor { * @param bscan - Candidate scan public key buffer. * @throws {Error} If `bscan` is not exactly 33 bytes. */ -export function assertValidBscan(bscan: Buffer): void { - if (bscan.length !== 33) { +function assertValidCompressedPoint(value: Buffer, name: string): void { + if (value.length !== 33) { throw new Error( - `bscan must be a 33-byte compressed pubkey, got ${bscan.length}`, + `${name} must be a 33-byte compressed pubkey, got ${value.length}`, ); } + if (value[0] !== 0x02 && value[0] !== 0x03) { + throw new Error( + `${name} must use compressed secp256k1 prefix 0x02 or 0x03`, + ); + } + secp256k1.ProjectivePoint.fromHex(value); +} + +export function assertValidBscan(bscan: Buffer): void { + assertValidCompressedPoint(bscan, "bscan"); +} + +export function parseSilentPaymentScanKeyData( + key: string, + keyType: string, + context: string, +): Buffer { + const scanKey = key.slice(keyType.length); + if (!/^[0-9a-fA-F]+$/.test(scanKey)) { + throw new Error(`${context} scan keydata must be hex encoded.`); + } + const bscan = Buffer.from(scanKey, "hex"); + assertValidBscan(bscan); + return bscan; +} + +export function scanKeyHexFromBIP375Key( + key: string, + keyType: string, + context: string, +): string { + return parseSilentPaymentScanKeyData(key, keyType, context).toString("hex"); } /** @@ -73,11 +114,7 @@ export function assertValidBscan(bscan: Buffer): void { * @throws {Error} If `bspend` is not exactly 33 bytes. */ export function assertValidBspend(bspend: Buffer): void { - if (bspend.length !== 33) { - throw new Error( - `bspend must be a 33-byte compressed pubkey, got ${bspend.length}`, - ); - } + assertValidCompressedPoint(bspend, "bspend"); } /** @@ -87,11 +124,7 @@ export function assertValidBspend(bspend: Buffer): void { * @throws {Error} If `share` is not exactly 33 bytes. */ export function assertValidECDHShare(share: Buffer): void { - if (share.length !== 33) { - throw new Error( - `ECDH share must be a 33-byte compressed EC point, got ${share.length}`, - ); - } + assertValidCompressedPoint(share, "ECDH share"); } /** @@ -121,6 +154,8 @@ export function assertValidSPV0Info(raw: Buffer, outputIndex: number): void { `expected 66 bytes, got ${raw.length}`, ); } + assertValidBscan(raw.subarray(0, 33)); + assertValidBspend(raw.subarray(33, 66)); } export function assertValidLabel(m: number, outputIndex: number): void { @@ -187,37 +222,124 @@ export function bip352TaggedHash(tag: string, data: Buffer): Buffer { * correspond to positions in the original input list. * @returns Array of input indices eligible for SP ECDH derivation. */ -export function eligibleIndices(inputs: SPInputDescriptor[]): number[] { - const eligible: number[] = []; +function readWitnessUtxoScript(witnessUtxo: Buffer): Buffer { + if (witnessUtxo.length < 9) return Buffer.alloc(0); + const scriptLen = witnessUtxo[8]; + return witnessUtxo.subarray(9, 9 + scriptLen); +} - for (let i = 0; i < inputs.length; i++) { - const { witnessUtxo } = inputs[i]; +function readNonWitnessUtxoScript( + nonWitnessUtxo?: Buffer | null, + outputIndex?: number | null, +): Buffer | null { + if (!nonWitnessUtxo || outputIndex === null || outputIndex === undefined) { + return null; + } - if (!witnessUtxo) { - // No witness UTXO — legacy input (P2PKH / P2SH-P2WPKH), eligible - eligible.push(i); - continue; + const tx = Transaction.fromBuffer(nonWitnessUtxo); + return tx.outs[outputIndex]?.script ?? null; +} + +export function classifyWitnessScript(scriptPubKey: Buffer): SPInputScriptType { + if ( + scriptPubKey.length === 34 && + scriptPubKey[0] === OPS.OP_1 && + scriptPubKey[1] === 0x20 + ) { + return "p2tr"; + } + if ( + scriptPubKey.length === 22 && + scriptPubKey[0] === OPS.OP_0 && + scriptPubKey[1] === 0x14 + ) { + return "p2wpkh"; + } + if ( + scriptPubKey.length === 34 && + scriptPubKey[0] === OPS.OP_0 && + scriptPubKey[1] === 0x20 + ) { + return "p2wsh"; + } + if ( + scriptPubKey.length >= 4 && + scriptPubKey[0] >= OPS.OP_2 && + scriptPubKey[0] <= OPS.OP_16 + ) { + return "segwit_v2plus"; + } + if ( + scriptPubKey.length === 25 && + scriptPubKey[0] === OPS.OP_DUP && + scriptPubKey[1] === OPS.OP_HASH160 && + scriptPubKey[2] === 0x14 && + scriptPubKey[23] === OPS.OP_EQUALVERIFY && + scriptPubKey[24] === OPS.OP_CHECKSIG + ) { + return "p2pkh_or_unknown_legacy"; + } + if ( + scriptPubKey.length === 23 && + scriptPubKey[0] === OPS.OP_HASH160 && + scriptPubKey[1] === 0x14 && + scriptPubKey[22] === OPS.OP_EQUAL + ) { + return "ineligible"; + } + return "ineligible"; +} + +export function classifyInputDescriptor( + input: SPInputDescriptor, +): SPInputScriptType { + const script = input.witnessUtxo + ? readWitnessUtxoScript(input.witnessUtxo) + : readNonWitnessUtxoScript(input.nonWitnessUtxo, input.outputIndex); + + if (!script) { + return "ineligible"; + } + + const scriptType = classifyWitnessScript(script); + + if (scriptType === "p2sh_p2wpkh") { + return scriptType; + } + + if ( + script.length === 23 && + script[0] === OPS.OP_HASH160 && + script[1] === 0x14 && + script[22] === OPS.OP_EQUAL + ) { + if ( + input.redeemScript && + classifyWitnessScript(input.redeemScript) === "p2wpkh" + ) { + return "p2sh_p2wpkh"; } - // witnessUtxo format: 8-byte amount || varint scriptLen || script - const scriptLen = witnessUtxo[8]; - const inputScript = witnessUtxo.slice(9, 9 + scriptLen); - const version = inputScript[0]; + return "ineligible"; + } + + return scriptType; +} - if (version === OPS.OP_1 && inputScript.length === 34) { - // P2TR (OP_1 + 32-byte x-only key) — eligible - eligible.push(i); - } else if (version === OPS.OP_0 && inputScript.length === 22) { - // P2WPKH (OP_0 + 20-byte hash) — eligible - eligible.push(i); - } else if (version === OPS.OP_0 && inputScript.length === 34) { - // P2WSH (OP_0 + 32-byte hash) — NOT eligible (multisig) - continue; - } else if (version >= OPS.OP_2 && version <= OPS.OP_16) { - // Segwit v2–v16 (OP_2–OP_16 range 0x52–0x60) — NOT eligible per BIP375 - continue; - } else { - // Anything else (P2SH-P2WPKH wrapped, P2PKH) — eligible +export function isEligibleInputType(type: SPInputScriptType): boolean { + return ( + type === "p2tr" || + type === "p2wpkh" || + type === "p2sh_p2wpkh" || + type === "p2pkh_or_unknown_legacy" + ); +} + +export function eligibleIndices(inputs: SPInputDescriptor[]): number[] { + const eligible: number[] = []; + + for (let i = 0; i < inputs.length; i++) { + if (isEligibleInputType(classifyInputDescriptor(inputs[i]))) { eligible.push(i); } } @@ -225,6 +347,38 @@ export function eligibleIndices(inputs: SPInputDescriptor[]): number[] { return eligible; } +export function hasSegwitV2PlusInput(inputs: SPInputDescriptor[]): boolean { + return inputs.some( + (input) => classifyInputDescriptor(input) === "segwit_v2plus", + ); +} + +export function getTaprootOutputKeyFromWitnessUtxo( + witnessUtxo: Buffer, +): Buffer | null { + const scriptPubKey = readWitnessUtxoScript(witnessUtxo); + if (classifyWitnessScript(scriptPubKey) !== "p2tr") return null; + return Buffer.concat([Buffer.from([0x02]), scriptPubKey.subarray(2, 34)]); +} + +export function groupSilentPaymentOutputs( + entries: SPOutputEntry[], +): Map { + const groups = new Map(); + for (const entry of entries) { + const key = entry.bscan.toString("hex"); + if (!groups.has(key)) groups.set(key, []); + groups.get(key)!.push(entry); + } + for (const group of groups.values()) { + group.sort((a, b) => { + const cmp = a.bspend.compare(b.bspend); + return cmp !== 0 ? cmp : a.outputIndex - b.outputIndex; + }); + } + return groups; +} + // ── ECDH share accumulation ──────────────────────────────────────────────── /** From 20b73950e9d5d6c42d5bd63f510aa6d0126ce070 Mon Sep 17 00:00:00 2001 From: Jasper van Gelder Date: Wed, 20 May 2026 12:24:01 +0200 Subject: [PATCH 12/26] feat(caravan-psbt): add BIP374 DLEQ proofs for silent payments --- packages/caravan-psbt/src/psbtv2/dleq.test.ts | 209 +++++++++++++ packages/caravan-psbt/src/psbtv2/dleq.ts | 287 ++++++++++++++++++ .../src/psbtv2/psbtv2-bip375.test.ts | 252 +++++++++++++++ packages/caravan-psbt/src/psbtv2/psbtv2.ts | 66 +++- .../caravan-psbt/src/psbtv2/silentpayment.ts | 59 ++++ 5 files changed, 865 insertions(+), 8 deletions(-) create mode 100644 packages/caravan-psbt/src/psbtv2/dleq.test.ts create mode 100644 packages/caravan-psbt/src/psbtv2/dleq.ts diff --git a/packages/caravan-psbt/src/psbtv2/dleq.test.ts b/packages/caravan-psbt/src/psbtv2/dleq.test.ts new file mode 100644 index 0000000000..482a78ec1c --- /dev/null +++ b/packages/caravan-psbt/src/psbtv2/dleq.test.ts @@ -0,0 +1,209 @@ +import { describe, expect, it } from "vitest"; +import { secp256k1 } from "@noble/curves/secp256k1"; + +import { + generateDLEQProof, + multiplyCompressedPoint, + verifyDLEQProof, +} from "./dleq"; +import { verifySilentPaymentDLEQProof } from "./silentpayment"; +function hex(s: string): Buffer { + return Buffer.from(s, "hex"); +} + +function pubkeyFromSecret(secret: Buffer): Buffer { + return Buffer.from( + secp256k1.ProjectivePoint.BASE.multiply( + BigInt(`0x${secret.toString("hex")}`), + ).toRawBytes(true), + ); +} + +describe("BIP374 DLEQ", () => { + it("generates a proof that verifies", () => { + const secret = hex( + "0000000000000000000000000000000000000000000000000000000000000001", + ); + const baseSecret = hex( + "0000000000000000000000000000000000000000000000000000000000000002", + ); + const auxRand = Buffer.alloc(32, 0); + + const publicKey = pubkeyFromSecret(secret); + const basePoint = pubkeyFromSecret(baseSecret); + const result = multiplyCompressedPoint(basePoint, secret); + + const proof = generateDLEQProof({ + secret, + basePoint, + auxRand, + }); + + expect(proof.length).toBe(64); + + expect( + verifyDLEQProof({ + proof, + publicKey, + basePoint, + result, + }), + ).toBe(true); + }); + + it("fails verification with the wrong public key", () => { + const secret = hex( + "0000000000000000000000000000000000000000000000000000000000000001", + ); + const wrongSecret = hex( + "0000000000000000000000000000000000000000000000000000000000000003", + ); + const baseSecret = hex( + "0000000000000000000000000000000000000000000000000000000000000002", + ); + + const basePoint = pubkeyFromSecret(baseSecret); + const result = multiplyCompressedPoint(basePoint, secret); + const wrongPublicKey = pubkeyFromSecret(wrongSecret); + + const proof = generateDLEQProof({ + secret, + basePoint, + auxRand: Buffer.alloc(32, 0), + }); + + expect( + verifyDLEQProof({ + proof, + publicKey: wrongPublicKey, + basePoint, + result, + }), + ).toBe(false); + }); + + it("fails verification with the wrong base point", () => { + const secret = hex( + "0000000000000000000000000000000000000000000000000000000000000001", + ); + const baseSecret = hex( + "0000000000000000000000000000000000000000000000000000000000000002", + ); + const wrongBaseSecret = hex( + "0000000000000000000000000000000000000000000000000000000000000003", + ); + + const publicKey = pubkeyFromSecret(secret); + const basePoint = pubkeyFromSecret(baseSecret); + const wrongBasePoint = pubkeyFromSecret(wrongBaseSecret); + const result = multiplyCompressedPoint(basePoint, secret); + + const proof = generateDLEQProof({ + secret, + basePoint, + auxRand: Buffer.alloc(32, 0), + }); + + expect( + verifyDLEQProof({ + proof, + publicKey, + basePoint: wrongBasePoint, + result, + }), + ).toBe(false); + }); + + it("fails verification with the wrong ECDH result", () => { + const secret = hex( + "0000000000000000000000000000000000000000000000000000000000000001", + ); + const baseSecret = hex( + "0000000000000000000000000000000000000000000000000000000000000002", + ); + const wrongSecret = hex( + "0000000000000000000000000000000000000000000000000000000000000003", + ); + + const publicKey = pubkeyFromSecret(secret); + const basePoint = pubkeyFromSecret(baseSecret); + const wrongResult = multiplyCompressedPoint(basePoint, wrongSecret); + + const proof = generateDLEQProof({ + secret, + basePoint, + auxRand: Buffer.alloc(32, 0), + }); + + expect( + verifyDLEQProof({ + proof, + publicKey, + basePoint, + result: wrongResult, + }), + ).toBe(false); + }); + + it("fails verification when proof bytes are mutated", () => { + const secret = hex( + "0000000000000000000000000000000000000000000000000000000000000001", + ); + const baseSecret = hex( + "0000000000000000000000000000000000000000000000000000000000000002", + ); + + const publicKey = pubkeyFromSecret(secret); + const basePoint = pubkeyFromSecret(baseSecret); + const result = multiplyCompressedPoint(basePoint, secret); + + const proof = generateDLEQProof({ + secret, + basePoint, + auxRand: Buffer.alloc(32, 0), + }); + + const mutated = Buffer.from(proof); + mutated[0] ^= 1; + + expect( + verifyDLEQProof({ + proof: mutated, + publicKey, + basePoint, + result, + }), + ).toBe(false); + }); + + it("rejects malformed proof lengths", () => { + const secret = hex( + "0000000000000000000000000000000000000000000000000000000000000001", + ); + const baseSecret = hex( + "0000000000000000000000000000000000000000000000000000000000000002", + ); + + const publicKey = pubkeyFromSecret(secret); + const basePoint = pubkeyFromSecret(baseSecret); + const result = multiplyCompressedPoint(basePoint, secret); + + expect( + verifyDLEQProof({ + proof: Buffer.alloc(63), + publicKey, + basePoint, + result, + }), + ).toBe(false); + + expect( + verifyDLEQProof({ + proof: Buffer.alloc(65), + publicKey, + basePoint, + result, + }), + ).toBe(false); + }); +}); diff --git a/packages/caravan-psbt/src/psbtv2/dleq.ts b/packages/caravan-psbt/src/psbtv2/dleq.ts new file mode 100644 index 0000000000..743a2ed46b --- /dev/null +++ b/packages/caravan-psbt/src/psbtv2/dleq.ts @@ -0,0 +1,287 @@ +import { randomBytes } from "crypto"; + +import { secp256k1 } from "@noble/curves/secp256k1"; +import { sha256 } from "@noble/hashes/sha256"; + +const N = secp256k1.CURVE.n; +const G = secp256k1.ProjectivePoint.BASE; +const ZERO = secp256k1.ProjectivePoint.ZERO; + +function taggedHash(tag: string, msg: Buffer): Buffer { + const tagHash = Buffer.from(sha256(Buffer.from(tag, "utf8"))); + return Buffer.from(sha256(Buffer.concat([tagHash, tagHash, msg]))); +} + +function bytesToBigInt(bytes: Buffer): bigint { + if (bytes.length === 0) return 0n; + return BigInt(`0x${bytes.toString("hex")}`); +} + +function bigIntTo32Bytes(n: bigint): Buffer { + if (n < 0n || n >= 1n << 256n) { + throw new Error("Integer does not fit in 32 bytes."); + } + + return Buffer.from(n.toString(16).padStart(64, "0"), "hex"); +} + +function modN(n: bigint): bigint { + const r = n % N; + return r >= 0n ? r : r + N; +} + +function scalarFrom32Bytes(bytes: Buffer, context: string): bigint { + if (bytes.length !== 32) { + throw new Error( + `${context}: expected 32-byte scalar, got ${bytes.length}.`, + ); + } + + const scalar = bytesToBigInt(bytes); + + if (scalar === 0n || scalar >= N) { + throw new Error(`${context}: scalar must be in range [1, n - 1].`); + } + + return scalar; +} + +function assertMessage(message?: Buffer): Buffer { + if (!message) return Buffer.alloc(0); + + if (message.length !== 32) { + throw new Error(`BIP374 message must be 32 bytes, got ${message.length}.`); + } + + return message; +} + +function assertAuxRand(auxRand: Buffer): void { + if (auxRand.length !== 32) { + throw new Error(`BIP374 auxRand must be 32 bytes, got ${auxRand.length}.`); + } +} + +function xor32(a: Buffer, b: Buffer): Buffer { + if (a.length !== 32 || b.length !== 32) { + throw new Error("xor32 requires two 32-byte buffers."); + } + + const out = Buffer.alloc(32); + + for (let i = 0; i < 32; i++) { + out[i] = a[i] ^ b[i]; + } + + return out; +} + +function parsePoint(bytes: Buffer, context: string): typeof G { + try { + const point = secp256k1.ProjectivePoint.fromHex(bytes); + + if (point.equals(ZERO)) { + throw new Error("point at infinity"); + } + + return point; + } catch (e) { + throw new Error(`${context}: invalid secp256k1 point.`); + } +} + +function pointToCompressedBytes(point: typeof G): Buffer { + if (point.equals(ZERO)) { + throw new Error("Cannot serialize point at infinity."); + } + + return Buffer.from(point.toRawBytes(true)); +} + +function multiplyPoint(point: typeof G, scalar: bigint): typeof G { + const k = modN(scalar); + + if (k === 0n) { + return ZERO; + } + + return point.multiply(k); +} + +function multiplyGenerator(scalar: bigint): typeof G { + const k = modN(scalar); + + if (k === 0n) { + return ZERO; + } + + return G.multiply(k); +} + +/** + * Computes scalar * compressedPoint and returns a compressed point. + */ +export function multiplyCompressedPoint( + compressedPoint: Buffer, + scalarBytes: Buffer, +): Buffer { + const scalar = scalarFrom32Bytes(scalarBytes, "multiplyCompressedPoint"); + const point = parsePoint(compressedPoint, "multiplyCompressedPoint point"); + const result = multiplyPoint(point, scalar); + + if (result.equals(ZERO)) { + throw new Error("multiplyCompressedPoint produced point at infinity."); + } + + return pointToCompressedBytes(result); +} + +export function generateDLEQProof({ + secret, + basePoint, + auxRand = randomBytes(32), + message, +}: { + secret: Buffer; + basePoint: Buffer; + auxRand?: Buffer; + message?: Buffer; +}): Buffer { + const a = scalarFrom32Bytes(secret, "BIP374 secret"); + const B = parsePoint(basePoint, "BIP374 basePoint"); + const m = assertMessage(message); + + assertAuxRand(auxRand); + + const A = multiplyGenerator(a); + const C = multiplyPoint(B, a); + + if (A.equals(ZERO) || C.equals(ZERO)) { + throw new Error("BIP374 proof generation produced point at infinity."); + } + + const t = xor32(secret, taggedHash("BIP0374/aux", auxRand)); + + const rand = taggedHash( + "BIP0374/nonce", + Buffer.concat([t, pointToCompressedBytes(A), pointToCompressedBytes(C), m]), + ); + + const k = modN(bytesToBigInt(rand)); + + if (k === 0n) { + throw new Error("BIP374 nonce produced zero scalar."); + } + + const R1 = multiplyGenerator(k); + const R2 = multiplyPoint(B, k); + + if (R1.equals(ZERO) || R2.equals(ZERO)) { + throw new Error("BIP374 nonce produced point at infinity."); + } + + const eBytes = taggedHash( + "BIP0374/challenge", + Buffer.concat([ + pointToCompressedBytes(A), + pointToCompressedBytes(B), + pointToCompressedBytes(C), + pointToCompressedBytes(G), + pointToCompressedBytes(R1), + pointToCompressedBytes(R2), + m, + ]), + ); + + const e = bytesToBigInt(eBytes); + const s = modN(k + modN(e) * a); + const proof = Buffer.concat([eBytes, bigIntTo32Bytes(s)]); + + if ( + !verifyDLEQProof({ + publicKey: pointToCompressedBytes(A), + basePoint, + result: pointToCompressedBytes(C), + proof, + message, + }) + ) { + throw new Error("Generated BIP374 DLEQ proof did not verify."); + } + + return proof; +} + +export function verifyDLEQProof({ + publicKey, + basePoint, + result, + proof, + message, +}: { + publicKey: Buffer; + basePoint: Buffer; + result: Buffer; + proof: Buffer; + message?: Buffer; +}): boolean { + if (proof.length !== 64) { + return false; + } + + let A: typeof G; + let B: typeof G; + let C: typeof G; + + try { + A = parsePoint(publicKey, "BIP374 publicKey"); + B = parsePoint(basePoint, "BIP374 basePoint"); + C = parsePoint(result, "BIP374 result"); + } catch { + return false; + } + + const eBytes = proof.subarray(0, 32); + const sBytes = proof.subarray(32, 64); + + const e = bytesToBigInt(eBytes); + const s = bytesToBigInt(sBytes); + + // BIP374 bounds s, but not e. e is the full 32-byte challenge hash integer. + if (s >= N) { + return false; + } + + let m: Buffer; + + try { + m = assertMessage(message); + } catch { + return false; + } + + const eA = multiplyPoint(A, e); + const eC = multiplyPoint(C, e); + + const R1 = multiplyGenerator(s).add(eA.negate()); + const R2 = multiplyPoint(B, s).add(eC.negate()); + + if (R1.equals(ZERO) || R2.equals(ZERO)) { + return false; + } + + const expectedE = taggedHash( + "BIP0374/challenge", + Buffer.concat([ + pointToCompressedBytes(A), + pointToCompressedBytes(B), + pointToCompressedBytes(C), + pointToCompressedBytes(G), + pointToCompressedBytes(R1), + pointToCompressedBytes(R2), + m, + ]), + ); + + return expectedE.equals(eBytes); +} diff --git a/packages/caravan-psbt/src/psbtv2/psbtv2-bip375.test.ts b/packages/caravan-psbt/src/psbtv2/psbtv2-bip375.test.ts index 6c1df78317..ec68f3e16d 100644 --- a/packages/caravan-psbt/src/psbtv2/psbtv2-bip375.test.ts +++ b/packages/caravan-psbt/src/psbtv2/psbtv2-bip375.test.ts @@ -6,12 +6,38 @@ import { describe, expect, test } from "vitest"; import { PsbtV2 } from "./psbtv2"; import bip375Vectors from "../fixtures/bip375_vectors.json"; import { KeyType } from "src/psbtv2/types"; +import { secp256k1 } from "@noble/curves/secp256k1"; const SKIP_DESCRIPTIONS = new Set([ "ecdh coverage: invalid proof in PSBT_IN_SP_DLEQ field", "ecdh coverage: invalid proof in PSBT_GLOBAL_SP_DLEQ field", ]); +function hex(s: string): Buffer { + return Buffer.from(s, "hex"); +} + +function pubkeyFromSecret(secret: Buffer): Buffer { + return Buffer.from( + secp256k1.ProjectivePoint.BASE.multiply( + BigInt(`0x${secret.toString("hex")}`), + ).toRawBytes(true), + ); +} + +function p2wpkhScript(pubkey: Buffer): Buffer { + // Test-only: use a fixed valid witness program derived from pubkey bytes. + // If the repo already has address/script helpers, prefer those. + const h = Buffer.from( + require("crypto") + .createHash("ripemd160") + .update(require("crypto").createHash("sha256").update(pubkey).digest()) + .digest(), + ); + + return Buffer.concat([Buffer.from([0x00, 0x14]), h]); +} + // ── Invalid vectors ──────────────────────────────────────────────────────── describe("BIP375 invalid vectors", () => { @@ -118,3 +144,229 @@ describe("BIP375 valid vectors", () => { } }); }); + +describe("BIP375 DLEQ integration", () => { + it("adds and validates a global ECDH share with DLEQ proof", () => { + const inputSecret = hex( + "0000000000000000000000000000000000000000000000000000000000000001", + ); + const scanSecret = hex( + "0000000000000000000000000000000000000000000000000000000000000002", + ); + const spendSecret = hex( + "0000000000000000000000000000000000000000000000000000000000000003", + ); + + const inputPubkey = pubkeyFromSecret(inputSecret); + const scanKey = pubkeyFromSecret(scanSecret); + const spendKey = pubkeyFromSecret(spendSecret); + + const psbt = new PsbtV2(); + + psbt.addInput({ + previousTxId: Buffer.alloc(32, 1), + outputIndex: 0, + witnessUtxo: { + amount: 100_000, + script: p2wpkhScript(inputPubkey), + }, + bip32Derivation: [ + { + pubkey: inputPubkey, + masterFingerprint: Buffer.alloc(4, 0), + path: "m/84'/0'/0'/0/0", + }, + ], + }); + + psbt.addOutput({ + amount: 50_000, + silentPayment: { + bscan: scanKey, + bspend: spendKey, + }, + }); + + psbt.addGlobalSPECDHShareWithDLEQ( + scanKey, + inputSecret, + Buffer.alloc(32, 0), + ); + + psbt.computeSilentPaymentOutputScripts(); + + expect(() => new PsbtV2(psbt.serialize())).not.toThrow(); + }); + + it("rejects a mutated global DLEQ proof", () => { + const inputSecret = hex( + "0000000000000000000000000000000000000000000000000000000000000001", + ); + const scanSecret = hex( + "0000000000000000000000000000000000000000000000000000000000000002", + ); + const spendSecret = hex( + "0000000000000000000000000000000000000000000000000000000000000003", + ); + + const inputPubkey = pubkeyFromSecret(inputSecret); + const scanKey = pubkeyFromSecret(scanSecret); + const spendKey = pubkeyFromSecret(spendSecret); + + const psbt = new PsbtV2(); + + psbt.addInput({ + previousTxId: Buffer.alloc(32, 1), + outputIndex: 0, + witnessUtxo: { + amount: 100_000, + script: p2wpkhScript(inputPubkey), + }, + bip32Derivation: [ + { + pubkey: inputPubkey, + masterFingerprint: Buffer.alloc(4, 0), + path: "m/84'/0'/0'/0/0", + }, + ], + }); + + psbt.addOutput({ + amount: 50_000, + silentPayment: { + bscan: scanKey, + bspend: spendKey, + }, + }); + + psbt.addGlobalSPECDHShareWithDLEQ( + scanKey, + inputSecret, + Buffer.alloc(32, 0), + ); + + const proofKey = KeyType.PSBT_GLOBAL_SP_DLEQ + scanKey.toString("hex"); + const proof = Buffer.from(psbt.globalMap.get(proofKey) as Buffer); + proof[0] ^= 1; + psbt.globalMap.set(proofKey, proof); + + psbt.computeSilentPaymentOutputScripts(); + + expect(() => new PsbtV2(psbt.serialize())).toThrow( + /Invalid global silent payment DLEQ proof/, + ); + }); + + it("adds and validates per-input ECDH shares with DLEQ proofs", () => { + const inputSecret = hex( + "0000000000000000000000000000000000000000000000000000000000000001", + ); + const scanSecret = hex( + "0000000000000000000000000000000000000000000000000000000000000002", + ); + const spendSecret = hex( + "0000000000000000000000000000000000000000000000000000000000000003", + ); + + const inputPubkey = pubkeyFromSecret(inputSecret); + const scanKey = pubkeyFromSecret(scanSecret); + const spendKey = pubkeyFromSecret(spendSecret); + + const psbt = new PsbtV2(); + + psbt.addInput({ + previousTxId: Buffer.alloc(32, 1), + outputIndex: 0, + witnessUtxo: { + amount: 100_000, + script: p2wpkhScript(inputPubkey), + }, + bip32Derivation: [ + { + pubkey: inputPubkey, + masterFingerprint: Buffer.alloc(4, 0), + path: "m/84'/0'/0'/0/0", + }, + ], + }); + + psbt.addOutput({ + amount: 50_000, + silentPayment: { + bscan: scanKey, + bspend: spendKey, + }, + }); + + psbt.addInputSPECDHShareWithDLEQ( + 0, + scanKey, + inputSecret, + Buffer.alloc(32, 0), + ); + + psbt.computeSilentPaymentOutputScripts(); + + expect(() => new PsbtV2(psbt.serialize())).not.toThrow(); + }); + + it("rejects a mutated per-input DLEQ proof", () => { + const inputSecret = hex( + "0000000000000000000000000000000000000000000000000000000000000001", + ); + const scanSecret = hex( + "0000000000000000000000000000000000000000000000000000000000000002", + ); + const spendSecret = hex( + "0000000000000000000000000000000000000000000000000000000000000003", + ); + + const inputPubkey = pubkeyFromSecret(inputSecret); + const scanKey = pubkeyFromSecret(scanSecret); + const spendKey = pubkeyFromSecret(spendSecret); + + const psbt = new PsbtV2(); + + psbt.addInput({ + previousTxId: Buffer.alloc(32, 1), + outputIndex: 0, + witnessUtxo: { + amount: 100_000, + script: p2wpkhScript(inputPubkey), + }, + bip32Derivation: [ + { + pubkey: inputPubkey, + masterFingerprint: Buffer.alloc(4, 0), + path: "m/84'/0'/0'/0/0", + }, + ], + }); + + psbt.addOutput({ + amount: 50_000, + silentPayment: { + bscan: scanKey, + bspend: spendKey, + }, + }); + + psbt.addInputSPECDHShareWithDLEQ( + 0, + scanKey, + inputSecret, + Buffer.alloc(32, 0), + ); + + const proofKey = KeyType.PSBT_IN_SP_DLEQ + scanKey.toString("hex"); + const proof = Buffer.from(psbt.inputMaps[0].get(proofKey) as Buffer); + proof[0] ^= 1; + psbt.inputMaps[0].set(proofKey, proof); + + psbt.computeSilentPaymentOutputScripts(); + + expect(() => new PsbtV2(psbt.serialize())).toThrow( + /Invalid input 0 silent payment DLEQ proof/, + ); + }); +}); diff --git a/packages/caravan-psbt/src/psbtv2/psbtv2.ts b/packages/caravan-psbt/src/psbtv2/psbtv2.ts index dcee1efd93..64ec9592ad 100644 --- a/packages/caravan-psbt/src/psbtv2/psbtv2.ts +++ b/packages/caravan-psbt/src/psbtv2/psbtv2.ts @@ -39,6 +39,8 @@ import { SPInputDescriptor, SPOutputEntry, sumECDHShares, + generateSilentPaymentDLEQProof, + verifySilentPaymentDLEQProof, } from "src/psbtv2/silentpayment"; /** @@ -1183,6 +1185,20 @@ export class PsbtV2 extends PsbtV2Maps { `Could not compute aggregate public key for global DLEQ verification for scan key ${bscanHex}.`, ); } + + if ( + !verifySilentPaymentDLEQProof({ + publicKey: Buffer.from(aggregatePubkey.toRawBytes(true)), + scanKey: Buffer.from(bscanHex, "hex"), + ecdhShare, + proof, + }) + ) { + throw Error( + `Invalid global silent payment DLEQ proof for scan key ${bscanHex}.`, + ); + } + continue; } @@ -1219,6 +1235,20 @@ export class PsbtV2 extends PsbtV2Maps { `Input ${i} missing public key for silent payment DLEQ verification.`, ); } + + if ( + !verifySilentPaymentDLEQProof({ + publicKey: Buffer.from(inputPubkey.toRawBytes(true)), + scanKey: Buffer.from(bscanHex, "hex"), + ecdhShare, + proof, + }) + ) { + throw Error( + `Invalid input ${i} silent payment DLEQ proof for scan key ${bscanHex}.`, + ); + } + // A per-input SP DLEQ proof requires the input public key as A. // Even before semantic BIP374 verification, reject proof-bearing // eligible inputs whose public key cannot be recovered from the PSBT. @@ -1835,23 +1865,43 @@ export class PsbtV2 extends PsbtV2Maps { this.globalMap.set(key, proof); } + public addGlobalSPECDHShareWithDLEQ( + bscan: Buffer, + aggregateSecret: Buffer, + auxRand?: Buffer, + ): void { + const { ecdhShare, proof } = generateSilentPaymentDLEQProof({ + secret: aggregateSecret, + scanKey: bscan, + auxRand, + }); - public addInputSPECDHShare( + this.addGlobalSPECDHShare(bscan, ecdhShare); + this.addGlobalSPDLEQProof(bscan, proof); + } + + public addInputSPECDHShareWithDLEQ( inputIndex: number, bscan: Buffer, - share: Buffer, + inputSecret: Buffer, + auxRand?: Buffer, ): void { if (inputIndex < 0 || inputIndex >= this.inputMaps.length) { throw new Error( `inputIndex ${inputIndex} out of range (${this.inputMaps.length} inputs)`, ); } - if (bscan.length !== 33) { - throw new Error( - `bscan must be a 33-byte compressed pubkey, got ${bscan.length}`, - ); - } - if (share.length !== 33) { + + const { ecdhShare, proof } = generateSilentPaymentDLEQProof({ + secret: inputSecret, + scanKey: bscan, + auxRand, + }); + + this.addInputSPECDHShare(inputIndex, bscan, ecdhShare); + this.addInputSPDLEQProof(inputIndex, bscan, proof); + } + // ── Per-input SP methods ────────────────────────────────────────────────── public addInputSPECDHShare( diff --git a/packages/caravan-psbt/src/psbtv2/silentpayment.ts b/packages/caravan-psbt/src/psbtv2/silentpayment.ts index 3a17cd80f3..7404523cc4 100644 --- a/packages/caravan-psbt/src/psbtv2/silentpayment.ts +++ b/packages/caravan-psbt/src/psbtv2/silentpayment.ts @@ -16,6 +16,11 @@ const CURVE_ORDER = secp256k1.CURVE.n; const { bytesToNumberBE } = schnorr.utils; const { OPS } = script; import { Transaction } from "bitcoinjs-lib-v6"; +import { + generateDLEQProof, + multiplyCompressedPoint, + verifyDLEQProof, +} from "./dleq"; // ── Internal types ───────────────────────────────────────────────────────── export type ProjectivePoint = InstanceType; @@ -493,3 +498,57 @@ export function deriveSilentPaymentOutput( const xOnlyPk = Pk.toRawBytes(true).subarray(1); return Buffer.concat([Buffer.from([OPS.OP_1, 0x20]), xOnlyPk]); } + +export function generateSilentPaymentDLEQProof({ + secret, + scanKey, + auxRand, +}: { + secret: Buffer; + scanKey: Buffer; + auxRand?: Buffer; +}): { + ecdhShare: Buffer; + proof: Buffer; +} { + assertValidBscan(scanKey); + + const ecdhShare = multiplyCompressedPoint(scanKey, secret); + assertValidECDHShare(ecdhShare); + + const proof = generateDLEQProof({ + secret, + basePoint: scanKey, + auxRand, + }); + + assertValidDLEQProof(proof); + + return { + ecdhShare, + proof, + }; +} + +export function verifySilentPaymentDLEQProof({ + publicKey, + scanKey, + ecdhShare, + proof, +}: { + publicKey: Buffer; + scanKey: Buffer; + ecdhShare: Buffer; + proof: Buffer; +}): boolean { + assertValidBscan(scanKey); + assertValidECDHShare(ecdhShare); + assertValidDLEQProof(proof); + + return verifyDLEQProof({ + publicKey, + basePoint: scanKey, + result: ecdhShare, + proof, + }); +} From 124ba9e81a5abc3560305ab6ba38de8fd5493ddb Mon Sep 17 00:00:00 2001 From: Jasper van Gelder Date: Wed, 20 May 2026 14:36:46 +0200 Subject: [PATCH 13/26] chore(dleq): Cleanup functions Removed function overhead. Moved ProjectivePoint for reusability. --- packages/caravan-psbt/src/psbtv2/dleq.ts | 168 +++++++----------- packages/caravan-psbt/src/psbtv2/psbtv2.ts | 3 +- .../caravan-psbt/src/psbtv2/silentpayment.ts | 4 +- 3 files changed, 64 insertions(+), 111 deletions(-) diff --git a/packages/caravan-psbt/src/psbtv2/dleq.ts b/packages/caravan-psbt/src/psbtv2/dleq.ts index 743a2ed46b..516f030c16 100644 --- a/packages/caravan-psbt/src/psbtv2/dleq.ts +++ b/packages/caravan-psbt/src/psbtv2/dleq.ts @@ -2,6 +2,10 @@ import { randomBytes } from "crypto"; import { secp256k1 } from "@noble/curves/secp256k1"; import { sha256 } from "@noble/hashes/sha256"; +import { bytesToNumberBE, numberToBytesBE } from "@noble/curves/abstract/utils"; +import { mod } from "@noble/curves/abstract/modular"; + +export type ProjectivePoint = InstanceType; const N = secp256k1.CURVE.n; const G = secp256k1.ProjectivePoint.BASE; @@ -12,38 +16,12 @@ function taggedHash(tag: string, msg: Buffer): Buffer { return Buffer.from(sha256(Buffer.concat([tagHash, tagHash, msg]))); } -function bytesToBigInt(bytes: Buffer): bigint { - if (bytes.length === 0) return 0n; - return BigInt(`0x${bytes.toString("hex")}`); -} - -function bigIntTo32Bytes(n: bigint): Buffer { - if (n < 0n || n >= 1n << 256n) { - throw new Error("Integer does not fit in 32 bytes."); - } - - return Buffer.from(n.toString(16).padStart(64, "0"), "hex"); -} - -function modN(n: bigint): bigint { - const r = n % N; - return r >= 0n ? r : r + N; -} - -function scalarFrom32Bytes(bytes: Buffer, context: string): bigint { - if (bytes.length !== 32) { - throw new Error( - `${context}: expected 32-byte scalar, got ${bytes.length}.`, - ); +function scalarFromPrivateKey(bytes: Buffer, context: string): bigint { + if (!secp256k1.utils.isValidPrivateKey(bytes)) { + throw new Error(`${context}: invalid secp256k1 scalar.`); } - const scalar = bytesToBigInt(bytes); - - if (scalar === 0n || scalar >= N) { - throw new Error(`${context}: scalar must be in range [1, n - 1].`); - } - - return scalar; + return bytesToNumberBE(bytes); } function assertMessage(message?: Buffer): Buffer { @@ -76,18 +54,8 @@ function xor32(a: Buffer, b: Buffer): Buffer { return out; } -function parsePoint(bytes: Buffer, context: string): typeof G { - try { - const point = secp256k1.ProjectivePoint.fromHex(bytes); - - if (point.equals(ZERO)) { - throw new Error("point at infinity"); - } - - return point; - } catch (e) { - throw new Error(`${context}: invalid secp256k1 point.`); - } +function pointFromCompressed(bytes: Buffer): ProjectivePoint { + return secp256k1.ProjectivePoint.fromHex(bytes); } function pointToCompressedBytes(point: typeof G): Buffer { @@ -98,26 +66,6 @@ function pointToCompressedBytes(point: typeof G): Buffer { return Buffer.from(point.toRawBytes(true)); } -function multiplyPoint(point: typeof G, scalar: bigint): typeof G { - const k = modN(scalar); - - if (k === 0n) { - return ZERO; - } - - return point.multiply(k); -} - -function multiplyGenerator(scalar: bigint): typeof G { - const k = modN(scalar); - - if (k === 0n) { - return ZERO; - } - - return G.multiply(k); -} - /** * Computes scalar * compressedPoint and returns a compressed point. */ @@ -125,15 +73,19 @@ export function multiplyCompressedPoint( compressedPoint: Buffer, scalarBytes: Buffer, ): Buffer { - const scalar = scalarFrom32Bytes(scalarBytes, "multiplyCompressedPoint"); - const point = parsePoint(compressedPoint, "multiplyCompressedPoint point"); - const result = multiplyPoint(point, scalar); + const scalar = scalarFromPrivateKey( + scalarBytes, + "multiplyCompressedPoint scalar", + ); + + const result = + secp256k1.ProjectivePoint.fromHex(compressedPoint).multiply(scalar); if (result.equals(ZERO)) { throw new Error("multiplyCompressedPoint produced point at infinity."); } - return pointToCompressedBytes(result); + return Buffer.from(result.toRawBytes(true)); } export function generateDLEQProof({ @@ -147,61 +99,69 @@ export function generateDLEQProof({ auxRand?: Buffer; message?: Buffer; }): Buffer { - const a = scalarFrom32Bytes(secret, "BIP374 secret"); - const B = parsePoint(basePoint, "BIP374 basePoint"); + const a = scalarFromPrivateKey(secret, "BIP374 secret"); + const B = pointFromCompressed(basePoint); const m = assertMessage(message); assertAuxRand(auxRand); - const A = multiplyGenerator(a); - const C = multiplyPoint(B, a); + const A = G.multiply(a); + const C = B.multiply(a); if (A.equals(ZERO) || C.equals(ZERO)) { throw new Error("BIP374 proof generation produced point at infinity."); } + const ABytes = Buffer.from(A.toRawBytes(true)); + const BBytes = Buffer.from(B.toRawBytes(true)); + const CBytes = Buffer.from(C.toRawBytes(true)); + const t = xor32(secret, taggedHash("BIP0374/aux", auxRand)); const rand = taggedHash( "BIP0374/nonce", - Buffer.concat([t, pointToCompressedBytes(A), pointToCompressedBytes(C), m]), + Buffer.concat([t, ABytes, CBytes, m]), ); - const k = modN(bytesToBigInt(rand)); + const k = mod(bytesToNumberBE(rand), N); if (k === 0n) { throw new Error("BIP374 nonce produced zero scalar."); } - const R1 = multiplyGenerator(k); - const R2 = multiplyPoint(B, k); + const R1 = G.multiply(k); + const R2 = B.multiply(k); if (R1.equals(ZERO) || R2.equals(ZERO)) { throw new Error("BIP374 nonce produced point at infinity."); } + const R1Bytes = Buffer.from(R1.toRawBytes(true)); + const R2Bytes = Buffer.from(R2.toRawBytes(true)); + const eBytes = taggedHash( "BIP0374/challenge", Buffer.concat([ - pointToCompressedBytes(A), - pointToCompressedBytes(B), - pointToCompressedBytes(C), - pointToCompressedBytes(G), - pointToCompressedBytes(R1), - pointToCompressedBytes(R2), + ABytes, + BBytes, + CBytes, + Buffer.from(G.toRawBytes(true)), + R1Bytes, + R2Bytes, m, ]), ); - const e = bytesToBigInt(eBytes); - const s = modN(k + modN(e) * a); - const proof = Buffer.concat([eBytes, bigIntTo32Bytes(s)]); + const e = bytesToNumberBE(eBytes); + const s = mod(k + mod(e, N) * a, N); + + const proof = Buffer.concat([eBytes, Buffer.from(numberToBytesBE(s, 32))]); if ( !verifyDLEQProof({ - publicKey: pointToCompressedBytes(A), + publicKey: ABytes, basePoint, - result: pointToCompressedBytes(C), + result: CBytes, proof, message, }) @@ -229,14 +189,13 @@ export function verifyDLEQProof({ return false; } - let A: typeof G; - let B: typeof G; - let C: typeof G; - + let A: ProjectivePoint; + let B: ProjectivePoint; + let C: ProjectivePoint; try { - A = parsePoint(publicKey, "BIP374 publicKey"); - B = parsePoint(basePoint, "BIP374 basePoint"); - C = parsePoint(result, "BIP374 result"); + A = pointFromCompressed(publicKey); + B = pointFromCompressed(basePoint); + C = pointFromCompressed(result); } catch { return false; } @@ -244,32 +203,29 @@ export function verifyDLEQProof({ const eBytes = proof.subarray(0, 32); const sBytes = proof.subarray(32, 64); - const e = bytesToBigInt(eBytes); - const s = bytesToBigInt(sBytes); + const e = bytesToNumberBE(eBytes); + const s = bytesToNumberBE(sBytes); - // BIP374 bounds s, but not e. e is the full 32-byte challenge hash integer. if (s >= N) { return false; } - let m: Buffer; + const eReduced = mod(e, N); - try { - m = assertMessage(message); - } catch { + const R1 = G.multiply(s).add(A.multiply(eReduced).negate()); + const R2 = B.multiply(s).add(C.multiply(eReduced).negate()); + + if (R1.equals(ZERO) || R2.equals(ZERO)) { return false; } - const eA = multiplyPoint(A, e); - const eC = multiplyPoint(C, e); - - const R1 = multiplyGenerator(s).add(eA.negate()); - const R2 = multiplyPoint(B, s).add(eC.negate()); + let m: Buffer; - if (R1.equals(ZERO) || R2.equals(ZERO)) { + try { + m = assertMessage(message); + } catch { return false; } - const expectedE = taggedHash( "BIP0374/challenge", Buffer.concat([ diff --git a/packages/caravan-psbt/src/psbtv2/psbtv2.ts b/packages/caravan-psbt/src/psbtv2/psbtv2.ts index 64ec9592ad..972cf74b00 100644 --- a/packages/caravan-psbt/src/psbtv2/psbtv2.ts +++ b/packages/caravan-psbt/src/psbtv2/psbtv2.ts @@ -35,14 +35,13 @@ import { groupSilentPaymentOutputs, hasSegwitV2PlusInput, BIP352_NUMS_H, - ProjectivePoint, SPInputDescriptor, SPOutputEntry, sumECDHShares, generateSilentPaymentDLEQProof, verifySilentPaymentDLEQProof, } from "src/psbtv2/silentpayment"; - +import { ProjectivePoint } from "src/psbtv2/dleq"; /** * The PsbtV2 class is intended to represent an easily modifiable and * serializable psbt of version 2 conforming to BIP0174. Getters exist for all diff --git a/packages/caravan-psbt/src/psbtv2/silentpayment.ts b/packages/caravan-psbt/src/psbtv2/silentpayment.ts index 7404523cc4..8d71cd6a42 100644 --- a/packages/caravan-psbt/src/psbtv2/silentpayment.ts +++ b/packages/caravan-psbt/src/psbtv2/silentpayment.ts @@ -20,10 +20,8 @@ import { generateDLEQProof, multiplyCompressedPoint, verifyDLEQProof, + ProjectivePoint, } from "./dleq"; -// ── Internal types ───────────────────────────────────────────────────────── - -export type ProjectivePoint = InstanceType; // ── Public types ─────────────────────────────────────────────────────────── From e1f7cfd2a7e537929056fa262c294ca0f708bb2c Mon Sep 17 00:00:00 2001 From: Jasper van Gelder Date: Wed, 20 May 2026 14:37:38 +0200 Subject: [PATCH 14/26] chore(bip375): Enable all tests We previously did not check dleq so we disabled those tests now we do so we reenable them. --- .../caravan-psbt/src/psbtv2/psbtv2-bip375.test.ts | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/packages/caravan-psbt/src/psbtv2/psbtv2-bip375.test.ts b/packages/caravan-psbt/src/psbtv2/psbtv2-bip375.test.ts index ec68f3e16d..943fd311f7 100644 --- a/packages/caravan-psbt/src/psbtv2/psbtv2-bip375.test.ts +++ b/packages/caravan-psbt/src/psbtv2/psbtv2-bip375.test.ts @@ -8,11 +8,6 @@ import bip375Vectors from "../fixtures/bip375_vectors.json"; import { KeyType } from "src/psbtv2/types"; import { secp256k1 } from "@noble/curves/secp256k1"; -const SKIP_DESCRIPTIONS = new Set([ - "ecdh coverage: invalid proof in PSBT_IN_SP_DLEQ field", - "ecdh coverage: invalid proof in PSBT_GLOBAL_SP_DLEQ field", -]); - function hex(s: string): Buffer { return Buffer.from(s, "hex"); } @@ -41,9 +36,7 @@ function p2wpkhScript(pubkey: Buffer): Buffer { // ── Invalid vectors ──────────────────────────────────────────────────────── describe("BIP375 invalid vectors", () => { - test.each( - bip375Vectors.invalid.filter((v) => !SKIP_DESCRIPTIONS.has(v.description)), - )("$description", ({ psbt }) => { + test.each(bip375Vectors.invalid)("$description", ({ psbt }) => { expect(() => { const p = new PsbtV2(psbt); p.validate(); @@ -54,9 +47,7 @@ describe("BIP375 invalid vectors", () => { // ── Valid vectors ────────────────────────────────────────────────────────── describe("BIP375 valid vectors", () => { - test.each( - bip375Vectors.valid.filter((v) => !SKIP_DESCRIPTIONS.has(v.description)), - )("$description", ({ psbt, supplementary }) => { + test.each(bip375Vectors.valid)("$description", ({ psbt, supplementary }) => { const p = new PsbtV2(psbt); expect(() => p.validate()).not.toThrow(); From 8ee5f65ee414dc31391b787aed621795369b4d89 Mon Sep 17 00:00:00 2001 From: Jasper van Gelder Date: Wed, 20 May 2026 14:57:19 +0200 Subject: [PATCH 15/26] fix(psbtv2): Fix nums check --- packages/caravan-psbt/src/psbtv2/psbtv2.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/caravan-psbt/src/psbtv2/psbtv2.ts b/packages/caravan-psbt/src/psbtv2/psbtv2.ts index 972cf74b00..5671ad7fce 100644 --- a/packages/caravan-psbt/src/psbtv2/psbtv2.ts +++ b/packages/caravan-psbt/src/psbtv2/psbtv2.ts @@ -933,9 +933,10 @@ export class PsbtV2 extends PsbtV2Maps { } private hasNumsTaprootScriptPathSpend(inputIndex: number): boolean { - const internalKey = this.PSBT_IN_TAP_INTERNAL_KEY[inputIndex]; + const internalKey: string | null = + this.PSBT_IN_TAP_INTERNAL_KEY[inputIndex]; - if (internalKey?.toString("hex") === BIP352_NUMS_H) { + if (internalKey === BIP352_NUMS_H) { return true; } From d1db68eb455ed9aa8a639aaf62d41115b5d1450b Mon Sep 17 00:00:00 2001 From: Jasper van Gelder Date: Fri, 5 Jun 2026 17:08:12 +0200 Subject: [PATCH 16/26] fix(caravan-psbt): require prevout-matched keys for SP derivation Replace the first-BIP32-pubkey fallback with candidate pubkey recovery from BIP32 derivations, partial signatures, and finalized input scripts. Only pubkeys matching the spent output are used for DLEQ verification and input_hash recomputation, preventing SP outputs from being derived from a decoy key. --- packages/caravan-psbt/src/psbtv2/psbtv2.ts | 608 +++++++++------------ 1 file changed, 253 insertions(+), 355 deletions(-) diff --git a/packages/caravan-psbt/src/psbtv2/psbtv2.ts b/packages/caravan-psbt/src/psbtv2/psbtv2.ts index 5671ad7fce..bb57a9a91f 100644 --- a/packages/caravan-psbt/src/psbtv2/psbtv2.ts +++ b/packages/caravan-psbt/src/psbtv2/psbtv2.ts @@ -30,11 +30,10 @@ import { scanKeyHexFromBIP375Key, computeInputHash, deriveSilentPaymentOutput, - eligibleIndices, - getTaprootOutputKeyFromWitnessUtxo, + contributingIndices, + getSilentPaymentPubkeyFromInputDescriptor, groupSilentPaymentOutputs, hasSegwitV2PlusInput, - BIP352_NUMS_H, SPInputDescriptor, SPOutputEntry, sumECDHShares, @@ -594,6 +593,7 @@ export class PsbtV2 extends PsbtV2Maps { if (this.isReadyForTransactionExtractor) { return false; } + // Per BIP375: if SP outputs are present, all must have a computed // PSBT_OUT_SCRIPT before signing is permitted. if (this.hasSilentPaymentOutputs && !this.hasAllSPOutputScripts) { @@ -845,7 +845,7 @@ export class PsbtV2 extends PsbtV2Maps { } private getSilentPaymentInputDescriptors(): SPInputDescriptor[] { - return this.inputMaps.map((map) => { + return this.inputMaps.map((map, i) => { const outputIndex = map.get(KeyType.PSBT_IN_OUTPUT_INDEX); return { @@ -853,6 +853,8 @@ export class PsbtV2 extends PsbtV2Maps { nonWitnessUtxo: map.get(KeyType.PSBT_IN_NON_WITNESS_UTXO) ?? null, outputIndex: outputIndex ? outputIndex.readUInt32LE(0) : null, redeemScript: map.get(KeyType.PSBT_IN_REDEEM_SCRIPT) ?? null, + tapInternalKey: this.PSBT_IN_TAP_INTERNAL_KEY[i], + tapLeafScriptKeys: this.PSBT_IN_TAP_LEAF_SCRIPT[i].map((e) => e.key), }; }); } @@ -867,7 +869,6 @@ export class PsbtV2 extends PsbtV2Maps { private getSilentPaymentOutputGroups( onlyWithScripts = false, - skipLabeled = false, ): Map { const entries: SPOutputEntry[] = []; @@ -875,10 +876,6 @@ export class PsbtV2 extends PsbtV2Maps { const info = this.getSilentPaymentOutputInfo(i); if (!info) continue; - if (skipLabeled && this.outputMaps[i].has(KeyType.PSBT_OUT_SP_V0_LABEL)) { - continue; - } - if (onlyWithScripts) { const script = this.outputMaps[i].get(KeyType.PSBT_OUT_SCRIPT); if (!script || script.length === 0) continue; @@ -890,38 +887,78 @@ export class PsbtV2 extends PsbtV2Maps { return groupSilentPaymentOutputs(entries); } - private getInputAggregatePubkey( - eligible: number[], - requirePubkeysForDleqVerification = false, - ): ProjectivePoint | null { - let combinedPubkey: ProjectivePoint | null = null; + private getFinalScriptWitnessPubkeys(inputIndex: number): Buffer[] { + const witnessHex = this.PSBT_IN_FINAL_SCRIPTWITNESS[inputIndex]; - for (const i of eligible) { - if (this.hasNumsTaprootScriptPathSpend(i)) { - continue; - } + if (!witnessHex) { + return []; + } + + const witness = Buffer.from(witnessHex, "hex"); + const pubkeys: Buffer[] = []; - const witnessUtxo = this.inputMaps[i].get(KeyType.PSBT_IN_WITNESS_UTXO); - let pubkeyBytes: Buffer | null = null; + for (let i = 0; i <= witness.length - 33; i++) { + const candidate = witness.subarray(i, i + 33); - if (witnessUtxo) { - pubkeyBytes = getTaprootOutputKeyFromWitnessUtxo(witnessUtxo); + if (candidate[0] === 0x02 || candidate[0] === 0x03) { + pubkeys.push(Buffer.from(candidate)); } + } - if (!pubkeyBytes) { - const entries = this.PSBT_IN_BIP32_DERIVATION[i]; - if (entries.length > 0) { - pubkeyBytes = Buffer.from(entries[0].key.slice(2), "hex"); - } + return pubkeys; + } + + private getFinalScriptSigPubkeys(inputIndex: number): Buffer[] { + const scriptSigHex = this.PSBT_IN_FINAL_SCRIPTSIG[inputIndex]; + + if (!scriptSigHex) { + return []; + } + + const scriptSig = Buffer.from(scriptSigHex, "hex"); + const pubkeys: Buffer[] = []; + + for (let i = 0; i <= scriptSig.length - 33; i++) { + const candidate = scriptSig.subarray(i, i + 33); + + if (candidate[0] === 0x02 || candidate[0] === 0x03) { + pubkeys.push(Buffer.from(candidate)); } + } - if (!pubkeyBytes) { - if (requirePubkeysForDleqVerification) { - throw Error( - `Input ${i} missing public key for silent payment DLEQ verification.`, - ); - } + return pubkeys; + } + + private getSilentPaymentCandidatePubkeys(inputIndex: number): Buffer[] { + const bip32Pubkeys = this.PSBT_IN_BIP32_DERIVATION[inputIndex].map( + (entry) => Buffer.from(entry.key.slice(2), "hex"), + ); + + const partialSigPubkeys = this.PSBT_IN_PARTIAL_SIG[inputIndex].map( + (entry) => Buffer.from(entry.key.slice(2), "hex"), + ); + + return [ + ...bip32Pubkeys, + ...partialSigPubkeys, + ...this.getFinalScriptWitnessPubkeys(inputIndex), + ...this.getFinalScriptSigPubkeys(inputIndex), + ]; + } + + private tryGetInputAggregatePubkey( + contributing: number[], + ): ProjectivePoint | null { + let combinedPubkey: ProjectivePoint | null = null; + const descriptors = this.getSilentPaymentInputDescriptors(); + + for (const i of contributing) { + const pubkeyBytes = getSilentPaymentPubkeyFromInputDescriptor( + descriptors[i], + this.getSilentPaymentCandidatePubkeys(i), + ); + if (!pubkeyBytes) { continue; } @@ -932,23 +969,133 @@ export class PsbtV2 extends PsbtV2Maps { return combinedPubkey; } - private hasNumsTaprootScriptPathSpend(inputIndex: number): boolean { - const internalKey: string | null = - this.PSBT_IN_TAP_INTERNAL_KEY[inputIndex]; + private getInputAggregatePubkey(contributing: number[]): ProjectivePoint { + const aggregate = this.tryGetInputAggregatePubkey(contributing); - if (internalKey === BIP352_NUMS_H) { - return true; + if (!aggregate) { + throw Error("Missing matching public key for silent payment derivation."); } - return this.PSBT_IN_TAP_LEAF_SCRIPT[inputIndex].some((entry) => { - const keydata = Buffer.from(entry.key.slice(2), "hex"); + return aggregate; + } - if (keydata.length < 33) { - return false; + /** + * Computes the BIP352 input hash from all outpoints and the aggregate public + * key of the contributing inputs. This is strict: callers that validate or + * create computed SP output scripts must be able to recover prevout-matched + * input pubkeys. + */ + private computeSilentPaymentInputHash(contributingInputs: number[]): Buffer { + const outpoints = this.getAllOutpoints(); + + if (outpoints.length === 0) { + throw Error("At least one outpoint is required to compute inputHash."); + } + + const combinedPubkey = this.getInputAggregatePubkey(contributingInputs); + + return computeInputHash( + outpoints, + Buffer.from(combinedPubkey.toRawBytes(true)), + ); + } + + /** + * Resolves the ECDH share for a scan key while verifying its DLEQ proof(s) + * when the required input pubkey is recoverable. Share/proof pairing is + * mandatory, but semantic proof verification can be deferred for in-progress + * PSBTs whose input pubkeys are not yet recoverable. + */ + private resolveAndVerifyScanKeyEcdhShare( + bscanHex: string, + contributingInputs: number[], + ): Buffer | null { + const globalShareKey = KeyType.PSBT_GLOBAL_SP_ECDH_SHARE + bscanHex; + + if (this.globalMap.has(globalShareKey)) { + const proofKey = KeyType.PSBT_GLOBAL_SP_DLEQ + bscanHex; + const ecdhShare = this.globalMap.get(globalShareKey) as Buffer; + const proof = this.globalMap.get(proofKey); + + if (!proof) { + throw Error( + `Global ECDH share missing PSBT_GLOBAL_SP_DLEQ for scan key ${bscanHex}.`, + ); } - return keydata.subarray(1, 33).toString("hex") === BIP352_NUMS_H; - }); + const aggregatePubkey = + this.tryGetInputAggregatePubkey(contributingInputs); + + if (aggregatePubkey) { + if ( + !verifySilentPaymentDLEQProof({ + publicKey: Buffer.from(aggregatePubkey.toRawBytes(true)), + scanKey: Buffer.from(bscanHex, "hex"), + ecdhShare, + proof, + }) + ) { + throw Error( + `Invalid global silent payment DLEQ proof for scan key ${bscanHex}.`, + ); + } + } + + return ecdhShare; + } + + if (contributingInputs.length === 0) { + throw Error( + `Output script set for scan key ${bscanHex} but no contributing inputs can derive it.`, + ); + } + + const perInputBuffers: Buffer[] = []; + + for (const i of contributingInputs) { + const shareKey = KeyType.PSBT_IN_SP_ECDH_SHARE + bscanHex; + const proofKey = KeyType.PSBT_IN_SP_DLEQ + bscanHex; + const ecdhShare = this.inputMaps[i].get(shareKey); + + if (!ecdhShare) { + throw Error( + `Output script set but contributing input ${i} missing ECDH share for scan key ${bscanHex}`, + ); + } + + const proof = this.inputMaps[i].get(proofKey); + + if (!proof) { + throw Error( + `Input ${i} ECDH share missing PSBT_IN_SP_DLEQ for scan key ${bscanHex}.`, + ); + } + + const inputPubkey = this.tryGetInputAggregatePubkey([i]); + + if (inputPubkey) { + if ( + !verifySilentPaymentDLEQProof({ + publicKey: Buffer.from(inputPubkey.toRawBytes(true)), + scanKey: Buffer.from(bscanHex, "hex"), + ecdhShare, + proof, + }) + ) { + throw Error( + `Invalid input ${i} silent payment DLEQ proof for scan key ${bscanHex}.`, + ); + } + } + + perInputBuffers.push(ecdhShare); + } + + if (perInputBuffers.length === 0) { + return null; + } + + return Buffer.from(sumECDHShares(perInputBuffers).toRawBytes(true)); } /** @@ -960,6 +1107,10 @@ export class PsbtV2 extends PsbtV2Maps { * 3. ECDH coverage checks — only when SP outputs have PSBT_OUT_SCRIPT set */ private validateSilentPayments() { + if (!this.hasSilentPaymentOutputs) { + return; + } + // ── Output map structural checks ─────────────────────────────────────── for (const [i, outputMap] of this.outputMaps.entries()) { const spInfo = outputMap.get(KeyType.PSBT_OUT_SP_V0_INFO); @@ -1068,10 +1219,6 @@ export class PsbtV2 extends PsbtV2Maps { } } - if (!this.hasSilentPaymentOutputs) { - return; - } - // ── SP-wide restrictions that apply whenever SP outputs exist ────────── if (hasSegwitV2PlusInput(this.getSilentPaymentInputDescriptors())) { throw Error( @@ -1093,262 +1240,23 @@ export class PsbtV2 extends PsbtV2Maps { } } - // Only non-labeled SP outputs can be recomputed from public PSBT data. - // Labeled outputs require recipient-side label state / scan private key. - const computedSPScanKeys = new Set(); - - for (let i = 0; i < this.outputMaps.length; i++) { - const outputMap = this.outputMaps[i]; + const contributingInputs = this.getContributingInputsForSilentPayments(); - if (!outputMap.has(KeyType.PSBT_OUT_SP_V0_INFO)) { - continue; - } + // ECDH coverage is only required per scan key that has a computed SP output + // script. Scan keys whose outputs are still in progress (no PSBT_OUT_SCRIPT) + // may have missing ECDH/DLEQ data + const inputHash = this.computeSilentPaymentInputHash(contributingInputs); - if (outputMap.has(KeyType.PSBT_OUT_SP_V0_LABEL)) { - continue; - } - - const script = outputMap.get(KeyType.PSBT_OUT_SCRIPT); - - if (!script || script.length === 0) { - continue; - } - - const info = this.getSilentPaymentOutputInfo(i); - - if (info) { - computedSPScanKeys.add(info.bscan.toString("hex")); - } - } - - // No non-labeled SP output script has been computed yet. Structural checks - // above are enough for an in-progress PSBT. - if (computedSPScanKeys.size === 0) { - return; - } - - const eligible = this.getEligibleInputsForSilentPayments(); - - if (eligible.length === 0) { - throw Error( - "No eligible inputs for silent payment ECDH derivation — all inputs are ineligible.", + for (const [bscanHex, group] of this.getSilentPaymentOutputGroups(true)) { + const ecdhShare = this.resolveAndVerifyScanKeyEcdhShare( + bscanHex, + contributingInputs, ); - } - // NUMS P2TR script-path inputs are skipped for SP derivation, but must not - // carry SP ECDH/DLEQ fields. - for (const i of eligible) { - if (!this.hasNumsTaprootScriptPathSpend(i)) { + if (!ecdhShare) { continue; } - for (const key of this.inputMaps[i].keys()) { - if ( - key.startsWith(KeyType.PSBT_IN_SP_ECDH_SHARE) || - key.startsWith(KeyType.PSBT_IN_SP_DLEQ) - ) { - throw Error( - `Input ${i}: NUMS P2TR script-path input must not have silent payment ECDH/DLEQ data.`, - ); - } - } - } - - // ECDH coverage is required per scan key that has at least one computed, - // non-labeled SP output script. Do not require coverage for outputs that are - // still in progress. - for (const bscanHex of computedSPScanKeys) { - const globalShareKey = KeyType.PSBT_GLOBAL_SP_ECDH_SHARE + bscanHex; - - if (this.globalMap.has(globalShareKey)) { - const proofKey = KeyType.PSBT_GLOBAL_SP_DLEQ + bscanHex; - const ecdhShare = this.globalMap.get(globalShareKey) as Buffer; - const proof = this.globalMap.get(proofKey); - - if (!proof) { - throw Error( - `Global ECDH share missing PSBT_GLOBAL_SP_DLEQ for scan key ${bscanHex}.`, - ); - } - - const nonNumsEligible = eligible.filter( - (i) => !this.hasNumsTaprootScriptPathSpend(i), - ); - - const aggregatePubkey = this.getInputAggregatePubkey( - nonNumsEligible, - true, - ); - - if (!aggregatePubkey) { - throw Error( - `Could not compute aggregate public key for global DLEQ verification for scan key ${bscanHex}.`, - ); - } - - if ( - !verifySilentPaymentDLEQProof({ - publicKey: Buffer.from(aggregatePubkey.toRawBytes(true)), - scanKey: Buffer.from(bscanHex, "hex"), - ecdhShare, - proof, - }) - ) { - throw Error( - `Invalid global silent payment DLEQ proof for scan key ${bscanHex}.`, - ); - } - - continue; - } - - const nonNumsEligible = eligible.filter( - (i) => !this.hasNumsTaprootScriptPathSpend(i), - ); - - const hasAnyInputShare = nonNumsEligible.some((i) => - this.inputMaps[i].has(KeyType.PSBT_IN_SP_ECDH_SHARE + bscanHex), - ); - - if (!hasAnyInputShare) { - throw Error( - `Silent payment output present but no ECDH share for scan key ${bscanHex}.`, - ); - } - - for (const i of nonNumsEligible) { - const shareKey = KeyType.PSBT_IN_SP_ECDH_SHARE + bscanHex; - const proofKey = KeyType.PSBT_IN_SP_DLEQ + bscanHex; - - if (!this.inputMaps[i].has(shareKey)) { - throw Error( - `Output script set but eligible input ${i} missing ECDH share for scan key ${bscanHex}`, - ); - } - - const inputPubkey = this.getInputAggregatePubkey([i], true); - const ecdhShare = this.inputMaps[i].get(shareKey) as Buffer; - const proof = this.inputMaps[i].get(proofKey) as Buffer; - - if (!inputPubkey) { - throw Error( - `Input ${i} missing public key for silent payment DLEQ verification.`, - ); - } - - if ( - !verifySilentPaymentDLEQProof({ - publicKey: Buffer.from(inputPubkey.toRawBytes(true)), - scanKey: Buffer.from(bscanHex, "hex"), - ecdhShare, - proof, - }) - ) { - throw Error( - `Invalid input ${i} silent payment DLEQ proof for scan key ${bscanHex}.`, - ); - } - - // A per-input SP DLEQ proof requires the input public key as A. - // Even before semantic BIP374 verification, reject proof-bearing - // eligible inputs whose public key cannot be recovered from the PSBT. - this.getInputAggregatePubkey([i], true); - } - } - - const allComparableSPOutputsHaveScripts = this.outputMaps.every((map) => { - if (!map.has(KeyType.PSBT_OUT_SP_V0_INFO)) { - return true; - } - - if (map.has(KeyType.PSBT_OUT_SP_V0_LABEL)) { - return true; - } - - const script = map.get(KeyType.PSBT_OUT_SCRIPT); - return !!script && script.length > 0; - }); - - if (!allComparableSPOutputsHaveScripts) { - return; - } - - const hasPartialSPComputation = this.outputMaps.some((map) => { - if (!map.has(KeyType.PSBT_OUT_SP_V0_INFO)) { - return false; - } - - if (map.has(KeyType.PSBT_OUT_SP_V0_LABEL)) { - return false; - } - - const script = map.get(KeyType.PSBT_OUT_SCRIPT); - return !script || script.length === 0; - }); - - if (hasPartialSPComputation) { - return; - } - - const allOutpoints = this.getAllOutpoints(); - - if (allOutpoints.length === 0) { - return; - } - - const combinedPubkey = this.getInputAggregatePubkey(eligible); - - if (!combinedPubkey) { - return; - } - - const inputHash = computeInputHash( - allOutpoints, - Buffer.from(combinedPubkey.toRawBytes(true)), - ); - - const outputGroups = this.getSilentPaymentOutputGroups(true, true); - - for (const [bscanHex, group] of outputGroups) { - if (!computedSPScanKeys.has(bscanHex)) { - continue; - } - - let ecdhShare: Buffer; - const globalShareKey = KeyType.PSBT_GLOBAL_SP_ECDH_SHARE + bscanHex; - - if (this.globalMap.has(globalShareKey)) { - ecdhShare = this.globalMap.get(globalShareKey) as Buffer; - } else { - const perInputBuffers: Buffer[] = []; - - for (const i of eligible) { - if (this.hasNumsTaprootScriptPathSpend(i)) { - continue; - } - - const share = this.inputMaps[i].get( - KeyType.PSBT_IN_SP_ECDH_SHARE + bscanHex, - ); - - if (!share) { - throw Error( - `Output script set but eligible input ${i} missing ECDH share for scan key ${bscanHex}`, - ); - } - - perInputBuffers.push(share); - } - - if (perInputBuffers.length === 0) { - continue; - } - - ecdhShare = Buffer.from( - sumECDHShares(perInputBuffers).toRawBytes(true), - ); - } - for (let k = 0; k < group.length; k++) { const { outputIndex, bspend } = group[k]; const actualScript = this.outputMaps[outputIndex].get( @@ -1376,6 +1284,7 @@ export class PsbtV2 extends PsbtV2Maps { } } } + /** * Sets the sequence number for a specific input in the transaction. * @@ -1774,14 +1683,24 @@ export class PsbtV2 extends PsbtV2Maps { throw Error(`PsbtV2 has no input at ${inputIndex}`); } - if (!pubkey || !sig) { + if (!pubkey || !sig || sig.length === 0) { throw Error( `PsbtV2.addPartialSig() missing argument ${ - (!pubkey && "pubkey") || (!sig && "sig") + (!pubkey && "pubkey") || ((!sig || sig.length === 0) && "sig") }`, ); } + if (this.hasSilentPaymentOutputs) { + const sighashType = sig[sig.length - 1]; + + if (sighashType !== SighashType.SIGHASH_ALL) { + throw new Error( + "Silent payment PSBTs require partial signatures to use SIGHASH_ALL.", + ); + } + } + const key = `${KeyType.PSBT_IN_PARTIAL_SIG}${pubkey.toString("hex")}`; if (this.inputMaps[inputIndex].has(key)) { throw Error( @@ -1789,12 +1708,15 @@ export class PsbtV2 extends PsbtV2Maps { ); } + // Per BIP375: re-verify silent-payment consistency on the live object before + // a signature locks the inputs. No-op when there are no SP outputs. + this.validateSilentPayments(); + const modBackup = this.PSBT_GLOBAL_TX_MODIFIABLE; try { this.inputMaps[inputIndex].set(key, sig); this.handleSighashType(sig); - } catch (err) { - console.error(err); + } catch { // To remain atomic, attempt to reset everything to the way it was. this.inputMaps[inputIndex].delete(key); this.PSBT_GLOBAL_TX_MODIFIABLE = modBackup; @@ -2301,7 +2223,11 @@ export class PsbtV2 extends PsbtV2Maps { * Used by the Signer to determine whether SP rules apply. */ get hasSilentPaymentOutputs(): boolean { - return this.outputMaps.some((map) => map.has(KeyType.PSBT_OUT_SP_V0_INFO)); + return this.outputMaps.some( + (map) => + map.has(KeyType.PSBT_OUT_SP_V0_INFO) || + map.has(KeyType.PSBT_OUT_SP_V0_LABEL), + ); } /** @@ -2340,21 +2266,21 @@ export class PsbtV2 extends PsbtV2Maps { ); } return { - bscan: raw.slice(0, 33), - bspend: raw.slice(33, 66), + bscan: raw.subarray(0, 33), + bspend: raw.subarray(33, 66), }; } /** - * Returns the indices of inputs eligible for SP ECDH derivation per BIP352. + * Returns the eligible inputs that contribute an ECDH share — i.e. eligible + * by type and not a NUMS taproot script-path spend. * - * Delegates to {@link eligibleIndices} in `silentpayment.ts`, passing the - * raw `PSBT_IN_WITNESS_UTXO` buffer for each input (or `null` if absent). + * Delegates to {@link contributingIndices} in `silentpayment.ts`. * - * @returns Array of eligible input indices. + * @returns Array of contributing input indices. */ - getEligibleInputsForSilentPayments(): number[] { - return eligibleIndices(this.getSilentPaymentInputDescriptors()); + getContributingInputsForSilentPayments(): number[] { + return contributingIndices(this.getSilentPaymentInputDescriptors()); } /** @@ -2367,18 +2293,16 @@ export class PsbtV2 extends PsbtV2Maps { if (!this.hasSilentPaymentOutputs) return false; const scanKeys = [...this.getSilentPaymentOutputGroups().keys()]; - const eligible = this.getEligibleInputsForSilentPayments(); + const contributing = this.getContributingInputsForSilentPayments(); for (const bscanHex of scanKeys) { if (this.globalMap.has(KeyType.PSBT_GLOBAL_SP_ECDH_SHARE + bscanHex)) { continue; } - const allEligibleInputsCovered = eligible.every( - (i) => - this.hasNumsTaprootScriptPathSpend(i) || - this.inputMaps[i].has(KeyType.PSBT_IN_SP_ECDH_SHARE + bscanHex), + const allContributingInputsCovered = contributing.every((i) => + this.inputMaps[i].has(KeyType.PSBT_IN_SP_ECDH_SHARE + bscanHex), ); - if (!allEligibleInputsCovered) return false; + if (!allContributingInputsCovered) return false; } return scanKeys.length > 0; @@ -2433,54 +2357,28 @@ export class PsbtV2 extends PsbtV2Maps { ); } - // ── Step 1: Build all outpoints + combined pubkey for inputHash ──────── - const eligible = this.getEligibleInputsForSilentPayments(); - const outpoints = this.getAllOutpoints(); - const combinedPubkey = this.getInputAggregatePubkey(eligible); + // ── Step 1: Build the inputHash from outpoints + aggregate pubkey ─────── + const contributing = this.getContributingInputsForSilentPayments(); + const inputHash = this.computeSilentPaymentInputHash(contributing); - if (!combinedPubkey) { + if (!inputHash) { throw new Error("Could not extract public keys from eligible inputs."); } - const inputHash = computeInputHash( - outpoints, - Buffer.from(combinedPubkey.toRawBytes(true)), - ); - // ── Step 2: Group SP outputs by Bscan, sort within groups ────────────── - const scanKeyGroups = this.getSilentPaymentOutputGroups(false); + const scanKeyGroups = this.getSilentPaymentOutputGroups(); // ── Step 3: Resolve ECDH share and derive output scripts ─────────────── for (const [bscanHex, group] of scanKeyGroups) { - const globalShareKey = KeyType.PSBT_GLOBAL_SP_ECDH_SHARE + bscanHex; - let ecdhShare: Buffer; - - if (this.globalMap.has(globalShareKey)) { - ecdhShare = this.globalMap.get(globalShareKey) as Buffer; - } else { - const perInputBuffers: Buffer[] = []; - - for (const i of eligible) { - if (this.hasNumsTaprootScriptPathSpend(i)) { - continue; - } - - const share = this.inputMaps[i].get( - KeyType.PSBT_IN_SP_ECDH_SHARE + bscanHex, - ); - - if (share) { - perInputBuffers.push(share); - } - } - - if (perInputBuffers.length === 0) { - throw new Error(`No ECDH share found for scan key ${bscanHex}`); - } + const ecdhShare = this.resolveAndVerifyScanKeyEcdhShare( + bscanHex, + contributing, + ); - ecdhShare = Buffer.from( - sumECDHShares(perInputBuffers).toRawBytes(true), - ); + // The producer is about to derive the script, so the share must be fully + // derivable and its DLEQ proof(s) verified before deriving. + if (!ecdhShare) { + throw new Error(`No ECDH share found for scan key ${bscanHex}`); } for (let k = 0; k < group.length; k++) { From 8e662e4fe220874ab531d3d191286238a9a6ab44 Mon Sep 17 00:00:00 2001 From: Jasper van Gelder Date: Fri, 5 Jun 2026 17:09:50 +0200 Subject: [PATCH 17/26] refactor(caravan-psbt): add prevout-matched SP pubkey helpers Add Silent Payment helpers that recover an input public key only when a candidate pubkey matches the prevout script. This prepares validation to reject PSBTs that provide decoy pubkeys for Silent Payment shares or DLEQ proofs. --- .../caravan-psbt/src/psbtv2/silentpayment.ts | 155 +++++++++++++++--- 1 file changed, 136 insertions(+), 19 deletions(-) diff --git a/packages/caravan-psbt/src/psbtv2/silentpayment.ts b/packages/caravan-psbt/src/psbtv2/silentpayment.ts index 8d71cd6a42..ac11433da0 100644 --- a/packages/caravan-psbt/src/psbtv2/silentpayment.ts +++ b/packages/caravan-psbt/src/psbtv2/silentpayment.ts @@ -47,6 +47,8 @@ export interface SPInputDescriptor { nonWitnessUtxo?: Buffer | null; outputIndex?: number | null; redeemScript?: Buffer | null; + tapInternalKey?: string | null; // PSBT_IN_TAP_INTERNAL_KEY, hex + tapLeafScriptKeys?: string[]; // PSBT_IN_TAP_LEAF_SCRIPT entry keys, hex } export type SPInputScriptType = @@ -207,24 +209,6 @@ export function bip352TaggedHash(tag: string, data: Buffer): Buffer { // ── Eligible input indices ───────────────────────────────────────────────── -/** - * Determines which transaction inputs are eligible for silent payment ECDH - * derivation per BIP352. - * - * Eligible input types: - * - P2TR (Taproot keypath) — `OP_1 <32-byte x-only key>` - * - P2WPKH — `OP_0 <20-byte hash>` - * - P2SH-P2WPKH / P2PKH — no witness UTXO present - * - * Ineligible input types: - * - P2WSH — `OP_0 <32-byte hash>` (multisig, multiple keys) - * - Segwit v2+ — not permitted alongside SP outputs per BIP375 - * - * @param inputs - One entry per input, in original index order. The array - * must be complete and unfiltered so that returned indices correctly - * correspond to positions in the original input list. - * @returns Array of input indices eligible for SP ECDH derivation. - */ function readWitnessUtxoScript(witnessUtxo: Buffer): Buffer { if (witnessUtxo.length < 9) return Buffer.alloc(0); const scriptLen = witnessUtxo[8]; @@ -338,7 +322,25 @@ export function isEligibleInputType(type: SPInputScriptType): boolean { ); } -export function eligibleIndices(inputs: SPInputDescriptor[]): number[] { +/** + * Determines which transaction inputs are eligible for silent payment ECDH + * derivation per BIP352. + * + * Eligible input types: + * - P2TR (Taproot keypath) — `OP_1 <32-byte x-only key>` + * - P2WPKH — `OP_0 <20-byte hash>` + * - P2SH-P2WPKH / P2PKH — no witness UTXO present + * + * Ineligible input types: + * - P2WSH — `OP_0 <32-byte hash>` (multisig, multiple keys) + * - Segwit v2+ — not permitted alongside SP outputs per BIP375 + * + * @param inputs - One entry per input, in original index order. The array + * must be complete and unfiltered so that returned indices correctly + * correspond to positions in the original input list. + * @returns Array of input indices eligible for SP ECDH derivation. + */ +function eligibleIndices(inputs: SPInputDescriptor[]): number[] { const eligible: number[] = []; for (let i = 0; i < inputs.length; i++) { @@ -350,6 +352,36 @@ export function eligibleIndices(inputs: SPInputDescriptor[]): number[] { return eligible; } +/** + * A taproot input spent via script path using the BIP352 NUMS point H as its + * internal key is eligible by type but never contributes an ECDH share. + */ +function isNumsScriptPathSpend(input: SPInputDescriptor): boolean { + if (input.tapInternalKey === BIP352_NUMS_H) { + return true; + } + + return (input.tapLeafScriptKeys ?? []).some((key) => { + const keydata = Buffer.from(key.slice(2), "hex"); + + if (keydata.length < 33) { + return false; + } + + return keydata.subarray(1, 33).toString("hex") === BIP352_NUMS_H; + }); +} + +/** + * Eligible inputs that actually contribute an ECDH share — i.e. eligible by + * type and not a NUMS script-path spend. + */ +export function contributingIndices(inputs: SPInputDescriptor[]): number[] { + return eligibleIndices(inputs).filter( + (i) => !isNumsScriptPathSpend(inputs[i]), + ); +} + export function hasSegwitV2PlusInput(inputs: SPInputDescriptor[]): boolean { return inputs.some( (input) => classifyInputDescriptor(input) === "segwit_v2plus", @@ -364,6 +396,91 @@ export function getTaprootOutputKeyFromWitnessUtxo( return Buffer.concat([Buffer.from([0x02]), scriptPubKey.subarray(2, 34)]); } +function hash160(buffer: Buffer): Buffer { + const sha = createHash("sha256").update(buffer).digest(); + return createHash("ripemd160").update(sha).digest(); +} + +/** + * Returns the public key that should contribute to BIP352 derivation for an + * input, but only when it is committed by that input's prevout script. + * + * `candidatePubkeys` may be sourced from PSBT_IN_BIP32_DERIVATION, + * PSBT_IN_PARTIAL_SIG, final script witness, or final scriptSig. This helper + * deliberately treats those as untrusted candidates and validates them against + * the prevout script before returning one. + */ +export function getSilentPaymentPubkeyFromInputDescriptor( + input: SPInputDescriptor, + candidatePubkeys: Buffer[], +): Buffer | null { + const scriptPubKey = input.witnessUtxo + ? readWitnessUtxoScript(input.witnessUtxo) + : readNonWitnessUtxoScript(input.nonWitnessUtxo, input.outputIndex); + + if (!scriptPubKey) { + return null; + } + + const scriptType = classifyInputDescriptor(input); + + if (scriptType === "p2tr") { + return input.witnessUtxo + ? getTaprootOutputKeyFromWitnessUtxo(input.witnessUtxo) + : null; + } + + for (const pubkey of candidatePubkeys) { + assertValidCompressedPoint(pubkey, "silent payment input pubkey"); + + const pubkeyHash = hash160(pubkey); + + if (scriptType === "p2wpkh") { + const witnessProgram = scriptPubKey.subarray(2, 22); + + if (pubkeyHash.equals(witnessProgram)) { + return pubkey; + } + + continue; + } + + if (scriptType === "p2pkh_or_unknown_legacy") { + const scriptPubkeyHash = scriptPubKey.subarray(3, 23); + + if (pubkeyHash.equals(scriptPubkeyHash)) { + return pubkey; + } + + continue; + } + + if (scriptType === "p2sh_p2wpkh") { + if (!input.redeemScript) { + continue; + } + + const p2shHash = scriptPubKey.subarray(2, 22); + + if (!hash160(input.redeemScript).equals(p2shHash)) { + continue; + } + + if (classifyWitnessScript(input.redeemScript) !== "p2wpkh") { + continue; + } + + const redeemWitnessProgram = input.redeemScript.subarray(2, 22); + + if (pubkeyHash.equals(redeemWitnessProgram)) { + return pubkey; + } + } + } + + return null; +} + export function groupSilentPaymentOutputs( entries: SPOutputEntry[], ): Map { From d97620aa363770c5352658f655a515da67e66d2e Mon Sep 17 00:00:00 2001 From: Jasper van Gelder Date: Fri, 5 Jun 2026 16:58:46 +0200 Subject: [PATCH 18/26] test(caravan-psbt): update BIP375 vector fixtures --- .../src/fixtures/bip375_vectors.json | 961 +++++++++++++----- 1 file changed, 722 insertions(+), 239 deletions(-) diff --git a/packages/caravan-psbt/src/fixtures/bip375_vectors.json b/packages/caravan-psbt/src/fixtures/bip375_vectors.json index a3d2ec0c10..8dd84b3774 100644 --- a/packages/caravan-psbt/src/fixtures/bip375_vectors.json +++ b/packages/caravan-psbt/src/fixtures/bip375_vectors.json @@ -1,62 +1,59 @@ { "description": "BIP-375 Test Vectors", - "version": "1.1", + "version": "1.2.2", "notes": [ "Generated by https://github.com/macgyver13/bip375-test-generator/", "Each vector includes: base64-encoded psbt and description", - "Supplementary material (inputs, outputs, sp_proofs) is included for diagnostics and should not be used for validation", - "'checks' overrides the validation sequence, e.g. skip structure checks to test input eligibility" + "Supplementary 'inputs', 'outputs', and 'sp_proofs' are diagnostic and should not be used for validation", + "'checks' overrides the validation sequence, e.g. skip structure checks to test input eligibility", + "'workflows' captures a PSBT step-by-step through the BIP-375 roles; each step is an atomic vector with supplementary scoped to that stage", + "'supplementary.psbt' (workflows) is the incoming PSBT for that step: read it, perform the step's role operation, then match 'expected'", + "'expected.unique_id' (workflows) is the BIP-375 PSBT unique identifier and is invariant across all steps once inputs and outputs are present" ], "invalid": [ { "description": "psbt structure: missing PSBT_OUT_SP_V0_INFO field when PSBT_OUT_SP_V0_LABEL set", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEgfCTD+UpVH5TLj1wOA8yaFwh/sU1xSl0vTp/Ux4nT02YBCgQBAAAAAA==", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQDA0MWZ04xLnQHpSq5jI2/aAbRMT5OsRKl39Iml2eMiwwIgfd311m6QKccuNVB0fZJjffaj5C4W9UJpdPi+uF0mIcABAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g907dH3W0uz5ddJwVv9tmNI9oBam01F/u4aLiAfUDu3EBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIGHMBAAAAAAABBCJRIBe/gYp0DI0Tuy5Y5sq4rrsiY8+rt5QENxNV46aiiaG0AQoEAQAAAAA=", "supplementary": {} }, { "description": "psbt structure: incorrect byte length for PSBT_OUT_SP_V0_INFO field", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEgMm31D+Cge3rLcgcL6ztjLrmtFbppXMHlqmqgB7YUb9gBCUECekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84AA=", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIG9hTKsWyAwmppZy4viq5wvAiLUgLqne/2rOeM2n+2JyAiAQVYeP/VlnUGDrYKAL+jNMnLJB+6EoTBEkkNEA2ex8LgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEgZG9JTKC7m86tFLjbfkxpRFYfryMufMzDa91YaV90kVkBCUECekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84AA=", "supplementary": {} }, { "description": "psbt structure: incorrect byte length for PSBT_IN_SP_ECDH_SHARE field", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GggA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QoiHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaECKE7OYVUX3K9bolxSuuQmz41SoQqm7i1bNDt7SHfihmVmLMSKKSeC9fpXOEFP3xbKKy1Q6aHB2AOPOiYIu4yAhAAEDCBhzAQAAAAAAAQQiUSAybfUP4KB7estyBwvrO2Muua0VumlcweWqaqAHthRv2AEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIG9hTKsWyAwmppZy4viq5wvAiLUgLqne/2rOeM2n+2JyAiAQVYeP/VlnUGDrYKAL+jNMnLJB+6EoTBEkkNEA2ex8LgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GggA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QoiHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaECKE7OYVUX3K9bolxSuuQmz41SoQqm7i1bNDt7SHfihmVmLMSKKSeC9fpXOEFP3xbKKy1Q6aHB2AOPOiYIu4yAhAAEDCBhzAQAAAAAAAQQiUSBkb0lMoLubzq0UuNt+TGlEVh+vIy58zMNr3VhpX3SRWQEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", "supplementary": {} }, { "description": "psbt structure: incorrect byte length for PSBT_IN_SP_DLEQ field", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4Gg/ihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgAAEDCBhzAQAAAAAAAQQiUSAybfUP4KB7estyBwvrO2Muua0VumlcweWqaqAHthRv2AEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIG9hTKsWyAwmppZy4viq5wvAiLUgLqne/2rOeM2n+2JyAiAQVYeP/VlnUGDrYKAL+jNMnLJB+6EoTBEkkNEA2ex8LgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4Gg/ihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgAAEDCBhzAQAAAAAAAQQiUSBkb0lMoLubzq0UuNt+TGlEVh+vIy58zMNr3VhpX3SRWQEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", "supplementary": {} }, { "description": "psbt structure: PSBT_GLOBAL_TX_MODIFIABLE field is non-zero when PSBT_OUT_SCRIPT set for sp output", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAQABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEgMm31D+Cge3rLcgcL6ztjLrmtFbppXMHlqmqgB7YUb9gBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEBAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIG9hTKsWyAwmppZy4viq5wvAiLUgLqne/2rOeM2n+2JyAiAQVYeP/VlnUGDrYKAL+jNMnLJB+6EoTBEkkNEA2ex8LgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEgZG9JTKC7m86tFLjbfkxpRFYfryMufMzDa91YaV90kVkBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", "supplementary": {} }, { "description": "psbt structure: missing PSBT_OUT_SCRIPT field when sending to non-sp output", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAA=", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9GMEMCHwfXEdsnLfzEuix6A+aihT1VxR5DeSoM+sSpV9cRhBsCIENgnob+SDV1lgnI3tO4nBZ5YcOpGfobJDWSa7Km/n7yAQEDBAEAAAAiBgLIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvwgAAACAAAAAAAEOIPdO3R91tLs+XXScFb/bZjSPaAWptNRf7uGi4gH1A7txAQ8EAAAAAAEQBP7///8iHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCED7KT/Ebco4uD2DOYiKUOm/1W52V9ie/mpnQhLyHLVClsiHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaECKE7OYVUX3K9bolxSuuQmz41SoQqm7i1bNDt7SHfihmVmLMSKKSeC9fpXOEFP3xbKKy1Q6aHB2AOPOiYIu4yAhAAEDCBhzAQAAAAAAAA==", "supplementary": {} }, { - "description": "psbt structure: empty PSBT_OUT_SCRIPT field when sending to non-sp output", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEAAA=", - "supplementary": {} - }, - { - "description": "ecdh coverage: only one ineligible P2MS input when PSBT_OUT_SCRIPT set for sp output", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiBPa2xI91PQstsuV3qY9lLMD4wBpxZ0Jhhhb5ag+ezmZwEPBAAAAAABASughgEAAAAAACIAIOr39e5jDu+omlGHtlFF4GmTiHzQv1oD8JZFgXkxw/hiAQVHUiEDaGidhEg6mw9BaLYu3+hU5d5PRyw42+0S4nN0susnfjohArPI8nEqzmYLPLqq/KShgFDY2qzp8YMkjzj0SWjwUgPjUq4BEAT+////AAEDCJBfAQAAAAAAAQQiUSDN452LBbSW+PGPILJ9CvmjIzMJ4EciGeCBP/O103h+KQEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "description": "ecdh coverage: only one ineligible P2SH multisig input when PSBT_OUT_SCRIPT set for sp output", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAFMCAAAAAXyoMfPUiQn+aMsOqqoR+Hc97n6McwhTN1kOJLsGOQ20AAAAAAD/////AaCGAQAAAAAAF6kU2OZohxTu7Qqi7dSJqhyjwXFwHk2HAAAAAAEER1IhAr5Ar99ismPLfe4rmF0cOP5BsZlNKwUHU0PRcsIY6rHEIQJ6R5JT0AogWhCpQ483IBm582TgqDaAC/g529KOfOa5VVKuAQ4gzTgaRVCP49nKtjt+D3BKD1adv9VamBAtnqM67mIbdfQBDwQAAAAAARAE/v///wABAwiQXwEAAAAAAAEEIlEgzeOdiwW0lvjxjyCyfQr5oyMzCeBHIhnggT/ztdN4fikBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", "supplementary": { "inputs": [ { "input_index": 0, "private_key": "", "public_key": "", - "prevout_txid": "4f6b6c48f753d0b2db2e577a98f652cc0f8c01a716742618616f96a0f9ece667", + "prevout_txid": "f4751b62ee3aa39e2d10985ad5bf9d560f4a700f7e3bb6cad9e38f50451a38cd", "prevout_index": 0, - "prevout_scriptpubkey": "52210368689d84483a9b0f4168b62edfe854e5de4f472c38dbed12e27374b2eb277e3a2102b3c8f2712ace660b3cbaaafca4a18050d8daace9f183248f38f44968f05203e352ae", "amount": 100000, - "witness_utxo": "a086010000000000220020eaf7f5ee630eefa89a5187b65145e06993887cd0bf5a03f09645817931c3f862", + "non_witness_utxo": "02000000017ca831f3d48909fe68cb0eaaaa11f8773dee7e8c73085337590e24bb06390db40000000000ffffffff01a08601000000000017a914d8e6688714eeed0aa2edd489aa1ca3c171701e4d8700000000", "sequence": 4294967294, "signed": false } @@ -65,18 +62,18 @@ }, { "description": "ecdh coverage: missing PSBT_IN_SP_ECDH_SHARE field for input 0 when PSBT_OUT_SCRIPT set for sp output", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////AAEOIL6dZcg5FfsJJIq738qMo+7mzjUMVU9l6NUm5d9SerUiAQ8EAAAAAAEBHxAnAAAAAAAAFgAURjPVnK0TQ0eZcuDJlpIdCl2ttl0BAwQBAAAAIgYCQ6DUDp3giCeUFhdSuuQrqQlSeEIJ8GNDDwryVjVKhbsIAAAAgAEAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghAuV6etywGNj7MVToDBS5elCZS0I1aEHqn8ExcGFEAOY3Ih4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhA9/o4HeILO0WcbkJsYhPUF1MI8kgqROMyhCMmJNTa/Vcymb868WqzAsViY2OjfUSHB/fnoevqBke8zUhiA7srpgABAwgYcwEAAAAAAAEEIlEgzeOdiwW0lvjxjyCyfQr5oyMzCeBHIhnggT/ztdN4fikBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABEAT+////AAEBHxAnAAAAAAAAFgAUNyH6c8IwXLL4joSJLWvWuXcmHmoBAwQBAAAAIgYCQ6DUDp3giCeUFhdSuuQrqQlSeEIJ8GNDDwryVjVKhbsIAAAAgAEAAAABDiCT02M2J+tY6dwwP275yxvoDBZhNzq+im1o30frVfCaGwEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghAuV6etywGNj7MVToDBS5elCZS0I1aEHqn8ExcGFEAOY3Ih4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhA9/o4HeILO0WcbkJsYhPUF1MI8kgqROMyhCMmJNTa/Vcymb868WqzAsViY2OjfUSHB/fnoevqBke8zUhiA7srpgABAwgYcwEAAAAAAAEEIlEgzeOdiwW0lvjxjyCyfQr5oyMzCeBHIhnggT/ztdN4fikBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", "supplementary": { "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 100000, - "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": false }, @@ -84,11 +81,11 @@ "input_index": 1, "private_key": "586b0810bbc3c7266971aeb7f8778b41707e092a1aeaf0d953b211f956e35541", "public_key": "0243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb", - "prevout_txid": "be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab522", + "prevout_txid": "1b9af055eb47df686d8abe3a3761160ce81bcbf96e3f30dce958eb273663d393", "prevout_index": 0, - "prevout_scriptpubkey": "00144633d59cad1343479972e0c996921d0a5dadb65d", "amount": 10000, - "witness_utxo": "10270000000000001600144633d59cad1343479972e0c996921d0a5dadb65d", + "non_witness_utxo": "0200000001be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab5220000000000ffffffff0110270000000000001600143721fa73c2305cb2f88e84892d6bd6b977261e6a00000000", + "witness_utxo": "10270000000000001600143721fa73c2305cb2f88e84892d6bd6b977261e6a", "sequence": 4294967294, "signed": false } @@ -105,18 +102,18 @@ }, { "description": "ecdh coverage: missing PSBT_IN_SP_DLEQ field for input when PSBT_IN_SP_ECDH_SHARE set", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbAAEDCBhzAQAAAAAAAQQiUSAybfUP4KB7estyBwvrO2Muua0VumlcweWqaqAHthRv2AEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIG9hTKsWyAwmppZy4viq5wvAiLUgLqne/2rOeM2n+2JyAiAQVYeP/VlnUGDrYKAL+jNMnLJB+6EoTBEkkNEA2ex8LgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbAAEDCBhzAQAAAAAAAQQiUSBkb0lMoLubzq0UuNt+TGlEVh+vIy58zMNr3VhpX3SRWQEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", "supplementary": { "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 100000, - "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": true } @@ -133,18 +130,18 @@ }, { "description": "ecdh coverage: missing PSBT_GLOBAL_SP_DLEQ field when PSBT_GLOBAL_SP_ECDH_SHARE set", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBACIHAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWwABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEiBgLIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvwgAAACAAAAAAAEQBP7///8AAQMIGHMBAAAAAAABBCJRIDJt9Q/goHt6y3IHC+s7Yy65rRW6aVzB5apqoAe2FG/YAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAIgcCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIG9hTKsWyAwmppZy4viq5wvAiLUgLqne/2rOeM2n+2JyAiAQVYeP/VlnUGDrYKAL+jNMnLJB+6EoTBEkkNEA2ex8LgEiBgLIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvwgAAACAAAAAAAEOIPdO3R91tLs+XXScFb/bZjSPaAWptNRf7uGi4gH1A7txAQ8EAAAAAAEQBP7///8AAQMIGHMBAAAAAAABBCJRIGRvSUygu5vOrRS4235MaURWH68jLnzMw2vdWGlfdJFZAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", "supplementary": { "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 100000, - "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": true } @@ -159,18 +156,18 @@ }, { "description": "ecdh coverage: invalid proof in PSBT_IN_SP_DLEQ field", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAbvHreDwFl9ZoVl4787j95b7SgVKV9D4XAVEk1EXcy9rdKkne51lhePEhbl1NuRdP/dpjNON8kDEQjAjOE3TeDwABAwgYcwEAAAAAAAEEIlEgMm31D+Cge3rLcgcL6ztjLrmtFbppXMHlqmqgB7YUb9gBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIG9hTKsWyAwmppZy4viq5wvAiLUgLqne/2rOeM2n+2JyAiAQVYeP/VlnUGDrYKAL+jNMnLJB+6EoTBEkkNEA2ex8LgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAbvHreDwFl9ZoVl4787j95b7SgVKV9D4XAVEk1EXcy9rdKkne51lhePEhbl1NuRdP/dpjNON8kDEQjAjOE3TeDwABAwgYcwEAAAAAAAEEIlEgZG9JTKC7m86tFLjbfkxpRFYfryMufMzDa91YaV90kVkBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", "supplementary": { "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 100000, - "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": true } @@ -187,18 +184,18 @@ }, { "description": "ecdh coverage: invalid proof in PSBT_GLOBAL_SP_DLEQ field", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBACIHAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIIAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQOfI/UQrlNiKKmoskrQ0ZI+gB8n+CARyozeA0LUjKETQm9iLP+6G0S1DhsRlf7t4Xi0vFL/PkYV0P+EqyCUPldkAAQ4gGKcXZjsLqxSxKhp3EyP/HkB53VMuXdE+KOoQgccAmEoBDwQAAAAAAQEfoIYBAAAAAAAWABQimnLTSmRb00lru/ULu4HJBj9PlCICAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/RzBEAiAJB3pqpkrBSuehqk/mjAKs4gbJ6scjSQYa52A5ALkibgIgbxQypXj44zCvC5ACVnRryfTlKqLozHkCncjnajwpSwYBIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////AAEDCBhzAQAAAAAAAQQiUSAybfUP4KB7estyBwvrO2Muua0VumlcweWqaqAHthRv2AEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAIgcCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIggCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhA58j9RCuU2IoqaiyStDRkj6AHyf4IBHKjN4DQtSMoRNCb2Is/7obRLUOGxGV/u3heLS8Uv8+RhXQ/4SrIJQ+V2QH7BAIAAAAAAQEfoIYBAAAAAAAWABQeKteHLTKUE6Vt8JaL4zgiJ4MWOyICAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/RzBEAiBvYUyrFsgMJqaWcuL4qucLwIi1IC6p3v9qznjNp/ticgIgEFWHj/1ZZ1Bg62CgC/ozTJyyQfuhKEwRJJDRANnsfC4BIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABEAT+////AAEDCBhzAQAAAAAAAQQiUSBkb0lMoLubzq0UuNt+TGlEVh+vIy58zMNr3VhpX3SRWQEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", "supplementary": { "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 100000, - "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": true } @@ -214,18 +211,18 @@ }, { "description": "ecdh coverage: missing PSBT_IN_BIP32_DERIVATION field for input when PSBT_IN_SP_DLEQ set", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEBAwQBAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIGHMBAAAAAAABBCJRIDJt9Q/goHt6y3IHC+s7Yy65rRW6aVzB5apqoAe2FG/YAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIG9hTKsWyAwmppZy4viq5wvAiLUgLqne/2rOeM2n+2JyAiAQVYeP/VlnUGDrYKAL+jNMnLJB+6EoTBEkkNEA2ex8LgEBAwQBAAAAAQ4g907dH3W0uz5ddJwVv9tmNI9oBam01F/u4aLiAfUDu3EBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIGHMBAAAAAAABBCJRIGRvSUygu5vOrRS4235MaURWH68jLnzMw2vdWGlfdJFZAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", "supplementary": { "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 100000, - "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": true } @@ -242,18 +239,18 @@ }, { "description": "ecdh coverage: output 1 missing ECDH share for scan key with one input / three sp outputs (different scan keys)", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEDAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR9ADQMAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdArlFYVfpRu8H90tU+gm+Sn6Tjcr7+ye0s3LFc8BZ8SqwIQLChkR0sISqyB9uMKxe30ZnOTzmBNgI0/SZoJhOi1JJdCIdA2UdLAc/ywKk2C3aU/HVAdd6A1BmZ5hUZHOyEmts0afeIQN2iSMnxOeAru7UzhvJK7ASK3t5ENlvCtUUi0lvnD6S+yIeArlFYVfpRu8H90tU+gm+Sn6Tjcr7+ye0s3LFc8BZ8SqwQPCxHVHD/ROzjgpsjvwu4Mpxdzr2dLMVHmiSFJJcS1fIFojJ4Hi3UIhabKsoa1d+k6JJfrSWNrGvG2vILnyRElEiHgNlHSwHP8sCpNgt2lPx1QHXegNQZmeYVGRzshJrbNGn3kCY8UrEWvZFmrDITUfaU2TPsUT/kL2scy+cq8bbAA3PGpXjsx97cKBCmKUbb9RRbIHXFsmVT4rxDD1ZgJruK704AAEDCJBfAQAAAAAAAQQiUSDTlxRqgoZbVOsSuepx1oJP6rD5KkgTf3p5OmhZazNnpAEJQgNlHSwHP8sCpNgt2lPx1QHXegNQZmeYVGRzshJrbNGn3gPycOClYyGDtqsBB06HfmgA2wD1x8XS+vu2j5wo1IVFJAABAwgQJwAAAAAAAAEEIlEgzeOdiwW0lvjxjyCyfQr5oyMzCeBHIhnggT/ztdN4fikBCUIDUteMQTkAMq2RgWppf8dA2OuQnPBNcIhSZLBR8jheJewC4MTBh7chX5l8hIWnW0WRtsKEd7laESO5lpItMVSGC/gAAQMIIE4AAAAAAAABBCJRINLSQezkGFFKoY45kuyVPE1K1exwSmk+IQa6IsOwWnqDAQlCArlFYVfpRu8H90tU+gm+Sn6Tjcr7+ye0s3LFc8BZ8SqwAhJoHj8J6uOKjy8/7NfdVvxYbPoCjoqzP3KpD4QKbSJcAA==", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQMBBgEAAfsEAgAAAAABAR9ADQMAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7AQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g/S309Ytav5uR/xoeQ+LjUj9QxqoZ1cIjYBQexIyagCEBDwQAAAAAARAE/v///yIdArlFYVfpRu8H90tU+gm+Sn6Tjcr7+ye0s3LFc8BZ8SqwIQLChkR0sISqyB9uMKxe30ZnOTzmBNgI0/SZoJhOi1JJdCIdA2UdLAc/ywKk2C3aU/HVAdd6A1BmZ5hUZHOyEmts0afeIQN2iSMnxOeAru7UzhvJK7ASK3t5ENlvCtUUi0lvnD6S+yIeArlFYVfpRu8H90tU+gm+Sn6Tjcr7+ye0s3LFc8BZ8SqwQPCxHVHD/ROzjgpsjvwu4Mpxdzr2dLMVHmiSFJJcS1fIFojJ4Hi3UIhabKsoa1d+k6JJfrSWNrGvG2vILnyRElEiHgNlHSwHP8sCpNgt2lPx1QHXegNQZmeYVGRzshJrbNGn3kCY8UrEWvZFmrDITUfaU2TPsUT/kL2scy+cq8bbAA3PGpXjsx97cKBCmKUbb9RRbIHXFsmVT4rxDD1ZgJruK704AAEDCJBfAQAAAAAAAQQiUSBg9n1lOOjDNhoPtXryD47AzuIAMtDb3yc6UykBnOW/TgEJQgNlHSwHP8sCpNgt2lPx1QHXegNQZmeYVGRzshJrbNGn3gPycOClYyGDtqsBB06HfmgA2wD1x8XS+vu2j5wo1IVFJAABAwgQJwAAAAAAAAEEIlEgzeOdiwW0lvjxjyCyfQr5oyMzCeBHIhnggT/ztdN4fikBCUIDUteMQTkAMq2RgWppf8dA2OuQnPBNcIhSZLBR8jheJewC4MTBh7chX5l8hIWnW0WRtsKEd7laESO5lpItMVSGC/gAAQMIIE4AAAAAAAABBCJRIM//VLPkWViKpOGXLVboPI42pZ2WjLKZ3vuvBMJDlKnuAQlCArlFYVfpRu8H90tU+gm+Sn6Tjcr7+ye0s3LFc8BZ8SqwAhJoHj8J6uOKjy8/7NfdVvxYbPoCjoqzP3KpD4QKbSJcAA==", "supplementary": { "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "21809a8cc41e146023c2d519aac6503f52e3e2431e1aff919bbf5a8bf5f42dfd", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 200000, - "witness_utxo": "400d030000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01400d0300000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "400d0300000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": false } @@ -276,18 +273,18 @@ }, { "description": "ecdh coverage: input 1 missing ECDH share for output 1 with two inputs / two sp outputs (different scan keys)", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQECAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsIQMJH9SAORd/RNe3npYWiEnGLrP4eADEZ2fFCo84+Y79FSIdA2UdLAc/ywKk2C3aU/HVAdd6A1BmZ5hUZHOyEmts0afeIQN2iSMnxOeAru7UzhvJK7ASK3t5ENlvCtUUi0lvnD6S+yIeA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsQL4acjrvVeiYG5lZmpvBKzj4froBWMxwZokPImnK3kY7dzQal9KScZZNAcAkHMMi/VOQwpuZFg+CbzKTZYmMvwIiHgNlHSwHP8sCpNgt2lPx1QHXegNQZmeYVGRzshJrbNGn3kCY8UrEWvZFmrDITUfaU2TPsUT/kL2scy+cq8bbAA3PGpXjsx97cKBCmKUbb9RRbIHXFsmVT4rxDD1ZgJruK704AAEOIL6dZcg5FfsJJIq738qMo+7mzjUMVU9l6NUm5d9SerUiAQ8EAAAAAAEBH6CGAQAAAAAAFgAURjPVnK0TQ0eZcuDJlpIdCl2ttl0BAwQBAAAAIgYCQ6DUDp3giCeUFhdSuuQrqQlSeEIJ8GNDDwryVjVKhbsIAAAAgAEAAAABEAT+////Ih0DZR0sBz/LAqTYLdpT8dUB13oDUGZnmFRkc7ISa2zRp94hAnUEQAf+LQMNV3wymRzyo+deU1BCRbPL5bMFOufF8iBaIh4DZR0sBz/LAqTYLdpT8dUB13oDUGZnmFRkc7ISa2zRp95AOLnjgGtJvr7vxs7gZcKwZv2wCuzs8ei1sqr0fPBBeyma4KJW7Xy2yCcC63E31zv1eSccQoTQBuO1nXCpuWfYiQABAwiQXwEAAAAAAAEEIlEg9Jwu8ZtnBhG4bd7+iQzvlCaKgq4zHkb+GVHWxuNyPLEBCUIDZR0sBz/LAqTYLdpT8dUB13oDUGZnmFRkc7ISa2zRp94D8nDgpWMhg7arAQdOh35oANsA9cfF0vr7to+cKNSFRSQAAQMIkF8BAAAAAAABBCJRID2h4XbGT7RZU+xG4FA2NLx+jjQ6do2+77sKPojMSkyaAQlCA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsAuDEwYe3IV+ZfISFp1tFkbbChHe5WhEjuZaSLTFUhgv4AA==", + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQIBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7AQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g907dH3W0uz5ddJwVv9tmNI9oBam01F/u4aLiAfUDu3EBDwQAAAAAARAE/v///yIdA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsIQMJH9SAORd/RNe3npYWiEnGLrP4eADEZ2fFCo84+Y79FSIdA2UdLAc/ywKk2C3aU/HVAdd6A1BmZ5hUZHOyEmts0afeIQN2iSMnxOeAru7UzhvJK7ASK3t5ENlvCtUUi0lvnD6S+yIeA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsQL4acjrvVeiYG5lZmpvBKzj4froBWMxwZokPImnK3kY7dzQal9KScZZNAcAkHMMi/VOQwpuZFg+CbzKTZYmMvwIiHgNlHSwHP8sCpNgt2lPx1QHXegNQZmeYVGRzshJrbNGn3kCY8UrEWvZFmrDITUfaU2TPsUT/kL2scy+cq8bbAA3PGpXjsx97cKBCmKUbb9RRbIHXFsmVT4rxDD1ZgJruK704AAEBH6CGAQAAAAAAFgAUNyH6c8IwXLL4joSJLWvWuXcmHmoBAwQBAAAAIgYCQ6DUDp3giCeUFhdSuuQrqQlSeEIJ8GNDDwryVjVKhbsIAAAAgAEAAAABDiDnbAFxCDpMX7Sv4vbWHwCkcwG50B+NLkd4CrdULjd8CAEPBAAAAAABEAT+////Ih0DZR0sBz/LAqTYLdpT8dUB13oDUGZnmFRkc7ISa2zRp94hAnUEQAf+LQMNV3wymRzyo+deU1BCRbPL5bMFOufF8iBaIh4DZR0sBz/LAqTYLdpT8dUB13oDUGZnmFRkc7ISa2zRp95AOLnjgGtJvr7vxs7gZcKwZv2wCuzs8ei1sqr0fPBBeyma4KJW7Xy2yCcC63E31zv1eSccQoTQBuO1nXCpuWfYiQABAwiQXwEAAAAAAAEEIlEgUYxvb4GbCpCxtzrI2r6I+6L7jU21kKWeh5y2htZLPwoBCUIDZR0sBz/LAqTYLdpT8dUB13oDUGZnmFRkc7ISa2zRp94D8nDgpWMhg7arAQdOh35oANsA9cfF0vr7to+cKNSFRSQAAQMIkF8BAAAAAAABBCJRIJPCrCoXvlxLW2ZvyHz2ESYroSl4aKSY4YV32/tFpEJwAQlCA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsAuDEwYe3IV+ZfISFp1tFkbbChHe5WhEjuZaSLTFUhgv4AA==", "supplementary": { "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 100000, - "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": false }, @@ -295,11 +292,11 @@ "input_index": 1, "private_key": "586b0810bbc3c7266971aeb7f8778b41707e092a1aeaf0d953b211f956e35541", "public_key": "0243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb", - "prevout_txid": "be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab522", + "prevout_txid": "087c372e54b70a78472e8d1fd0b90173a4001fd6f6e2afb45f4c3a0871016ce7", "prevout_index": 0, - "prevout_scriptpubkey": "00144633d59cad1343479972e0c996921d0a5dadb65d", "amount": 100000, - "witness_utxo": "a0860100000000001600144633d59cad1343479972e0c996921d0a5dadb65d", + "non_witness_utxo": "0200000001be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab5220000000000ffffffff01a0860100000000001600143721fa73c2305cb2f88e84892d6bd6b977261e6a00000000", + "witness_utxo": "a0860100000000001600143721fa73c2305cb2f88e84892d6bd6b977261e6a", "sequence": 4294967294, "signed": false } @@ -328,18 +325,18 @@ }, { "description": "ecdh coverage: input 1 missing ECDH share for scan key with two inputs / one sp output", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR9QwwAAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQ4gvp1lyDkV+wkkirvfyoyj7ubONQxVT2Xo1Sbl31J6tSIBDwQAAAAAAQEfUMMAAAAAAAAWABRGM9WcrRNDR5ly4MmWkh0KXa22XSIGAkOg1A6d4IgnlBYXUrrkK6kJUnhCCfBjQw8K8lY1SoW7CAAAAIABAAAAARAE/v///wABAwgYcwEAAAAAAAEEIlEgzeOdiwW0lvjxjyCyfQr5oyMzCeBHIhnggT/ztdN4fikBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAAfsEAgAAAAABAR9QwwAAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7AQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g6xHhra18MFGah0Q1Mm7jehlliBwKVcouqa/tQZZIthYBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQEfUMMAAAAAAAAWABQ3IfpzwjBcsviOhIkta9a5dyYeaiIGAkOg1A6d4IgnlBYXUrrkK6kJUnhCCfBjQw8K8lY1SoW7CAAAAIABAAAAAQ4g245T4MzJHLEs15uROavlPi9D3Liqq6r37/AsHsiwHCgBDwQAAAAAARAE/v///wABAwgYcwEAAAAAAAEEIlEgzeOdiwW0lvjxjyCyfQr5oyMzCeBHIhnggT/ztdN4fikBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", "supplementary": { "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "16b6489641edafa92eca550a1c8865197ae36e323544879a51307cadade111eb", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 50000, - "witness_utxo": "50c3000000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff0150c30000000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "50c30000000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": false }, @@ -347,11 +344,11 @@ "input_index": 1, "private_key": "586b0810bbc3c7266971aeb7f8778b41707e092a1aeaf0d953b211f956e35541", "public_key": "0243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb", - "prevout_txid": "be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab522", + "prevout_txid": "281cb0c81e2cf0eff7aaabaab8dc432f3ee5ab39919bd72cb11cc9cce0538edb", "prevout_index": 0, - "prevout_scriptpubkey": "00144633d59cad1343479972e0c996921d0a5dadb65d", "amount": 50000, - "witness_utxo": "50c30000000000001600144633d59cad1343479972e0c996921d0a5dadb65d", + "non_witness_utxo": "0200000001be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab5220000000000ffffffff0150c30000000000001600143721fa73c2305cb2f88e84892d6bd6b977261e6a00000000", + "witness_utxo": "50c30000000000001600143721fa73c2305cb2f88e84892d6bd6b977261e6a", "sequence": 4294967294, "signed": false } @@ -368,18 +365,18 @@ }, { "description": "input eligibility: segwit version greater than 1 in transaction inputs with sp output", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABZSFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIHLzeIUvuENyYHLyUHbw53Vg7UwuBHFm7mpibHW/2znWAiAhKq5fCVdONB9YhvX/8y9XFuq5AwpKU3nmAWtqTULcJAEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEgMm31D+Cge3rLcgcL6ztjLrmtFbppXMHlqmqgB7YUb9gBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABZSFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQD/G0d7SFEcnvURdIK0VbinRBzrmgXCDZ4gwhD+Z4IEJAIgJ32Cr+1Q28AA/sbFs+Rp61l2dsYw+TpBveyIolGGf00BAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g0w9eTlaTsy1vWnieNwu2RHFBjAHb48ufI2BmfBwTOaUBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIGHMBAAAAAAABBCJRIPGzmH+N0VjGTWFO/Otm7DX662b5nu+5arlL2tCh6dqAAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", "supplementary": { "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "a539131c7c6660239fcbe3db018c417144b60b379e785a6f2db393564e5e0fd3", "prevout_index": 0, - "prevout_scriptpubkey": "5214229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 100000, - "witness_utxo": "a086010000000000165214229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001652141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001652141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": true } @@ -391,18 +388,18 @@ }, { "description": "input eligibility: non-SIGHASH_ALL signature on input with sp output", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIHLzeIUvuENyYHLyUHbw53Vg7UwuBHFm7mpibHW/2znWAiAhKq5fCVdONB9YhvX/8y9XFuq5AwpKU3nmAWtqTULcJAEBAwQCAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEgMm31D+Cge3rLcgcL6ztjLrmtFbppXMHlqmqgB7YUb9gBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCID1lvc+owIu6KcBlzqbELkBAvrwUG9UvgfUD9jrZiAZUAiBGU0AdzeUC8dVS4BTFAgx1UerNOncuiYVMYBgzYyB9FAEBAwQCAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEgZG9JTKC7m86tFLjbfkxpRFYfryMufMzDa91YaV90kVkBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", "supplementary": { "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 100000, - "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": true } @@ -411,20 +408,20 @@ }, { "description": "output scripts: P2TR input with NUMS internal key cannot derive sp output", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAT8Qa2S1e1sTdvn2xHGQ9AzAazvty4qrqXhQqz1/Z9AgEPBAAAAAABASsQJwAAAAAAACJRIFCSm3TBoElUt4tLYDXpel4HiloPKOyW1Ue/7prOgDrAAQMEAQAAAAEQBP7///8BFyBQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wCIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIHCUAAAAAAAABBCJRICdoyIruoiMiW6OthOeGNS+YKdLT6TeKOToL/1mvh83QAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABASsQJwAAAAAAACJRIFCSm3TBoElUt4tLYDXpel4HiloPKOyW1Ue/7prOgDrAAQMEAQAAAAEOIGAXtZAPmL6eOm19nK05Aozq0/UhOaeh2exXaT6+bJqjAQ8EAAAAAAEQBP7///8BE0GNRXo+4wxRWCxWlnde57pemE/F12ztqkpOiq6N0zSCTmgoW/X1/csnFdpquwq4GYc+jRqcEsI7W5NJsxitYlNOAQEXIFCSm3TBoElUt4tLYDXpel4HiloPKOyW1Ue/7prOgDrAIh0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgcJQAAAAAAAAEEIlEgfyDVlx0Qd+n5jEZf6tapililLCV2WAM/PZUgmGiUkfQBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", "supplementary": { "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "13f106b64b57b5b1376f9f6c47190f40cc06b3bedcb8aaba97850ab3d7f67d02", + "prevout_txid": "a39a6cbe3e6957ecd9a1a73921f5d3ea8c0239ad9c7d6d3a9ebe980f90b51760", "prevout_index": 0, - "prevout_scriptpubkey": "512050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", "amount": 10000, + "non_witness_utxo": "020000000113f106b64b57b5b1376f9f6c47190f40cc06b3bedcb8aaba97850ab3d7f67d020000000000ffffffff01102700000000000022512050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac000000000", "witness_utxo": "102700000000000022512050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", "sequence": 4294967294, - "signed": false + "signed": true } ], "sp_proofs": [ @@ -440,25 +437,25 @@ "output_index": 0, "amount": 9500, "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", - "script": "51202768c88aeea223225ba3ad84e786352f9829d2d3e9378a393a0bff59af87cdd0" + "script": "51207f20d5971d1077e9f98c465fead6a98a58a52c257658033f3d952098689491f4" } ] } }, { "description": "output scripts: PSBT_OUT_SCRIPT does not match derived sp output", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIGHMBAAAAAAABBCJRIM3jnYsFtJb48Y8gsn0K+aMjMwngRyIZ4IE/87XTeH4pAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7AQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g907dH3W0uz5ddJwVv9tmNI9oBam01F/u4aLiAfUDu3EBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIGHMBAAAAAAABBCJRIM3jnYsFtJb48Y8gsn0K+aMjMwngRyIZ4IE/87XTeH4pAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", "supplementary": { "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 100000, - "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": false } @@ -483,18 +480,18 @@ }, { "description": "output scripts: two sp outputs (same scan / different spend keys) not sorted lexicographically by spend key", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQECAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCID9iBcRocGpGJF8XE6u4uLmjp7/YOsdF98ByDUQxtM38AiBxWKv7gg8r9a1nRfVvwHCcmVzMrP4XCY2KobYfjJ/y/wEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwiQXwEAAAAAAAEEIlEgdUe4Fj1bvFSYQL5MwUaq0JUgc2e565RwbeZwjUCPk/kBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgCi4D5lDNIleEbx2x1q254/iwluzMvIXshHEAXvx9nfYYAAQMIECcAAAAAAAABBCJRIGziw1OV8XDyS20tgNCkDEb0a6S0hD9qsxGpNLMcXYTcAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA6r4Yq7amM+SU5r33DN10dpfsGsSHvCh8DGp9zgv1T27AA==", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQIBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIExYL+wZvNCU5oIsqPD7MiK6sIG6J64r3IOIgwa67SNWAiAfxZx06/JBydKQqMxQ8qOYD8DANBNXtltjINXNPOpPBAEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwiQXwEAAAAAAAEEIlEgPajcATlIcUBND7sqMXcLxrF+r7rr33jiwy48KFZTJ1kBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgCi4D5lDNIleEbx2x1q254/iwluzMvIXshHEAXvx9nfYYAAQMIECcAAAAAAAABBCJRINcZ2dcurhCyj8MgCzL61dlJboWOixbkdXjXyMFEkzsEAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA6r4Yq7amM+SU5r33DN10dpfsGsSHvCh8DGp9zgv1T27AA==", "supplementary": { "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 100000, - "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": true } @@ -512,31 +509,31 @@ "output_index": 0, "amount": 90000, "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068028b80f994334895e11bc76c75ab6e78fe2c25bb332f217b211c4017bf1f677d86", - "script": "51207547b8163d5bbc549840be4cc146aad095207367b9eb94706de6708d408f93f9" + "script": "51203da8dc01394871404d0fbb2a31770bc6b17eafbaebdf78e2c32e3c2856532759" }, { "output_index": 1, "amount": 10000, "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe06803aaf862aeda98cf92539af7dc3375d1da5fb06b121ef0a1f031a9f7382fd53dbb", - "script": "51206ce2c35395f170f24b6d2d80d0a40c46f46ba4b4843f6ab311a934b31c5d84dc" + "script": "5120d719d9d72eae10b28fc3200b32fad5d9496e858e8b16e47578d7c8c144933b04" } ] } }, { "description": "output scripts: k values assigned to wrong output indices with three sp outputs (same scan / spend keys)", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEDAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIFg36hg2U7tRrGNQq+bDhHvokGogZdwwSNbSCOp8DkyCAiAQ+0/6sv7Vqmy2KAqTxHnPsE5Gyp7fF6owXNFnSiQsSQEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwiQXwEAAAAAAAEEIlEgMm31D+Cge3rLcgcL6ztjLrmtFbppXMHlqmqgB7YUb9gBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkAAQMIECcAAAAAAAABBCJRIJcUQsifBHhuCCcorhFu6rgC8/qelf2w03U6aEAgIAbeAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AAEDCBAnAAAAAAAAAQQiUSA/y66kkIf44D2d79Ory9bejAMrWD+Fpl0FeIHExEPNwAEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQMBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQDmsaUAuR12tiR/luLlnUQZ6/oZayCC6yzQGczKmeec6wIgVp/snmnIG0ZomQT4uGSrck/xFnuR58NgeHpzOZqLvNMBAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g907dH3W0uz5ddJwVv9tmNI9oBam01F/u4aLiAfUDu3EBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIkF8BAAAAAAABBCJRIGRvSUygu5vOrRS4235MaURWH68jLnzMw2vdWGlfdJFZAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AAEDCBAnAAAAAAAAAQQiUSBnO3Y1anIQCkUV5BRRrprC+6ap0dft7SIJEBvVLxrrVwEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQABAwgQJwAAAAAAAAEEIlEgpRVl2ozof5Td+ErkDvaYxXSb8mLkE+ryjVDYvYtTJ8UBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", "supplementary": { "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 100000, - "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": true } @@ -554,19 +551,161 @@ "output_index": 0, "amount": 90000, "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", - "script": "5120326df50fe0a07b7acb72070beb3b632eb9ad15ba695cc1e5aa6aa007b6146fd8" + "script": "5120646f494ca0bb9bcead14b8db7e4c6944561faf232e7cccc36bdd58695f749159" }, { "output_index": 1, "amount": 10000, "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", - "script": "5120971442c89f04786e082728ae116eeab802f3fa9e95fdb0d3753a6840202006de" + "script": "5120673b76356a72100a4515e41451ae9ac2fba6a9d1d7eded2209101bd52f1aeb57" }, { "output_index": 2, "amount": 10000, "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", - "script": "51203fcbaea49087f8e03d9defd3abcbd6de8c032b583f85a65d057881c4c443cdc0" + "script": "5120a51565da8ce87f94ddf84ae40ef698c5749bf262e413eaf28d50d8bd8b5327c5" + } + ] + } + }, + { + "description": "input derivation: P2WPKH BIP32_DERIVATION pubkey does not match prevout script", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7AQMEAQAAACIGA4+plDX6lbGV+mADtXE+Da7qAMH/S8LLYDK0ccl7HFljCAAAAIAAAAAAAQ4g907dH3W0uz5ddJwVv9tmNI9oBam01F/u4aLiAfUDu3EBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQKJrr4cMdjZlp7VADdXOchNeqbQV2h/Ck5cuA0KBg03eyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQGuT/wfJyZrQjEXeF8f1vcx1OVZshsaec0slVfrS+N2b/dKk5yicBub1fk9ybpw0focikVH4GsoUDYT1KdSOi+sAAQMIGHMBAAAAAAABBCJRIDg/2sQx5SQpQX9uJOugHYH842VRzMvwmLrPHqoDNNhPAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "29e8eff75528710ebbe15ca4e257292ab9e0923ae827de3dc12efce5aa37f1e8", + "public_key": "038fa99435fa95b195fa6003b5713e0daeea00c1ff4bc2cb6032b471c97b1c5963", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", + "prevout_index": 0, + "amount": 100000, + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", + "sequence": 4294967294, + "signed": false + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "0289aebe1c31d8d9969ed500375739c84d7aa6d057687f0a4e5cb80d0a060d377b", + "dleq_proof": "6b93ff07c9c99ad08c45de17c7f5bdcc7539566c86c69e734b2555fad2f8dd9bfdd2a4e7289c06e6f57e4f726e9c347e87229151f81aca140d84f529d48e8beb", + "input_index": 0 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 95000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "5120383fdac431e52429417f6e24eba01d81fce36551cccbf098bacf1eaa0334d84f" + } + ] + } + }, + { + "description": "input derivation: P2PKH BIP32_DERIVATION pubkey does not match prevout script", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAFUCAAAAAfTCEtWu0ef2/2M/LOCcZHxXvt2TAxTZjed1A9WOlAszAAAAAAD/////AaCGAQAAAAAAGXapFB4q14ctMpQTpW3wlovjOCIngxY7iKwAAAAAAQMEAQAAACIGA4+plDX6lbGV+mADtXE+Da7qAMH/S8LLYDK0ccl7HFljCAAAAIAAAAAAAQ4gUidI6xd2TSjKSUgV7I1J59MNUrxzQix8hut045cFcpQBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQKJrr4cMdjZlp7VADdXOchNeqbQV2h/Ck5cuA0KBg03eyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQGuT/wfJyZrQjEXeF8f1vcx1OVZshsaec0slVfrS+N2b/dKk5yicBub1fk9ybpw0focikVH4GsoUDYT1KdSOi+sAAQMIGHMBAAAAAAABBCJRICKBfO5dYbj9zQAUBomhNyYIpsMCvUqPU6EYTAlCDalDAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "29e8eff75528710ebbe15ca4e257292ab9e0923ae827de3dc12efce5aa37f1e8", + "public_key": "038fa99435fa95b195fa6003b5713e0daeea00c1ff4bc2cb6032b471c97b1c5963", + "prevout_txid": "94720597e374eb867c2c4273bc520dd3e7498dec154849ca284d7617eb482752", + "prevout_index": 0, + "amount": 100000, + "non_witness_utxo": "0200000001f4c212d5aed1e7f6ff633f2ce09c647c57bedd930314d98de77503d58e940b330000000000ffffffff01a0860100000000001976a9141e2ad7872d329413a56df0968be338222783163b88ac00000000", + "sequence": 4294967294, + "signed": false + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "0289aebe1c31d8d9969ed500375739c84d7aa6d057687f0a4e5cb80d0a060d377b", + "dleq_proof": "6b93ff07c9c99ad08c45de17c7f5bdcc7539566c86c69e734b2555fad2f8dd9bfdd2a4e7289c06e6f57e4f726e9c347e87229151f81aca140d84f529d48e8beb", + "input_index": 0 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 95000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "512022817cee5d61b8fdcd00140689a1372608a6c302bd4a8f53a1184c09420da943" + } + ] + } + }, + { + "description": "input derivation: P2SH-P2WPKH BIP32_DERIVATION pubkey does not match prevout script", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAFMCAAAAAa0yiGinxhSdpSUXfZUerAPh/iyT6DzlNGVjrZNjwndMAAAAAAD/////AaCGAQAAAAAAF6kU1JxxjCdjjcMGkgbmNVqpXZ1duKWHAAAAAAEBIKCGAQAAAAAAF6kU1JxxjCdjjcMGkgbmNVqpXZ1duKWHAQMEAQAAAAEEFgAUHirXhy0ylBOlbfCWi+M4IieDFjsiBgOPqZQ1+pWxlfpgA7VxPg2u6gDB/0vCy2AytHHJexxZYwgAAACAAAAAAAEOIF9UazGnjEZsRZPeIw6ZO8mTW57s1NKnf3O6VVxSQgOFAQ8EAAAAAAEQBP7///8iHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCECia6+HDHY2Zae1QA3VznITXqm0FdofwpOXLgNCgYNN3siHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaEBrk/8Hycma0IxF3hfH9b3MdTlWbIbGnnNLJVX60vjdm/3SpOconAbm9X5Pcm6cNH6HIpFR+BrKFA2E9SnUjovrAAEDCBhzAQAAAAAAAQQiUSCWlm1C2LBhTynYvjvzYYQujiUMMJ4GK3it91Pn25LXpAEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "29e8eff75528710ebbe15ca4e257292ab9e0923ae827de3dc12efce5aa37f1e8", + "public_key": "038fa99435fa95b195fa6003b5713e0daeea00c1ff4bc2cb6032b471c97b1c5963", + "prevout_txid": "850342525c55ba737fa7d2d4ec9e5b93c93b990e23de93456c468ca7316b545f", + "prevout_index": 0, + "amount": 100000, + "non_witness_utxo": "0200000001ad328868a7c6149da525177d951eac03e1fe2c93e83ce5346563ad9363c2774c0000000000ffffffff01a08601000000000017a914d49c718c27638dc3069206e6355aa95d9d5db8a58700000000", + "witness_utxo": "a08601000000000017a914d49c718c27638dc3069206e6355aa95d9d5db8a587", + "sequence": 4294967294, + "signed": false + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "0289aebe1c31d8d9969ed500375739c84d7aa6d057687f0a4e5cb80d0a060d377b", + "dleq_proof": "6b93ff07c9c99ad08c45de17c7f5bdcc7539566c86c69e734b2555fad2f8dd9bfdd2a4e7289c06e6f57e4f726e9c347e87229151f81aca140d84f529d48e8beb", + "input_index": 0 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 95000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "512096966d42d8b0614f29d8be3bf361842e8e250c309e062b78adf753e7db92d7a4" + } + ] + } + }, + { + "description": "input pubkey mismatch: global ECDH share computed from decoy pubkey not matching prevout script", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAIgcCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghAomuvhwx2NmWntUAN1c5yE16ptBXaH8KTly4DQoGDTd7IggCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhApCBNyEZUGJiLPKlVE9fVdU+ywDiriYHCI0/jxSu1Fl1DsrLP2Gmzffkyvnairni2DokSMDz8aC7ijH1vSWivpAH7BAIAAAAAAQEfoIYBAAAAAAAWABQeKteHLTKUE6Vt8JaL4zgiJ4MWOyIGA4+plDX6lbGV+mADtXE+Da7qAMH/S8LLYDK0ccl7HFljCAAAAIAAAAAAAQ4g907dH3W0uz5ddJwVv9tmNI9oBam01F/u4aLiAfUDu3EBDwQAAAAAARAE/v///wABAwgYcwEAAAAAAAEEIlEgOD/axDHlJClBf24k66AdgfzjZVHMy/CYus8eqgM02E8BCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "29e8eff75528710ebbe15ca4e257292ab9e0923ae827de3dc12efce5aa37f1e8", + "public_key": "038fa99435fa95b195fa6003b5713e0daeea00c1ff4bc2cb6032b471c97b1c5963", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", + "prevout_index": 0, + "amount": 100000, + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", + "sequence": 4294967294, + "signed": false + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "0289aebe1c31d8d9969ed500375739c84d7aa6d057687f0a4e5cb80d0a060d377b", + "dleq_proof": "a4204dc8465418988b3ca95513d7d5754fb2c038ab8981c2234fe3c52bb5165d43b2b2cfd869b37df932be76a2ae78b60e8912303cfc682ee28c7d6f4968afa4" + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 95000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "5120383fdac431e52429417f6e24eba01d81fce36551cccbf098bacf1eaa0334d84f" } ] } @@ -574,19 +713,18 @@ ], "valid": [ { - "description": "can finalize: one input single-signer", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEgMm31D+Cge3rLcgcL6ztjLrmtFbppXMHlqmqgB7YUb9gBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "description": "can finalize: one P2PKH input single-signer", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAFUCAAAAAfTCEtWu0ef2/2M/LOCcZHxXvt2TAxTZjed1A9WOlAszAAAAAAD/////AaCGAQAAAAAAGXapFB4q14ctMpQTpW3wlovjOCIngxY7iKwAAAAAIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQCKz65hp7Ug/wQxkrbclMyEJpEkQIMSdkyI3dldqY0pVQIgIIfDsRj5aZKk2iQTz/6RcPJQ4n48FMtd7z5jjDDX6oABAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4gUidI6xd2TSjKSUgV7I1J59MNUrxzQix8hut045cFcpQBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIGHMBAAAAAAABBCJRIOFA0oe0W0bNTqr6Q3cGFXC6voPRuLyVCnSp/qCSM9emAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", "supplementary": { "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "94720597e374eb867c2c4273bc520dd3e7498dec154849ca284d7617eb482752", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 100000, - "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "0200000001f4c212d5aed1e7f6ff633f2ce09c647c57bedd930314d98de77503d58e940b330000000000ffffffff01a0860100000000001976a9141e2ad7872d329413a56df0968be338222783163b88ac00000000", "sequence": 4294967294, "signed": true } @@ -604,25 +742,25 @@ "output_index": 0, "amount": 95000, "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", - "script": "5120326df50fe0a07b7acb72070beb3b632eb9ad15ba695cc1e5aa6aa007b6146fd8" + "script": "5120e140d287b45b46cd4eaafa4377061570babe83d1b8bc950a74a9fea09233d7a6" } ] } }, { "description": "can finalize: two inputs single-signer using global ECDH share", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEBAQYBACIHAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQLTJicjNSYH6E/K92UfjS1jfgIK6obfrYDTBs1PSM/MYiIIAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQMZTtx+UaBipW9w58JGERbyQOgh2tzgGDp5dsdzsMKvfVOC18XhXP1EZ3nGqY60ZtEnjvLZUY5Nsi67qTZFzkrkAAQ4gGKcXZjsLqxSxKhp3EyP/HkB53VMuXdE+KOoQgccAmEoBDwQAAAAAAQEfoIYBAAAAAAAWABQimnLTSmRb00lru/ULu4HJBj9PlCICAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/RzBEAiAXBfzaBiZu2zKxaYZ3s39nu25F1JLr/OZWqIDufxOOtgIgPc3jI53ZBjavZPskEspB45fJWKAwd3z/nIlAucd310wBIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////AAEOIL6dZcg5FfsJJIq738qMo+7mzjUMVU9l6NUm5d9SerUiAQ8EAAAAAAEBH6CGAQAAAAAAFgAUE5NQEXxXeUGphYArue3vwROTK8ciAgL1tZ+l5JIiHr9VunitRCYFvq6VFmuh66MlDQu6rH4u3EcwRAIgA4mx4K7v1/q2Ce+rAYv7AWrP8hu4EPPEjDi6ckQYDpUCIBUP7GDiVvQMR1dN/RKaCOr3rB2Xq+4x9AaZ+Hk1RhnzASIGAvW1n6XkkiIev1W6eK1EJgW+rpUWa6HroyUNC7qsfi7cCAAAAIABAAAAARAE/v///wABAwgYcwEAAAAAAAEEIlEgEz1qT1CQlbV5T3SR+8PxLDxFvC2bYK8luLunBMgHKq8BCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAIgcCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghAtMmJyM1JgfoT8r3ZR+NLWN+Agrqht+tgNMGzU9Iz8xiIggCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAxlO3H5RoGKlb3DnwkYRFvJA6CHa3OAYOnl2x3Owwq99U4LXxeFc/URnecapjrRm0SeO8tlRjk2yLrupNkXOSuQH7BAIAAAAAAQEfoIYBAAAAAAAWABQeKteHLTKUE6Vt8JaL4zgiJ4MWOyICAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/SDBFAiEA7BqWeJn9r3jg2rH/VnzzA3wMo9G7Im8q7sP98KfSmdcCIBHdNztMi7HrfRAkJSDvxy+E7Un3b0H78IdNp0bjoGOoASIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g907dH3W0uz5ddJwVv9tmNI9oBam01F/u4aLiAfUDu3EBDwQAAAAAARAE/v///wABAR+ghgEAAAAAABYAFKaSURwHlXW/N1bavFatcdQoSmkOIgIC9bWfpeSSIh6/Vbp4rUQmBb6ulRZroeujJQ0Luqx+LtxIMEUCIQDelwGo+8K1FHCnn5V0LTz/267tYvzpJKCg1dcFYFFTxQIgRd8PiHo5I7pLMWKTtgzZ/xAdiZUqfbBpxHlWMzJ8PKIBIgYC9bWfpeSSIh6/Vbp4rUQmBb6ulRZroeujJQ0Luqx+LtwIAAAAgAEAAAABDiC81IWnCcsl0TRjoYMtshlMbJ2f5yuWmfT+Qsgr7ZPTJgEPBAAAAAABEAT+////AAEDCBhzAQAAAAAAAQQiUSCZu9KYLwKAvNwmQx1rKc9nkRilu7tgkU1v+s+rvFy0WwEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", "supplementary": { "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 100000, - "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": true }, @@ -630,11 +768,11 @@ "input_index": 1, "private_key": "295c2eedddd8331d20b5d4cf9e69bb523ed85cb0bf35ab12e04fea66fe6d4a4a", "public_key": "02f5b59fa5e492221ebf55ba78ad442605beae95166ba1eba3250d0bbaac7e2edc", - "prevout_txid": "be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab522", + "prevout_txid": "26d393ed2bc842fef499962be79f9d6c4c19b22d83a16334d125cb09a785d4bc", "prevout_index": 0, - "prevout_scriptpubkey": "0014139350117c577941a985802bb9edefc113932bc7", "amount": 100000, - "witness_utxo": "a086010000000000160014139350117c577941a985802bb9edefc113932bc7", + "non_witness_utxo": "0200000001be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab5220000000000ffffffff01a086010000000000160014a692511c079575bf3756dabc56ad71d4284a690e00000000", + "witness_utxo": "a086010000000000160014a692511c079575bf3756dabc56ad71d4284a690e", "sequence": 4294967294, "signed": true } @@ -651,25 +789,25 @@ "output_index": 0, "amount": 95000, "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", - "script": "5120133d6a4f509095b5794f7491fbc3f12c3c45bc2d9b60af25b8bba704c8072aaf" + "script": "512099bbd2982f0280bcdc26431d6b29cf679118a5bbbb60914d6ffacfabbc5cb45b" } ] } }, { "description": "can finalize: two inputs single-signer using per-input ECDH shares", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIBcF/NoGJm7bMrFphnezf2e7bkXUkuv85laogO5/E462AiA9zeMjndkGNq9k+yQSykHjl8lYoDB3fP+ciUC5x3fXTAEiBgLIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvwgAAACAAAAAAAEQBP7///8iHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCED7KT/Ebco4uD2DOYiKUOm/1W52V9ie/mpnQhLyHLVClsiHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaECKE7OYVUX3K9bolxSuuQmz41SoQqm7i1bNDt7SHfihmVmLMSKKSeC9fpXOEFP3xbKKy1Q6aHB2AOPOiYIu4yAhAAEOIL6dZcg5FfsJJIq738qMo+7mzjUMVU9l6NUm5d9SerUiAQ8EAAAAAAEBH6CGAQAAAAAAFgAUE5NQEXxXeUGphYArue3vwROTK8ciAgL1tZ+l5JIiHr9VunitRCYFvq6VFmuh66MlDQu6rH4u3EcwRAIgA4mx4K7v1/q2Ce+rAYv7AWrP8hu4EPPEjDi6ckQYDpUCIBUP7GDiVvQMR1dN/RKaCOr3rB2Xq+4x9AaZ+Hk1RhnzAQEDBAEAAAAiBgL1tZ+l5JIiHr9VunitRCYFvq6VFmuh66MlDQu6rH4u3AgAAACAAQAAAAEQBP7///8iHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCEDNNLO907e1EZCJ2B/xZrB3oDBKiQzpWJxUo7cz1D6bCsiHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaEA3wAwLQqBz9rZfDEtuVuBndLOAwd894otkCxIe4LO0z3hQ30VuC12OGXXd/yUmLIOB4g+FLNhwveP2qDKmMlvMAAEDCBhzAQAAAAAAAQQiUSATPWpPUJCVtXlPdJH7w/EsPEW8LZtgryW4u6cEyAcqrwEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQDsGpZ4mf2veODasf9WfPMDfAyj0bsibyruw/3wp9KZ1wIgEd03O0yLset9ECQlIO/HL4TtSfdvQfvwh02nRuOgY6gBIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAR+ghgEAAAAAABYAFKaSURwHlXW/N1bavFatcdQoSmkOIgIC9bWfpeSSIh6/Vbp4rUQmBb6ulRZroeujJQ0Luqx+LtxIMEUCIQDelwGo+8K1FHCnn5V0LTz/267tYvzpJKCg1dcFYFFTxQIgRd8PiHo5I7pLMWKTtgzZ/xAdiZUqfbBpxHlWMzJ8PKIBAQMEAQAAACIGAvW1n6XkkiIev1W6eK1EJgW+rpUWa6HroyUNC7qsfi7cCAAAAIABAAAAAQ4gvNSFpwnLJdE0Y6GDLbIZTGydn+crlpn0/kLIK+2T0yYBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQM00s73Tt7URkInYH/FmsHegMEqJDOlYnFSjtzPUPpsKyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQDfADAtCoHP2tl8MS25W4Gd0s4DB3z3ii2QLEh7gs7TPeFDfRW4LXY4Zdd3/JSYsg4HiD4Us2HC94/aoMqYyW8wAAQMIGHMBAAAAAAABBCJRIJm70pgvAoC83CZDHWspz2eRGKW7u2CRTW/6z6u8XLRbAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", "supplementary": { "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 100000, - "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": true }, @@ -677,11 +815,11 @@ "input_index": 1, "private_key": "295c2eedddd8331d20b5d4cf9e69bb523ed85cb0bf35ab12e04fea66fe6d4a4a", "public_key": "02f5b59fa5e492221ebf55ba78ad442605beae95166ba1eba3250d0bbaac7e2edc", - "prevout_txid": "be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab522", + "prevout_txid": "26d393ed2bc842fef499962be79f9d6c4c19b22d83a16334d125cb09a785d4bc", "prevout_index": 0, - "prevout_scriptpubkey": "0014139350117c577941a985802bb9edefc113932bc7", "amount": 100000, - "witness_utxo": "a086010000000000160014139350117c577941a985802bb9edefc113932bc7", + "non_witness_utxo": "0200000001be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab5220000000000ffffffff01a086010000000000160014a692511c079575bf3756dabc56ad71d4284a690e00000000", + "witness_utxo": "a086010000000000160014a692511c079575bf3756dabc56ad71d4284a690e", "sequence": 4294967294, "signed": true } @@ -705,25 +843,25 @@ "output_index": 0, "amount": 95000, "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", - "script": "5120133d6a4f509095b5794f7491fbc3f12c3c45bc2d9b60af25b8bba704c8072aaf" + "script": "512099bbd2982f0280bcdc26431d6b29cf679118a5bbbb60914d6ffacfabbc5cb45b" } ] } }, { "description": "can finalize: two inputs / two sp outputs with mixed global and per-input ECDH shares", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQECAQYBACIHAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oIQNmz8f9zgbgjtSbGzlSuNFRqPfgdf5fbdWN1o+dre7KlCIIAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oQF6riwhtSFD+nRyflhqR+Ze2HKjQhQr8BqeL3zx0nvVAUOaStT+1sIbl54eT8B5203R/ieMXen/v9vjBYX8bBuMAAQ4gGKcXZjsLqxSxKhp3EyP/HkB53VMuXdE+KOoQgccAmEoBDwQAAAAAAQEfQA0DAAAAAAAWABQimnLTSmRb00lru/ULu4HJBj9PlCICAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/SDBFAiEA1k6e8CREAEbpyjkwLrh7LfYN/FHJwKkX1oLzz4EFkIwCIB6+EqXx/SGW8u+11Tr+V850W5Af6ImXitWa7+FKT1A3AQEDBAEAAAAiBgLIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvwgAAACAAAAAAAEQBP7///8iHQKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVECED+9Fz2cSNWMUCJCbQUni8oXuajiKCZmkBobALngS3mUkiHgKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVEEDAXaQQSHz67DeP6+avUAXjrmyGI2gYsOVbIUAX61Bz7e9AF5V1tdzaqQY0kayLg/0GJNQXek0t1JlMRkDWuMzeAAEOIL6dZcg5FfsJJIq738qMo+7mzjUMVU9l6NUm5d9SerUiAQ8EAAAAAAEBH0ANAwAAAAAAFgAUE5NQEXxXeUGphYArue3vwROTK8ciAgL1tZ+l5JIiHr9VunitRCYFvq6VFmuh66MlDQu6rH4u3EcwRAIgWoJ5pshwRPECyFkwyJ7C/wGUKGJBraOMeFTy6DZR1fICICvMZkqflwTVcxLbwryDaGcIDyLEdYuR27ktF6HkEeqpAQEDBAEAAAAiBgL1tZ+l5JIiHr9VunitRCYFvq6VFmuh66MlDQu6rH4u3AgAAACAAQAAAAEQBP7///8iHQKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVECEDpqibG5hqmVUz4XvtZFALVBuw1zkHHv4q4rfvsKDKa88iHgKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVEEDDSmopQLvppzVsHMb/41jdREHbWIl8upnCEut1KF59oeyhHHksl6OASTNFqyJN6dlMKzbuhSauI1KBcaMjHeczAAEDCJBfAQAAAAAAAQQiUSCA65gxi89t1hGsF6lksJFzbATK6t8ubodOXO+Gx8YFFwEJQgMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKAMSZlgePoQcu5TeYupzVYOiMsTIiPpu3vLsL4cHifwd1AABAwiQXwEAAAAAAAEEIlEgELYvxakKvKAWeWHb/0zq6aoyTvssfyRmJ+i1oz3jfIQBCUICqfH6wsxFdoTzPekAc/4g0iyUfJIWO4YrFNCrod9HFRACSkjXbiDUC89fLhpcP/6z3CqLO4jXmkhtVMnZ6qj6GI4A", + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQIBBgEAIgcDM2HT/3LzTmtOenvvluW4FR5mqXmtznU8OcWDy+V2bSghA2bPx/3OBuCO1JsbOVK40VGo9+B1/l9t1Y3Wj52t7sqUIggDM2HT/3LzTmtOenvvluW4FR5mqXmtznU8OcWDy+V2bShAXquLCG1IUP6dHJ+WGpH5l7YcqNCFCvwGp4vfPHSe9UBQ5pK1P7WwhuXnh5PwHnbTdH+J4xd6f+/2+MFhfxsG4wH7BAIAAAAAAQEfQA0DAAAAAAAWABQeKteHLTKUE6Vt8JaL4zgiJ4MWOyICAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/RzBEAiAKK+ZG0anqXBVNlCNCmskJl9/09NFCJp/mC8dvxE42HAIgCANa6s/ngmX6X6JTanzM6oXez4bcGYlSGOAMQI1gw7ABAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g/S309Ytav5uR/xoeQ+LjUj9QxqoZ1cIjYBQexIyagCEBDwQAAAAAARAE/v///yIdAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQIQP70XPZxI1YxQIkJtBSeLyhe5qOIoJmaQGhsAueBLeZSSIeAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQQMBdpBBIfPrsN4/r5q9QBeOubIYjaBiw5VshQBfrUHPt70AXlXW13NqpBjSRrIuD/QYk1Bd6TS3UmUxGQNa4zN4AAQEfQA0DAAAAAAAWABSmklEcB5V1vzdW2rxWrXHUKEppDiICAvW1n6XkkiIev1W6eK1EJgW+rpUWa6HroyUNC7qsfi7cSDBFAiEA1c3ZMOY2lwfrZ4b1q8L00OgVt4cmVi2tA1VpGbbQIjgCIF8zRs9QoCxciaScoUlqFfUE49+mFdDTyCBi0nGS0uE5AQEDBAEAAAAiBgL1tZ+l5JIiHr9VunitRCYFvq6VFmuh66MlDQu6rH4u3AgAAACAAQAAAAEOIITULym/Ww9KyMHgbIoBNLUz+CwKAffuThNSpATHWvsuAQ8EAAAAAAEQBP7///8iHQKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVECEDpqibG5hqmVUz4XvtZFALVBuw1zkHHv4q4rfvsKDKa88iHgKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVEEDDSmopQLvppzVsHMb/41jdREHbWIl8upnCEut1KF59oeyhHHksl6OASTNFqyJN6dlMKzbuhSauI1KBcaMjHeczAAEDCJBfAQAAAAAAAQQiUSCxKAm+EU5RY5SZU7O++G4xbRcMZzZlTdRqkb2+RLxVEAEJQgMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKAMSZlgePoQcu5TeYupzVYOiMsTIiPpu3vLsL4cHifwd1AABAwiQXwEAAAAAAAEEIlEge2sCToSJVp8gv7oB/byYmecZMBVcHiDoeJIGlPmxpggBCUICqfH6wsxFdoTzPekAc/4g0iyUfJIWO4YrFNCrod9HFRACSkjXbiDUC89fLhpcP/6z3CqLO4jXmkhtVMnZ6qj6GI4A", "supplementary": { "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "21809a8cc41e146023c2d519aac6503f52e3e2431e1aff919bbf5a8bf5f42dfd", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 200000, - "witness_utxo": "400d030000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01400d0300000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "400d0300000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": true }, @@ -731,11 +869,11 @@ "input_index": 1, "private_key": "295c2eedddd8331d20b5d4cf9e69bb523ed85cb0bf35ab12e04fea66fe6d4a4a", "public_key": "02f5b59fa5e492221ebf55ba78ad442605beae95166ba1eba3250d0bbaac7e2edc", - "prevout_txid": "be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab522", + "prevout_txid": "2efb5ac704a452134eeef7010a2cf833b534018a6ce0c1c84a0f5bbf292fd484", "prevout_index": 0, - "prevout_scriptpubkey": "0014139350117c577941a985802bb9edefc113932bc7", "amount": 200000, - "witness_utxo": "400d030000000000160014139350117c577941a985802bb9edefc113932bc7", + "non_witness_utxo": "0200000001be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab5220000000000ffffffff01400d030000000000160014a692511c079575bf3756dabc56ad71d4284a690e00000000", + "witness_utxo": "400d030000000000160014a692511c079575bf3756dabc56ad71d4284a690e", "sequence": 4294967294, "signed": true } @@ -764,31 +902,31 @@ "output_index": 0, "amount": 90000, "sp_v0_info": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28031266581e3e841cbb94de62ea735583a232c4c888fa6edef2ec2f870789fc1dd4", - "script": "512080eb98318bcf6dd611ac17a964b091736c04caeadf2e6e874e5cef86c7c60517" + "script": "5120b12809be114e5163949953b3bef86e316d170c6736654dd46a91bdbe44bc5510" }, { "output_index": 1, "amount": 90000, "sp_v0_info": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510024a48d76e20d40bcf5f2e1a5c3ffeb3dc2a8b3b88d79a486d54c9d9eaa8fa188e", - "script": "512010b62fc5a90abca0167961dbff4ceae9aa324efb2c7f246627e8b5a33de37c84" + "script": "51207b6b024e8489569f20bfba01fdbc9899e71930155c1e20e878920694f9b1a608" } ] } }, { "description": "can finalize: one input / one sp output with both global and per-input ECDH shares", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBACIHAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oIQMKGLm7QZm4kzDrF/juWseG4IU9zS88zfF0S5fOTt4FPiIIAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oQCf7kMXWHHjjEVIA/9GD0o0KtIOAYslUGTTGQW1CZ84xvUKH6TWUUsCBevDvTVDP9XhDaw0o+e2PIbeaRHZAgI4AAQ4gGKcXZjsLqxSxKhp3EyP/HkB53VMuXdE+KOoQgccAmEoBDwQAAAAAAQEfQA0DAAAAAAAWABQimnLTSmRb00lru/ULu4HJBj9PlCICAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/RzBEAiA3eo+fWjPY+iVcM7OSJtO88CKd+tlgRw74AWpxQvIzWAIgCBvWlIh63us2Ia9aLeTw05yxNpLQQb99vM00oysFQekBAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oIQMKGLm7QZm4kzDrF/juWseG4IU9zS88zfF0S5fOTt4FPiIeAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oQAATg9RmG+hyXvKQSPSMkR+J9fNDF9fAwKzGDvZfG1K//3qW2DObYl34Orq1eqJz7c2aNceU2suxyGEXG7JnB18AAQMIkF8BAAAAAAABBCJRINxNRNnjYeXnQ2V5x44lklVB4in9wVOtWYmtiuawYkx4AQlCAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oAxJmWB4+hBy7lN5i6nNVg6IyxMiI+m7e8uwvhweJ/B3UAA==", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAIgcDM2HT/3LzTmtOenvvluW4FR5mqXmtznU8OcWDy+V2bSghAwoYubtBmbiTMOsX+O5ax4bghT3NLzzN8XRLl85O3gU+IggDM2HT/3LzTmtOenvvluW4FR5mqXmtznU8OcWDy+V2bShAJ/uQxdYceOMRUgD/0YPSjQq0g4BiyVQZNMZBbUJnzjG9QofpNZRSwIF68O9NUM/1eENrDSj57Y8ht5pEdkCAjgH7BAIAAAAAAQEfQA0DAAAAAAAWABQeKteHLTKUE6Vt8JaL4zgiJ4MWOyICAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/SDBFAiEAyFvlr5bhqKf1YcXDSFBg36YAz/htqrTzO6OY5lBittkCIBPq0/BHmz/uJrpIh+BRh2ZjzRP8fmHmDS6WBkIym0HkAQEDBAEAAAAiBgLIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvwgAAACAAAAAAAEOIP0t9PWLWr+bkf8aHkPi41I/UMaqGdXCI2AUHsSMmoAhAQ8EAAAAAAEQBP7///8iHQMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKCEDChi5u0GZuJMw6xf47lrHhuCFPc0vPM3xdEuXzk7eBT4iHgMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKEAAE4PUZhvocl7ykEj0jJEfifXzQxfXwMCsxg72XxtSv/96ltgzm2Jd+Dq6tXqic+3NmjXHlNrLschhFxuyZwdfAAEDCJBfAQAAAAAAAQQiUSAqcL4BPYeh6B6gH736DPH/CNUqaNGMExqMyWAfhKagrAEJQgMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKAMSZlgePoQcu5TeYupzVYOiMsTIiPpu3vLsL4cHifwd1AA=", "supplementary": { "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "21809a8cc41e146023c2d519aac6503f52e3e2431e1aff919bbf5a8bf5f42dfd", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 200000, - "witness_utxo": "400d030000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01400d0300000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "400d0300000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": true } @@ -805,25 +943,25 @@ "output_index": 0, "amount": 90000, "sp_v0_info": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28031266581e3e841cbb94de62ea735583a232c4c888fa6edef2ec2f870789fc1dd4", - "script": "5120dc4d44d9e361e5e7436579c78e25925541e229fdc153ad5989ad8ae6b0624c78" + "script": "51202a70be013d87a1e81ea01fbdfa0cf1ff08d52a68d18c131a8cc9601f84a6a0ac" } ] } }, { "description": "can finalize: three sp outputs (different scan keys) with multiple global ECDH shares", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEDAQYBACIHAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQIQLC2d9g7mmlqGYE3ZpigsIu+OLJJ22m5ZWlRj83Gq3uJCIHAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oIQLcfS7KxWiwEVF1ujzVSW/0xLbZCUItvMrrjyUvpU+L0CIHA47TIg5zNE+R4tMzkePhaR2zna8G5CN+GX7Q0Ae/JyhsIQJwvvXAapqFX8Y7/yvQvi1wAzyCC2FTQTyNbtpR8lobKSIIAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQQOyCQr97WIHO4GBWbH8TzEfkcQyJomRYwgMBswMeSBc7wL6gFoDTN1616AYRqw1Qix5Jq7VxsYeAMqrknwsC99IiCAMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKEDqQ0cOXhvjKRtIoLy1P1WVLGSGDnY177pQA8yt7XfdEo4hZpew9SO+IX7Gh1B3l8zOvFzZQ2KvG0bYA2Qr1flAIggDjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGxAG9/lTtSioG//mwAJrk49gPxHYWR1r98hJEz+PG0QTfJHQah1UU14ZU+5yhEY5tPlUvOPjKujVS6DM8UBvwy9PwABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR8goQcAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQCLg3ekbsHGTj/QlvLhIwW7hrrfzKDP2b9X3JYim55whAIgfn3H3eyoVVwXfr7/yUnqTDNSD+W+7Hun4nJ+NPvUjf0BIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////AAEOIL6dZcg5FfsJJIq738qMo+7mzjUMVU9l6NUm5d9SerUiAQ8EAAAAAAEBH6CGAQAAAAAAFgAURjPVnK0TQ0eZcuDJlpIdCl2ttl0iAgJDoNQOneCIJ5QWF1K65CupCVJ4QgnwY0MPCvJWNUqFu0gwRQIhAPmSLe+tUsYSCQS6pacAUymDbsHD2uFsoGjAFrJrBNLYAiBw+V8k+cklbkGWlGnDUqz6yOiUMjUC6s0WPJSi42nuHwEiBgJDoNQOneCIJ5QWF1K65CupCVJ4QgnwY0MPCvJWNUqFuwgAAACAAQAAAAEQBP7///8AAQMIkF8BAAAAAAABBCJRIKFPr9x+36QEQnF0sSasoOmZMTP+F+JCCurtIO9U/DjcAQlCAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oAxJmWB4+hBy7lN5i6nNVg6IyxMiI+m7e8uwvhweJ/B3UAAEDCJBfAQAAAAAAAQQiUSB99fJJWUQ0FLvv6J0tqJSGSlYotoAzuSPoaGvcw96dlAEJQgKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVEAJKSNduINQLz18uGlw//rPcKos7iNeaSG1UydnqqPoYjgABAwiQXwEAAAAAAAEEIlEgsvEqf1cMxQV4QPpjk/cfBpABQgiBgYEMNLuIdh2SlQ0BCUIDjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGwD+BRzhEyddMkh/xelr0ELYzc0jXr7/3OJG8XLDLJMsMAA", + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQMBBgEAIgcCqfH6wsxFdoTzPekAc/4g0iyUfJIWO4YrFNCrod9HFRAhAsLZ32DuaaWoZgTdmmKCwi744sknbabllaVGPzcare4kIgcDM2HT/3LzTmtOenvvluW4FR5mqXmtznU8OcWDy+V2bSghAtx9LsrFaLARUXW6PNVJb/TEttkJQi28yuuPJS+lT4vQIgcDjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGwhAnC+9cBqmoVfxjv/K9C+LXADPIILYVNBPI1u2lHyWhspIggCqfH6wsxFdoTzPekAc/4g0iyUfJIWO4YrFNCrod9HFRBA7IJCv3tYgc7gYFZsfxPMR+RxDImiZFjCAwGzAx5IFzvAvqAWgNM3XrXoBhGrDVCLHkmrtXGxh4AyquSfCwL30iIIAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oQOpDRw5eG+MpG0igvLU/VZUsZIYOdjXvulADzK3td90SjiFml7D1I74hfsaHUHeXzM68XNlDYq8bRtgDZCvV+UAiCAOO0yIOczRPkeLTM5Hj4Wkds52vBuQjfhl+0NAHvycobEAb3+VO1KKgb/+bAAmuTj2A/EdhZHWv3yEkTP48bRBN8kdBqHVRTXhlT7nKERjm0+VS84+Mq6NVLoMzxQG/DL0/AfsEAgAAAAABAR8goQcAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQC42QsRZqzXY8+uqHOJGaBPRdBVbSvLD2Z/C6PEGO5f2QIgI64RGn6itGrUpKOIKuT++973rl0BtM22H1aXmv9SahgBIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiDUQOda/N1TGlkeN6vSbkryvw9v8uGRgwI1Yej8VxOPSgEPBAAAAAABEAT+////AAEBH6CGAQAAAAAAFgAUNyH6c8IwXLL4joSJLWvWuXcmHmoiAgJDoNQOneCIJ5QWF1K65CupCVJ4QgnwY0MPCvJWNUqFu0gwRQIhAJfXTGL5WdOu1bnHpXDy1zyq0MCrseRy1E/UxirCYuS5AiAX2VXEZF+Fr+z2aKPQRlXWdZPyNXYrGm9SKYcXYECqoAEiBgJDoNQOneCIJ5QWF1K65CupCVJ4QgnwY0MPCvJWNUqFuwgAAACAAQAAAAEOIOdsAXEIOkxftK/i9tYfAKRzAbnQH40uR3gKt1QuN3wIAQ8EAAAAAAEQBP7///8AAQMIkF8BAAAAAAABBCJRIE6KUf3Rq9Uk/FLWkolTgu5u3MSNN3228eZRXyNALkgnAQlCAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oAxJmWB4+hBy7lN5i6nNVg6IyxMiI+m7e8uwvhweJ/B3UAAEDCJBfAQAAAAAAAQQiUSB+MV8kXPlXXxNDwxcP/O42rUbTO1ZfCji5lDx8AqzXawEJQgKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVEAJKSNduINQLz18uGlw//rPcKos7iNeaSG1UydnqqPoYjgABAwiQXwEAAAAAAAEEIlEgPK1PnUbiURy2iCuvYOjtgGIgsUFRPWkE2s0r6qE3w5UBCUIDjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGwD+BRzhEyddMkh/xelr0ELYzc0jXr7/3OJG8XLDLJMsMAA", "supplementary": { "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "4a8f1357fce86135028391e1f26f0fbff24a6ed2ab371e591a53ddfc5ae740d4", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 500000, - "witness_utxo": "20a1070000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff0120a10700000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "20a10700000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": true }, @@ -831,11 +969,11 @@ "input_index": 1, "private_key": "586b0810bbc3c7266971aeb7f8778b41707e092a1aeaf0d953b211f956e35541", "public_key": "0243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb", - "prevout_txid": "be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab522", + "prevout_txid": "087c372e54b70a78472e8d1fd0b90173a4001fd6f6e2afb45f4c3a0871016ce7", "prevout_index": 0, - "prevout_scriptpubkey": "00144633d59cad1343479972e0c996921d0a5dadb65d", "amount": 100000, - "witness_utxo": "a0860100000000001600144633d59cad1343479972e0c996921d0a5dadb65d", + "non_witness_utxo": "0200000001be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab5220000000000ffffffff01a0860100000000001600143721fa73c2305cb2f88e84892d6bd6b977261e6a00000000", + "witness_utxo": "a0860100000000001600143721fa73c2305cb2f88e84892d6bd6b977261e6a", "sequence": 4294967294, "signed": true } @@ -862,37 +1000,37 @@ "output_index": 0, "amount": 90000, "sp_v0_info": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28031266581e3e841cbb94de62ea735583a232c4c888fa6edef2ec2f870789fc1dd4", - "script": "5120a14fafdc7edfa404427174b126aca0e9993133fe17e2420aeaed20ef54fc38dc" + "script": "51204e8a51fdd1abd524fc52d692895382ee6edcc48d377db6f1e6515f23402e4827" }, { "output_index": 1, "amount": 90000, "sp_v0_info": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510024a48d76e20d40bcf5f2e1a5c3ffeb3dc2a8b3b88d79a486d54c9d9eaa8fa188e", - "script": "51207df5f24959443414bbefe89d2da894864a5628b68033b923e8686bdcc3de9d94" + "script": "51207e315f245cf9575f1343c3170ffcee36ad46d33b565f0a38b9943c7c02acd76b" }, { "output_index": 2, "amount": 90000, "sp_v0_info": "038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c03f81473844c9d74c921ff17a5af410b6337348d7afbff73891bc5cb0cb24cb0c0", - "script": "5120b2f12a7f570cc5057840fa6393f71f06900142088181810c34bb88761d92950d" + "script": "51203cad4f9d46e2511cb6882baf60e8ed806220b141513d6904dacd2beaa137c395" } ] } }, { "description": "can finalize: one P2WPKH input / two mixed outputs - labeled sp output and BIP 32 change", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQECAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR8goQcAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQCspcmETsmSLIHmcIF+My2i3RXSxdOpRiq21l5TtoKJXgIgTfMs6jgucsQ8BYQE/a5wWVHmuj3jPYM8g6lbsBg4CscBAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIoIYBAAAAAAABBCJRIHwkw/lKVR+Uy49cDgPMmhcIf7FNcUpdL06f1MeJ09NmAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoAuJBKtaGGMwJH8G/tuRd4l0b3BZXsljCbRYdEtLosDafAQoEAQAAAAABAwhw8wUAAAAAAAEEFgAUOMGPNd2AY+OApw/+tPmP9O80gXciAgLIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvwwAAAAAAAAAAAAAAAEA", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQIBBgEAAfsEAgAAAAABAR8goQcAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9GMEMCIHcTD90bfOCOxkvITdaflmuTJVdETA9hMOK+XNqEia5EAh938mc1PdR7+Nrf+wdHBtYIqIWc7eTcyYzYZ3xl0LWsAQEDBAEAAAAiBgLIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvwgAAACAAAAAAAEOINRA51r83VMaWR43q9JuSvK/D2/y4ZGDAjVh6PxXE49KAQ8EAAAAAAEQBP7///8iHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCED7KT/Ebco4uD2DOYiKUOm/1W52V9ie/mpnQhLyHLVClsiHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaECKE7OYVUX3K9bolxSuuQmz41SoQqm7i1bNDt7SHfihmVmLMSKKSeC9fpXOEFP3xbKKy1Q6aHB2AOPOiYIu4yAhAAEDCKCGAQAAAAAAAQQiUSCy11CmDsTQW9LCInHwj+IbAOJxHTgjBIu5ZaIrxBc9LwEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaAPqjyKL4rcW2s3vyygQByh08ApHb1wHvQUZFxJsxks97wEKBAEAAAAAIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8MAAAAAAAAAAAAAAABAQMIcPMFAAAAAAABBBYAFDjBjzXdgGPjgKcP/rT5j/TvNIF3AA==", "supplementary": { "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "4a8f1357fce86135028391e1f26f0fbff24a6ed2ab371e591a53ddfc5ae740d4", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 500000, - "witness_utxo": "20a1070000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff0120a10700000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "20a10700000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": true } @@ -909,9 +1047,9 @@ { "output_index": 0, "amount": 100000, - "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe06803ea8f228be2b716dacdefcb2810072874f00a476f5c07bd051917126cc64b3def", "sp_v0_label": 1, - "script": "51207c24c3f94a551f94cb8f5c0e03cc9a17087fb14d714a5d2f4e9fd4c789d3d366" + "script": "5120b2d750a60ec4d05bd2c22271f08fe21b00e2711d3823048bb965a22bc4173d2f" }, { "output_index": 1, @@ -923,18 +1061,18 @@ }, { "description": "can finalize: one input / two sp outputs - output 0 has no label / output 1 uses label=0 convention for sp change", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQECAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR/gkwQAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCICJa45kPVF365uoUKpN0arSqgSfjyBNY63wha08anrtiAiBl42BSGRArJQdeOVXz80zjvPKjXR4QFd1dw7/tPs81qQEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0CXw7Bs42ZhKfrYvFb5AMCBBDxQu301p42P1YVr9Kmts0hA84eNnXZDZkmSfqd2xH5AlSbs7AvVvbonMCgTIuMN92UIh0Ci3kOCYf96fDRI5jra+MMc3Z5PGR4ZaKgLy78lg2WZWghAlWBv6pzMVb2uY5xom9w/XazZ4ZJ9isfxed7jpq45hBQIh4CXw7Bs42ZhKfrYvFb5AMCBBDxQu301p42P1YVr9Kmts1ADolhPR9rJTbbj6kkIA2zpvjvyhciVWTVaxEuUIZbTTAuBY+m9hwp4jZqSnJp1FVaXGHWVVnb+/rJ4urf5TY31SIeAot5DgmH/enw0SOY62vjDHN2eTxkeGWioC8u/JYNlmVoQHlAgZ626fJYwVg4fApkzBb1F8fvRAkSLM6qlPTi/1N2xCR7/BcNmyY7Dj0ga2aMh+lLNN7q+gCheSsEeteIdbsAAQMIoIYBAAAAAAABBCJRIKBIDZZnnBk25au9SLqw4B/6yx7n0cnhaC8VQBaZZYXZAQlCAot5DgmH/enw0SOY62vjDHN2eTxkeGWioC8u/JYNlmVoA7RDRzNcY/UF5V4mirKA8xi0pqoUSS/zecNmih9U74ybAAEDCDDmAgAAAAAAAQQiUSB2Hb00kpiEpmcp69zbrPFnSC32LBTwmOTvGNcP4Grv0AEJQgJfDsGzjZmEp+ti8VvkAwIEEPFC7fTWnjY/VhWv0qa2zQK+EFEqlVNkHkB62OUJo0GEUqkC6FVqDboumD9eAPe8UQEKBAAAAAAA", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQIBBgEAAfsEAgAAAAABAR/gkwQAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIFB2CeL9erskEbcJ/ZjL+pgC0nxcDrLBEMLU8/EJ61yYAiBeYmSIxVqzZbFYt+8gUlTszHEFFvbNOzksUNGJgWmDsQEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiDXHS3QFsrGYSyer5hVH2eAhRu3czlByBTq+trO3jDcPQEPBAAAAAABEAT+////Ih0CXw7Bs42ZhKfrYvFb5AMCBBDxQu301p42P1YVr9Kmts0hA84eNnXZDZkmSfqd2xH5AlSbs7AvVvbonMCgTIuMN92UIh0Ci3kOCYf96fDRI5jra+MMc3Z5PGR4ZaKgLy78lg2WZWghAlWBv6pzMVb2uY5xom9w/XazZ4ZJ9isfxed7jpq45hBQIh4CXw7Bs42ZhKfrYvFb5AMCBBDxQu301p42P1YVr9Kmts1ADolhPR9rJTbbj6kkIA2zpvjvyhciVWTVaxEuUIZbTTAuBY+m9hwp4jZqSnJp1FVaXGHWVVnb+/rJ4urf5TY31SIeAot5DgmH/enw0SOY62vjDHN2eTxkeGWioC8u/JYNlmVoQHlAgZ626fJYwVg4fApkzBb1F8fvRAkSLM6qlPTi/1N2xCR7/BcNmyY7Dj0ga2aMh+lLNN7q+gCheSsEeteIdbsAAQMIoIYBAAAAAAABBCJRIBM/6m8cjln0UbKW1K2xPs7sf8M9vFNq5NY3WropOE+LAQlCAot5DgmH/enw0SOY62vjDHN2eTxkeGWioC8u/JYNlmVoA7RDRzNcY/UF5V4mirKA8xi0pqoUSS/zecNmih9U74ybAAEDCDDmAgAAAAAAAQQiUSBgK8NLBuQ1Rvh+VIKxETqr+cn+KSUJmpItXCPYS7zqxgEJQgJfDsGzjZmEp+ti8VvkAwIEEPFC7fTWnjY/VhWv0qa2zQLOCzIZpapd+PIc45PpYs3afVFUbaTTXDjtAYilludg8wEKBAAAAAAA", "supplementary": { "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "3ddc30decedafaea14c8413973b71b8580671f5598af9e2c61c6ca16d02d1dd7", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 300000, - "witness_utxo": "e093040000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01e0930400000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "e0930400000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": true } @@ -958,32 +1096,32 @@ "output_index": 0, "amount": 100000, "sp_v0_info": "028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d96656803b44347335c63f505e55e268ab280f318b4a6aa14492ff379c3668a1f54ef8c9b", - "script": "5120a0480d96679c1936e5abbd48bab0e01ffacb1ee7d1c9e1682f154016996585d9" + "script": "5120133fea6f1c8e59f451b296d4adb13eceec7fc33dbc536ae4d6375aba29384f8b" }, { "output_index": 1, "amount": 190000, - "sp_v0_info": "025f0ec1b38d9984a7eb62f15be403020410f142edf4d69e363f5615afd2a6b6cd037cd462358c69c40525247a8793944d9e67484b248fd84a1e7ee4f920b4da41b5", + "sp_v0_info": "025f0ec1b38d9984a7eb62f15be403020410f142edf4d69e363f5615afd2a6b6cd02ce0b3219a5aa5df8f21ce393e962cdda7d51546da4d35c38ed0188a596e760f3", "sp_v0_label": 0, - "script": "5120761dbd34929884a66729ebdcdbacf167482df62c14f098e4ef18d70fe06aefd0" + "script": "5120602bc34b06e43546f87e5482b1113aabf9c9fe2925099a922d5c23d84bbceac6" } ] } }, { "description": "can finalize: two sp outputs - output 0 uses label=3 / output 1 uses label=1", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQECAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR/gkwQAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCICJa45kPVF365uoUKpN0arSqgSfjyBNY63wha08anrtiAiBl42BSGRArJQdeOVXz80zjvPKjXR4QFd1dw7/tPs81qQEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Ci3kOCYf96fDRI5jra+MMc3Z5PGR4ZaKgLy78lg2WZWghAlWBv6pzMVb2uY5xom9w/XazZ4ZJ9isfxed7jpq45hBQIh4Ci3kOCYf96fDRI5jra+MMc3Z5PGR4ZaKgLy78lg2WZWhAeUCBnrbp8ljBWDh8CmTMFvUXx+9ECRIszqqU9OL/U3bEJHv8Fw2bJjsOPSBrZoyH6Us03ur6AKF5KwR614h1uwABAwighgEAAAAAAAEEIlEgjkFVhZ37qH3uVCd4eSDGlYuRbXrHP02lCyzrTAnwYY8BCUICi3kOCYf96fDRI5jra+MMc3Z5PGR4ZaKgLy78lg2WZWgD8+Tq+VWJ7fdfgshaz/nQvOSCnhaA85Xsfq1iaXfwhRMBCgQDAAAAAAEDCDDmAgAAAAAAAQQiUSDj5vwH7Pa/a1m0ubaqUxM11laKeL6AjUVOAg1+jH/aUwEJQgKLeQ4Jh/3p8NEjmOtr4wxzdnk8ZHhloqAvLvyWDZZlaALcqxqjkFTkguCjoiOo8Sgs1xGXZTHGeaoggF9/X6TxawEKBAEAAAAA", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQIBBgEAAfsEAgAAAAABAR/gkwQAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQDZJbO/p1XneLxjndqLedHNDt2LpWCdfZLLHzJ9banHkQIgFXaZjOtRHGsMQla9SjGh3cNAEDNdyZq7TBmbyhEV5PIBAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g1x0t0BbKxmEsnq+YVR9ngIUbt3M5QcgU6vrazt4w3D0BDwQAAAAAARAE/v///yIdAot5DgmH/enw0SOY62vjDHN2eTxkeGWioC8u/JYNlmVoIQJVgb+qczFW9rmOcaJvcP12s2eGSfYrH8Xne46auOYQUCIeAot5DgmH/enw0SOY62vjDHN2eTxkeGWioC8u/JYNlmVoQHlAgZ626fJYwVg4fApkzBb1F8fvRAkSLM6qlPTi/1N2xCR7/BcNmyY7Dj0ga2aMh+lLNN7q+gCheSsEeteIdbsAAQMIoIYBAAAAAAABBCJRIBPSHod1uahNrA4VjbAnhGU9Fr1/sv3Qw+Wjq6KVgWLGAQlCAot5DgmH/enw0SOY62vjDHN2eTxkeGWioC8u/JYNlmVoAu+oIvCuW/9HHRN09ozClt/pcxrzh2/50ThqMLAf/pwQAQoEAwAAAAABAwgw5gIAAAAAAAEEIlEg3h2DrBUJUvALticyRSb2WFv4fjk4CIFK2VYmY5+H+rcBCUICi3kOCYf96fDRI5jra+MMc3Z5PGR4ZaKgLy78lg2WZWgD1DFYje5hqzo5clspnDdC3Gaghh3s9ZG0I7DlJwcPgjQBCgQBAAAAAA==", "supplementary": { "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "3ddc30decedafaea14c8413973b71b8580671f5598af9e2c61c6ca16d02d1dd7", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 300000, - "witness_utxo": "e093040000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01e0930400000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "e0930400000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": true } @@ -1000,34 +1138,90 @@ { "output_index": 0, "amount": 100000, - "sp_v0_info": "028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d96656803b44347335c63f505e55e268ab280f318b4a6aa14492ff379c3668a1f54ef8c9b", + "sp_v0_info": "028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d96656802efa822f0ae5bff471d1374f68cc296dfe9731af3876ff9d1386a30b01ffe9c10", "sp_v0_label": 3, - "script": "51208e4155859dfba87dee5427787920c6958b916d7ac73f4da50b2ceb4c09f0618f" + "script": "512013d21e8775b9a84dac0e158db02784653d16bd7fb2fdd0c3e5a3aba2958162c6" }, { "output_index": 1, "amount": 190000, - "sp_v0_info": "028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d96656803b44347335c63f505e55e268ab280f318b4a6aa14492ff379c3668a1f54ef8c9b", + "sp_v0_info": "028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d96656803d431588dee61ab3a39725b299c3742dc66a0861decf591b423b0e527070f8234", + "sp_v0_label": 1, + "script": "5120de1d83ac150952f00bb627324526f6585bf87e393808814ad95626639f87fab7" + } + ] + } + }, + { + "description": "can finalize: three labeled sp outputs (same scan key) - k assigned by lexicographic code order, not output index", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQQBBgEAAfsEAgAAAAABAR+AGgYAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQCETtmM8YHVKfxkiglfbVPircDEwSMyChfNxQUn7aoyVwIgaPox6uw1Qu5x0FpEPsML+NyyJhyEv9LMl7vq6ZJpYp4BAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4gcOBrhlWVxMJzHTP1pq0oD7hwNVRmYpiAyl3NjpAH4ZoBDwQAAAAAARAE/v///yIdAot5DgmH/enw0SOY62vjDHN2eTxkeGWioC8u/JYNlmVoIQJVgb+qczFW9rmOcaJvcP12s2eGSfYrH8Xne46auOYQUCIeAot5DgmH/enw0SOY62vjDHN2eTxkeGWioC8u/JYNlmVoQHlAgZ626fJYwVg4fApkzBb1F8fvRAkSLM6qlPTi/1N2xCR7/BcNmyY7Dj0ga2aMh+lLNN7q+gCheSsEeteIdbsAAQMIoIYBAAAAAAABBCJRIJPaXrkneTYjgSVQ+GmdZjtxlvDMnUiEWLtoH+srb/y6AQlCAot5DgmH/enw0SOY62vjDHN2eTxkeGWioC8u/JYNlmVoA9QxWI3uYas6OXJbKZw3QtxmoIYd7PWRtCOw5ScHD4I0AQoEAQAAAAABAwighgEAAAAAAAEEIlEg9OMGNuSPanr+mE+gslRbJX6q6MqhbsSBk9s0iSaVh1sBCUICi3kOCYf96fDRI5jra+MMc3Z5PGR4ZaKgLy78lg2WZWgDIZOtDIdfrFJDc4AikAp3JMYXXdrJlEFlqrRXqt+cTzwBCgQCAAAAAAEDCKCGAQAAAAAAAQQiUSCGOyN7vyTS6f5I4im0Hh4KYPO5s8eCeXJrcqYFAWh14AEJQgKLeQ4Jh/3p8NEjmOtr4wxzdnk8ZHhloqAvLvyWDZZlaAMWwyp3CNHuEMhsTASy75yG3jAzxOzK2QptA0tTHnE1awEKBAQAAAAAAQMIkF8BAAAAAAABBCJRIHnvVoij+n/vw5InRVsfHC8IxwCHQk1qAPhMMUIayo2kAA==", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "9ae107908ecd5dca80986266543570b80f28ada6f5331d73c2c49555866be070", + "prevout_index": 0, + "amount": 400000, + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01801a0600000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "801a0600000000001600141e2ad7872d329413a56df0968be338222783163b", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d966568", + "ecdh_share": "025581bfaa733156f6b98e71a26f70fd76b3678649f62b1fc5e77b8e9ab8e61050", + "dleq_proof": "7940819eb6e9f258c158387c0a64cc16f517c7ef4409122cceaa94f4e2ff5376c4247bfc170d9b263b0e3d206b668c87e94b34deeafa00a1792b047ad78875bb", + "input_index": 0 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 100000, + "sp_v0_info": "028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d96656803d431588dee61ab3a39725b299c3742dc66a0861decf591b423b0e527070f8234", "sp_v0_label": 1, - "script": "5120e3e6fc07ecf6bf6b59b4b9b6aa531335d6568a78be808d454e020d7e8c7fda53" + "script": "512093da5eb927793623812550f8699d663b7196f0cc9d488458bb681feb2b6ffcba" + }, + { + "output_index": 1, + "amount": 100000, + "sp_v0_info": "028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d966568032193ad0c875fac5243738022900a7724c6175ddac9944165aab457aadf9c4f3c", + "sp_v0_label": 2, + "script": "5120f4e30636e48f6a7afe984fa0b2545b257eaae8caa16ec48193db34892695875b" + }, + { + "output_index": 2, + "amount": 100000, + "sp_v0_info": "028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d9665680316c32a7708d1ee10c86c4c04b2ef9c86de3033c4eccad90a6d034b531e71356b", + "sp_v0_label": 4, + "script": "5120863b237bbf24d2e9fe48e229b41e1e0a60f3b9b3c78279726b72a605016875e0" + }, + { + "output_index": 3, + "amount": 90000, + "script": "512079ef5688a3fa7fefc39227455b1f1c2f08c70087424d6a00f84c31421aca8da4" } ] } }, { - "description": "can finalize: two mixed input types - only eligible inputs contribute ECDH shares (P2SH excluded)", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQCLTLcGPIp7P5Ia4ABZbNd4jlRA4dY+8e4bzsjCrJQMogIgNw2OmoWgzI3SWwuwgfMaotzFugoiSOqGCoFlHKNKDGgBAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQ4g0iImLyaHKbt8hMVYEppdaYYYXO9TXsFJwN9g3UqSwgQBDwQAAAAAAQBTAgAAAAFA5vqmEmjxehAQHWJVNYKIKuSFi+4TNj24D98oH4Jf/AAAAAAA/////wHwSQIAAAAAABepFPRfjMomjsJuS76JkXDxOCUNfPVehwAAAAABBEdSIQKHfKAvFEBZvYLQDhs5muN094pSzvehyjfyjXiLNA0veSEDTIekSHL14fAG002IoAlZKCvUU150d8PWjDFlmR6hs5ZSrgEQBP7///8AAQMIkF8BAAAAAAABBCJRIDJt9Q/goHt6y3IHC+s7Yy65rRW6aVzB5apqoAe2FG/YAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "description": "can finalize: two inputs using per-input ECDH shares - only eligible inputs contribute shares (P2SH excluded)", + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIHX/+DN7oavaEJzJjnIcVUgz9mY0VLyglR21zhcuA3LjAiAFXY5F4lr2Gu+QPcbwd9LpuW0Ut5Op7+w5K5bqn1Hf7gEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAFMCAAAAAUDm+qYSaPF6EBAdYlU1gogq5IWL7hM2PbgP3ygfgl/8AAAAAAD/////AfBJAgAAAAAAF6kU9F+MyiaOwm5LvomRcPE4JQ189V6HAAAAAAEER1IhAod8oC8UQFm9gtAOGzma43T3ilLO96HKN/KNeIs0DS95IQNMh6RIcvXh8AbTTYigCVkoK9RTXnR3w9aMMWWZHqGzllKuAQ4g0iImLyaHKbt8hMVYEppdaYYYXO9TXsFJwN9g3UqSwgQBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQJii2i2RG5qhwJZc9k6+xlOQgoQ86HMs4rdgtRkqJSkKCIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQMIkF8BAAAAAAABBCJRIBZV0TJCpxR530ke2cObPHWqWxzY0Ba/jLNUp013dB3eAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", "supplementary": { "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 100000, - "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": true }, @@ -1035,11 +1229,10 @@ "input_index": 1, "private_key": "", "public_key": "", - "prevout_txid": "d222262f268729bb7c84c558129a5d6986185cef535ec149c0df60dd4a92c204", + "prevout_txid": "04c2924add60dfc049c15e53ef5c1886695d9a1258c5847cbb2987262f2622d2", "prevout_index": 0, - "prevout_scriptpubkey": "a914f45f8cca268ec26e4bbe899170f138250d7cf55e87", "amount": 150000, - "witness_utxo": "020000000140e6faa61268f17a10101d62553582882ae4858bee13363db80fdf281f825ffc0000000000ffffffff01f04902000000000017a914f45f8cca268ec26e4bbe899170f138250d7cf55e8700000000", + "non_witness_utxo": "020000000140e6faa61268f17a10101d62553582882ae4858bee13363db80fdf281f825ffc0000000000ffffffff01f04902000000000017a914f45f8cca268ec26e4bbe899170f138250d7cf55e8700000000", "sequence": 4294967294, "signed": false } @@ -1057,24 +1250,70 @@ "output_index": 0, "amount": 90000, "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", - "script": "5120326df50fe0a07b7acb72070beb3b632eb9ad15ba695cc1e5aa6aa007b6146fd8" + "script": "51201655d13242a71479df491ed9c39b3c75aa5b1cd8d016bf8cb354a74d77741dde" + } + ] + } + }, + { + "description": "can finalize: two inputs using global ECDH share - only eligible inputs contribute shares (P2SH excluded)", + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAIgcCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIggCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAJDBHnS2hMQoCTSqrjkx7Sdds1R9F7oEnwVmwOTpnW291xYHr49CBfdrzu1mM/XoCLxqH7UeWZPa5R6R9tZQcsgH7BAIAAAAAAQEfoIYBAAAAAAAWABQeKteHLTKUE6Vt8JaL4zgiJ4MWOyICAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/RzBEAiB1//gze6Gr2hCcyY5yHFVIM/ZmNFS8oJUdtc4XLgNy4wIgBV2OReJa9hrvkD3G8HfS6bltFLeTqe/sOSuW6p9R3+4BIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABEAT+////AAEAUwIAAAABQOb6phJo8XoQEB1iVTWCiCrkhYvuEzY9uA/fKB+CX/wAAAAAAP////8B8EkCAAAAAAAXqRT0X4zKJo7Cbku+iZFw8TglDXz1XocAAAAAAQRHUiECh3ygLxRAWb2C0A4bOZrjdPeKUs73oco38o14izQNL3khA0yHpEhy9eHwBtNNiKAJWSgr1FNedHfD1owxZZkeobOWUq4BDiDSIiYvJocpu3yExVgSml1phhhc71NewUnA32DdSpLCBAEPBAAAAAABEAT+////AAEDCJBfAQAAAAAAAQQiUSAWVdEyQqcUed9JHtnDmzx1qlsc2NAWv4yzVKdNd3Qd3gEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", + "prevout_index": 0, + "amount": 100000, + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", + "sequence": 4294967294, + "signed": true + }, + { + "input_index": 1, + "private_key": "", + "public_key": "", + "prevout_txid": "04c2924add60dfc049c15e53ef5c1886695d9a1258c5847cbb2987262f2622d2", + "prevout_index": 0, + "amount": 150000, + "non_witness_utxo": "020000000140e6faa61268f17a10101d62553582882ae4858bee13363db80fdf281f825ffc0000000000ffffffff01f04902000000000017a914f45f8cca268ec26e4bbe899170f138250d7cf55e8700000000", + "sequence": 4294967294, + "signed": false + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "2430479d2da1310a024d2aab8e4c7b49d76cd51f45ee8127c159b0393a675b6f75c581ebe3d0817ddaf3bb598cfd7a022f1a87ed479664f6b947a47db5941cb2" + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 90000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "51201655d13242a71479df491ed9c39b3c75aa5b1cd8d016bf8cb354a74d77741dde" } ] } }, { "description": "can finalize: two mixed input types - only eligible inputs contribute ECDH shares (NUMS internal key excluded)", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEBAQYBAAABDiAT8Qa2S1e1sTdvn2xHGQ9AzAazvty4qrqXhQqz1/Z9AgEPBAAAAAABASsQJwAAAAAAACJRIFCSm3TBoElUt4tLYDXpel4HiloPKOyW1Ue/7prOgDrAARAE/v///wEXIFCSm3TBoElUt4tLYDXpel4HiloPKOyW1Ue/7prOgDrAAAEOIL6dZcg5FfsJJIq738qMo+7mzjUMVU9l6NUm5d9SerUiAQ8EAAAAAAEBH6CGAQAAAAAAFgAURjPVnK0TQ0eZcuDJlpIdCl2ttl0iAgJDoNQOneCIJ5QWF1K65CupCVJ4QgnwY0MPCvJWNUqFu0gwRQIhAPRhsN/2Q/wKVsFSIUU2OBYiEkh+UGpZ4GnXXtHwq4T2AiBSxx6U6TEuqKkAH80mNyvnCZfdwqpinFqBFtxR9bfpogEBAwQBAAAAIgYCQ6DUDp3giCeUFhdSuuQrqQlSeEIJ8GNDDwryVjVKhbsIAAAAgAEAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghAuV6etywGNj7MVToDBS5elCZS0I1aEHqn8ExcGFEAOY3Ih4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhA9/o4HeILO0WcbkJsYhPUF1MI8kgqROMyhCMmJNTa/Vcymb868WqzAsViY2OjfUSHB/fnoevqBke8zUhiA7srpgABAwgcJQAAAAAAAAEEIlEgBXZyJSSDmoybydLZc46Yu0DdLsUCO9x9p/cGI818hfsBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAAfsEAgAAAAABASsQJwAAAAAAACJRIFCSm3TBoElUt4tLYDXpel4HiloPKOyW1Ue/7prOgDrAAQ4gYBe1kA+Yvp46bX2crTkCjOrT9SE5p6HZ7FdpPr5smqMBDwQAAAAAARAE/v///wEXIFCSm3TBoElUt4tLYDXpel4HiloPKOyW1Ue/7prOgDrAAAEBH6CGAQAAAAAAFgAUNyH6c8IwXLL4joSJLWvWuXcmHmoiAgJDoNQOneCIJ5QWF1K65CupCVJ4QgnwY0MPCvJWNUqFu0gwRQIhAO0WpquzlGlzstbNkuuIIEIYnLRxCQgyQW7wr3v6HSWoAiA1FLIzGTu4Yav6kSdimxf0vM37oWNLD/S2liY86GL7RQEBAwQBAAAAIgYCQ6DUDp3giCeUFhdSuuQrqQlSeEIJ8GNDDwryVjVKhbsIAAAAgAEAAAABDiDnbAFxCDpMX7Sv4vbWHwCkcwG50B+NLkd4CrdULjd8CAEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghAuV6etywGNj7MVToDBS5elCZS0I1aEHqn8ExcGFEAOY3Ih4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhA9/o4HeILO0WcbkJsYhPUF1MI8kgqROMyhCMmJNTa/Vcymb868WqzAsViY2OjfUSHB/fnoevqBke8zUhiA7srpgABAwgcJQAAAAAAAAEEIlEgPyxAG2oKe3La4XJhY5bRV7fyUUpeQT24CXc2wsuWezYBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", "supplementary": { "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "13f106b64b57b5b1376f9f6c47190f40cc06b3bedcb8aaba97850ab3d7f67d02", + "prevout_txid": "a39a6cbe3e6957ecd9a1a73921f5d3ea8c0239ad9c7d6d3a9ebe980f90b51760", "prevout_index": 0, - "prevout_scriptpubkey": "512050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", "amount": 10000, + "non_witness_utxo": "020000000113f106b64b57b5b1376f9f6c47190f40cc06b3bedcb8aaba97850ab3d7f67d020000000000ffffffff01102700000000000022512050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac000000000", "witness_utxo": "102700000000000022512050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", "sequence": 4294967294, "signed": false @@ -1083,11 +1322,11 @@ "input_index": 1, "private_key": "586b0810bbc3c7266971aeb7f8778b41707e092a1aeaf0d953b211f956e35541", "public_key": "0243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb", - "prevout_txid": "be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab522", + "prevout_txid": "087c372e54b70a78472e8d1fd0b90173a4001fd6f6e2afb45f4c3a0871016ce7", "prevout_index": 0, - "prevout_scriptpubkey": "00144633d59cad1343479972e0c996921d0a5dadb65d", "amount": 100000, - "witness_utxo": "a0860100000000001600144633d59cad1343479972e0c996921d0a5dadb65d", + "non_witness_utxo": "0200000001be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab5220000000000ffffffff01a0860100000000001600143721fa73c2305cb2f88e84892d6bd6b977261e6a00000000", + "witness_utxo": "a0860100000000001600143721fa73c2305cb2f88e84892d6bd6b977261e6a", "sequence": 4294967294, "signed": true } @@ -1105,25 +1344,25 @@ "output_index": 0, "amount": 9500, "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", - "script": "51200576722524839a8c9bc9d2d9738e98bb40dd2ec5023bdc7da7f70623cd7c85fb" + "script": "51203f2c401b6a0a7b72dae172616396d157b7f2514a5e413db8097736c2cb967b36" } ] } }, { "description": "can finalize: three sp outputs (same scan key) - each output has distinct k value", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEEAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+AGgYAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIA3+9XB4r8pV2yK0ze42yxF/h2HkeAgptCHRBkisr62PAiBk5vWJD0/QW3emSnGDHJiGTZyYTJ7x/r6afFC08VkHIQEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwighgEAAAAAAAEEIlEgMm31D+Cge3rLcgcL6ztjLrmtFbppXMHlqmqgB7YUb9gBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkAAQMIoIYBAAAAAAABBCJRID/LrqSQh/jgPZ3v06vL1t6MAytYP4WmXQV4gcTEQ83AAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AAEDCKCGAQAAAAAAAQQiUSCXFELInwR4bggnKK4Rbuq4AvP6npX9sNN1OmhAICAG3gEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQABAwiQXwEAAAAAAAEEIlEgee9WiKP6f+/DkidFWx8cLwjHAIdCTWoA+EwxQhrKjaQA", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQQBBgEAAfsEAgAAAAABAR+AGgYAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIH2bvrz6uqFt0Kqa+PjltDT3VIfbiiHm1QtEnjAT9WsrAiAlq8iYSKvhCgxaq6TPG5n553yKIkS2xy6zrFdRfncXuAEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiBw4GuGVZXEwnMdM/WmrSgPuHA1VGZimIDKXc2OkAfhmgEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwighgEAAAAAAAEEIlEgpL1hojWVPFX7Ib8SF+ZZlw+BcVUweVNwtqhuui4/buABCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkAAQMIoIYBAAAAAAABBCJRIEZ7FHQz3K03MqLFl4fZe6tlntq7U2+lo3EHQLVhS4t1AQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AAEDCKCGAQAAAAAAAQQiUSCkZ5TVNLTq9lSGWuFY2oR7xga4HYq3jhMySv5KWUnbhQEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQABAwiQXwEAAAAAAAEEIlEgee9WiKP6f+/DkidFWx8cLwjHAIdCTWoA+EwxQhrKjaQA", "supplementary": { "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "9ae107908ecd5dca80986266543570b80f28ada6f5331d73c2c49555866be070", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 400000, - "witness_utxo": "801a060000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01801a0600000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "801a0600000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": true } @@ -1141,19 +1380,19 @@ "output_index": 0, "amount": 100000, "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", - "script": "5120326df50fe0a07b7acb72070beb3b632eb9ad15ba695cc1e5aa6aa007b6146fd8" + "script": "5120a4bd61a235953c55fb21bf1217e659970f81715530795370b6a86eba2e3f6ee0" }, { "output_index": 1, "amount": 100000, "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", - "script": "51203fcbaea49087f8e03d9defd3abcbd6de8c032b583f85a65d057881c4c443cdc0" + "script": "5120467b147433dcad3732a2c59787d97bab659edabb536fa5a3710740b5614b8b75" }, { "output_index": 2, "amount": 100000, "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", - "script": "5120971442c89f04786e082728ae116eeab802f3fa9e95fdb0d3753a6840202006de" + "script": "5120a46794d534b4eaf654865ae158da847bc606b81d8ab78e13324afe4a5949db85" }, { "output_index": 3, @@ -1165,18 +1404,18 @@ }, { "description": "can finalize: three sp outputs (same scan key) / two regular outputs - k values assigned independently of output index", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEGAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR8goQcAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQD333KAYwDd2+SyTNcz9TsypkayNsKUYFfeR65QOyqxaAIgTGlAW3e+2vOyB+3ll0m7o9VMRhWoi7025Ugkr3fJ5zEBAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIoIYBAAAAAAABBCJRIDJt9Q/goHt6y3IHC+s7Yy65rRW6aVzB5apqoAe2FG/YAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AAEDCFDDAAAAAAAAAQQiUSCcaj0jgY6CDtHQz965Y2V8jsMne32bhlx411V/Xe3WogABAwighgEAAAAAAAEEIlEgP8uupJCH+OA9ne/Tq8vW3owDK1g/haZdBXiBxMRDzcABCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkAAQMIUMMAAAAAAAABBCJRIHnvVoij+n/vw5InRVsfHC8IxwCHQk1qAPhMMUIayo2kAAEDCKCGAQAAAAAAAQQiUSCXFELInwR4bggnKK4Rbuq4AvP6npX9sNN1OmhAICAG3gEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQABAwjILAEAAAAAAAEEIlEgb8UG+AUqn1qKqbmQ1emU9JXd7W1HusRMqs2t2NiZHNAA", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQYBBgEAAfsEAgAAAAABAR8goQcAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCICcgzDtRc5g6XoCKbBZuU04tEOEjpGhrAqg+sdM9G3B6AiBdslMBO2N4nLRYrOIxjHkT9mvR6OIXHye1MrEw+uWDNQEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiDUQOda/N1TGlkeN6vSbkryvw9v8uGRgwI1Yej8VxOPSgEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwighgEAAAAAAAEEIlEgcjuJtcY4edW50HowRRu91I43rAOOZvcm83ykCrJkq3IBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkAAQMIUMMAAAAAAAABBCJRIJxqPSOBjoIO0dDP3rljZXyOwyd7fZuGXHjXVX9d7daiAAEDCKCGAQAAAAAAAQQiUSCvFHbuA/XpiJDsVJYDYaxJHFbjCpPrKYD8MiuYN6dYugEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQABAwhQwwAAAAAAAAEEIlEgee9WiKP6f+/DkidFWx8cLwjHAIdCTWoA+EwxQhrKjaQAAQMIoIYBAAAAAAABBCJRIJ5nNdGxGWsLGu/g5NEOytKTdJZLn1mSBdF8qrYcp4VFAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AAEDCMgsAQAAAAAAAQQiUSBvxQb4BSqfWoqpuZDV6ZT0ld3tbUe6xEyqza3Y2Jkc0AA=", "supplementary": { "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "4a8f1357fce86135028391e1f26f0fbff24a6ed2ab371e591a53ddfc5ae740d4", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 500000, - "witness_utxo": "20a1070000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff0120a10700000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "20a10700000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": true } @@ -1194,7 +1433,7 @@ "output_index": 0, "amount": 100000, "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", - "script": "5120326df50fe0a07b7acb72070beb3b632eb9ad15ba695cc1e5aa6aa007b6146fd8" + "script": "5120723b89b5c63879d5b9d07a30451bbdd48e37ac038e66f726f37ca40ab264ab72" }, { "output_index": 1, @@ -1205,7 +1444,7 @@ "output_index": 2, "amount": 100000, "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", - "script": "51203fcbaea49087f8e03d9defd3abcbd6de8c032b583f85a65d057881c4c443cdc0" + "script": "5120af1476ee03f5e98890ec54960361ac491c56e30a93eb2980fc322b9837a758ba" }, { "output_index": 3, @@ -1216,7 +1455,7 @@ "output_index": 4, "amount": 100000, "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", - "script": "5120971442c89f04786e082728ae116eeab802f3fa9e95fdb0d3753a6840202006de" + "script": "51209e6735d1b1196b0b1aefe0e4d10ecad29374964b9f599205d17caab61ca78545" }, { "output_index": 5, @@ -1227,19 +1466,126 @@ } }, { - "description": "in progress: two P2TR inputs, neither is signed", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEBAQYBAAABDiAT8Qa2S1e1sTdvn2xHGQ9AzAazvty4qrqXhQqz1/Z9AgEPBAAAAAABASughgEAAAAAACJRIMgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/AQMEAQAAAAEQBP7///8BFyDIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvyIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQ4gK5A3/0HdF05VIvD0BFw/QENiMq8mANTaXJ6hPMPKtLUBDwQAAAAAAQErECcAAAAAAAAiUSBDoNQOneCIJ5QWF1K65CupCVJ4QgnwY0MPCvJWNUqFuwEDBAEAAAABEAT+////ARcgQ6DUDp3giCeUFhdSuuQrqQlSeEIJ8GNDDwryVjVKhbsiHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCEC5Xp63LAY2PsxVOgMFLl6UJlLQjVoQeqfwTFwYUQA5jciHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaED3+jgd4gs7RZxuQmxiE9QXUwjySCpE4zKEIyYk1Nr9VzKZvzrxarMCxWJjY6N9RIcH9+eh6+oGR7zNSGIDuyumAAEDCLj5AgAAAAAAAQQiUSDLH766UNBuv/tpC9qdX/Oc4vrbT87clmMu/xukHMDAewEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "description": "can finalize: P2WPKH with decoy BIP32_DERIVATION before the matching key", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIG9hTKsWyAwmppZy4viq5wvAiLUgLqne/2rOeM2n+2JyAiAQVYeP/VlnUGDrYKAL+jNMnLJB+6EoTBEkkNEA2ex8LgEBAwQBAAAAIgYCpRa89dF+FVVFALBtY95Srqd8dFqTvkLq2/Sunj4dEqAIAAAAgP8AAAAiBgLIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvwgAAACAAAAAAAEOIPdO3R91tLs+XXScFb/bZjSPaAWptNRf7uGi4gH1A7txAQ8EAAAAAAEQBP7///8iHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCED7KT/Ebco4uD2DOYiKUOm/1W52V9ie/mpnQhLyHLVClsiHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaECKE7OYVUX3K9bolxSuuQmz41SoQqm7i1bNDt7SHfihmVmLMSKKSeC9fpXOEFP3xbKKy1Q6aHB2AOPOiYIu4yAhAAEDCBhzAQAAAAAAAQQiUSBkb0lMoLubzq0UuNt+TGlEVh+vIy58zMNr3VhpX3SRWQEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", "supplementary": { "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "13f106b64b57b5b1376f9f6c47190f40cc06b3bedcb8aaba97850ab3d7f67d02", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", "prevout_index": 0, - "prevout_scriptpubkey": "5120c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", "amount": 100000, - "witness_utxo": "a086010000000000225120c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", + "input_index": 0 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 95000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "5120646f494ca0bb9bcead14b8db7e4c6944561faf232e7cccc36bdd58695f749159" + } + ] + } + }, + { + "description": "can finalize: P2PKH with decoy BIP32_DERIVATION before the matching key", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAFUCAAAAAfTCEtWu0ef2/2M/LOCcZHxXvt2TAxTZjed1A9WOlAszAAAAAAD/////AaCGAQAAAAAAGXapFB4q14ctMpQTpW3wlovjOCIngxY7iKwAAAAAIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQCKz65hp7Ug/wQxkrbclMyEJpEkQIMSdkyI3dldqY0pVQIgIIfDsRj5aZKk2iQTz/6RcPJQ4n48FMtd7z5jjDDX6oABAQMEAQAAACIGAqUWvPXRfhVVRQCwbWPeUq6nfHRak75C6tv0rp4+HRKgCAAAAID/AAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiBSJ0jrF3ZNKMpJSBXsjUnn0w1SvHNCLHyG63TjlwVylAEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEg4UDSh7RbRs1OqvpDdwYVcLq+g9G4vJUKdKn+oJIz16YBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "94720597e374eb867c2c4273bc520dd3e7498dec154849ca284d7617eb482752", + "prevout_index": 0, + "amount": 100000, + "non_witness_utxo": "0200000001f4c212d5aed1e7f6ff633f2ce09c647c57bedd930314d98de77503d58e940b330000000000ffffffff01a0860100000000001976a9141e2ad7872d329413a56df0968be338222783163b88ac00000000", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", + "input_index": 0 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 95000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "5120e140d287b45b46cd4eaafa4377061570babe83d1b8bc950a74a9fea09233d7a6" + } + ] + } + }, + { + "description": "can finalize: P2SH-P2WPKH with decoy BIP32_DERIVATION before the matching key", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAFMCAAAAAa0yiGinxhSdpSUXfZUerAPh/iyT6DzlNGVjrZNjwndMAAAAAAD/////AaCGAQAAAAAAF6kU1JxxjCdjjcMGkgbmNVqpXZ1duKWHAAAAAAEBIKCGAQAAAAAAF6kU1JxxjCdjjcMGkgbmNVqpXZ1duKWHIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIFBuSluOMYyBrd9OR3Ekc0Wn5JubCy7y8tHyslkj1IWiAiAlJe9tm34eaBzNTTivDPyzNKKgc3+gfalxSAq06ezHBgEBAwQBAAAAAQQWABQeKteHLTKUE6Vt8JaL4zgiJ4MWOyIGAqUWvPXRfhVVRQCwbWPeUq6nfHRak75C6tv0rp4+HRKgCAAAAID/AAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiBfVGsxp4xGbEWT3iMOmTvJk1ue7NTSp39zulVcUkIDhQEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEgKV0FbmDiskmZ/sNpyGa9XoHA09MFqZ7rUSB0qfd8cFMBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "850342525c55ba737fa7d2d4ec9e5b93c93b990e23de93456c468ca7316b545f", + "prevout_index": 0, + "amount": 100000, + "non_witness_utxo": "0200000001ad328868a7c6149da525177d951eac03e1fe2c93e83ce5346563ad9363c2774c0000000000ffffffff01a08601000000000017a914d49c718c27638dc3069206e6355aa95d9d5db8a58700000000", + "witness_utxo": "a08601000000000017a914d49c718c27638dc3069206e6355aa95d9d5db8a587", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", + "input_index": 0 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 95000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "5120295d056e60e2b24999fec369c866bd5e81c0d3d305a99eeb512074a9f77c7053" + } + ] + } + }, + { + "description": "in progress: two P2TR inputs, neither is signed", + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAAfsEAgAAAAABAStADQMAAAAAACJRIMgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/AQMEAQAAAAEOIOJh+vHI4yk0OVQtKlp35brqbxAwWLwV/LJyqNqQxuPNAQ8EAAAAAAEQBP7///8BFyDIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvyIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQErECcAAAAAAAAiUSBDoNQOneCIJ5QWF1K65CupCVJ4QgnwY0MPCvJWNUqFuwEDBAEAAAABDiCIKHQ5bbf1J6fjPTRao7j7VR+MxUUp+Du85P11q+G6yQEPBAAAAAABEAT+////ARcgQ6DUDp3giCeUFhdSuuQrqQlSeEIJ8GNDDwryVjVKhbsiHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCEC5Xp63LAY2PsxVOgMFLl6UJlLQjVoQeqfwTFwYUQA5jciHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaED3+jgd4gs7RZxuQmxiE9QXUwjySCpE4zKEIyYk1Nr9VzKZvzrxarMCxWJjY6N9RIcH9+eh6+oGR7zNSGIDuyumAAEDCLj5AgAAAAAAAQQiUSDuvwDmhUt84x4LCQCf5zbeTa0t0Hk6nrKLDm+jAO2+FAEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "cde3c690daa872b2fc15bc5830106feabae5775a2a2d54393429e3c8f1fa61e2", + "prevout_index": 0, + "amount": 200000, + "non_witness_utxo": "020000000113f106b64b57b5b1376f9f6c47190f40cc06b3bedcb8aaba97850ab3d7f67d020000000000ffffffff01400d030000000000225120c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf00000000", + "witness_utxo": "400d030000000000225120c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", "sequence": 4294967294, "signed": false }, @@ -1247,10 +1593,10 @@ "input_index": 1, "private_key": "586b0810bbc3c7266971aeb7f8778b41707e092a1aeaf0d953b211f956e35541", "public_key": "0243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb", - "prevout_txid": "2b9037ff41dd174e5522f0f4045c3f40436232af2600d4da5c9ea13cc3cab4b5", + "prevout_txid": "c9bae1ab75fde4bc3bf82945c58c1f55fbb8a35a343de3a727f5b76d39742888", "prevout_index": 0, - "prevout_scriptpubkey": "512043a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb", "amount": 10000, + "non_witness_utxo": "02000000012b9037ff41dd174e5522f0f4045c3f40436232af2600d4da5c9ea13cc3cab4b50000000000ffffffff01102700000000000022512043a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb00000000", "witness_utxo": "102700000000000022512043a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb", "sequence": 4294967294, "signed": false @@ -1275,24 +1621,24 @@ "output_index": 0, "amount": 195000, "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", - "script": "5120cb1fbeba50d06ebffb690bda9d5ff39ce2fadb4fcedc96632eff1ba41cc0c07b" + "script": "5120eebf00e6854b7ce31e0b09009fe736de4dad2dd0793a9eb28b0e6fa300edbe14" } ] } }, { "description": "in progress: one P2TR input / one sp output with no ECDH shares when PSBT_OUT_SCRIPT field is not set", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAT8Qa2S1e1sTdvn2xHGQ9AzAazvty4qrqXhQqz1/Z9AgEPBAAAAAABASughgEAAAAAACJRIMgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/ARAE/v///wEXIMgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/AAEDCBhzAQAAAAAAAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABASughgEAAAAAACJRIMgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/AQ4go8Kr7b6RMdXjhleFYNR+NopA2asmCdsgpHnDBLBkU2wBDwQAAAAAARAE/v///wEXIMgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/AAEDCBhzAQAAAAAAAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", "supplementary": { "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "13f106b64b57b5b1376f9f6c47190f40cc06b3bedcb8aaba97850ab3d7f67d02", + "prevout_txid": "6c5364b004c379a420db0926abd9408a367ed460855786e3d53191beedabc2a3", "prevout_index": 0, - "prevout_scriptpubkey": "5120c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", "amount": 100000, + "non_witness_utxo": "020000000113f106b64b57b5b1376f9f6c47190f40cc06b3bedcb8aaba97850ab3d7f67d020000000000ffffffff01a086010000000000225120c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf00000000", "witness_utxo": "a086010000000000225120c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", "sequence": 4294967294, "signed": false @@ -1310,18 +1656,18 @@ }, { "description": "in progress: two inputs / one sp output, input 1 missing ECDH share when PSBT_OUT_SCRIPT field is not set", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQ4gvp1lyDkV+wkkirvfyoyj7ubONQxVT2Xo1Sbl31J6tSIBDwQAAAAAAQEf8EkCAAAAAAAWABRGM9WcrRNDR5ly4MmWkh0KXa22XSIGAkOg1A6d4IgnlBYXUrrkK6kJUnhCCfBjQw8K8lY1SoW7CAAAAIABAAAAARAE/v///wABAwhADQMAAAAAAAEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7AQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g907dH3W0uz5ddJwVv9tmNI9oBam01F/u4aLiAfUDu3EBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQEf8EkCAAAAAAAWABQ3IfpzwjBcsviOhIkta9a5dyYeaiIGAkOg1A6d4IgnlBYXUrrkK6kJUnhCCfBjQw8K8lY1SoW7CAAAAIABAAAAAQ4gSQv/chrf7ISJdgPfb7uyrbjEZTqaQrLW0VICyiQN4LEBDwQAAAAAARAE/v///wABAwhADQMAAAAAAAEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", "supplementary": { "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 100000, - "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": false }, @@ -1329,11 +1675,11 @@ "input_index": 1, "private_key": "586b0810bbc3c7266971aeb7f8778b41707e092a1aeaf0d953b211f956e35541", "public_key": "0243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb", - "prevout_txid": "be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab522", + "prevout_txid": "b1e00d24ca0252d1d6b2429a3a65c4b8adb2bb6fdf03768984ecdf1a72ff0b49", "prevout_index": 0, - "prevout_scriptpubkey": "00144633d59cad1343479972e0c996921d0a5dadb65d", "amount": 150000, - "witness_utxo": "f0490200000000001600144633d59cad1343479972e0c996921d0a5dadb65d", + "non_witness_utxo": "0200000001be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab5220000000000ffffffff01f0490200000000001600143721fa73c2305cb2f88e84892d6bd6b977261e6a00000000", + "witness_utxo": "f0490200000000001600143721fa73c2305cb2f88e84892d6bd6b977261e6a", "sequence": 4294967294, "signed": false } @@ -1357,18 +1703,18 @@ }, { "description": "in progress: one input / two sp outputs, input 0 missing ECDH share for output 0 when PSBT_OUT_SCRIPT field is not set", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQECAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR9ADQMAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsIQMJH9SAORd/RNe3npYWiEnGLrP4eADEZ2fFCo84+Y79FSIeA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsQL4acjrvVeiYG5lZmpvBKzj4froBWMxwZokPImnK3kY7dzQal9KScZZNAcAkHMMi/VOQwpuZFg+CbzKTZYmMvwIAAQMIkF8BAAAAAAABCUIDZR0sBz/LAqTYLdpT8dUB13oDUGZnmFRkc7ISa2zRp94D8nDgpWMhg7arAQdOh35oANsA9cfF0vr7to+cKNSFRSQAAQMIkF8BAAAAAAABBCJRIENYHfbIefmqrcU2YN6xVrnxIr0a7KczIDvOh/zx84buAQlCA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsAuDEwYe3IV+ZfISFp1tFkbbChHe5WhEjuZaSLTFUhgv4AA==", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQIBBgEAAfsEAgAAAAABAR9ADQMAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7AQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g/S309Ytav5uR/xoeQ+LjUj9QxqoZ1cIjYBQexIyagCEBDwQAAAAAARAE/v///yIdA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsIQMJH9SAORd/RNe3npYWiEnGLrP4eADEZ2fFCo84+Y79FSIeA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsQL4acjrvVeiYG5lZmpvBKzj4froBWMxwZokPImnK3kY7dzQal9KScZZNAcAkHMMi/VOQwpuZFg+CbzKTZYmMvwIAAQMIkF8BAAAAAAABCUIDZR0sBz/LAqTYLdpT8dUB13oDUGZnmFRkc7ISa2zRp94D8nDgpWMhg7arAQdOh35oANsA9cfF0vr7to+cKNSFRSQAAQMIkF8BAAAAAAABBCJRIGMlBrk4zY0hMZ/eTlk5KyP5juuXb0OS1jPxg+Iut/qxAQlCA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsAuDEwYe3IV+ZfISFp1tFkbbChHe5WhEjuZaSLTFUhgv4AA==", "supplementary": { "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "21809a8cc41e146023c2d519aac6503f52e3e2431e1aff919bbf5a8bf5f42dfd", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 200000, - "witness_utxo": "400d030000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01400d0300000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "400d0300000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": false } @@ -1391,25 +1737,25 @@ "output_index": 1, "amount": 90000, "sp_v0_info": "0352d78c41390032ad91816a697fc740d8eb909cf04d70885264b051f2385e25ec02e0c4c187b7215f997c8485a75b4591b6c28477b95a1123b996922d3154860bf8", - "script": "512043581df6c879f9aaadc53660deb156b9f122bd1aeca733203bce87fcf1f386ee" + "script": "5120632506b938cd8d21319fde4e59392b23f98eeb976f4392d633f183e22eb7fab1" } ] } }, { "description": "in progress: large PSBT with nine mixed inputs / six outputs - some inputs signed", - "psbt": "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", + "psbt": "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", "supplementary": { "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 100000, - "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": true }, @@ -1417,11 +1763,11 @@ "input_index": 1, "private_key": "295c2eedddd8331d20b5d4cf9e69bb523ed85cb0bf35ab12e04fea66fe6d4a4a", "public_key": "02f5b59fa5e492221ebf55ba78ad442605beae95166ba1eba3250d0bbaac7e2edc", - "prevout_txid": "be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab522", + "prevout_txid": "26d393ed2bc842fef499962be79f9d6c4c19b22d83a16334d125cb09a785d4bc", "prevout_index": 0, - "prevout_scriptpubkey": "0014139350117c577941a985802bb9edefc113932bc7", "amount": 100000, - "witness_utxo": "a086010000000000160014139350117c577941a985802bb9edefc113932bc7", + "non_witness_utxo": "0200000001be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab5220000000000ffffffff01a086010000000000160014a692511c079575bf3756dabc56ad71d4284a690e00000000", + "witness_utxo": "a086010000000000160014a692511c079575bf3756dabc56ad71d4284a690e", "sequence": 4294967294, "signed": true }, @@ -1429,11 +1775,11 @@ "input_index": 2, "private_key": "e6db4a04e2fc29745ea1a9dcf1fed7449c8228ffe0503d8171e64126d5399800", "public_key": "02655ef5daf05d28d1ca73ba8e211300db2b70416737183e0fa8c355ee4c1cbac6", - "prevout_txid": "d041c742ca364472d1a18c7a8eae07e6e904a9ea1b85f198525fb83ef276e343", + "prevout_txid": "9c232013b443ff8ad80b3b0d02959832565c0a1f09f62a53ca75024467779da2", "prevout_index": 0, - "prevout_scriptpubkey": "00142307fc774ca174b42ada814bc2e6e444ff3d830c", "amount": 100000, - "witness_utxo": "a0860100000000001600142307fc774ca174b42ada814bc2e6e444ff3d830c", + "non_witness_utxo": "0200000001d041c742ca364472d1a18c7a8eae07e6e904a9ea1b85f198525fb83ef276e3430000000000ffffffff01a086010000000000160014d4dc903f7116602ee358ec8edf3284e6ff0294e300000000", + "witness_utxo": "a086010000000000160014d4dc903f7116602ee358ec8edf3284e6ff0294e3", "sequence": 4294967294, "signed": true }, @@ -1441,11 +1787,11 @@ "input_index": 3, "private_key": "f5208ed67b0019ba4e306aff029d247931e0dfacd1fe6e69091bc6bc70a42619", "public_key": "0303a0f4528d264e8e95256634b94414e2748f72962704fe57e8b0a2cc44d2383d", - "prevout_txid": "52262cd5d402bf32616d07fc03286a8f7fe78af7ac411dfff41655ddc1011e6f", + "prevout_txid": "bb0453858ffa2cdf93741335de9a8003062ea65909c49781a88de5bee7ce7f1e", "prevout_index": 0, - "prevout_scriptpubkey": "00147018bce965288d8bf0ccf3e0ec48b6f1dbbfe548", "amount": 100000, - "witness_utxo": "a0860100000000001600147018bce965288d8bf0ccf3e0ec48b6f1dbbfe548", + "non_witness_utxo": "020000000152262cd5d402bf32616d07fc03286a8f7fe78af7ac411dfff41655ddc1011e6f0000000000ffffffff01a086010000000000160014fb6d08dfb14f001dc98cf17c4d7322b07bf0754f00000000", + "witness_utxo": "a086010000000000160014fb6d08dfb14f001dc98cf17c4d7322b07bf0754f", "sequence": 4294967294, "signed": true }, @@ -1453,11 +1799,11 @@ "input_index": 4, "private_key": "0c19c34dc1005feb5ca60104d20472f7f2f97bd4d521264618196bf71155b20a", "public_key": "03a8911beb5a48fe119cb015088cf0c3a118cf026772448972d1b70c764ac59412", - "prevout_txid": "e298eaf24fe1ca68b41e4b6b83cc3d91ced99c6e78d5b992cfb15771b5457064", + "prevout_txid": "071974f8c90e078b5a86fa456d80f458cc35d46755ab71df1da3fbfedd5a11d3", "prevout_index": 0, - "prevout_scriptpubkey": "00149332bb020cb03d49eb4d04712c1cc08e2b06d8d8", "amount": 100000, - "witness_utxo": "a0860100000000001600149332bb020cb03d49eb4d04712c1cc08e2b06d8d8", + "non_witness_utxo": "0200000001e298eaf24fe1ca68b41e4b6b83cc3d91ced99c6e78d5b992cfb15771b54570640000000000ffffffff01a0860100000000001600140b1845f4c80dabe2c5dc8a567fbe410a78e486c800000000", + "witness_utxo": "a0860100000000001600140b1845f4c80dabe2c5dc8a567fbe410a78e486c8", "sequence": 4294967294, "signed": true }, @@ -1465,10 +1811,10 @@ "input_index": 5, "private_key": "5aaa151cbdeb566911784d166b01ce57f35993b98f96846efec1cfefcc0d8f56", "public_key": "02d155713c520ce2d8276164215d659ab623c5f7306f8652c1756e26833e886e01", - "prevout_txid": "1730833ecb5be01362d7149522604484216e1c7b18cf313d1cf1543ef85df3b6", + "prevout_txid": "0dd7b58523da5296e04203dbbe52fdeadea821d26cc7b8c285fddf63586b9390", "prevout_index": 0, - "prevout_scriptpubkey": "5120d155713c520ce2d8276164215d659ab623c5f7306f8652c1756e26833e886e01", "amount": 100000, + "non_witness_utxo": "02000000011730833ecb5be01362d7149522604484216e1c7b18cf313d1cf1543ef85df3b60000000000ffffffff01a086010000000000225120d155713c520ce2d8276164215d659ab623c5f7306f8652c1756e26833e886e0100000000", "witness_utxo": "a086010000000000225120d155713c520ce2d8276164215d659ab623c5f7306f8652c1756e26833e886e01", "sequence": 4294967294, "signed": false @@ -1477,10 +1823,10 @@ "input_index": 6, "private_key": "d92c1506167b3a00a21f4d90d7b5ccb4713c00194aa66f9c7deb162c467f9643", "public_key": "02d00e15fb626a7efee85c5bce676d636b6048914e9a34ace0b4cbc44bc948077a", - "prevout_txid": "e93532e0eda39c4d39da2d3f91d14529bc435fc2efb9196e25fbaac4b4e89b81", + "prevout_txid": "23e1a4f0d932721f487d47979a3bb75d5760ce033696f217ce023a03fa1179f8", "prevout_index": 0, - "prevout_scriptpubkey": "5120d00e15fb626a7efee85c5bce676d636b6048914e9a34ace0b4cbc44bc948077a", "amount": 100000, + "non_witness_utxo": "0200000001e93532e0eda39c4d39da2d3f91d14529bc435fc2efb9196e25fbaac4b4e89b810000000000ffffffff01a086010000000000225120d00e15fb626a7efee85c5bce676d636b6048914e9a34ace0b4cbc44bc948077a00000000", "witness_utxo": "a086010000000000225120d00e15fb626a7efee85c5bce676d636b6048914e9a34ace0b4cbc44bc948077a", "sequence": 4294967294, "signed": false @@ -1489,10 +1835,10 @@ "input_index": 7, "private_key": "d8bc8d0e1233a97133f3573d6dceb6736e8b6d2e4839925145022ea3efdad8f8", "public_key": "020500f167cf669e7dac39e6aecda1f28c66b78ec7097eefef25d54f7be785e7f6", - "prevout_txid": "b6368bbc330cddfe9e2550edb7dfc15ae74cac9bcc7d967fe81e6f27f8597b1d", + "prevout_txid": "1d7b59f8276f1ee87f967dcc9bac4ce75ac1dfb7ed50259efedd0c33bc8b36b6", "prevout_index": 0, - "prevout_scriptpubkey": "a9140df101357f73e6658500cf56f3a132d7bb8afbdd87", "amount": 100000, + "non_witness_utxo": "0200000001fea14f3d169b2b0400db14996221b31182bb9e86ca169e91b9c7bd93f9c73e880000000000ffffffff01a08601000000000017a9140df101357f73e6658500cf56f3a132d7bb8afbdd8700000000", "witness_utxo": "a08601000000000017a9140df101357f73e6658500cf56f3a132d7bb8afbdd87", "sequence": 4294967294, "signed": true @@ -1501,11 +1847,10 @@ "input_index": 8, "private_key": "81e30f5b5d049bdf5c5bea9c3329bf57cc8b473240182a9f2a6eee07435bd54a", "public_key": "03199d2f155f32ebb167aeb0ccca6e5afb7340898df1b7ab9936500f6d4391902a", - "prevout_txid": "03bceba5379d73daeafe677972b03dcf7ef30b7f10eaa83ad04bc0bf00d8b2f7", + "prevout_txid": "f7b2d800bfc04bd03aa8ea107f0bf37ecf3db0727967feeada739d37a5ebbc03", "prevout_index": 0, - "prevout_scriptpubkey": "76a914569bf311e68a383767b43f83042dfabe60093ede88ac", "amount": 100000, - "witness_utxo": "02000000012a34ac1b0db77a8198c1e29002cc47bbfcd6ed830960304d2c9a3ab548486b5d0000000000ffffffff01a0860100000000001976a914569bf311e68a383767b43f83042dfabe60093ede88ac00000000", + "non_witness_utxo": "02000000012a34ac1b0db77a8198c1e29002cc47bbfcd6ed830960304d2c9a3ab548486b5d0000000000ffffffff01a0860100000000001976a914569bf311e68a383767b43f83042dfabe60093ede88ac00000000", "sequence": 4294967294, "signed": true } @@ -1713,5 +2058,143 @@ ] } } + ], + "workflows": [ + { + "step": "created", + "description": "Creator produces an empty PSBT v2", + "supplementary": {}, + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAAEFAQABBgEDAfsEAgAAAAA=" + } + }, + { + "step": "constructed", + "description": "Constructor adds inputs and SP outputs (no ECDH yet)", + "supplementary": { + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEDAfsEAgAAAAABDiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEPBAAAAAAAAQMIAAAAAAAAAAAA", + "inputs": [ + { + "input_index": 0, + "prevout_txid": "6244422c1833da958781dacfc349368ab886650033514ba7c773691a5da057ab", + "prevout_index": 0, + "sequence": 4294967294 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 90000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039" + } + ] + }, + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEDAfsEAgAAAAABAR+ghgEAAAAAABYAFMFaMn8CdS4U7n3BlH5Fe7aOmXikAQ4gq1egXRppc8enS1EzAGWGuIo2ScPP2oGHldozGCxCRGIBDwQAAAAAARAE/v///wABAwiQXwEAAAAAAAEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "unique_id": "541c997611395ccf867da76839dd0da75f2a5ead4ce22eef2c0d987544368266" + } + }, + { + "step": "updated", + "description": "Updater adds UTXO/pubkey data plus ECDH shares and DLEQ proofs", + "supplementary": { + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEDAfsEAgAAAAABAR+ghgEAAAAAABYAFMFaMn8CdS4U7n3BlH5Fe7aOmXikAQ4gq1egXRppc8enS1EzAGWGuIo2ScPP2oGHldozGCxCRGIBDwQAAAAAARAE/v///wABAwiQXwEAAAAAAAEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "inputs": [ + { + "input_index": 0, + "public_key": "0356c51fd2d03d6907ec025384e68ee2329f1e48dabb18144a959fc6a67425e245", + "prevout_txid": "6244422c1833da958781dacfc349368ab886650033514ba7c773691a5da057ab", + "prevout_index": 0, + "amount": 100000, + "witness_utxo": "a086010000000000160014c15a327f02752e14ee7dc1947e457bb68e9978a4", + "sequence": 4294967294 + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "034e54f4dff2bb9cee30e30e93bdbff7508b1f11085f2b794731b680f4d7c71642", + "dleq_proof": "f3eb7de65597bcf0b182396aae454ba61f5633e7ceae3c9a1ad2b9f1a5fe81826ed402b27a2d28c933f50111c715c0afca99af088aad9690f31ee970a2a0842a" + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 90000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039" + } + ] + }, + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEDAfsEAgAAAAABAR+ghgEAAAAAABYAFMFaMn8CdS4U7n3BlH5Fe7aOmXikIgYDVsUf0tA9aQfsAlOE5o7iMp8eSNq7GBRKlZ/GpnQl4kUEAAAAAAEOIKtXoF0aaXPHp0tRMwBlhriKNknDz9qBh5XaMxgsQkRiAQ8EAAAAAAEQBP7///8iHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCEDTlT03/K7nO4w4w6Tvb/3UIsfEQhfK3lHMbaA9NfHFkIiHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaEAtPzykoyXOiOFG75KyWIqahljrU3l0nB7OaDK5ObNoabNWz+GGhg3J8Om3M9Fkvdp4EriHDkBvYoM6fROVLjMRAAEDCJBfAQAAAAAAAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "unique_id": "541c997611395ccf867da76839dd0da75f2a5ead4ce22eef2c0d987544368266" + } + }, + { + "step": "sp_finalized", + "description": "SP Output Finalizer computes the silent payment output scripts", + "supplementary": { + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEDAfsEAgAAAAABAR+ghgEAAAAAABYAFMFaMn8CdS4U7n3BlH5Fe7aOmXikIgYDVsUf0tA9aQfsAlOE5o7iMp8eSNq7GBRKlZ/GpnQl4kUEAAAAAAEOIKtXoF0aaXPHp0tRMwBlhriKNknDz9qBh5XaMxgsQkRiAQ8EAAAAAAEQBP7///8iHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCEDTlT03/K7nO4w4w6Tvb/3UIsfEQhfK3lHMbaA9NfHFkIiHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaEAtPzykoyXOiOFG75KyWIqahljrU3l0nB7OaDK5ObNoabNWz+GGhg3J8Om3M9Fkvdp4EriHDkBvYoM6fROVLjMRAAEDCJBfAQAAAAAAAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "outputs": [ + { + "output_index": 0, + "amount": 90000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "5120aa55e2357f08a95293e2e28f9bfedb2f7f1af12c7419a2bb15b79b923c9f5d04" + } + ] + }, + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFMFaMn8CdS4U7n3BlH5Fe7aOmXikIgYDVsUf0tA9aQfsAlOE5o7iMp8eSNq7GBRKlZ/GpnQl4kUEAAAAAAEOIKtXoF0aaXPHp0tRMwBlhriKNknDz9qBh5XaMxgsQkRiAQ8EAAAAAAEQBP7///8iHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCEDTlT03/K7nO4w4w6Tvb/3UIsfEQhfK3lHMbaA9NfHFkIiHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaEAtPzykoyXOiOFG75KyWIqahljrU3l0nB7OaDK5ObNoabNWz+GGhg3J8Om3M9Fkvdp4EriHDkBvYoM6fROVLjMRAAEDCJBfAQAAAAAAAQQiUSCqVeI1fwipUpPi4o+b/tsvfxrxLHQZorsVt5uSPJ9dBAEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "unique_id": "541c997611395ccf867da76839dd0da75f2a5ead4ce22eef2c0d987544368266" + } + }, + { + "step": "signed", + "description": "Signer signs the eligible inputs", + "supplementary": { + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFMFaMn8CdS4U7n3BlH5Fe7aOmXikIgYDVsUf0tA9aQfsAlOE5o7iMp8eSNq7GBRKlZ/GpnQl4kUEAAAAAAEOIKtXoF0aaXPHp0tRMwBlhriKNknDz9qBh5XaMxgsQkRiAQ8EAAAAAAEQBP7///8iHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCEDTlT03/K7nO4w4w6Tvb/3UIsfEQhfK3lHMbaA9NfHFkIiHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaEAtPzykoyXOiOFG75KyWIqahljrU3l0nB7OaDK5ObNoabNWz+GGhg3J8Om3M9Fkvdp4EriHDkBvYoM6fROVLjMRAAEDCJBfAQAAAAAAAQQiUSCqVeI1fwipUpPi4o+b/tsvfxrxLHQZorsVt5uSPJ9dBAEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "inputs": [ + { + "input_index": 0, + "private_key": "e8a1d3762682c9f559441aa519b61c269d59210cdb9a59ac37f5d83a6f725015", + "signed": true + } + ] + }, + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFMFaMn8CdS4U7n3BlH5Fe7aOmXikIgIDVsUf0tA9aQfsAlOE5o7iMp8eSNq7GBRKlZ/GpnQl4kVHMEQCIGAUx1TZpeshKb1hh+8lRn9ZpgkuEze7li5arLlNMqnfAiBZFLtCV9tnbvdefmsXbuZRFJTifFPN8ibm9owXrCI7yAEiBgNWxR/S0D1pB+wCU4TmjuIynx5I2rsYFEqVn8amdCXiRQQAAAAAAQ4gq1egXRppc8enS1EzAGWGuIo2ScPP2oGHldozGCxCRGIBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQNOVPTf8ruc7jDjDpO9v/dQix8RCF8reUcxtoD018cWQiIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQC0/PKSjJc6I4UbvkrJYipqGWOtTeXScHs5oMrk5s2hps1bP4YaGDcnw6bcz0WS92ngSuIcOQG9igzp9E5UuMxEAAQMIkF8BAAAAAAABBCJRIKpV4jV/CKlSk+Lij5v+2y9/GvEsdBmiuxW3m5I8n10EAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "unique_id": "541c997611395ccf867da76839dd0da75f2a5ead4ce22eef2c0d987544368266" + } + }, + { + "step": "finalized", + "description": "Input Finalizer builds the final scriptwitness", + "supplementary": { + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFMFaMn8CdS4U7n3BlH5Fe7aOmXikIgIDVsUf0tA9aQfsAlOE5o7iMp8eSNq7GBRKlZ/GpnQl4kVHMEQCIGAUx1TZpeshKb1hh+8lRn9ZpgkuEze7li5arLlNMqnfAiBZFLtCV9tnbvdefmsXbuZRFJTifFPN8ibm9owXrCI7yAEiBgNWxR/S0D1pB+wCU4TmjuIynx5I2rsYFEqVn8amdCXiRQQAAAAAAQ4gq1egXRppc8enS1EzAGWGuIo2ScPP2oGHldozGCxCRGIBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQNOVPTf8ruc7jDjDpO9v/dQix8RCF8reUcxtoD018cWQiIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQC0/PKSjJc6I4UbvkrJYipqGWOtTeXScHs5oMrk5s2hps1bP4YaGDcnw6bcz0WS92ngSuIcOQG9igzp9E5UuMxEAAQMIkF8BAAAAAAABBCJRIKpV4jV/CKlSk+Lij5v+2y9/GvEsdBmiuxW3m5I8n10EAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "inputs": [ + { + "input_index": 0, + "signed": true + } + ] + }, + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFMFaMn8CdS4U7n3BlH5Fe7aOmXikAQhrAkcwRAIgYBTHVNml6yEpvWGH7yVGf1mmCS4TN7uWLlqsuU0yqd8CIFkUu0JX22du915+axdu5lEUlOJ8U83yJub2jBesIjvIASEDVsUf0tA9aQfsAlOE5o7iMp8eSNq7GBRKlZ/GpnQl4kUBDiCrV6BdGmlzx6dLUTMAZYa4ijZJw8/agYeV2jMYLEJEYgEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA05U9N/yu5zuMOMOk72/91CLHxEIXyt5RzG2gPTXxxZCIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhALT88pKMlzojhRu+SsliKmoZY61N5dJwezmgyuTmzaGmzVs/hhoYNyfDptzPRZL3aeBK4hw5Ab2KDOn0TlS4zEQABAwiQXwEAAAAAAAEEIlEgqlXiNX8IqVKT4uKPm/7bL38a8Sx0GaK7FbebkjyfXQQBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "unique_id": "541c997611395ccf867da76839dd0da75f2a5ead4ce22eef2c0d987544368266" + } + }, + { + "step": "transaction", + "description": "Extractor produces the raw transaction", + "supplementary": { + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFMFaMn8CdS4U7n3BlH5Fe7aOmXikAQhrAkcwRAIgYBTHVNml6yEpvWGH7yVGf1mmCS4TN7uWLlqsuU0yqd8CIFkUu0JX22du915+axdu5lEUlOJ8U83yJub2jBesIjvIASEDVsUf0tA9aQfsAlOE5o7iMp8eSNq7GBRKlZ/GpnQl4kUBDiCrV6BdGmlzx6dLUTMAZYa4ijZJw8/agYeV2jMYLEJEYgEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA05U9N/yu5zuMOMOk72/91CLHxEIXyt5RzG2gPTXxxZCIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhALT88pKMlzojhRu+SsliKmoZY61N5dJwezmgyuTmzaGmzVs/hhoYNyfDptzPRZL3aeBK4hw5Ab2KDOn0TlS4zEQABAwiQXwEAAAAAAAEEIlEgqlXiNX8IqVKT4uKPm/7bL38a8Sx0GaK7FbebkjyfXQQBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA" + }, + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFMFaMn8CdS4U7n3BlH5Fe7aOmXikAQhrAkcwRAIgYBTHVNml6yEpvWGH7yVGf1mmCS4TN7uWLlqsuU0yqd8CIFkUu0JX22du915+axdu5lEUlOJ8U83yJub2jBesIjvIASEDVsUf0tA9aQfsAlOE5o7iMp8eSNq7GBRKlZ/GpnQl4kUBDiCrV6BdGmlzx6dLUTMAZYa4ijZJw8/agYeV2jMYLEJEYgEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA05U9N/yu5zuMOMOk72/91CLHxEIXyt5RzG2gPTXxxZCIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhALT88pKMlzojhRu+SsliKmoZY61N5dJwezmgyuTmzaGmzVs/hhoYNyfDptzPRZL3aeBK4hw5Ab2KDOn0TlS4zEQABAwiQXwEAAAAAAAEEIlEgqlXiNX8IqVKT4uKPm/7bL38a8Sx0GaK7FbebkjyfXQQBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "unique_id": "541c997611395ccf867da76839dd0da75f2a5ead4ce22eef2c0d987544368266", + "tx": "02000000000101ab57a05d1a6973c7a74b5133006586b88a3649c3cfda818795da33182c4244620000000000feffffff01905f010000000000225120aa55e2357f08a95293e2e28f9bfedb2f7f1af12c7419a2bb15b79b923c9f5d040247304402206014c754d9a5eb2129bd6187ef25467f59a6092e1337bb962e5aacb94d32a9df02205914bb4257db676ef75e7e6b176ee6511494e27c53cdf226e6f68c17ac223bc801210356c51fd2d03d6907ec025384e68ee2329f1e48dabb18144a959fc6a67425e24500000000" + } + } ] } \ No newline at end of file From 80bfcccd7a6f76c24573d8e1def071733d537b76 Mon Sep 17 00:00:00 2001 From: Jasper van Gelder Date: Fri, 5 Jun 2026 17:01:34 +0200 Subject: [PATCH 19/26] fix(caravan-psbt): enforce prevout-matched silent payment input keys --- .../src/psbtv2/psbtv2-bip375.test.ts | 129 ++++++++++++++++-- 1 file changed, 121 insertions(+), 8 deletions(-) diff --git a/packages/caravan-psbt/src/psbtv2/psbtv2-bip375.test.ts b/packages/caravan-psbt/src/psbtv2/psbtv2-bip375.test.ts index 943fd311f7..0276affca4 100644 --- a/packages/caravan-psbt/src/psbtv2/psbtv2-bip375.test.ts +++ b/packages/caravan-psbt/src/psbtv2/psbtv2-bip375.test.ts @@ -37,10 +37,17 @@ function p2wpkhScript(pubkey: Buffer): Buffer { describe("BIP375 invalid vectors", () => { test.each(bip375Vectors.invalid)("$description", ({ psbt }) => { + let thrown: unknown; expect(() => { - const p = new PsbtV2(psbt); - p.validate(); + try { + new PsbtV2(psbt); + } catch (e) { + thrown = e; + throw e; + } }).toThrow(); + + console.log(` throw reason: ${(thrown as Error).message}`); }); }); @@ -241,9 +248,9 @@ describe("BIP375 DLEQ integration", () => { proof[0] ^= 1; psbt.globalMap.set(proofKey, proof); - psbt.computeSilentPaymentOutputScripts(); - - expect(() => new PsbtV2(psbt.serialize())).toThrow( + // The producer verifies DLEQ proofs before deriving, so the tampered proof + // is rejected at compute time rather than later on round-trip construction. + expect(() => psbt.computeSilentPaymentOutputScripts()).toThrow( /Invalid global silent payment DLEQ proof/, ); }); @@ -354,10 +361,116 @@ describe("BIP375 DLEQ integration", () => { proof[0] ^= 1; psbt.inputMaps[0].set(proofKey, proof); - psbt.computeSilentPaymentOutputScripts(); - - expect(() => new PsbtV2(psbt.serialize())).toThrow( + // The producer verifies DLEQ proofs before deriving, so the tampered proof + // is rejected at compute time rather than later on round-trip construction. + expect(() => psbt.computeSilentPaymentOutputScripts()).toThrow( /Invalid input 0 silent payment DLEQ proof/, ); }); }); + +describe("BIP375 signing gate", () => { + const inputSecret = hex( + "0000000000000000000000000000000000000000000000000000000000000001", + ); + const scanSecret = hex( + "0000000000000000000000000000000000000000000000000000000000000002", + ); + const spendSecret = hex( + "0000000000000000000000000000000000000000000000000000000000000003", + ); + + const inputPubkey = pubkeyFromSecret(inputSecret); + const scanKey = pubkeyFromSecret(scanSecret); + const spendKey = pubkeyFromSecret(spendSecret); + + // 71-byte SIGHASH_ALL dummy sig: only the trailing sighash byte is parsed + // by addPartialSig (handleSighashType reads the last byte). + const dummySig = Buffer.concat([Buffer.alloc(71, 0), Buffer.from([0x01])]); + + function buildSPPsbt(): PsbtV2 { + const psbt = new PsbtV2(); + + psbt.addInput({ + previousTxId: Buffer.alloc(32, 1), + outputIndex: 0, + witnessUtxo: { + amount: 100_000, + script: p2wpkhScript(inputPubkey), + }, + bip32Derivation: [ + { + pubkey: inputPubkey, + masterFingerprint: Buffer.alloc(4, 0), + path: "m/84'/0'/0'/0/0", + }, + ], + }); + + psbt.addOutput({ + amount: 50_000, + silentPayment: { + bscan: scanKey, + bspend: spendKey, + }, + }); + + psbt.addGlobalSPECDHShareWithDLEQ( + scanKey, + inputSecret, + Buffer.alloc(32, 0), + ); + + return psbt; + } + + it("signs a valid SP PSBT on the live object after computing scripts", () => { + const psbt = buildSPPsbt(); + psbt.computeSilentPaymentOutputScripts(); + + expect(() => psbt.addPartialSig(0, inputPubkey, dummySig)).not.toThrow(); + expect(psbt.PSBT_IN_PARTIAL_SIG[0].length).toBe(1); + }); + + it("rejects signing when the SP output script was tampered after computing", () => { + const psbt = buildSPPsbt(); + psbt.computeSilentPaymentOutputScripts(); + + const proofKey = KeyType.PSBT_GLOBAL_SP_DLEQ + scanKey.toString("hex"); + const proof = Buffer.from(psbt.globalMap.get(proofKey) as Buffer); + proof[0] ^= 1; + psbt.globalMap.set(proofKey, proof); + + expect(() => psbt.addPartialSig(0, inputPubkey, dummySig)).toThrow(); + // The signature must not have been written. + expect(psbt.PSBT_IN_PARTIAL_SIG[0].length).toBe(0); + }); + + it("allows signing a non-SP PSBT (early-return path is a no-op)", () => { + const psbt = new PsbtV2(); + + psbt.addInput({ + previousTxId: Buffer.alloc(32, 1), + outputIndex: 0, + witnessUtxo: { + amount: 100_000, + script: p2wpkhScript(inputPubkey), + }, + bip32Derivation: [ + { + pubkey: inputPubkey, + masterFingerprint: Buffer.alloc(4, 0), + path: "m/84'/0'/0'/0/0", + }, + ], + }); + + psbt.addOutput({ + amount: 50_000, + script: p2wpkhScript(spendKey), + }); + + expect(() => psbt.addPartialSig(0, inputPubkey, dummySig)).not.toThrow(); + expect(psbt.PSBT_IN_PARTIAL_SIG[0].length).toBe(1); + }); +}); From 98ce2c3f7867bffbbaafbda432cd53929b0b26cc Mon Sep 17 00:00:00 2001 From: Jasper van Gelder Date: Wed, 10 Jun 2026 17:07:49 +0200 Subject: [PATCH 20/26] refactor(caravan-psbt): expose NUMS script-path detection for validation --- packages/caravan-psbt/src/psbtv2/psbtv2.ts | 239 ++++++++++++++---- .../caravan-psbt/src/psbtv2/silentpayment.ts | 61 ++++- 2 files changed, 250 insertions(+), 50 deletions(-) diff --git a/packages/caravan-psbt/src/psbtv2/psbtv2.ts b/packages/caravan-psbt/src/psbtv2/psbtv2.ts index bb57a9a91f..3640a911bf 100644 --- a/packages/caravan-psbt/src/psbtv2/psbtv2.ts +++ b/packages/caravan-psbt/src/psbtv2/psbtv2.ts @@ -34,6 +34,7 @@ import { getSilentPaymentPubkeyFromInputDescriptor, groupSilentPaymentOutputs, hasSegwitV2PlusInput, + isNumsScriptPathSpend, SPInputDescriptor, SPOutputEntry, sumECDHShares, @@ -869,6 +870,7 @@ export class PsbtV2 extends PsbtV2Maps { private getSilentPaymentOutputGroups( onlyWithScripts = false, + skipLabeled = false, ): Map { const entries: SPOutputEntry[] = []; @@ -876,6 +878,10 @@ export class PsbtV2 extends PsbtV2Maps { const info = this.getSilentPaymentOutputInfo(i); if (!info) continue; + if (skipLabeled && this.outputMaps[i].has(KeyType.PSBT_OUT_SP_V0_LABEL)) { + continue; + } + if (onlyWithScripts) { const script = this.outputMaps[i].get(KeyType.PSBT_OUT_SCRIPT); if (!script || script.length === 0) continue; @@ -887,46 +893,142 @@ export class PsbtV2 extends PsbtV2Maps { return groupSilentPaymentOutputs(entries); } - private getFinalScriptWitnessPubkeys(inputIndex: number): Buffer[] { - const witnessHex = this.PSBT_IN_FINAL_SCRIPTWITNESS[inputIndex]; + private static isCompressedPubkeyCandidate(candidate: Buffer): boolean { + return ( + candidate.length === 33 && + (candidate[0] === 0x02 || candidate[0] === 0x03) + ); + } - if (!witnessHex) { + private static readCompactSize( + data: Buffer, + offset: number, + ): { value: number; offset: number } | null { + if (offset >= data.length) return null; + + const first = data[offset]; + + if (first < 0xfd) { + return { value: first, offset: offset + 1 }; + } + + if (first === 0xfd) { + if (offset + 3 > data.length) return null; + return { value: data.readUInt16LE(offset + 1), offset: offset + 3 }; + } + + if (first === 0xfe) { + if (offset + 5 > data.length) return null; + return { value: data.readUInt32LE(offset + 1), offset: offset + 5 }; + } + + if (offset + 9 > data.length) return null; + + const value = data.readBigUInt64LE(offset + 1); + if (value > BigInt(Number.MAX_SAFE_INTEGER)) return null; + + return { value: Number(value), offset: offset + 9 }; + } + + private static parseScriptWitnessStack(witness: Buffer): Buffer[] { + const stackCount = PsbtV2.readCompactSize(witness, 0); + + if (!stackCount) { return []; } - const witness = Buffer.from(witnessHex, "hex"); - const pubkeys: Buffer[] = []; + const stack: Buffer[] = []; + let offset = stackCount.offset; + + for (let i = 0; i < stackCount.value; i++) { + const itemLength = PsbtV2.readCompactSize(witness, offset); + + if (!itemLength) { + return []; + } + + offset = itemLength.offset; + + if (offset + itemLength.value > witness.length) { + return []; + } + + stack.push(witness.subarray(offset, offset + itemLength.value)); + offset += itemLength.value; + } + + return offset === witness.length ? stack : []; + } + + private static parseScriptPushes(scriptSig: Buffer): Buffer[] { + const pushes: Buffer[] = []; + let offset = 0; - for (let i = 0; i <= witness.length - 33; i++) { - const candidate = witness.subarray(i, i + 33); + while (offset < scriptSig.length) { + const opcode = scriptSig[offset++]; + let length: number; - if (candidate[0] === 0x02 || candidate[0] === 0x03) { - pubkeys.push(Buffer.from(candidate)); + if (opcode === 0x00) { + pushes.push(Buffer.alloc(0)); + continue; + } + + if (opcode >= 0x01 && opcode <= 0x4b) { + length = opcode; + } else if (opcode === 0x4c) { + if (offset + 1 > scriptSig.length) return []; + length = scriptSig[offset++]; + } else if (opcode === 0x4d) { + if (offset + 2 > scriptSig.length) return []; + length = scriptSig.readUInt16LE(offset); + offset += 2; + } else if (opcode === 0x4e) { + if (offset + 4 > scriptSig.length) return []; + length = scriptSig.readUInt32LE(offset); + offset += 4; + } else { + return []; } + + if (offset + length > scriptSig.length) { + return []; + } + + pushes.push(scriptSig.subarray(offset, offset + length)); + offset += length; } - return pubkeys; + return pushes; } - private getFinalScriptSigPubkeys(inputIndex: number): Buffer[] { - const scriptSigHex = this.PSBT_IN_FINAL_SCRIPTSIG[inputIndex]; + private static getCompressedPubkeysFromPushes(pushes: Buffer[]): Buffer[] { + return pushes + .filter(PsbtV2.isCompressedPubkeyCandidate) + .map((pubkey) => Buffer.from(pubkey)); + } - if (!scriptSigHex) { + private getFinalScriptWitnessPubkeys(inputIndex: number): Buffer[] { + const witnessHex = this.PSBT_IN_FINAL_SCRIPTWITNESS[inputIndex]; + + if (!witnessHex) { return []; } - const scriptSig = Buffer.from(scriptSigHex, "hex"); - const pubkeys: Buffer[] = []; + return PsbtV2.getCompressedPubkeysFromPushes( + PsbtV2.parseScriptWitnessStack(Buffer.from(witnessHex, "hex")), + ); + } - for (let i = 0; i <= scriptSig.length - 33; i++) { - const candidate = scriptSig.subarray(i, i + 33); + private getFinalScriptSigPubkeys(inputIndex: number): Buffer[] { + const scriptSigHex = this.PSBT_IN_FINAL_SCRIPTSIG[inputIndex]; - if (candidate[0] === 0x02 || candidate[0] === 0x03) { - pubkeys.push(Buffer.from(candidate)); - } + if (!scriptSigHex) { + return []; } - return pubkeys; + return PsbtV2.getCompressedPubkeysFromPushes( + PsbtV2.parseScriptPushes(Buffer.from(scriptSigHex, "hex")), + ); } private getSilentPaymentCandidatePubkeys(inputIndex: number): Buffer[] { @@ -1098,20 +1200,7 @@ export class PsbtV2 extends PsbtV2Maps { return Buffer.from(sumECDHShares(perInputBuffers).toRawBytes(true)); } - /** - * Validates all BIP375 silent payment constraints. - * - * Three phases: - * 1. Output map structural checks — always run - * 2. Input eligibility checks — only when SP outputs present - * 3. ECDH coverage checks — only when SP outputs have PSBT_OUT_SCRIPT set - */ - private validateSilentPayments() { - if (!this.hasSilentPaymentOutputs) { - return; - } - - // ── Output map structural checks ─────────────────────────────────────── + private validateSilentPaymentOutputMaps(): void { for (const [i, outputMap] of this.outputMaps.entries()) { const spInfo = outputMap.get(KeyType.PSBT_OUT_SP_V0_INFO); const spLabel = outputMap.get(KeyType.PSBT_OUT_SP_V0_LABEL); @@ -1146,8 +1235,9 @@ export class PsbtV2 extends PsbtV2Maps { } } } + } - // ── Global map: keydata/valuedata + pairing checks ──────────────────── + private validateSilentPaymentGlobalFields(): void { for (const [key, value] of this.globalMap.entries()) { if (key.startsWith(KeyType.PSBT_GLOBAL_SP_ECDH_SHARE)) { const scanKey = scanKeyHexFromBIP375Key( @@ -1181,8 +1271,9 @@ export class PsbtV2 extends PsbtV2Maps { } } } + } - // ── Input map: keydata/valuedata + pairing checks ───────────────────── + private validateSilentPaymentInputFields(): void { for (const [i, inputMap] of this.inputMaps.entries()) { for (const [key, value] of inputMap.entries()) { if (key.startsWith(KeyType.PSBT_IN_SP_ECDH_SHARE)) { @@ -1218,15 +1309,31 @@ export class PsbtV2 extends PsbtV2Maps { } } } + } - // ── SP-wide restrictions that apply whenever SP outputs exist ────────── - if (hasSegwitV2PlusInput(this.getSilentPaymentInputDescriptors())) { + private validateSilentPaymentWideRestrictions(): void { + const inputDescriptors = this.getSilentPaymentInputDescriptors(); + + if (hasSegwitV2PlusInput(inputDescriptors)) { throw Error( "A PSBT with PSBT_OUT_SP_V0_INFO must not contain SegWit v2+ inputs.", ); } for (const [i, inputMap] of this.inputMaps.entries()) { + if (isNumsScriptPathSpend(inputDescriptors[i])) { + for (const key of inputMap.keys()) { + if ( + key.startsWith(KeyType.PSBT_IN_SP_ECDH_SHARE) || + key.startsWith(KeyType.PSBT_IN_SP_DLEQ) + ) { + throw Error( + `Input ${i} is a NUMS taproot script-path spend and must not have silent payment ECDH/DLEQ data.`, + ); + } + } + } + const sighash = inputMap.get(KeyType.PSBT_IN_SIGHASH_TYPE); if (sighash && sighash.length >= 4) { @@ -1239,22 +1346,36 @@ export class PsbtV2 extends PsbtV2Maps { } } } + } - const contributingInputs = this.getContributingInputsForSilentPayments(); - + private validateComputedSilentPaymentOutputScripts(): void { // ECDH coverage is only required per scan key that has a computed SP output // script. Scan keys whose outputs are still in progress (no PSBT_OUT_SCRIPT) - // may have missing ECDH/DLEQ data + // may have missing ECDH/DLEQ data. + const outputGroups = this.getSilentPaymentOutputGroups(true, true); + if (outputGroups.size === 0) { + return; + } + + const contributingInputs = this.getContributingInputsForSilentPayments(); + if (contributingInputs.length === 0) { + throw Error( + "No contributing inputs for silent payment ECDH derivation.", + ); + } + const inputHash = this.computeSilentPaymentInputHash(contributingInputs); - for (const [bscanHex, group] of this.getSilentPaymentOutputGroups(true)) { + for (const [bscanHex, group] of outputGroups) { const ecdhShare = this.resolveAndVerifyScanKeyEcdhShare( bscanHex, contributingInputs, ); if (!ecdhShare) { - continue; + throw Error( + `Missing silent payment ECDH share for scan key ${bscanHex}.`, + ); } for (let k = 0; k < group.length; k++) { @@ -1285,6 +1406,25 @@ export class PsbtV2 extends PsbtV2Maps { } } + /** + * Validates all BIP375 silent payment constraints. + * + * The structural checks always run for SP PSBTs. Expensive ECDH/share + * verification is limited to outputs whose scripts have already been + * computed and can be compared from public PSBT data. + */ + private validateSilentPayments(): void { + if (!this.hasSilentPaymentOutputs) { + return; + } + + this.validateSilentPaymentOutputMaps(); + this.validateSilentPaymentGlobalFields(); + this.validateSilentPaymentInputFields(); + this.validateSilentPaymentWideRestrictions(); + this.validateComputedSilentPaymentOutputScripts(); + } + /** * Sets the sequence number for a specific input in the transaction. * @@ -2238,11 +2378,12 @@ export class PsbtV2 extends PsbtV2Maps { * Per BIP375: the Signer must not add a signature until this is true. */ get hasAllSPOutputScripts(): boolean { - return this.outputMaps.every( - (map) => - !map.has(KeyType.PSBT_OUT_SP_V0_INFO) || - map.has(KeyType.PSBT_OUT_SCRIPT), - ); + return this.outputMaps.every((map) => { + if (!map.has(KeyType.PSBT_OUT_SP_V0_INFO)) return true; + + const script = map.get(KeyType.PSBT_OUT_SCRIPT); + return !!script && script.length > 0; + }); } /** diff --git a/packages/caravan-psbt/src/psbtv2/silentpayment.ts b/packages/caravan-psbt/src/psbtv2/silentpayment.ts index ac11433da0..47a9c09ecc 100644 --- a/packages/caravan-psbt/src/psbtv2/silentpayment.ts +++ b/packages/caravan-psbt/src/psbtv2/silentpayment.ts @@ -322,6 +322,65 @@ export function isEligibleInputType(type: SPInputScriptType): boolean { ); } + +function hash160(buffer: Buffer): Buffer { + const sha = createHash("sha256").update(buffer).digest(); + return createHash("ripemd160").update(sha).digest(); +} + +/** + * Returns the public key committed to an input's prevout script from a list of + * candidate pubkeys, or null when no candidate matches. This prevents callers + * from using an arbitrary PSBT-provided pubkey for silent-payment DLEQ + * verification and input_hash derivation. + */ +export function getSilentPaymentPubkeyFromInputDescriptor( + input: SPInputDescriptor, + candidatePubkeys: Buffer[], +): Buffer | null { + const scriptPubKey = input.witnessUtxo + ? readWitnessUtxoScript(input.witnessUtxo) + : readNonWitnessUtxoScript(input.nonWitnessUtxo, input.outputIndex); + + if (!scriptPubKey) return null; + + const scriptType = classifyInputDescriptor(input); + + if (scriptType === "p2tr") { + return input.witnessUtxo + ? getTaprootOutputKeyFromWitnessUtxo(input.witnessUtxo) + : null; + } + + for (const pubkey of candidatePubkeys) { + assertValidCompressedPoint(pubkey, "silent payment input pubkey"); + const pubkeyHash = hash160(pubkey); + + if (scriptType === "p2wpkh") { + if (pubkeyHash.equals(scriptPubKey.subarray(2, 22))) return pubkey; + continue; + } + + if (scriptType === "p2pkh_or_unknown_legacy") { + if (pubkeyHash.equals(scriptPubKey.subarray(3, 23))) return pubkey; + continue; + } + + if (scriptType === "p2sh_p2wpkh") { + if (!input.redeemScript) continue; + + const p2shHash = scriptPubKey.subarray(2, 22); + if (!hash160(input.redeemScript).equals(p2shHash)) continue; + if (classifyWitnessScript(input.redeemScript) !== "p2wpkh") continue; + + const redeemWitnessProgram = input.redeemScript.subarray(2, 22); + if (pubkeyHash.equals(redeemWitnessProgram)) return pubkey; + } + } + + return null; +} + /** * Determines which transaction inputs are eligible for silent payment ECDH * derivation per BIP352. @@ -356,7 +415,7 @@ function eligibleIndices(inputs: SPInputDescriptor[]): number[] { * A taproot input spent via script path using the BIP352 NUMS point H as its * internal key is eligible by type but never contributes an ECDH share. */ -function isNumsScriptPathSpend(input: SPInputDescriptor): boolean { +export function isNumsScriptPathSpend(input: SPInputDescriptor): boolean { if (input.tapInternalKey === BIP352_NUMS_H) { return true; } From a391dd201735c128d8c6dfd1197f2288b775e6a9 Mon Sep 17 00:00:00 2001 From: Jasper van Gelder Date: Wed, 10 Jun 2026 17:29:42 +0200 Subject: [PATCH 21/26] fix(caravan-psbt): require prevout-matched keys for SP derivation Use only input pubkeys that match the spent prevout script when verifying silent payment DLEQ proofs and computing BIP352 input_hash. This prevents PSBTs from deriving silent payment outputs from a decoy pubkey while spending with a different key. Also tighten SP signing/validation guards for computed outputs, NUMS taproot script-path inputs, and non-SIGHASH_ALL partial signatures. --- packages/caravan-psbt/src/psbtv2/psbtv2.ts | 382 ++++++------------ .../caravan-psbt/src/psbtv2/silentpayment.ts | 106 +---- 2 files changed, 121 insertions(+), 367 deletions(-) diff --git a/packages/caravan-psbt/src/psbtv2/psbtv2.ts b/packages/caravan-psbt/src/psbtv2/psbtv2.ts index 3640a911bf..232ef3d285 100644 --- a/packages/caravan-psbt/src/psbtv2/psbtv2.ts +++ b/packages/caravan-psbt/src/psbtv2/psbtv2.ts @@ -27,7 +27,6 @@ import { assertValidLabel, assertValidOutputK, assertValidSPV0Info, - scanKeyHexFromBIP375Key, computeInputHash, deriveSilentPaymentOutput, contributingIndices, @@ -893,142 +892,38 @@ export class PsbtV2 extends PsbtV2Maps { return groupSilentPaymentOutputs(entries); } - private static isCompressedPubkeyCandidate(candidate: Buffer): boolean { - return ( - candidate.length === 33 && - (candidate[0] === 0x02 || candidate[0] === 0x03) - ); - } - - private static readCompactSize( - data: Buffer, - offset: number, - ): { value: number; offset: number } | null { - if (offset >= data.length) return null; - - const first = data[offset]; - - if (first < 0xfd) { - return { value: first, offset: offset + 1 }; - } - - if (first === 0xfd) { - if (offset + 3 > data.length) return null; - return { value: data.readUInt16LE(offset + 1), offset: offset + 3 }; - } - - if (first === 0xfe) { - if (offset + 5 > data.length) return null; - return { value: data.readUInt32LE(offset + 1), offset: offset + 5 }; - } - - if (offset + 9 > data.length) return null; - - const value = data.readBigUInt64LE(offset + 1); - if (value > BigInt(Number.MAX_SAFE_INTEGER)) return null; - - return { value: Number(value), offset: offset + 9 }; - } - - private static parseScriptWitnessStack(witness: Buffer): Buffer[] { - const stackCount = PsbtV2.readCompactSize(witness, 0); - - if (!stackCount) { - return []; - } - - const stack: Buffer[] = []; - let offset = stackCount.offset; - - for (let i = 0; i < stackCount.value; i++) { - const itemLength = PsbtV2.readCompactSize(witness, offset); - - if (!itemLength) { - return []; - } - - offset = itemLength.offset; - - if (offset + itemLength.value > witness.length) { - return []; - } - - stack.push(witness.subarray(offset, offset + itemLength.value)); - offset += itemLength.value; - } - - return offset === witness.length ? stack : []; - } - - private static parseScriptPushes(scriptSig: Buffer): Buffer[] { - const pushes: Buffer[] = []; - let offset = 0; - - while (offset < scriptSig.length) { - const opcode = scriptSig[offset++]; - let length: number; - - if (opcode === 0x00) { - pushes.push(Buffer.alloc(0)); - continue; - } - - if (opcode >= 0x01 && opcode <= 0x4b) { - length = opcode; - } else if (opcode === 0x4c) { - if (offset + 1 > scriptSig.length) return []; - length = scriptSig[offset++]; - } else if (opcode === 0x4d) { - if (offset + 2 > scriptSig.length) return []; - length = scriptSig.readUInt16LE(offset); - offset += 2; - } else if (opcode === 0x4e) { - if (offset + 4 > scriptSig.length) return []; - length = scriptSig.readUInt32LE(offset); - offset += 4; - } else { - return []; - } - - if (offset + length > scriptSig.length) { - return []; - } - - pushes.push(scriptSig.subarray(offset, offset + length)); - offset += length; - } - - return pushes; - } - - private static getCompressedPubkeysFromPushes(pushes: Buffer[]): Buffer[] { - return pushes - .filter(PsbtV2.isCompressedPubkeyCandidate) - .map((pubkey) => Buffer.from(pubkey)); - } - private getFinalScriptWitnessPubkeys(inputIndex: number): Buffer[] { const witnessHex = this.PSBT_IN_FINAL_SCRIPTWITNESS[inputIndex]; + if (!witnessHex) return []; + + const witness = Buffer.from(witnessHex, "hex"); + const pubkeys: Buffer[] = []; - if (!witnessHex) { - return []; + for (let i = 0; i <= witness.length - 33; i++) { + const candidate = witness.subarray(i, i + 33); + if (candidate[0] === 0x02 || candidate[0] === 0x03) { + pubkeys.push(Buffer.from(candidate)); + } } - return PsbtV2.getCompressedPubkeysFromPushes( - PsbtV2.parseScriptWitnessStack(Buffer.from(witnessHex, "hex")), - ); + return pubkeys; } private getFinalScriptSigPubkeys(inputIndex: number): Buffer[] { const scriptSigHex = this.PSBT_IN_FINAL_SCRIPTSIG[inputIndex]; + if (!scriptSigHex) return []; - if (!scriptSigHex) { - return []; + const scriptSig = Buffer.from(scriptSigHex, "hex"); + const pubkeys: Buffer[] = []; + + for (let i = 0; i <= scriptSig.length - 33; i++) { + const candidate = scriptSig.subarray(i, i + 33); + if (candidate[0] === 0x02 || candidate[0] === 0x03) { + pubkeys.push(Buffer.from(candidate)); + } } - return PsbtV2.getCompressedPubkeysFromPushes( - PsbtV2.parseScriptPushes(Buffer.from(scriptSigHex, "hex")), - ); + return pubkeys; } private getSilentPaymentCandidatePubkeys(inputIndex: number): Buffer[] { @@ -1083,13 +978,12 @@ export class PsbtV2 extends PsbtV2Maps { /** * Computes the BIP352 input hash from all outpoints and the aggregate public - * key of the contributing inputs. This is strict: callers that validate or - * create computed SP output scripts must be able to recover prevout-matched - * input pubkeys. + * key of the contributing inputs. This is strict because computed SP output + * scripts can only be verified when every contributing input has a pubkey that + * matches its prevout script. */ private computeSilentPaymentInputHash(contributingInputs: number[]): Buffer { const outpoints = this.getAllOutpoints(); - if (outpoints.length === 0) { throw Error("At least one outpoint is required to compute inputHash."); } @@ -1103,10 +997,11 @@ export class PsbtV2 extends PsbtV2Maps { } /** - * Resolves the ECDH share for a scan key while verifying its DLEQ proof(s) - * when the required input pubkey is recoverable. Share/proof pairing is - * mandatory, but semantic proof verification can be deferred for in-progress - * PSBTs whose input pubkeys are not yet recoverable. + * Resolves the ECDH share for a scan key while verifying its DLEQ proof(s). + * + * Returns the share — either the global share or the sum of per-input shares + * — or null when the scan key's output is still in progress (no derivable + * share has been contributed yet). */ private resolveAndVerifyScanKeyEcdhShare( bscanHex: string, @@ -1127,25 +1022,27 @@ export class PsbtV2 extends PsbtV2Maps { const aggregatePubkey = this.tryGetInputAggregatePubkey(contributingInputs); + if (!aggregatePubkey) { + return null; + } - if (aggregatePubkey) { - if ( - !verifySilentPaymentDLEQProof({ - publicKey: Buffer.from(aggregatePubkey.toRawBytes(true)), - scanKey: Buffer.from(bscanHex, "hex"), - ecdhShare, - proof, - }) - ) { - throw Error( - `Invalid global silent payment DLEQ proof for scan key ${bscanHex}.`, - ); - } + if ( + !verifySilentPaymentDLEQProof({ + publicKey: Buffer.from(aggregatePubkey.toRawBytes(true)), + scanKey: Buffer.from(bscanHex, "hex"), + ecdhShare, + proof, + }) + ) { + throw Error( + `Invalid global silent payment DLEQ proof for scan key ${bscanHex}.`, + ); } return ecdhShare; } + // At least one contributing input when there is no global share is required if (contributingInputs.length === 0) { throw Error( `Output script set for scan key ${bscanHex} but no contributing inputs can derive it.`, @@ -1161,11 +1058,12 @@ export class PsbtV2 extends PsbtV2Maps { if (!ecdhShare) { throw Error( - `Output script set but contributing input ${i} missing ECDH share for scan key ${bscanHex}`, + `Output script set but eligible input ${i} missing ECDH share for scan key ${bscanHex}`, ); } - const proof = this.inputMaps[i].get(proofKey); + const inputPubkey = this.tryGetInputAggregatePubkey([i]); + const proof = this.inputMaps[i].get(proofKey) as Buffer; if (!proof) { throw Error( @@ -1173,21 +1071,23 @@ export class PsbtV2 extends PsbtV2Maps { ); } - const inputPubkey = this.tryGetInputAggregatePubkey([i]); + if (!inputPubkey) { + throw Error( + `Input ${i} missing public key for silent payment DLEQ verification.`, + ); + } - if (inputPubkey) { - if ( - !verifySilentPaymentDLEQProof({ - publicKey: Buffer.from(inputPubkey.toRawBytes(true)), - scanKey: Buffer.from(bscanHex, "hex"), - ecdhShare, - proof, - }) - ) { - throw Error( - `Invalid input ${i} silent payment DLEQ proof for scan key ${bscanHex}.`, - ); - } + if ( + !verifySilentPaymentDLEQProof({ + publicKey: Buffer.from(inputPubkey.toRawBytes(true)), + scanKey: Buffer.from(bscanHex, "hex"), + ecdhShare, + proof, + }) + ) { + throw Error( + `Invalid input ${i} silent payment DLEQ proof for scan key ${bscanHex}.`, + ); } perInputBuffers.push(ecdhShare); @@ -1200,7 +1100,20 @@ export class PsbtV2 extends PsbtV2Maps { return Buffer.from(sumECDHShares(perInputBuffers).toRawBytes(true)); } - private validateSilentPaymentOutputMaps(): void { + /** + * Validates all BIP375 silent payment constraints. + * + * Three phases: + * 1. Output map structural checks — always run + * 2. Input eligibility checks — only when SP outputs present + * 3. ECDH coverage checks — only when SP outputs have PSBT_OUT_SCRIPT set + */ + private validateSilentPayments() { + if (!this.hasSilentPaymentOutputs) { + return; + } + + // ── Output map structural checks ─────────────────────────────────────── for (const [i, outputMap] of this.outputMaps.entries()) { const spInfo = outputMap.get(KeyType.PSBT_OUT_SP_V0_INFO); const spLabel = outputMap.get(KeyType.PSBT_OUT_SP_V0_LABEL); @@ -1235,105 +1148,54 @@ export class PsbtV2 extends PsbtV2Maps { } } } - } - private validateSilentPaymentGlobalFields(): void { + // ── Global map: keydata/valuedata + pairing checks ──────────────────── for (const [key, value] of this.globalMap.entries()) { if (key.startsWith(KeyType.PSBT_GLOBAL_SP_ECDH_SHARE)) { - const scanKey = scanKeyHexFromBIP375Key( - key, - KeyType.PSBT_GLOBAL_SP_ECDH_SHARE, - "Global ECDH share", - ); - assertValidECDHShare(value); - - if (!this.globalMap.has(KeyType.PSBT_GLOBAL_SP_DLEQ + scanKey)) { - throw Error( - `Global ECDH share missing PSBT_GLOBAL_SP_DLEQ for scan key ${scanKey}.`, - ); - } } - if (key.startsWith(KeyType.PSBT_GLOBAL_SP_DLEQ)) { - const scanKey = scanKeyHexFromBIP375Key( - key, - KeyType.PSBT_GLOBAL_SP_DLEQ, - "Global DLEQ proof", - ); - assertValidDLEQProof(value); - - if (!this.globalMap.has(KeyType.PSBT_GLOBAL_SP_ECDH_SHARE + scanKey)) { - throw Error( - `Global DLEQ proof missing PSBT_GLOBAL_SP_ECDH_SHARE for scan key ${scanKey}.`, - ); - } } } - } - private validateSilentPaymentInputFields(): void { - for (const [i, inputMap] of this.inputMaps.entries()) { - for (const [key, value] of inputMap.entries()) { + // ── Input map: keydata/valuedata + pairing checks ───────────────────── + for (const inputMap of this.inputMaps.values()) { + for (const [key, value] of inputMap) { if (key.startsWith(KeyType.PSBT_IN_SP_ECDH_SHARE)) { - const scanKey = scanKeyHexFromBIP375Key( - key, - KeyType.PSBT_IN_SP_ECDH_SHARE, - `Input ${i} ECDH share`, - ); - assertValidECDHShare(value); - - if (!inputMap.has(KeyType.PSBT_IN_SP_DLEQ + scanKey)) { - throw Error( - `Input ${i} ECDH share missing PSBT_IN_SP_DLEQ for scan key ${scanKey}.`, - ); - } } - if (key.startsWith(KeyType.PSBT_IN_SP_DLEQ)) { - const scanKey = scanKeyHexFromBIP375Key( - key, - KeyType.PSBT_IN_SP_DLEQ, - `Input ${i} DLEQ proof`, - ); - assertValidDLEQProof(value); - - if (!inputMap.has(KeyType.PSBT_IN_SP_ECDH_SHARE + scanKey)) { - throw Error( - `Input ${i} DLEQ proof missing PSBT_IN_SP_ECDH_SHARE for scan key ${scanKey}.`, - ); - } } } } - } - private validateSilentPaymentWideRestrictions(): void { - const inputDescriptors = this.getSilentPaymentInputDescriptors(); + // ── SP-wide restrictions that apply whenever SP outputs exist ────────── + const descriptors = this.getSilentPaymentInputDescriptors(); - if (hasSegwitV2PlusInput(inputDescriptors)) { + if (hasSegwitV2PlusInput(descriptors)) { throw Error( "A PSBT with PSBT_OUT_SP_V0_INFO must not contain SegWit v2+ inputs.", ); } for (const [i, inputMap] of this.inputMaps.entries()) { - if (isNumsScriptPathSpend(inputDescriptors[i])) { - for (const key of inputMap.keys()) { - if ( - key.startsWith(KeyType.PSBT_IN_SP_ECDH_SHARE) || - key.startsWith(KeyType.PSBT_IN_SP_DLEQ) - ) { - throw Error( - `Input ${i} is a NUMS taproot script-path spend and must not have silent payment ECDH/DLEQ data.`, - ); - } + if (!isNumsScriptPathSpend(descriptors[i])) continue; + + for (const key of inputMap.keys()) { + if ( + key.startsWith(KeyType.PSBT_IN_SP_ECDH_SHARE) || + key.startsWith(KeyType.PSBT_IN_SP_DLEQ) + ) { + throw Error( + `Input ${i} is a NUMS taproot script-path spend and must not have silent payment ECDH/DLEQ data.`, + ); } } + } + for (const [i, inputMap] of this.inputMaps.entries()) { const sighash = inputMap.get(KeyType.PSBT_IN_SIGHASH_TYPE); if (sighash && sighash.length >= 4) { @@ -1346,22 +1208,21 @@ export class PsbtV2 extends PsbtV2Maps { } } } - } - private validateComputedSilentPaymentOutputScripts(): void { // ECDH coverage is only required per scan key that has a computed SP output // script. Scan keys whose outputs are still in progress (no PSBT_OUT_SCRIPT) - // may have missing ECDH/DLEQ data. + // may have missing ECDH/DLEQ data. Labeled outputs are skipped here until + // label-aware public recomputation is implemented. const outputGroups = this.getSilentPaymentOutputGroups(true, true); + if (outputGroups.size === 0) { return; } const contributingInputs = this.getContributingInputsForSilentPayments(); + if (contributingInputs.length === 0) { - throw Error( - "No contributing inputs for silent payment ECDH derivation.", - ); + throw Error("No contributing inputs for silent payment ECDH derivation."); } const inputHash = this.computeSilentPaymentInputHash(contributingInputs); @@ -1406,25 +1267,6 @@ export class PsbtV2 extends PsbtV2Maps { } } - /** - * Validates all BIP375 silent payment constraints. - * - * The structural checks always run for SP PSBTs. Expensive ECDH/share - * verification is limited to outputs whose scripts have already been - * computed and can be compared from public PSBT data. - */ - private validateSilentPayments(): void { - if (!this.hasSilentPaymentOutputs) { - return; - } - - this.validateSilentPaymentOutputMaps(); - this.validateSilentPaymentGlobalFields(); - this.validateSilentPaymentInputFields(); - this.validateSilentPaymentWideRestrictions(); - this.validateComputedSilentPaymentOutputScripts(); - } - /** * Sets the sequence number for a specific input in the transaction. * @@ -1823,31 +1665,35 @@ export class PsbtV2 extends PsbtV2Maps { throw Error(`PsbtV2 has no input at ${inputIndex}`); } - if (!pubkey || !sig || sig.length === 0) { + if (!pubkey || !sig) { throw Error( `PsbtV2.addPartialSig() missing argument ${ - (!pubkey && "pubkey") || ((!sig || sig.length === 0) && "sig") + (!pubkey && "pubkey") || (!sig && "sig") }`, ); } + const key = `${KeyType.PSBT_IN_PARTIAL_SIG}${pubkey.toString("hex")}`; + if (this.inputMaps[inputIndex].has(key)) { + throw Error( + "PsbtV2 already has a signature for this input with this pubkey", + ); + } + if (this.hasSilentPaymentOutputs) { + if (sig.length === 0) { + throw Error("PsbtV2.addPartialSig() received empty signature."); + } + const sighashType = sig[sig.length - 1]; if (sighashType !== SighashType.SIGHASH_ALL) { - throw new Error( + throw Error( "Silent payment PSBTs require partial signatures to use SIGHASH_ALL.", ); } } - const key = `${KeyType.PSBT_IN_PARTIAL_SIG}${pubkey.toString("hex")}`; - if (this.inputMaps[inputIndex].has(key)) { - throw Error( - "PsbtV2 already has a signature for this input with this pubkey", - ); - } - // Per BIP375: re-verify silent-payment consistency on the live object before // a signature locks the inputs. No-op when there are no SP outputs. this.validateSilentPayments(); diff --git a/packages/caravan-psbt/src/psbtv2/silentpayment.ts b/packages/caravan-psbt/src/psbtv2/silentpayment.ts index 47a9c09ecc..b3701e3e3f 100644 --- a/packages/caravan-psbt/src/psbtv2/silentpayment.ts +++ b/packages/caravan-psbt/src/psbtv2/silentpayment.ts @@ -322,65 +322,6 @@ export function isEligibleInputType(type: SPInputScriptType): boolean { ); } - -function hash160(buffer: Buffer): Buffer { - const sha = createHash("sha256").update(buffer).digest(); - return createHash("ripemd160").update(sha).digest(); -} - -/** - * Returns the public key committed to an input's prevout script from a list of - * candidate pubkeys, or null when no candidate matches. This prevents callers - * from using an arbitrary PSBT-provided pubkey for silent-payment DLEQ - * verification and input_hash derivation. - */ -export function getSilentPaymentPubkeyFromInputDescriptor( - input: SPInputDescriptor, - candidatePubkeys: Buffer[], -): Buffer | null { - const scriptPubKey = input.witnessUtxo - ? readWitnessUtxoScript(input.witnessUtxo) - : readNonWitnessUtxoScript(input.nonWitnessUtxo, input.outputIndex); - - if (!scriptPubKey) return null; - - const scriptType = classifyInputDescriptor(input); - - if (scriptType === "p2tr") { - return input.witnessUtxo - ? getTaprootOutputKeyFromWitnessUtxo(input.witnessUtxo) - : null; - } - - for (const pubkey of candidatePubkeys) { - assertValidCompressedPoint(pubkey, "silent payment input pubkey"); - const pubkeyHash = hash160(pubkey); - - if (scriptType === "p2wpkh") { - if (pubkeyHash.equals(scriptPubKey.subarray(2, 22))) return pubkey; - continue; - } - - if (scriptType === "p2pkh_or_unknown_legacy") { - if (pubkeyHash.equals(scriptPubKey.subarray(3, 23))) return pubkey; - continue; - } - - if (scriptType === "p2sh_p2wpkh") { - if (!input.redeemScript) continue; - - const p2shHash = scriptPubKey.subarray(2, 22); - if (!hash160(input.redeemScript).equals(p2shHash)) continue; - if (classifyWitnessScript(input.redeemScript) !== "p2wpkh") continue; - - const redeemWitnessProgram = input.redeemScript.subarray(2, 22); - if (pubkeyHash.equals(redeemWitnessProgram)) return pubkey; - } - } - - return null; -} - /** * Determines which transaction inputs are eligible for silent payment ECDH * derivation per BIP352. @@ -460,15 +401,6 @@ function hash160(buffer: Buffer): Buffer { return createHash("ripemd160").update(sha).digest(); } -/** - * Returns the public key that should contribute to BIP352 derivation for an - * input, but only when it is committed by that input's prevout script. - * - * `candidatePubkeys` may be sourced from PSBT_IN_BIP32_DERIVATION, - * PSBT_IN_PARTIAL_SIG, final script witness, or final scriptSig. This helper - * deliberately treats those as untrusted candidates and validates them against - * the prevout script before returning one. - */ export function getSilentPaymentPubkeyFromInputDescriptor( input: SPInputDescriptor, candidatePubkeys: Buffer[], @@ -477,9 +409,7 @@ export function getSilentPaymentPubkeyFromInputDescriptor( ? readWitnessUtxoScript(input.witnessUtxo) : readNonWitnessUtxoScript(input.nonWitnessUtxo, input.outputIndex); - if (!scriptPubKey) { - return null; - } + if (!scriptPubKey) return null; const scriptType = classifyInputDescriptor(input); @@ -491,49 +421,27 @@ export function getSilentPaymentPubkeyFromInputDescriptor( for (const pubkey of candidatePubkeys) { assertValidCompressedPoint(pubkey, "silent payment input pubkey"); - const pubkeyHash = hash160(pubkey); if (scriptType === "p2wpkh") { - const witnessProgram = scriptPubKey.subarray(2, 22); - - if (pubkeyHash.equals(witnessProgram)) { - return pubkey; - } - + if (pubkeyHash.equals(scriptPubKey.subarray(2, 22))) return pubkey; continue; } if (scriptType === "p2pkh_or_unknown_legacy") { - const scriptPubkeyHash = scriptPubKey.subarray(3, 23); - - if (pubkeyHash.equals(scriptPubkeyHash)) { - return pubkey; - } - + if (pubkeyHash.equals(scriptPubKey.subarray(3, 23))) return pubkey; continue; } if (scriptType === "p2sh_p2wpkh") { - if (!input.redeemScript) { - continue; - } + if (!input.redeemScript) continue; const p2shHash = scriptPubKey.subarray(2, 22); - - if (!hash160(input.redeemScript).equals(p2shHash)) { - continue; - } - - if (classifyWitnessScript(input.redeemScript) !== "p2wpkh") { - continue; - } + if (!hash160(input.redeemScript).equals(p2shHash)) continue; + if (classifyWitnessScript(input.redeemScript) !== "p2wpkh") continue; const redeemWitnessProgram = input.redeemScript.subarray(2, 22); - - if (pubkeyHash.equals(redeemWitnessProgram)) { - return pubkey; - } + if (pubkeyHash.equals(redeemWitnessProgram)) return pubkey; } } From af82d43575ff81627396fb23320e14a03aaced0d Mon Sep 17 00:00:00 2001 From: Jasper van Gelder Date: Wed, 10 Jun 2026 23:41:46 +0200 Subject: [PATCH 22/26] chore(pstv2): Update vectors Even though the version number is lower the tests should be newer. --- .../src/fixtures/bip375_vectors.json | 598 +++++++----------- 1 file changed, 236 insertions(+), 362 deletions(-) diff --git a/packages/caravan-psbt/src/fixtures/bip375_vectors.json b/packages/caravan-psbt/src/fixtures/bip375_vectors.json index 8dd84b3774..48d840027c 100644 --- a/packages/caravan-psbt/src/fixtures/bip375_vectors.json +++ b/packages/caravan-psbt/src/fixtures/bip375_vectors.json @@ -1,50 +1,66 @@ { "description": "BIP-375 Test Vectors", - "version": "1.2.2", + "version": "1.1.2", "notes": [ "Generated by https://github.com/macgyver13/bip375-test-generator/", "Each vector includes: base64-encoded psbt and description", - "Supplementary 'inputs', 'outputs', and 'sp_proofs' are diagnostic and should not be used for validation", - "'checks' overrides the validation sequence, e.g. skip structure checks to test input eligibility", - "'workflows' captures a PSBT step-by-step through the BIP-375 roles; each step is an atomic vector with supplementary scoped to that stage", - "'supplementary.psbt' (workflows) is the incoming PSBT for that step: read it, perform the step's role operation, then match 'expected'", - "'expected.unique_id' (workflows) is the BIP-375 PSBT unique identifier and is invariant across all steps once inputs and outputs are present" + "Supplementary material (hex, inputs, outputs, sp_proofs) is included for diagnostics and should not be used for validation", + "'checks' overrides the validation sequence, e.g. skip structure checks to test input eligibility" ], "invalid": [ { "description": "psbt structure: missing PSBT_OUT_SP_V0_INFO field when PSBT_OUT_SP_V0_LABEL set", - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQDA0MWZ04xLnQHpSq5jI2/aAbRMT5OsRKl39Iml2eMiwwIgfd311m6QKccuNVB0fZJjffaj5C4W9UJpdPi+uF0mIcABAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g907dH3W0uz5ddJwVv9tmNI9oBam01F/u4aLiAfUDu3EBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIGHMBAAAAAAABBCJRIBe/gYp0DI0Tuy5Y5sq4rrsiY8+rt5QENxNV46aiiaG0AQoEAQAAAAA=", - "supplementary": {} + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQDA0MWZ04xLnQHpSq5jI2/aAbRMT5OsRKl39Iml2eMiwwIgfd311m6QKccuNVB0fZJjffaj5C4W9UJpdPi+uF0mIcABAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIGHMBAAAAAAABBCJRIBe/gYp0DI0Tuy5Y5sq4rrsiY8+rt5QENxNV46aiiaG0AQoEAQAAAAA=", + "supplementary": { + "hex": "70736274ff01fb04020000000102040200000001040101010501010106010000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f040000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf483045022100c0d0c599d38c4b9d01e94aae63236fda01b44c4f93ac44a977f489a5d9e322c302207dddf5d66e9029c72e3550747d92637df6a3e42e16f5426974f8beb85d2621c00101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021000103081873010000000000010422512017bf818a740c8d13bb2e58e6cab8aebb2263cfabb79404371355e3a6a289a1b4010a040100000000", + "task": "fail_deserialize" + } }, { "description": "psbt structure: incorrect byte length for PSBT_OUT_SP_V0_INFO field", - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIG9hTKsWyAwmppZy4viq5wvAiLUgLqne/2rOeM2n+2JyAiAQVYeP/VlnUGDrYKAL+jNMnLJB+6EoTBEkkNEA2ex8LgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEgZG9JTKC7m86tFLjbfkxpRFYfryMufMzDa91YaV90kVkBCUECekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84AA=", - "supplementary": {} + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIG9hTKsWyAwmppZy4viq5wvAiLUgLqne/2rOeM2n+2JyAiAQVYeP/VlnUGDrYKAL+jNMnLJB+6EoTBEkkNEA2ex8LgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEgZG9JTKC7m86tFLjbfkxpRFYfryMufMzDa91YaV90kVkBCUECekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84AA=", + "supplementary": { + "hex": "70736274ff01fb04020000000102040200000001040101010501010106010000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f040000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf47304402206f614cab16c80c26a69672e2f8aae70bc088b5202ea9deff6ace78cda7fb627202201055878ffd59675060eb60a00bfa334c9cb241fba1284c112490d100d9ec7c2e0101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee320210001030818730100000000000104225120646f494ca0bb9bcead14b8db7e4c6944561faf232e7cccc36bdd58695f749159010941027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce000", + "task": "fail_deserialize" + } }, { "description": "psbt structure: incorrect byte length for PSBT_IN_SP_ECDH_SHARE field", - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIG9hTKsWyAwmppZy4viq5wvAiLUgLqne/2rOeM2n+2JyAiAQVYeP/VlnUGDrYKAL+jNMnLJB+6EoTBEkkNEA2ex8LgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GggA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QoiHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaECKE7OYVUX3K9bolxSuuQmz41SoQqm7i1bNDt7SHfihmVmLMSKKSeC9fpXOEFP3xbKKy1Q6aHB2AOPOiYIu4yAhAAEDCBhzAQAAAAAAAQQiUSBkb0lMoLubzq0UuNt+TGlEVh+vIy58zMNr3VhpX3SRWQEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", - "supplementary": {} + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIG9hTKsWyAwmppZy4viq5wvAiLUgLqne/2rOeM2n+2JyAiAQVYeP/VlnUGDrYKAL+jNMnLJB+6EoTBEkkNEA2ex8LgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GggA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QoiHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaECKE7OYVUX3K9bolxSuuQmz41SoQqm7i1bNDt7SHfihmVmLMSKKSeC9fpXOEFP3xbKKy1Q6aHB2AOPOiYIu4yAhAAEDCBhzAQAAAAAAAQQiUSBkb0lMoLubzq0UuNt+TGlEVh+vIy58zMNr3VhpX3SRWQEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "supplementary": { + "hex": "70736274ff01fb04020000000102040200000001040101010501010106010000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f040000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf47304402206f614cab16c80c26a69672e2f8aae70bc088b5202ea9deff6ace78cda7fb627202201055878ffd59675060eb60a00bfa334c9cb241fba1284c112490d100d9ec7c2e0101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682003eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee320210001030818730100000000000104225120646f494ca0bb9bcead14b8db7e4c6944561faf232e7cccc36bdd58695f749159010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", + "task": "fail_deserialize" + } }, { "description": "psbt structure: incorrect byte length for PSBT_IN_SP_DLEQ field", - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIG9hTKsWyAwmppZy4viq5wvAiLUgLqne/2rOeM2n+2JyAiAQVYeP/VlnUGDrYKAL+jNMnLJB+6EoTBEkkNEA2ex8LgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4Gg/ihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgAAEDCBhzAQAAAAAAAQQiUSBkb0lMoLubzq0UuNt+TGlEVh+vIy58zMNr3VhpX3SRWQEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", - "supplementary": {} + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIG9hTKsWyAwmppZy4viq5wvAiLUgLqne/2rOeM2n+2JyAiAQVYeP/VlnUGDrYKAL+jNMnLJB+6EoTBEkkNEA2ex8LgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4Gg/ihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgAAEDCBhzAQAAAAAAAQQiUSBkb0lMoLubzq0UuNt+TGlEVh+vIy58zMNr3VhpX3SRWQEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "supplementary": { + "hex": "70736274ff01fb04020000000102040200000001040101010501010106010000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f040000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf47304402206f614cab16c80c26a69672e2f8aae70bc088b5202ea9deff6ace78cda7fb627202201055878ffd59675060eb60a00bfa334c9cb241fba1284c112490d100d9ec7c2e0101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0683f8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee3200001030818730100000000000104225120646f494ca0bb9bcead14b8db7e4c6944561faf232e7cccc36bdd58695f749159010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", + "task": "fail_deserialize" + } }, { "description": "psbt structure: PSBT_GLOBAL_TX_MODIFIABLE field is non-zero when PSBT_OUT_SCRIPT set for sp output", - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEBAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIG9hTKsWyAwmppZy4viq5wvAiLUgLqne/2rOeM2n+2JyAiAQVYeP/VlnUGDrYKAL+jNMnLJB+6EoTBEkkNEA2ex8LgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEgZG9JTKC7m86tFLjbfkxpRFYfryMufMzDa91YaV90kVkBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", - "supplementary": {} + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAQABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIG9hTKsWyAwmppZy4viq5wvAiLUgLqne/2rOeM2n+2JyAiAQVYeP/VlnUGDrYKAL+jNMnLJB+6EoTBEkkNEA2ex8LgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEgZG9JTKC7m86tFLjbfkxpRFYfryMufMzDa91YaV90kVkBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "supplementary": { + "hex": "70736274ff01fb04020000000102040200000001040101010501010106010100010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f040000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf47304402206f614cab16c80c26a69672e2f8aae70bc088b5202ea9deff6ace78cda7fb627202201055878ffd59675060eb60a00bfa334c9cb241fba1284c112490d100d9ec7c2e0101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee320210001030818730100000000000104225120646f494ca0bb9bcead14b8db7e4c6944561faf232e7cccc36bdd58695f749159010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", + "task": "fail_sign" + } }, { "description": "psbt structure: missing PSBT_OUT_SCRIPT field when sending to non-sp output", - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9GMEMCHwfXEdsnLfzEuix6A+aihT1VxR5DeSoM+sSpV9cRhBsCIENgnob+SDV1lgnI3tO4nBZ5YcOpGfobJDWSa7Km/n7yAQEDBAEAAAAiBgLIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvwgAAACAAAAAAAEOIPdO3R91tLs+XXScFb/bZjSPaAWptNRf7uGi4gH1A7txAQ8EAAAAAAEQBP7///8iHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCED7KT/Ebco4uD2DOYiKUOm/1W52V9ie/mpnQhLyHLVClsiHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaECKE7OYVUX3K9bolxSuuQmz41SoQqm7i1bNDt7SHfihmVmLMSKKSeC9fpXOEFP3xbKKy1Q6aHB2AOPOiYIu4yAhAAEDCBhzAQAAAAAAAA==", - "supplementary": {} + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9GMEMCHwfXEdsnLfzEuix6A+aihT1VxR5DeSoM+sSpV9cRhBsCIENgnob+SDV1lgnI3tO4nBZ5YcOpGfobJDWSa7Km/n7yAQEDBAEAAAAiBgLIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvwgAAACAAAAAAAEQBP7///8iHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCED7KT/Ebco4uD2DOYiKUOm/1W52V9ie/mpnQhLyHLVClsiHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaECKE7OYVUX3K9bolxSuuQmz41SoQqm7i1bNDt7SHfihmVmLMSKKSeC9fpXOEFP3xbKKy1Q6aHB2AOPOiYIu4yAhAAEDCBhzAQAAAAAAAA==", + "supplementary": { + "hex": "70736274ff01fb04020000000102040200000001040101010501010106010000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f040000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf463043021f07d711db272dfcc4ba2c7a03e6a2853d55c51e43792a0cfac4a957d711841b022043609e86fe4835759609c8ded3b89c167961c3a919fa1b2435926bb2a6fe7ef20101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee3202100010308187301000000000000", + "task": "fail_deserialize" + } }, { "description": "ecdh coverage: only one ineligible P2SH multisig input when PSBT_OUT_SCRIPT set for sp output", - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAFMCAAAAAXyoMfPUiQn+aMsOqqoR+Hc97n6McwhTN1kOJLsGOQ20AAAAAAD/////AaCGAQAAAAAAF6kU2OZohxTu7Qqi7dSJqhyjwXFwHk2HAAAAAAEER1IhAr5Ar99ismPLfe4rmF0cOP5BsZlNKwUHU0PRcsIY6rHEIQJ6R5JT0AogWhCpQ483IBm582TgqDaAC/g529KOfOa5VVKuAQ4gzTgaRVCP49nKtjt+D3BKD1adv9VamBAtnqM67mIbdfQBDwQAAAAAARAE/v///wABAwiQXwEAAAAAAAEEIlEgzeOdiwW0lvjxjyCyfQr5oyMzCeBHIhnggT/ztdN4fikBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiDNOBpFUI/j2cq2O34PcEoPVp2/1VqYEC2eozruYht19AEPBAAAAAABAFMCAAAAAXyoMfPUiQn+aMsOqqoR+Hc97n6McwhTN1kOJLsGOQ20AAAAAAD/////AaCGAQAAAAAAF6kU2OZohxTu7Qqi7dSJqhyjwXFwHk2HAAAAAAEER1IhAr5Ar99ismPLfe4rmF0cOP5BsZlNKwUHU0PRcsIY6rHEIQJ6R5JT0AogWhCpQ483IBm582TgqDaAC/g529KOfOa5VVKuARAE/v///wABAwiQXwEAAAAAAAEEIlEgzeOdiwW0lvjxjyCyfQr5oyMzCeBHIhnggT/ztdN4fikBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", "supplementary": { + "hex": "70736274ff01fb04020000000102040200000001040101010501010106010000010e20cd381a45508fe3d9cab63b7e0f704a0f569dbfd55a98102d9ea33aee621b75f4010f040000000001005302000000017ca831f3d48909fe68cb0eaaaa11f8773dee7e8c73085337590e24bb06390db40000000000ffffffff01a08601000000000017a914d8e6688714eeed0aa2edd489aa1ca3c171701e4d8700000000010447522102be40afdf62b263cb7dee2b985d1c38fe41b1994d2b05075343d172c218eab1c421027a479253d00a205a10a9438f372019b9f364e0a836800bf839dbd28e7ce6b95552ae011004feffffff00010308905f0100000000000104225120cde39d8b05b496f8f18f20b27d0af9a3233309e0472219e0813ff3b5d3787e29010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, @@ -57,13 +73,15 @@ "sequence": 4294967294, "signed": false } - ] + ], + "task": "fail_sign" } }, { "description": "ecdh coverage: missing PSBT_IN_SP_ECDH_SHARE field for input 0 when PSBT_OUT_SCRIPT set for sp output", - "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABEAT+////AAEBHxAnAAAAAAAAFgAUNyH6c8IwXLL4joSJLWvWuXcmHmoBAwQBAAAAIgYCQ6DUDp3giCeUFhdSuuQrqQlSeEIJ8GNDDwryVjVKhbsIAAAAgAEAAAABDiCT02M2J+tY6dwwP275yxvoDBZhNzq+im1o30frVfCaGwEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghAuV6etywGNj7MVToDBS5elCZS0I1aEHqn8ExcGFEAOY3Ih4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhA9/o4HeILO0WcbkJsYhPUF1MI8kgqROMyhCMmJNTa/Vcymb868WqzAsViY2OjfUSHB/fnoevqBke8zUhiA7srpgABAwgYcwEAAAAAAAEEIlEgzeOdiwW0lvjxjyCyfQr5oyMzCeBHIhnggT/ztdN4fikBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEBAQYBAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////AAEOIJPTYzYn61jp3DA/bvnLG+gMFmE3Or6KbWjfR+tV8JobAQ8EAAAAAAEBHxAnAAAAAAAAFgAUNyH6c8IwXLL4joSJLWvWuXcmHmoBAwQBAAAAIgYCQ6DUDp3giCeUFhdSuuQrqQlSeEIJ8GNDDwryVjVKhbsIAAAAgAEAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghAuV6etywGNj7MVToDBS5elCZS0I1aEHqn8ExcGFEAOY3Ih4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhA9/o4HeILO0WcbkJsYhPUF1MI8kgqROMyhCMmJNTa/Vcymb868WqzAsViY2OjfUSHB/fnoevqBke8zUhiA7srpgABAwgYcwEAAAAAAAEEIlEgzeOdiwW0lvjxjyCyfQr5oyMzCeBHIhnggT/ztdN4fikBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", "supplementary": { + "hex": "70736274ff01fb04020000000102040200000001040102010501010106010000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f040000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000011004feffffff00010e2093d3633627eb58e9dc303f6ef9cb1be80c1661373abe8a6d68df47eb55f09a1b010f040000000001011f10270000000000001600143721fa73c2305cb2f88e84892d6bd6b977261e6a0103040100000022060243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb080000008001000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682102e57a7adcb018d8fb3154e80c14b97a50994b42356841ea9fc13170614400e637221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe06840f7fa381de20b3b459c6e426c6213d4175308f2482a44e33284232624d4dafd573299bf3af16ab302c5626363a37d448707f7e7a1ebea0647bccd486203bb2ba60001030818730100000000000104225120cde39d8b05b496f8f18f20b27d0af9a3233309e0472219e0813ff3b5d3787e29010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, @@ -97,13 +115,15 @@ "dleq_proof": "f7fa381de20b3b459c6e426c6213d4175308f2482a44e33284232624d4dafd573299bf3af16ab302c5626363a37d448707f7e7a1ebea0647bccd486203bb2ba6", "input_index": 1 } - ] + ], + "task": "fail_sign" } }, { "description": "ecdh coverage: missing PSBT_IN_SP_DLEQ field for input when PSBT_IN_SP_ECDH_SHARE set", - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIG9hTKsWyAwmppZy4viq5wvAiLUgLqne/2rOeM2n+2JyAiAQVYeP/VlnUGDrYKAL+jNMnLJB+6EoTBEkkNEA2ex8LgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbAAEDCBhzAQAAAAAAAQQiUSBkb0lMoLubzq0UuNt+TGlEVh+vIy58zMNr3VhpX3SRWQEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIG9hTKsWyAwmppZy4viq5wvAiLUgLqne/2rOeM2n+2JyAiAQVYeP/VlnUGDrYKAL+jNMnLJB+6EoTBEkkNEA2ex8LgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbAAEDCBhzAQAAAAAAAQQiUSBkb0lMoLubzq0UuNt+TGlEVh+vIy58zMNr3VhpX3SRWQEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", "supplementary": { + "hex": "70736274ff01fb04020000000102040200000001040101010501010106010000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f040000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf47304402206f614cab16c80c26a69672e2f8aae70bc088b5202ea9deff6ace78cda7fb627202201055878ffd59675060eb60a00bfa334c9cb241fba1284c112490d100d9ec7c2e0101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b0001030818730100000000000104225120646f494ca0bb9bcead14b8db7e4c6944561faf232e7cccc36bdd58695f749159010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, @@ -125,13 +145,15 @@ "dleq_proof": null, "input_index": 0 } - ] + ], + "task": "fail_deserialize" } }, { "description": "ecdh coverage: missing PSBT_GLOBAL_SP_DLEQ field when PSBT_GLOBAL_SP_ECDH_SHARE set", - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAIgcCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIG9hTKsWyAwmppZy4viq5wvAiLUgLqne/2rOeM2n+2JyAiAQVYeP/VlnUGDrYKAL+jNMnLJB+6EoTBEkkNEA2ex8LgEiBgLIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvwgAAACAAAAAAAEOIPdO3R91tLs+XXScFb/bZjSPaAWptNRf7uGi4gH1A7txAQ8EAAAAAAEQBP7///8AAQMIGHMBAAAAAAABBCJRIGRvSUygu5vOrRS4235MaURWH68jLnzMw2vdWGlfdJFZAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBACIHAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWwABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIG9hTKsWyAwmppZy4viq5wvAiLUgLqne/2rOeM2n+2JyAiAQVYeP/VlnUGDrYKAL+jNMnLJB+6EoTBEkkNEA2ex8LgEiBgLIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvwgAAACAAAAAAAEQBP7///8AAQMIGHMBAAAAAAABBCJRIGRvSUygu5vOrRS4235MaURWH68jLnzMw2vdWGlfdJFZAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", "supplementary": { + "hex": "70736274ff01fb0402000000010204020000000104010101050101010601002207027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b00010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f040000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf47304402206f614cab16c80c26a69672e2f8aae70bc088b5202ea9deff6ace78cda7fb627202201055878ffd59675060eb60a00bfa334c9cb241fba1284c112490d100d9ec7c2e01220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000011004feffffff0001030818730100000000000104225120646f494ca0bb9bcead14b8db7e4c6944561faf232e7cccc36bdd58695f749159010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, @@ -151,13 +173,15 @@ "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b" } - ] + ], + "task": "fail_deserialize" } }, { "description": "ecdh coverage: invalid proof in PSBT_IN_SP_DLEQ field", - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIG9hTKsWyAwmppZy4viq5wvAiLUgLqne/2rOeM2n+2JyAiAQVYeP/VlnUGDrYKAL+jNMnLJB+6EoTBEkkNEA2ex8LgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAbvHreDwFl9ZoVl4787j95b7SgVKV9D4XAVEk1EXcy9rdKkne51lhePEhbl1NuRdP/dpjNON8kDEQjAjOE3TeDwABAwgYcwEAAAAAAAEEIlEgZG9JTKC7m86tFLjbfkxpRFYfryMufMzDa91YaV90kVkBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIG9hTKsWyAwmppZy4viq5wvAiLUgLqne/2rOeM2n+2JyAiAQVYeP/VlnUGDrYKAL+jNMnLJB+6EoTBEkkNEA2ex8LgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAbvHreDwFl9ZoVl4787j95b7SgVKV9D4XAVEk1EXcy9rdKkne51lhePEhbl1NuRdP/dpjNON8kDEQjAjOE3TeDwABAwgYcwEAAAAAAAEEIlEgZG9JTKC7m86tFLjbfkxpRFYfryMufMzDa91YaV90kVkBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", "supplementary": { + "hex": "70736274ff01fb04020000000102040200000001040101010501010106010000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f040000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf47304402206f614cab16c80c26a69672e2f8aae70bc088b5202ea9deff6ace78cda7fb627202201055878ffd59675060eb60a00bfa334c9cb241fba1284c112490d100d9ec7c2e0101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068406ef1eb783c0597d668565e3bf3b8fde5bed2815295f43e17015124d445dccbdadd2a49dee7596178f1216e5d4db9174ffdda6334e37c9031108c08ce1374de0f0001030818730100000000000104225120646f494ca0bb9bcead14b8db7e4c6944561faf232e7cccc36bdd58695f749159010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, @@ -179,13 +203,15 @@ "dleq_proof": "6ef1eb783c0597d668565e3bf3b8fde5bed2815295f43e17015124d445dccbdadd2a49dee7596178f1216e5d4db9174ffdda6334e37c9031108c08ce1374de0f", "input_index": 0 } - ] + ], + "task": "fail_sign" } }, { "description": "ecdh coverage: invalid proof in PSBT_GLOBAL_SP_DLEQ field", - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAIgcCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIggCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhA58j9RCuU2IoqaiyStDRkj6AHyf4IBHKjN4DQtSMoRNCb2Is/7obRLUOGxGV/u3heLS8Uv8+RhXQ/4SrIJQ+V2QH7BAIAAAAAAQEfoIYBAAAAAAAWABQeKteHLTKUE6Vt8JaL4zgiJ4MWOyICAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/RzBEAiBvYUyrFsgMJqaWcuL4qucLwIi1IC6p3v9qznjNp/ticgIgEFWHj/1ZZ1Bg62CgC/ozTJyyQfuhKEwRJJDRANnsfC4BIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABEAT+////AAEDCBhzAQAAAAAAAQQiUSBkb0lMoLubzq0UuNt+TGlEVh+vIy58zMNr3VhpX3SRWQEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBACIHAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIIAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQOfI/UQrlNiKKmoskrQ0ZI+gB8n+CARyozeA0LUjKETQm9iLP+6G0S1DhsRlf7t4Xi0vFL/PkYV0P+EqyCUPldkAAQ4g907dH3W0uz5ddJwVv9tmNI9oBam01F/u4aLiAfUDu3EBDwQAAAAAAQEfoIYBAAAAAAAWABQeKteHLTKUE6Vt8JaL4zgiJ4MWOyICAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/RzBEAiBvYUyrFsgMJqaWcuL4qucLwIi1IC6p3v9qznjNp/ticgIgEFWHj/1ZZ1Bg62CgC/ozTJyyQfuhKEwRJJDRANnsfC4BIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////AAEDCBhzAQAAAAAAAQQiUSBkb0lMoLubzq0UuNt+TGlEVh+vIy58zMNr3VhpX3SRWQEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", "supplementary": { + "hex": "70736274ff01fb0402000000010204020000000104010101050101010601002207027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b2208027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe06840e7c8fd442b94d88a2a6a2c92b434648fa007c9fe080472a33780d0b5232844d09bd88b3fee86d12d4386c4657fbb785e2d2f14bfcf9185743fe12ac8250f95d900010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f040000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf47304402206f614cab16c80c26a69672e2f8aae70bc088b5202ea9deff6ace78cda7fb627202201055878ffd59675060eb60a00bfa334c9cb241fba1284c112490d100d9ec7c2e01220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000011004feffffff0001030818730100000000000104225120646f494ca0bb9bcead14b8db7e4c6944561faf232e7cccc36bdd58695f749159010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, @@ -206,13 +232,15 @@ "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", "dleq_proof": "2430479d2da1310a024d2aab8e4c7b49d76cd51f45ee8127c159b0393a675b6f75c581ebe3d0817ddaf3bb598cfd7a022f1a87ed479664f6b947a47db5941cb2" } - ] + ], + "task": "fail_sign" } }, { "description": "ecdh coverage: missing PSBT_IN_BIP32_DERIVATION field for input when PSBT_IN_SP_DLEQ set", - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIG9hTKsWyAwmppZy4viq5wvAiLUgLqne/2rOeM2n+2JyAiAQVYeP/VlnUGDrYKAL+jNMnLJB+6EoTBEkkNEA2ex8LgEBAwQBAAAAAQ4g907dH3W0uz5ddJwVv9tmNI9oBam01F/u4aLiAfUDu3EBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIGHMBAAAAAAABBCJRIGRvSUygu5vOrRS4235MaURWH68jLnzMw2vdWGlfdJFZAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7AQMEAQAAAAEQBP7///8iHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCED7KT/Ebco4uD2DOYiKUOm/1W52V9ie/mpnQhLyHLVClsiHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaECKE7OYVUX3K9bolxSuuQmz41SoQqm7i1bNDt7SHfihmVmLMSKKSeC9fpXOEFP3xbKKy1Q6aHB2AOPOiYIu4yAhAAEDCBhzAQAAAAAAAQQiUSBkb0lMoLubzq0UuNt+TGlEVh+vIy58zMNr3VhpX3SRWQEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", "supplementary": { + "hex": "70736274ff01fb04020000000102040200000001040101010501010106010000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f040000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b01030401000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee320210001030818730100000000000104225120646f494ca0bb9bcead14b8db7e4c6944561faf232e7cccc36bdd58695f749159010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, @@ -224,7 +252,7 @@ "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, - "signed": true + "signed": false } ], "sp_proofs": [ @@ -234,13 +262,15 @@ "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", "input_index": 0 } - ] + ], + "task": "fail_sign" } }, { "description": "ecdh coverage: output 1 missing ECDH share for scan key with one input / three sp outputs (different scan keys)", - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQMBBgEAAfsEAgAAAAABAR9ADQMAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7AQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g/S309Ytav5uR/xoeQ+LjUj9QxqoZ1cIjYBQexIyagCEBDwQAAAAAARAE/v///yIdArlFYVfpRu8H90tU+gm+Sn6Tjcr7+ye0s3LFc8BZ8SqwIQLChkR0sISqyB9uMKxe30ZnOTzmBNgI0/SZoJhOi1JJdCIdA2UdLAc/ywKk2C3aU/HVAdd6A1BmZ5hUZHOyEmts0afeIQN2iSMnxOeAru7UzhvJK7ASK3t5ENlvCtUUi0lvnD6S+yIeArlFYVfpRu8H90tU+gm+Sn6Tjcr7+ye0s3LFc8BZ8SqwQPCxHVHD/ROzjgpsjvwu4Mpxdzr2dLMVHmiSFJJcS1fIFojJ4Hi3UIhabKsoa1d+k6JJfrSWNrGvG2vILnyRElEiHgNlHSwHP8sCpNgt2lPx1QHXegNQZmeYVGRzshJrbNGn3kCY8UrEWvZFmrDITUfaU2TPsUT/kL2scy+cq8bbAA3PGpXjsx97cKBCmKUbb9RRbIHXFsmVT4rxDD1ZgJruK704AAEDCJBfAQAAAAAAAQQiUSBg9n1lOOjDNhoPtXryD47AzuIAMtDb3yc6UykBnOW/TgEJQgNlHSwHP8sCpNgt2lPx1QHXegNQZmeYVGRzshJrbNGn3gPycOClYyGDtqsBB06HfmgA2wD1x8XS+vu2j5wo1IVFJAABAwgQJwAAAAAAAAEEIlEgzeOdiwW0lvjxjyCyfQr5oyMzCeBHIhnggT/ztdN4fikBCUIDUteMQTkAMq2RgWppf8dA2OuQnPBNcIhSZLBR8jheJewC4MTBh7chX5l8hIWnW0WRtsKEd7laESO5lpItMVSGC/gAAQMIIE4AAAAAAAABBCJRIM//VLPkWViKpOGXLVboPI42pZ2WjLKZ3vuvBMJDlKnuAQlCArlFYVfpRu8H90tU+gm+Sn6Tjcr7+ye0s3LFc8BZ8SqwAhJoHj8J6uOKjy8/7NfdVvxYbPoCjoqzP3KpD4QKbSJcAA==", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEDAQYBAAABDiD9LfT1i1q/m5H/Gh5D4uNSP1DGqhnVwiNgFB7EjJqAIQEPBAAAAAABAR9ADQMAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7AQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdArlFYVfpRu8H90tU+gm+Sn6Tjcr7+ye0s3LFc8BZ8SqwIQLChkR0sISqyB9uMKxe30ZnOTzmBNgI0/SZoJhOi1JJdCIdA2UdLAc/ywKk2C3aU/HVAdd6A1BmZ5hUZHOyEmts0afeIQN2iSMnxOeAru7UzhvJK7ASK3t5ENlvCtUUi0lvnD6S+yIeArlFYVfpRu8H90tU+gm+Sn6Tjcr7+ye0s3LFc8BZ8SqwQPCxHVHD/ROzjgpsjvwu4Mpxdzr2dLMVHmiSFJJcS1fIFojJ4Hi3UIhabKsoa1d+k6JJfrSWNrGvG2vILnyRElEiHgNlHSwHP8sCpNgt2lPx1QHXegNQZmeYVGRzshJrbNGn3kCY8UrEWvZFmrDITUfaU2TPsUT/kL2scy+cq8bbAA3PGpXjsx97cKBCmKUbb9RRbIHXFsmVT4rxDD1ZgJruK704AAEDCJBfAQAAAAAAAQQiUSBg9n1lOOjDNhoPtXryD47AzuIAMtDb3yc6UykBnOW/TgEJQgNlHSwHP8sCpNgt2lPx1QHXegNQZmeYVGRzshJrbNGn3gPycOClYyGDtqsBB06HfmgA2wD1x8XS+vu2j5wo1IVFJAABAwgQJwAAAAAAAAEEIlEgzeOdiwW0lvjxjyCyfQr5oyMzCeBHIhnggT/ztdN4fikBCUIDUteMQTkAMq2RgWppf8dA2OuQnPBNcIhSZLBR8jheJewC4MTBh7chX5l8hIWnW0WRtsKEd7laESO5lpItMVSGC/gAAQMIIE4AAAAAAAABBCJRIM//VLPkWViKpOGXLVboPI42pZ2WjLKZ3vuvBMJDlKnuAQlCArlFYVfpRu8H90tU+gm+Sn6Tjcr7+ye0s3LFc8BZ8SqwAhJoHj8J6uOKjy8/7NfdVvxYbPoCjoqzP3KpD4QKbSJcAA==", "supplementary": { + "hex": "70736274ff01fb04020000000102040200000001040101010501030106010000010e20fd2df4f58b5abf9b91ff1a1e43e2e3523f50c6aa19d5c22360141ec48c9a8021010f040000000001011f400d0300000000001600141e2ad7872d329413a56df0968be338222783163b01030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000011004feffffff221d02b9456157e946ef07f74b54fa09be4a7e938dcafbfb27b4b372c573c059f12ab02102c2864474b084aac81f6e30ac5edf4667393ce604d808d3f499a0984e8b524974221d03651d2c073fcb02a4d82dda53f1d501d77a0350666798546473b2126b6cd1a7de210376892327c4e780aeeed4ce1bc92bb0122b7b7910d96f0ad5148b496f9c3e92fb221e02b9456157e946ef07f74b54fa09be4a7e938dcafbfb27b4b372c573c059f12ab040f0b11d51c3fd13b38e0a6c8efc2ee0ca71773af674b3151e689214925c4b57c81688c9e078b750885a6cab286b577e93a2497eb49636b1af1b6bc82e7c911251221e03651d2c073fcb02a4d82dda53f1d501d77a0350666798546473b2126b6cd1a7de4098f14ac45af6459ab0c84d47da5364cfb144ff90bdac732f9cabc6db000dcf1a95e3b31f7b70a04298a51b6fd4516c81d716c9954f8af10c3d59809aee2bbd3800010308905f010000000000010422512060f67d6538e8c3361a0fb57af20f8ec0cee20032d0dbdf273a5329019ce5bf4e01094203651d2c073fcb02a4d82dda53f1d501d77a0350666798546473b2126b6cd1a7de03f270e0a5632183b6ab01074e877e6800db00f5c7c5d2fafbb68f9c28d48545240001030810270000000000000104225120cde39d8b05b496f8f18f20b27d0af9a3233309e0472219e0813ff3b5d3787e290109420352d78c41390032ad91816a697fc740d8eb909cf04d70885264b051f2385e25ec02e0c4c187b7215f997c8485a75b4591b6c28477b95a1123b996922d3154860bf800010308204e0000000000000104225120cfff54b3e459588aa4e1972d56e83c8e36a59d968cb299defbaf04c24394a9ee01094202b9456157e946ef07f74b54fa09be4a7e938dcafbfb27b4b372c573c059f12ab00212681e3f09eae38a8f2f3fecd7dd56fc586cfa028e8ab33f72a90f840a6d225c00", "inputs": [ { "input_index": 0, @@ -268,13 +298,15 @@ "dleq_proof": "f0b11d51c3fd13b38e0a6c8efc2ee0ca71773af674b3151e689214925c4b57c81688c9e078b750885a6cab286b577e93a2497eb49636b1af1b6bc82e7c911251", "input_index": 0 } - ] + ], + "task": "fail_sign" } }, { "description": "ecdh coverage: input 1 missing ECDH share for output 1 with two inputs / two sp outputs (different scan keys)", - "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQIBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7AQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g907dH3W0uz5ddJwVv9tmNI9oBam01F/u4aLiAfUDu3EBDwQAAAAAARAE/v///yIdA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsIQMJH9SAORd/RNe3npYWiEnGLrP4eADEZ2fFCo84+Y79FSIdA2UdLAc/ywKk2C3aU/HVAdd6A1BmZ5hUZHOyEmts0afeIQN2iSMnxOeAru7UzhvJK7ASK3t5ENlvCtUUi0lvnD6S+yIeA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsQL4acjrvVeiYG5lZmpvBKzj4froBWMxwZokPImnK3kY7dzQal9KScZZNAcAkHMMi/VOQwpuZFg+CbzKTZYmMvwIiHgNlHSwHP8sCpNgt2lPx1QHXegNQZmeYVGRzshJrbNGn3kCY8UrEWvZFmrDITUfaU2TPsUT/kL2scy+cq8bbAA3PGpXjsx97cKBCmKUbb9RRbIHXFsmVT4rxDD1ZgJruK704AAEBH6CGAQAAAAAAFgAUNyH6c8IwXLL4joSJLWvWuXcmHmoBAwQBAAAAIgYCQ6DUDp3giCeUFhdSuuQrqQlSeEIJ8GNDDwryVjVKhbsIAAAAgAEAAAABDiDnbAFxCDpMX7Sv4vbWHwCkcwG50B+NLkd4CrdULjd8CAEPBAAAAAABEAT+////Ih0DZR0sBz/LAqTYLdpT8dUB13oDUGZnmFRkc7ISa2zRp94hAnUEQAf+LQMNV3wymRzyo+deU1BCRbPL5bMFOufF8iBaIh4DZR0sBz/LAqTYLdpT8dUB13oDUGZnmFRkc7ISa2zRp95AOLnjgGtJvr7vxs7gZcKwZv2wCuzs8ei1sqr0fPBBeyma4KJW7Xy2yCcC63E31zv1eSccQoTQBuO1nXCpuWfYiQABAwiQXwEAAAAAAAEEIlEgUYxvb4GbCpCxtzrI2r6I+6L7jU21kKWeh5y2htZLPwoBCUIDZR0sBz/LAqTYLdpT8dUB13oDUGZnmFRkc7ISa2zRp94D8nDgpWMhg7arAQdOh35oANsA9cfF0vr7to+cKNSFRSQAAQMIkF8BAAAAAAABBCJRIJPCrCoXvlxLW2ZvyHz2ESYroSl4aKSY4YV32/tFpEJwAQlCA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsAuDEwYe3IV+ZfISFp1tFkbbChHe5WhEjuZaSLTFUhgv4AA==", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQECAQYBAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7AQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsIQMJH9SAORd/RNe3npYWiEnGLrP4eADEZ2fFCo84+Y79FSIdA2UdLAc/ywKk2C3aU/HVAdd6A1BmZ5hUZHOyEmts0afeIQN2iSMnxOeAru7UzhvJK7ASK3t5ENlvCtUUi0lvnD6S+yIeA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsQL4acjrvVeiYG5lZmpvBKzj4froBWMxwZokPImnK3kY7dzQal9KScZZNAcAkHMMi/VOQwpuZFg+CbzKTZYmMvwIiHgNlHSwHP8sCpNgt2lPx1QHXegNQZmeYVGRzshJrbNGn3kCY8UrEWvZFmrDITUfaU2TPsUT/kL2scy+cq8bbAA3PGpXjsx97cKBCmKUbb9RRbIHXFsmVT4rxDD1ZgJruK704AAEOIOdsAXEIOkxftK/i9tYfAKRzAbnQH40uR3gKt1QuN3wIAQ8EAAAAAAEBH6CGAQAAAAAAFgAUNyH6c8IwXLL4joSJLWvWuXcmHmoBAwQBAAAAIgYCQ6DUDp3giCeUFhdSuuQrqQlSeEIJ8GNDDwryVjVKhbsIAAAAgAEAAAABEAT+////Ih0DZR0sBz/LAqTYLdpT8dUB13oDUGZnmFRkc7ISa2zRp94hAnUEQAf+LQMNV3wymRzyo+deU1BCRbPL5bMFOufF8iBaIh4DZR0sBz/LAqTYLdpT8dUB13oDUGZnmFRkc7ISa2zRp95AOLnjgGtJvr7vxs7gZcKwZv2wCuzs8ei1sqr0fPBBeyma4KJW7Xy2yCcC63E31zv1eSccQoTQBuO1nXCpuWfYiQABAwiQXwEAAAAAAAEEIlEgUYxvb4GbCpCxtzrI2r6I+6L7jU21kKWeh5y2htZLPwoBCUIDZR0sBz/LAqTYLdpT8dUB13oDUGZnmFRkc7ISa2zRp94D8nDgpWMhg7arAQdOh35oANsA9cfF0vr7to+cKNSFRSQAAQMIkF8BAAAAAAABBCJRIJPCrCoXvlxLW2ZvyHz2ESYroSl4aKSY4YV32/tFpEJwAQlCA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsAuDEwYe3IV+ZfISFp1tFkbbChHe5WhEjuZaSLTFUhgv4AA==", "supplementary": { + "hex": "70736274ff01fb04020000000102040200000001040102010501020106010000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f040000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b01030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000011004feffffff221d0352d78c41390032ad91816a697fc740d8eb909cf04d70885264b051f2385e25ec2103091fd48039177f44d7b79e96168849c62eb3f87800c46767c50a8f38f98efd15221d03651d2c073fcb02a4d82dda53f1d501d77a0350666798546473b2126b6cd1a7de210376892327c4e780aeeed4ce1bc92bb0122b7b7910d96f0ad5148b496f9c3e92fb221e0352d78c41390032ad91816a697fc740d8eb909cf04d70885264b051f2385e25ec40be1a723aef55e8981b99599a9bc12b38f87eba0158cc7066890f2269cade463b77341a97d29271964d01c0241cc322fd5390c29b99160f826f329365898cbf02221e03651d2c073fcb02a4d82dda53f1d501d77a0350666798546473b2126b6cd1a7de4098f14ac45af6459ab0c84d47da5364cfb144ff90bdac732f9cabc6db000dcf1a95e3b31f7b70a04298a51b6fd4516c81d716c9954f8af10c3d59809aee2bbd3800010e20e76c0171083a4c5fb4afe2f6d61f00a47301b9d01f8d2e47780ab7542e377c08010f040000000001011fa0860100000000001600143721fa73c2305cb2f88e84892d6bd6b977261e6a0103040100000022060243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb080000008001000000011004feffffff221d03651d2c073fcb02a4d82dda53f1d501d77a0350666798546473b2126b6cd1a7de210275044007fe2d030d577c32991cf2a3e75e53504245b3cbe5b3053ae7c5f2205a221e03651d2c073fcb02a4d82dda53f1d501d77a0350666798546473b2126b6cd1a7de4038b9e3806b49bebeefc6cee065c2b066fdb00aececf1e8b5b2aaf47cf0417b299ae0a256ed7cb6c82702eb7137d73bf579271c4284d006e3b59d70a9b967d88900010308905f0100000000000104225120518c6f6f819b0a90b1b73ac8dabe88fba2fb8d4db590a59e879cb686d64b3f0a01094203651d2c073fcb02a4d82dda53f1d501d77a0350666798546473b2126b6cd1a7de03f270e0a5632183b6ab01074e877e6800db00f5c7c5d2fafbb68f9c28d485452400010308905f010000000000010422512093c2ac2a17be5c4b5b666fc87cf611262ba1297868a498e18577dbfb45a442700109420352d78c41390032ad91816a697fc740d8eb909cf04d70885264b051f2385e25ec02e0c4c187b7215f997c8485a75b4591b6c28477b95a1123b996922d3154860bf800", "inputs": [ { "input_index": 0, @@ -320,13 +352,15 @@ "dleq_proof": "38b9e3806b49bebeefc6cee065c2b066fdb00aececf1e8b5b2aaf47cf0417b299ae0a256ed7cb6c82702eb7137d73bf579271c4284d006e3b59d70a9b967d889", "input_index": 1 } - ] + ], + "task": "fail_sign" } }, { "description": "ecdh coverage: input 1 missing ECDH share for scan key with two inputs / one sp output", - "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAAfsEAgAAAAABAR9QwwAAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7AQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g6xHhra18MFGah0Q1Mm7jehlliBwKVcouqa/tQZZIthYBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQEfUMMAAAAAAAAWABQ3IfpzwjBcsviOhIkta9a5dyYeaiIGAkOg1A6d4IgnlBYXUrrkK6kJUnhCCfBjQw8K8lY1SoW7CAAAAIABAAAAAQ4g245T4MzJHLEs15uROavlPi9D3Liqq6r37/AsHsiwHCgBDwQAAAAAARAE/v///wABAwgYcwEAAAAAAAEEIlEgzeOdiwW0lvjxjyCyfQr5oyMzCeBHIhnggT/ztdN4fikBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEBAQYBAAABDiDrEeGtrXwwUZqHRDUybuN6GWWIHApVyi6pr+1Blki2FgEPBAAAAAABAR9QwwAAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7AQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQ4g245T4MzJHLEs15uROavlPi9D3Liqq6r37/AsHsiwHCgBDwQAAAAAAQEfUMMAAAAAAAAWABQ3IfpzwjBcsviOhIkta9a5dyYeaiIGAkOg1A6d4IgnlBYXUrrkK6kJUnhCCfBjQw8K8lY1SoW7CAAAAIABAAAAARAE/v///wABAwgYcwEAAAAAAAEEIlEgzeOdiwW0lvjxjyCyfQr5oyMzCeBHIhnggT/ztdN4fikBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", "supplementary": { + "hex": "70736274ff01fb04020000000102040200000001040102010501010106010000010e20eb11e1adad7c30519a874435326ee37a1965881c0a55ca2ea9afed419648b616010f040000000001011f50c30000000000001600141e2ad7872d329413a56df0968be338222783163b01030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee3202100010e20db8e53e0ccc91cb12cd79b9139abe53e2f43dcb8aaabaaf7eff02c1ec8b01c28010f040000000001011f50c30000000000001600143721fa73c2305cb2f88e84892d6bd6b977261e6a22060243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb080000008001000000011004feffffff0001030818730100000000000104225120cde39d8b05b496f8f18f20b27d0af9a3233309e0472219e0813ff3b5d3787e29010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, @@ -360,13 +394,15 @@ "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", "input_index": 0 } - ] + ], + "task": "fail_sign" } }, { "description": "input eligibility: segwit version greater than 1 in transaction inputs with sp output", - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABZSFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQD/G0d7SFEcnvURdIK0VbinRBzrmgXCDZ4gwhD+Z4IEJAIgJ32Cr+1Q28AA/sbFs+Rp61l2dsYw+TpBveyIolGGf00BAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g0w9eTlaTsy1vWnieNwu2RHFBjAHb48ufI2BmfBwTOaUBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIGHMBAAAAAAABBCJRIPGzmH+N0VjGTWFO/Otm7DX662b5nu+5arlL2tCh6dqAAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiDTD15OVpOzLW9aeJ43C7ZEcUGMAdvjy58jYGZ8HBM5pQEPBAAAAAABAR+ghgEAAAAAABZSFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQD/G0d7SFEcnvURdIK0VbinRBzrmgXCDZ4gwhD+Z4IEJAIgJ32Cr+1Q28AA/sbFs+Rp61l2dsYw+TpBveyIolGGf00BAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIGHMBAAAAAAABBCJRIPGzmH+N0VjGTWFO/Otm7DX662b5nu+5arlL2tCh6dqAAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", "supplementary": { + "hex": "70736274ff01fb04020000000102040200000001040101010501010106010000010e20d30f5e4e5693b32d6f5a789e370bb64471418c01dbe3cb9f2360667c1c1339a5010f040000000001011fa0860100000000001652141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf483045022100ff1b477b48511c9ef5117482b455b8a7441ceb9a05c20d9e20c210fe678204240220277d82afed50dbc000fec6c5b3e469eb597676c630f93a41bdec88a251867f4d0101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee320210001030818730100000000000104225120f1b3987f8dd158c64d614efceb66ec35faeb66f99eefb96ab94bdad0a1e9da80010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, @@ -380,7 +416,8 @@ "sequence": 4294967294, "signed": true } - ] + ], + "task": "fail_sign" }, "checks": [ "input_eligibility" @@ -388,8 +425,9 @@ }, { "description": "input eligibility: non-SIGHASH_ALL signature on input with sp output", - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCID1lvc+owIu6KcBlzqbELkBAvrwUG9UvgfUD9jrZiAZUAiBGU0AdzeUC8dVS4BTFAgx1UerNOncuiYVMYBgzYyB9FAEBAwQCAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEgZG9JTKC7m86tFLjbfkxpRFYfryMufMzDa91YaV90kVkBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCID1lvc+owIu6KcBlzqbELkBAvrwUG9UvgfUD9jrZiAZUAiBGU0AdzeUC8dVS4BTFAgx1UerNOncuiYVMYBgzYyB9FAEBAwQCAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEgZG9JTKC7m86tFLjbfkxpRFYfryMufMzDa91YaV90kVkBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", "supplementary": { + "hex": "70736274ff01fb04020000000102040200000001040101010501010106010000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f040000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf47304402203d65bdcfa8c08bba29c065cea6c42e4040bebc141bd52f81f503f63ad988065402204653401dcde502f1d552e014c5020c7551eacd3a772e89854c60183363207d140101030402000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee320210001030818730100000000000104225120646f494ca0bb9bcead14b8db7e4c6944561faf232e7cccc36bdd58695f749159010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, @@ -403,13 +441,15 @@ "sequence": 4294967294, "signed": true } - ] + ], + "task": "fail_sp_sign" } }, { "description": "output scripts: P2TR input with NUMS internal key cannot derive sp output", - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABASsQJwAAAAAAACJRIFCSm3TBoElUt4tLYDXpel4HiloPKOyW1Ue/7prOgDrAAQMEAQAAAAEOIGAXtZAPmL6eOm19nK05Aozq0/UhOaeh2exXaT6+bJqjAQ8EAAAAAAEQBP7///8BE0GNRXo+4wxRWCxWlnde57pemE/F12ztqkpOiq6N0zSCTmgoW/X1/csnFdpquwq4GYc+jRqcEsI7W5NJsxitYlNOAQEXIFCSm3TBoElUt4tLYDXpel4HiloPKOyW1Ue/7prOgDrAIh0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgcJQAAAAAAAAEEIlEgfyDVlx0Qd+n5jEZf6tapililLCV2WAM/PZUgmGiUkfQBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiBgF7WQD5i+njptfZytOQKM6tP1ITmnodnsV2k+vmyaowEPBAAAAAABASsQJwAAAAAAACJRIFCSm3TBoElUt4tLYDXpel4HiloPKOyW1Ue/7prOgDrAAQMEAQAAAAEQBP7///8BE0GNRXo+4wxRWCxWlnde57pemE/F12ztqkpOiq6N0zSCTmgoW/X1/csnFdpquwq4GYc+jRqcEsI7W5NJsxitYlNOAQEXIFCSm3TBoElUt4tLYDXpel4HiloPKOyW1Ue/7prOgDrAIh0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgcJQAAAAAAAAEEIlEgfyDVlx0Qd+n5jEZf6tapililLCV2WAM/PZUgmGiUkfQBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", "supplementary": { + "hex": "70736274ff01fb04020000000102040200000001040101010501010106010000010e206017b5900f98be9e3a6d7d9cad39028cead3f52139a7a1d9ec57693ebe6c9aa3010f040000000001012b102700000000000022512050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac001030401000000011004feffffff0113418d457a3ee30c51582c5696775ee7ba5e984fc5d76cedaa4a4e8aae8dd334824e68285bf5f5fdcb2715da6abb0ab819873e8d1a9c12c23b5b9349b318ad62534e0101172050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021000103081c2500000000000001042251207f20d5971d1077e9f98c465fead6a98a58a52c257658033f3d952098689491f4010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, @@ -439,13 +479,15 @@ "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", "script": "51207f20d5971d1077e9f98c465fead6a98a58a52c257658033f3d952098689491f4" } - ] + ], + "task": "fail_sign" } }, { "description": "output scripts: PSBT_OUT_SCRIPT does not match derived sp output", - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7AQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g907dH3W0uz5ddJwVv9tmNI9oBam01F/u4aLiAfUDu3EBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIGHMBAAAAAAABBCJRIM3jnYsFtJb48Y8gsn0K+aMjMwngRyIZ4IE/87XTeH4pAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7AQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIGHMBAAAAAAABBCJRIM3jnYsFtJb48Y8gsn0K+aMjMwngRyIZ4IE/87XTeH4pAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", "supplementary": { + "hex": "70736274ff01fb04020000000102040200000001040101010501010106010000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f040000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b01030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee320210001030818730100000000000104225120cde39d8b05b496f8f18f20b27d0af9a3233309e0472219e0813ff3b5d3787e29010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, @@ -475,13 +517,15 @@ "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", "script": "5120cde39d8b05b496f8f18f20b27d0af9a3233309e0472219e0813ff3b5d3787e29" } - ] + ], + "task": "fail_sign" } }, { "description": "output scripts: two sp outputs (same scan / different spend keys) not sorted lexicographically by spend key", - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQIBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIExYL+wZvNCU5oIsqPD7MiK6sIG6J64r3IOIgwa67SNWAiAfxZx06/JBydKQqMxQ8qOYD8DANBNXtltjINXNPOpPBAEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwiQXwEAAAAAAAEEIlEgPajcATlIcUBND7sqMXcLxrF+r7rr33jiwy48KFZTJ1kBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgCi4D5lDNIleEbx2x1q254/iwluzMvIXshHEAXvx9nfYYAAQMIECcAAAAAAAABBCJRINcZ2dcurhCyj8MgCzL61dlJboWOixbkdXjXyMFEkzsEAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA6r4Yq7amM+SU5r33DN10dpfsGsSHvCh8DGp9zgv1T27AA==", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQECAQYBAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIExYL+wZvNCU5oIsqPD7MiK6sIG6J64r3IOIgwa67SNWAiAfxZx06/JBydKQqMxQ8qOYD8DANBNXtltjINXNPOpPBAEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwiQXwEAAAAAAAEEIlEgPajcATlIcUBND7sqMXcLxrF+r7rr33jiwy48KFZTJ1kBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgCi4D5lDNIleEbx2x1q254/iwluzMvIXshHEAXvx9nfYYAAQMIECcAAAAAAAABBCJRINcZ2dcurhCyj8MgCzL61dlJboWOixbkdXjXyMFEkzsEAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA6r4Yq7amM+SU5r33DN10dpfsGsSHvCh8DGp9zgv1T27AA==", "supplementary": { + "hex": "70736274ff01fb04020000000102040200000001040101010501020106010000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f040000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf47304402204c582fec19bcd094e6822ca8f0fb3222bab081ba27ae2bdc83888306baed235602201fc59c74ebf241c9d290a8cc50f2a3980fc0c0341357b65b6320d5cd3cea4f040101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee3202100010308905f01000000000001042251203da8dc01394871404d0fbb2a31770bc6b17eafbaebdf78e2c32e3c2856532759010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068028b80f994334895e11bc76c75ab6e78fe2c25bb332f217b211c4017bf1f677d860001030810270000000000000104225120d719d9d72eae10b28fc3200b32fad5d9496e858e8b16e47578d7c8c144933b04010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe06803aaf862aeda98cf92539af7dc3375d1da5fb06b121ef0a1f031a9f7382fd53dbb00", "inputs": [ { "input_index": 0, @@ -517,13 +561,15 @@ "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe06803aaf862aeda98cf92539af7dc3375d1da5fb06b121ef0a1f031a9f7382fd53dbb", "script": "5120d719d9d72eae10b28fc3200b32fad5d9496e858e8b16e47578d7c8c144933b04" } - ] + ], + "task": "fail_sign" } }, { "description": "output scripts: k values assigned to wrong output indices with three sp outputs (same scan / spend keys)", - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQMBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQDmsaUAuR12tiR/luLlnUQZ6/oZayCC6yzQGczKmeec6wIgVp/snmnIG0ZomQT4uGSrck/xFnuR58NgeHpzOZqLvNMBAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g907dH3W0uz5ddJwVv9tmNI9oBam01F/u4aLiAfUDu3EBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIkF8BAAAAAAABBCJRIGRvSUygu5vOrRS4235MaURWH68jLnzMw2vdWGlfdJFZAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AAEDCBAnAAAAAAAAAQQiUSBnO3Y1anIQCkUV5BRRrprC+6ap0dft7SIJEBvVLxrrVwEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQABAwgQJwAAAAAAAAEEIlEgpRVl2ozof5Td+ErkDvaYxXSb8mLkE+ryjVDYvYtTJ8UBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEDAQYBAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQDmsaUAuR12tiR/luLlnUQZ6/oZayCC6yzQGczKmeec6wIgVp/snmnIG0ZomQT4uGSrck/xFnuR58NgeHpzOZqLvNMBAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIkF8BAAAAAAABBCJRIGRvSUygu5vOrRS4235MaURWH68jLnzMw2vdWGlfdJFZAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AAEDCBAnAAAAAAAAAQQiUSBnO3Y1anIQCkUV5BRRrprC+6ap0dft7SIJEBvVLxrrVwEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQABAwgQJwAAAAAAAAEEIlEgpRVl2ozof5Td+ErkDvaYxXSb8mLkE+ryjVDYvYtTJ8UBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", "supplementary": { + "hex": "70736274ff01fb04020000000102040200000001040101010501030106010000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f040000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf483045022100e6b1a500b91d76b6247f96e2e59d4419ebfa196b2082eb2cd019ccca99e79ceb0220569fec9e69c81b46689904f8b864ab724ff1167b91e7c360787a73399a8bbcd30101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee3202100010308905f0100000000000104225120646f494ca0bb9bcead14b8db7e4c6944561faf232e7cccc36bdd58695f749159010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce0390001030810270000000000000104225120673b76356a72100a4515e41451ae9ac2fba6a9d1d7eded2209101bd52f1aeb57010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce0390001030810270000000000000104225120a51565da8ce87f94ddf84ae40ef698c5749bf262e413eaf28d50d8bd8b5327c5010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, @@ -565,13 +611,15 @@ "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", "script": "5120a51565da8ce87f94ddf84ae40ef698c5749bf262e413eaf28d50d8bd8b5327c5" } - ] + ], + "task": "fail_sign" } }, { "description": "input derivation: P2WPKH BIP32_DERIVATION pubkey does not match prevout script", - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7AQMEAQAAACIGA4+plDX6lbGV+mADtXE+Da7qAMH/S8LLYDK0ccl7HFljCAAAAIAAAAAAAQ4g907dH3W0uz5ddJwVv9tmNI9oBam01F/u4aLiAfUDu3EBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQKJrr4cMdjZlp7VADdXOchNeqbQV2h/Ck5cuA0KBg03eyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQGuT/wfJyZrQjEXeF8f1vcx1OVZshsaec0slVfrS+N2b/dKk5yicBub1fk9ybpw0focikVH4GsoUDYT1KdSOi+sAAQMIGHMBAAAAAAABBCJRIDg/2sQx5SQpQX9uJOugHYH842VRzMvwmLrPHqoDNNhPAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7AQMEAQAAACIGA4+plDX6lbGV+mADtXE+Da7qAMH/S8LLYDK0ccl7HFljCAAAAIAAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQKJrr4cMdjZlp7VADdXOchNeqbQV2h/Ck5cuA0KBg03eyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQGuT/wfJyZrQjEXeF8f1vcx1OVZshsaec0slVfrS+N2b/dKk5yicBub1fk9ybpw0focikVH4GsoUDYT1KdSOi+sAAQMIGHMBAAAAAAABBCJRIDg/2sQx5SQpQX9uJOugHYH842VRzMvwmLrPHqoDNNhPAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", "supplementary": { + "hex": "70736274ff01fb04020000000102040200000001040101010501010106010000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f040000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b010304010000002206038fa99435fa95b195fa6003b5713e0daeea00c1ff4bc2cb6032b471c97b1c5963080000008000000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068210289aebe1c31d8d9969ed500375739c84d7aa6d057687f0a4e5cb80d0a060d377b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068406b93ff07c9c99ad08c45de17c7f5bdcc7539566c86c69e734b2555fad2f8dd9bfdd2a4e7289c06e6f57e4f726e9c347e87229151f81aca140d84f529d48e8beb0001030818730100000000000104225120383fdac431e52429417f6e24eba01d81fce36551cccbf098bacf1eaa0334d84f010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, @@ -601,13 +649,15 @@ "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", "script": "5120383fdac431e52429417f6e24eba01d81fce36551cccbf098bacf1eaa0334d84f" } - ] + ], + "task": "deserialize" } }, { "description": "input derivation: P2PKH BIP32_DERIVATION pubkey does not match prevout script", - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAFUCAAAAAfTCEtWu0ef2/2M/LOCcZHxXvt2TAxTZjed1A9WOlAszAAAAAAD/////AaCGAQAAAAAAGXapFB4q14ctMpQTpW3wlovjOCIngxY7iKwAAAAAAQMEAQAAACIGA4+plDX6lbGV+mADtXE+Da7qAMH/S8LLYDK0ccl7HFljCAAAAIAAAAAAAQ4gUidI6xd2TSjKSUgV7I1J59MNUrxzQix8hut045cFcpQBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQKJrr4cMdjZlp7VADdXOchNeqbQV2h/Ck5cuA0KBg03eyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQGuT/wfJyZrQjEXeF8f1vcx1OVZshsaec0slVfrS+N2b/dKk5yicBub1fk9ybpw0focikVH4GsoUDYT1KdSOi+sAAQMIGHMBAAAAAAABBCJRICKBfO5dYbj9zQAUBomhNyYIpsMCvUqPU6EYTAlCDalDAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiBSJ0jrF3ZNKMpJSBXsjUnn0w1SvHNCLHyG63TjlwVylAEPBAAAAAABAFUCAAAAAfTCEtWu0ef2/2M/LOCcZHxXvt2TAxTZjed1A9WOlAszAAAAAAD/////AaCGAQAAAAAAGXapFB4q14ctMpQTpW3wlovjOCIngxY7iKwAAAAAAQMEAQAAACIGA4+plDX6lbGV+mADtXE+Da7qAMH/S8LLYDK0ccl7HFljCAAAAIAAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQKJrr4cMdjZlp7VADdXOchNeqbQV2h/Ck5cuA0KBg03eyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQGuT/wfJyZrQjEXeF8f1vcx1OVZshsaec0slVfrS+N2b/dKk5yicBub1fk9ybpw0focikVH4GsoUDYT1KdSOi+sAAQMIGHMBAAAAAAABBCJRICKBfO5dYbj9zQAUBomhNyYIpsMCvUqPU6EYTAlCDalDAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", "supplementary": { + "hex": "70736274ff01fb04020000000102040200000001040101010501010106010000010e20522748eb17764d28ca494815ec8d49e7d30d52bc73422c7c86eb74e397057294010f04000000000100550200000001f4c212d5aed1e7f6ff633f2ce09c647c57bedd930314d98de77503d58e940b330000000000ffffffff01a0860100000000001976a9141e2ad7872d329413a56df0968be338222783163b88ac00000000010304010000002206038fa99435fa95b195fa6003b5713e0daeea00c1ff4bc2cb6032b471c97b1c5963080000008000000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068210289aebe1c31d8d9969ed500375739c84d7aa6d057687f0a4e5cb80d0a060d377b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068406b93ff07c9c99ad08c45de17c7f5bdcc7539566c86c69e734b2555fad2f8dd9bfdd2a4e7289c06e6f57e4f726e9c347e87229151f81aca140d84f529d48e8beb000103081873010000000000010422512022817cee5d61b8fdcd00140689a1372608a6c302bd4a8f53a1184c09420da943010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, @@ -636,13 +686,15 @@ "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", "script": "512022817cee5d61b8fdcd00140689a1372608a6c302bd4a8f53a1184c09420da943" } - ] + ], + "task": "deserialize" } }, { "description": "input derivation: P2SH-P2WPKH BIP32_DERIVATION pubkey does not match prevout script", - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAFMCAAAAAa0yiGinxhSdpSUXfZUerAPh/iyT6DzlNGVjrZNjwndMAAAAAAD/////AaCGAQAAAAAAF6kU1JxxjCdjjcMGkgbmNVqpXZ1duKWHAAAAAAEBIKCGAQAAAAAAF6kU1JxxjCdjjcMGkgbmNVqpXZ1duKWHAQMEAQAAAAEEFgAUHirXhy0ylBOlbfCWi+M4IieDFjsiBgOPqZQ1+pWxlfpgA7VxPg2u6gDB/0vCy2AytHHJexxZYwgAAACAAAAAAAEOIF9UazGnjEZsRZPeIw6ZO8mTW57s1NKnf3O6VVxSQgOFAQ8EAAAAAAEQBP7///8iHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCECia6+HDHY2Zae1QA3VznITXqm0FdofwpOXLgNCgYNN3siHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaEBrk/8Hycma0IxF3hfH9b3MdTlWbIbGnnNLJVX60vjdm/3SpOconAbm9X5Pcm6cNH6HIpFR+BrKFA2E9SnUjovrAAEDCBhzAQAAAAAAAQQiUSCWlm1C2LBhTynYvjvzYYQujiUMMJ4GK3it91Pn25LXpAEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiBfVGsxp4xGbEWT3iMOmTvJk1ue7NTSp39zulVcUkIDhQEPBAAAAAABAFMCAAAAAa0yiGinxhSdpSUXfZUerAPh/iyT6DzlNGVjrZNjwndMAAAAAAD/////AaCGAQAAAAAAF6kU1JxxjCdjjcMGkgbmNVqpXZ1duKWHAAAAAAEBIKCGAQAAAAAAF6kU1JxxjCdjjcMGkgbmNVqpXZ1duKWHAQMEAQAAAAEEFgAUHirXhy0ylBOlbfCWi+M4IieDFjsiBgOPqZQ1+pWxlfpgA7VxPg2u6gDB/0vCy2AytHHJexxZYwgAAACAAAAAAAEQBP7///8iHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCECia6+HDHY2Zae1QA3VznITXqm0FdofwpOXLgNCgYNN3siHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaEBrk/8Hycma0IxF3hfH9b3MdTlWbIbGnnNLJVX60vjdm/3SpOconAbm9X5Pcm6cNH6HIpFR+BrKFA2E9SnUjovrAAEDCBhzAQAAAAAAAQQiUSCWlm1C2LBhTynYvjvzYYQujiUMMJ4GK3it91Pn25LXpAEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", "supplementary": { + "hex": "70736274ff01fb04020000000102040200000001040101010501010106010000010e205f546b31a78c466c4593de230e993bc9935b9eecd4d2a77f73ba555c52420385010f04000000000100530200000001ad328868a7c6149da525177d951eac03e1fe2c93e83ce5346563ad9363c2774c0000000000ffffffff01a08601000000000017a914d49c718c27638dc3069206e6355aa95d9d5db8a58700000000010120a08601000000000017a914d49c718c27638dc3069206e6355aa95d9d5db8a5870103040100000001041600141e2ad7872d329413a56df0968be338222783163b2206038fa99435fa95b195fa6003b5713e0daeea00c1ff4bc2cb6032b471c97b1c5963080000008000000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068210289aebe1c31d8d9969ed500375739c84d7aa6d057687f0a4e5cb80d0a060d377b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068406b93ff07c9c99ad08c45de17c7f5bdcc7539566c86c69e734b2555fad2f8dd9bfdd2a4e7289c06e6f57e4f726e9c347e87229151f81aca140d84f529d48e8beb000103081873010000000000010422512096966d42d8b0614f29d8be3bf361842e8e250c309e062b78adf753e7db92d7a4010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, @@ -672,13 +724,15 @@ "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", "script": "512096966d42d8b0614f29d8be3bf361842e8e250c309e062b78adf753e7db92d7a4" } - ] + ], + "task": "deserialize" } }, { "description": "input pubkey mismatch: global ECDH share computed from decoy pubkey not matching prevout script", - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAIgcCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghAomuvhwx2NmWntUAN1c5yE16ptBXaH8KTly4DQoGDTd7IggCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhApCBNyEZUGJiLPKlVE9fVdU+ywDiriYHCI0/jxSu1Fl1DsrLP2Gmzffkyvnairni2DokSMDz8aC7ijH1vSWivpAH7BAIAAAAAAQEfoIYBAAAAAAAWABQeKteHLTKUE6Vt8JaL4zgiJ4MWOyIGA4+plDX6lbGV+mADtXE+Da7qAMH/S8LLYDK0ccl7HFljCAAAAIAAAAAAAQ4g907dH3W0uz5ddJwVv9tmNI9oBam01F/u4aLiAfUDu3EBDwQAAAAAARAE/v///wABAwgYcwEAAAAAAAEEIlEgOD/axDHlJClBf24k66AdgfzjZVHMy/CYus8eqgM02E8BCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBACIHAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQKJrr4cMdjZlp7VADdXOchNeqbQV2h/Ck5cuA0KBg03eyIIAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQKQgTchGVBiYizypVRPX1XVPssA4q4mBwiNP48UrtRZdQ7Kyz9hps335Mr52oq54tg6JEjA8/Ggu4ox9b0lor6QAAQ4g907dH3W0uz5ddJwVv9tmNI9oBam01F/u4aLiAfUDu3EBDwQAAAAAAQEfoIYBAAAAAAAWABQeKteHLTKUE6Vt8JaL4zgiJ4MWOyIGA4+plDX6lbGV+mADtXE+Da7qAMH/S8LLYDK0ccl7HFljCAAAAIAAAAAAARAE/v///wABAwgYcwEAAAAAAAEEIlEgOD/axDHlJClBf24k66AdgfzjZVHMy/CYus8eqgM02E8BCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", "supplementary": { + "hex": "70736274ff01fb0402000000010204020000000104010101050101010601002207027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068210289aebe1c31d8d9969ed500375739c84d7aa6d057687f0a4e5cb80d0a060d377b2208027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe06840a4204dc8465418988b3ca95513d7d5754fb2c038ab8981c2234fe3c52bb5165d43b2b2cfd869b37df932be76a2ae78b60e8912303cfc682ee28c7d6f4968afa400010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f040000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b2206038fa99435fa95b195fa6003b5713e0daeea00c1ff4bc2cb6032b471c97b1c5963080000008000000000011004feffffff0001030818730100000000000104225120383fdac431e52429417f6e24eba01d81fce36551cccbf098bacf1eaa0334d84f010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, @@ -707,15 +761,17 @@ "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", "script": "5120383fdac431e52429417f6e24eba01d81fce36551cccbf098bacf1eaa0334d84f" } - ] + ], + "task": "deserialize" } } ], "valid": [ { "description": "can finalize: one P2PKH input single-signer", - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAFUCAAAAAfTCEtWu0ef2/2M/LOCcZHxXvt2TAxTZjed1A9WOlAszAAAAAAD/////AaCGAQAAAAAAGXapFB4q14ctMpQTpW3wlovjOCIngxY7iKwAAAAAIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQCKz65hp7Ug/wQxkrbclMyEJpEkQIMSdkyI3dldqY0pVQIgIIfDsRj5aZKk2iQTz/6RcPJQ4n48FMtd7z5jjDDX6oABAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4gUidI6xd2TSjKSUgV7I1J59MNUrxzQix8hut045cFcpQBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIGHMBAAAAAAABBCJRIOFA0oe0W0bNTqr6Q3cGFXC6voPRuLyVCnSp/qCSM9emAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiBSJ0jrF3ZNKMpJSBXsjUnn0w1SvHNCLHyG63TjlwVylAEPBAAAAAABAFUCAAAAAfTCEtWu0ef2/2M/LOCcZHxXvt2TAxTZjed1A9WOlAszAAAAAAD/////AaCGAQAAAAAAGXapFB4q14ctMpQTpW3wlovjOCIngxY7iKwAAAAAIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQCKz65hp7Ug/wQxkrbclMyEJpEkQIMSdkyI3dldqY0pVQIgIIfDsRj5aZKk2iQTz/6RcPJQ4n48FMtd7z5jjDDX6oABAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIGHMBAAAAAAABBCJRIOFA0oe0W0bNTqr6Q3cGFXC6voPRuLyVCnSp/qCSM9emAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", "supplementary": { + "hex": "70736274ff01fb04020000000102040200000001040101010501010106010000010e20522748eb17764d28ca494815ec8d49e7d30d52bc73422c7c86eb74e397057294010f04000000000100550200000001f4c212d5aed1e7f6ff633f2ce09c647c57bedd930314d98de77503d58e940b330000000000ffffffff01a0860100000000001976a9141e2ad7872d329413a56df0968be338222783163b88ac00000000220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf4830450221008acfae61a7b520ff043192b6dc94cc84269124408312764c88ddd95da98d295502202087c3b118f96992a4da2413cffe9170f250e27e3c14cb5def3e638c30d7ea800101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee320210001030818730100000000000104225120e140d287b45b46cd4eaafa4377061570babe83d1b8bc950a74a9fea09233d7a6010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, @@ -744,13 +800,15 @@ "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", "script": "5120e140d287b45b46cd4eaafa4377061570babe83d1b8bc950a74a9fea09233d7a6" } - ] + ], + "task": "sign" } }, { "description": "can finalize: two inputs single-signer using global ECDH share", - "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAIgcCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghAtMmJyM1JgfoT8r3ZR+NLWN+Agrqht+tgNMGzU9Iz8xiIggCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAxlO3H5RoGKlb3DnwkYRFvJA6CHa3OAYOnl2x3Owwq99U4LXxeFc/URnecapjrRm0SeO8tlRjk2yLrupNkXOSuQH7BAIAAAAAAQEfoIYBAAAAAAAWABQeKteHLTKUE6Vt8JaL4zgiJ4MWOyICAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/SDBFAiEA7BqWeJn9r3jg2rH/VnzzA3wMo9G7Im8q7sP98KfSmdcCIBHdNztMi7HrfRAkJSDvxy+E7Un3b0H78IdNp0bjoGOoASIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g907dH3W0uz5ddJwVv9tmNI9oBam01F/u4aLiAfUDu3EBDwQAAAAAARAE/v///wABAR+ghgEAAAAAABYAFKaSURwHlXW/N1bavFatcdQoSmkOIgIC9bWfpeSSIh6/Vbp4rUQmBb6ulRZroeujJQ0Luqx+LtxIMEUCIQDelwGo+8K1FHCnn5V0LTz/267tYvzpJKCg1dcFYFFTxQIgRd8PiHo5I7pLMWKTtgzZ/xAdiZUqfbBpxHlWMzJ8PKIBIgYC9bWfpeSSIh6/Vbp4rUQmBb6ulRZroeujJQ0Luqx+LtwIAAAAgAEAAAABDiC81IWnCcsl0TRjoYMtshlMbJ2f5yuWmfT+Qsgr7ZPTJgEPBAAAAAABEAT+////AAEDCBhzAQAAAAAAAQQiUSCZu9KYLwKAvNwmQx1rKc9nkRilu7tgkU1v+s+rvFy0WwEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEBAQYBACIHAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQLTJicjNSYH6E/K92UfjS1jfgIK6obfrYDTBs1PSM/MYiIIAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQMZTtx+UaBipW9w58JGERbyQOgh2tzgGDp5dsdzsMKvfVOC18XhXP1EZ3nGqY60ZtEnjvLZUY5Nsi67qTZFzkrkAAQ4g907dH3W0uz5ddJwVv9tmNI9oBam01F/u4aLiAfUDu3EBDwQAAAAAAQEfoIYBAAAAAAAWABQeKteHLTKUE6Vt8JaL4zgiJ4MWOyICAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/SDBFAiEA7BqWeJn9r3jg2rH/VnzzA3wMo9G7Im8q7sP98KfSmdcCIBHdNztMi7HrfRAkJSDvxy+E7Un3b0H78IdNp0bjoGOoASIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///wABDiC81IWnCcsl0TRjoYMtshlMbJ2f5yuWmfT+Qsgr7ZPTJgEPBAAAAAABAR+ghgEAAAAAABYAFKaSURwHlXW/N1bavFatcdQoSmkOIgIC9bWfpeSSIh6/Vbp4rUQmBb6ulRZroeujJQ0Luqx+LtxIMEUCIQDelwGo+8K1FHCnn5V0LTz/267tYvzpJKCg1dcFYFFTxQIgRd8PiHo5I7pLMWKTtgzZ/xAdiZUqfbBpxHlWMzJ8PKIBIgYC9bWfpeSSIh6/Vbp4rUQmBb6ulRZroeujJQ0Luqx+LtwIAAAAgAEAAAABEAT+////AAEDCBhzAQAAAAAAAQQiUSCZu9KYLwKAvNwmQx1rKc9nkRilu7tgkU1v+s+rvFy0WwEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", "supplementary": { + "hex": "70736274ff01fb0402000000010204020000000104010201050101010601002207027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682102d3262723352607e84fcaf7651f8d2d637e020aea86dfad80d306cd4f48cfcc622208027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe06840c653b71f946818a95bdc39f0918445bc903a0876b738060e9e5db1dcec30abdf54e0b5f178573f5119de71aa63ad19b449e3bcb65463936c8baeea4d917392b900010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f040000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf483045022100ec1a967899fdaf78e0dab1ff567cf3037c0ca3d1bb226f2aeec3fdf0a7d299d7022011dd373b4c8bb1eb7d10242520efc72f84ed49f76f41fbf0874da746e3a063a801220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000011004feffffff00010e20bcd485a709cb25d13463a1832db2194c6c9d9fe72b9699f4fe42c82bed93d326010f040000000001011fa086010000000000160014a692511c079575bf3756dabc56ad71d4284a690e220202f5b59fa5e492221ebf55ba78ad442605beae95166ba1eba3250d0bbaac7e2edc483045022100de9701a8fbc2b51470a79f95742d3cffdbaeed62fce924a0a0d5d705605153c5022045df0f887a3923ba4b316293b60cd9ff101d89952a7db069c4795633327c3ca201220602f5b59fa5e492221ebf55ba78ad442605beae95166ba1eba3250d0bbaac7e2edc080000008001000000011004feffffff000103081873010000000000010422512099bbd2982f0280bcdc26431d6b29cf679118a5bbbb60914d6ffacfabbc5cb45b010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, @@ -791,13 +849,15 @@ "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", "script": "512099bbd2982f0280bcdc26431d6b29cf679118a5bbbb60914d6ffacfabbc5cb45b" } - ] + ], + "task": "sign" } }, { "description": "can finalize: two inputs single-signer using per-input ECDH shares", - "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQDsGpZ4mf2veODasf9WfPMDfAyj0bsibyruw/3wp9KZ1wIgEd03O0yLset9ECQlIO/HL4TtSfdvQfvwh02nRuOgY6gBIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAR+ghgEAAAAAABYAFKaSURwHlXW/N1bavFatcdQoSmkOIgIC9bWfpeSSIh6/Vbp4rUQmBb6ulRZroeujJQ0Luqx+LtxIMEUCIQDelwGo+8K1FHCnn5V0LTz/267tYvzpJKCg1dcFYFFTxQIgRd8PiHo5I7pLMWKTtgzZ/xAdiZUqfbBpxHlWMzJ8PKIBAQMEAQAAACIGAvW1n6XkkiIev1W6eK1EJgW+rpUWa6HroyUNC7qsfi7cCAAAAIABAAAAAQ4gvNSFpwnLJdE0Y6GDLbIZTGydn+crlpn0/kLIK+2T0yYBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQM00s73Tt7URkInYH/FmsHegMEqJDOlYnFSjtzPUPpsKyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQDfADAtCoHP2tl8MS25W4Gd0s4DB3z3ii2QLEh7gs7TPeFDfRW4LXY4Zdd3/JSYsg4HiD4Us2HC94/aoMqYyW8wAAQMIGHMBAAAAAAABBCJRIJm70pgvAoC83CZDHWspz2eRGKW7u2CRTW/6z6u8XLRbAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEBAQYBAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQDsGpZ4mf2veODasf9WfPMDfAyj0bsibyruw/3wp9KZ1wIgEd03O0yLset9ECQlIO/HL4TtSfdvQfvwh02nRuOgY6gBIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABDiC81IWnCcsl0TRjoYMtshlMbJ2f5yuWmfT+Qsgr7ZPTJgEPBAAAAAABAR+ghgEAAAAAABYAFKaSURwHlXW/N1bavFatcdQoSmkOIgIC9bWfpeSSIh6/Vbp4rUQmBb6ulRZroeujJQ0Luqx+LtxIMEUCIQDelwGo+8K1FHCnn5V0LTz/267tYvzpJKCg1dcFYFFTxQIgRd8PiHo5I7pLMWKTtgzZ/xAdiZUqfbBpxHlWMzJ8PKIBAQMEAQAAACIGAvW1n6XkkiIev1W6eK1EJgW+rpUWa6HroyUNC7qsfi7cCAAAAIABAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQM00s73Tt7URkInYH/FmsHegMEqJDOlYnFSjtzPUPpsKyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQDfADAtCoHP2tl8MS25W4Gd0s4DB3z3ii2QLEh7gs7TPeFDfRW4LXY4Zdd3/JSYsg4HiD4Us2HC94/aoMqYyW8wAAQMIGHMBAAAAAAABBCJRIJm70pgvAoC83CZDHWspz2eRGKW7u2CRTW/6z6u8XLRbAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", "supplementary": { + "hex": "70736274ff01fb04020000000102040200000001040102010501010106010000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f040000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf483045022100ec1a967899fdaf78e0dab1ff567cf3037c0ca3d1bb226f2aeec3fdf0a7d299d7022011dd373b4c8bb1eb7d10242520efc72f84ed49f76f41fbf0874da746e3a063a801220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee3202100010e20bcd485a709cb25d13463a1832db2194c6c9d9fe72b9699f4fe42c82bed93d326010f040000000001011fa086010000000000160014a692511c079575bf3756dabc56ad71d4284a690e220202f5b59fa5e492221ebf55ba78ad442605beae95166ba1eba3250d0bbaac7e2edc483045022100de9701a8fbc2b51470a79f95742d3cffdbaeed62fce924a0a0d5d705605153c5022045df0f887a3923ba4b316293b60cd9ff101d89952a7db069c4795633327c3ca20101030401000000220602f5b59fa5e492221ebf55ba78ad442605beae95166ba1eba3250d0bbaac7e2edc080000008001000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068210334d2cef74eded4464227607fc59ac1de80c12a2433a56271528edccf50fa6c2b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0684037c00c0b42a073f6b65f0c4b6e56e06774b380c1df3de28b640b121ee0b3b4cf7850df456e0b5d8e1975ddff25262c8381e20f852cd870bde3f6a832a6325bcc000103081873010000000000010422512099bbd2982f0280bcdc26431d6b29cf679118a5bbbb60914d6ffacfabbc5cb45b010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, @@ -845,13 +905,15 @@ "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", "script": "512099bbd2982f0280bcdc26431d6b29cf679118a5bbbb60914d6ffacfabbc5cb45b" } - ] + ], + "task": "sign" } }, { "description": "can finalize: two inputs / two sp outputs with mixed global and per-input ECDH shares", - "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQIBBgEAIgcDM2HT/3LzTmtOenvvluW4FR5mqXmtznU8OcWDy+V2bSghA2bPx/3OBuCO1JsbOVK40VGo9+B1/l9t1Y3Wj52t7sqUIggDM2HT/3LzTmtOenvvluW4FR5mqXmtznU8OcWDy+V2bShAXquLCG1IUP6dHJ+WGpH5l7YcqNCFCvwGp4vfPHSe9UBQ5pK1P7WwhuXnh5PwHnbTdH+J4xd6f+/2+MFhfxsG4wH7BAIAAAAAAQEfQA0DAAAAAAAWABQeKteHLTKUE6Vt8JaL4zgiJ4MWOyICAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/RzBEAiAKK+ZG0anqXBVNlCNCmskJl9/09NFCJp/mC8dvxE42HAIgCANa6s/ngmX6X6JTanzM6oXez4bcGYlSGOAMQI1gw7ABAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g/S309Ytav5uR/xoeQ+LjUj9QxqoZ1cIjYBQexIyagCEBDwQAAAAAARAE/v///yIdAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQIQP70XPZxI1YxQIkJtBSeLyhe5qOIoJmaQGhsAueBLeZSSIeAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQQMBdpBBIfPrsN4/r5q9QBeOubIYjaBiw5VshQBfrUHPt70AXlXW13NqpBjSRrIuD/QYk1Bd6TS3UmUxGQNa4zN4AAQEfQA0DAAAAAAAWABSmklEcB5V1vzdW2rxWrXHUKEppDiICAvW1n6XkkiIev1W6eK1EJgW+rpUWa6HroyUNC7qsfi7cSDBFAiEA1c3ZMOY2lwfrZ4b1q8L00OgVt4cmVi2tA1VpGbbQIjgCIF8zRs9QoCxciaScoUlqFfUE49+mFdDTyCBi0nGS0uE5AQEDBAEAAAAiBgL1tZ+l5JIiHr9VunitRCYFvq6VFmuh66MlDQu6rH4u3AgAAACAAQAAAAEOIITULym/Ww9KyMHgbIoBNLUz+CwKAffuThNSpATHWvsuAQ8EAAAAAAEQBP7///8iHQKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVECEDpqibG5hqmVUz4XvtZFALVBuw1zkHHv4q4rfvsKDKa88iHgKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVEEDDSmopQLvppzVsHMb/41jdREHbWIl8upnCEut1KF59oeyhHHksl6OASTNFqyJN6dlMKzbuhSauI1KBcaMjHeczAAEDCJBfAQAAAAAAAQQiUSCxKAm+EU5RY5SZU7O++G4xbRcMZzZlTdRqkb2+RLxVEAEJQgMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKAMSZlgePoQcu5TeYupzVYOiMsTIiPpu3vLsL4cHifwd1AABAwiQXwEAAAAAAAEEIlEge2sCToSJVp8gv7oB/byYmecZMBVcHiDoeJIGlPmxpggBCUICqfH6wsxFdoTzPekAc/4g0iyUfJIWO4YrFNCrod9HFRACSkjXbiDUC89fLhpcP/6z3CqLO4jXmkhtVMnZ6qj6GI4A", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQECAQYBACIHAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oIQNmz8f9zgbgjtSbGzlSuNFRqPfgdf5fbdWN1o+dre7KlCIIAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oQF6riwhtSFD+nRyflhqR+Ze2HKjQhQr8BqeL3zx0nvVAUOaStT+1sIbl54eT8B5203R/ieMXen/v9vjBYX8bBuMAAQ4g/S309Ytav5uR/xoeQ+LjUj9QxqoZ1cIjYBQexIyagCEBDwQAAAAAAQEfQA0DAAAAAAAWABQeKteHLTKUE6Vt8JaL4zgiJ4MWOyICAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/RzBEAiAKK+ZG0anqXBVNlCNCmskJl9/09NFCJp/mC8dvxE42HAIgCANa6s/ngmX6X6JTanzM6oXez4bcGYlSGOAMQI1gw7ABAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQIQP70XPZxI1YxQIkJtBSeLyhe5qOIoJmaQGhsAueBLeZSSIeAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQQMBdpBBIfPrsN4/r5q9QBeOubIYjaBiw5VshQBfrUHPt70AXlXW13NqpBjSRrIuD/QYk1Bd6TS3UmUxGQNa4zN4AAQ4ghNQvKb9bD0rIweBsigE0tTP4LAoB9+5OE1KkBMda+y4BDwQAAAAAAQEfQA0DAAAAAAAWABSmklEcB5V1vzdW2rxWrXHUKEppDiICAvW1n6XkkiIev1W6eK1EJgW+rpUWa6HroyUNC7qsfi7cSDBFAiEA1c3ZMOY2lwfrZ4b1q8L00OgVt4cmVi2tA1VpGbbQIjgCIF8zRs9QoCxciaScoUlqFfUE49+mFdDTyCBi0nGS0uE5AQEDBAEAAAAiBgL1tZ+l5JIiHr9VunitRCYFvq6VFmuh66MlDQu6rH4u3AgAAACAAQAAAAEQBP7///8iHQKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVECEDpqibG5hqmVUz4XvtZFALVBuw1zkHHv4q4rfvsKDKa88iHgKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVEEDDSmopQLvppzVsHMb/41jdREHbWIl8upnCEut1KF59oeyhHHksl6OASTNFqyJN6dlMKzbuhSauI1KBcaMjHeczAAEDCJBfAQAAAAAAAQQiUSCxKAm+EU5RY5SZU7O++G4xbRcMZzZlTdRqkb2+RLxVEAEJQgMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKAMSZlgePoQcu5TeYupzVYOiMsTIiPpu3vLsL4cHifwd1AABAwiQXwEAAAAAAAEEIlEge2sCToSJVp8gv7oB/byYmecZMBVcHiDoeJIGlPmxpggBCUICqfH6wsxFdoTzPekAc/4g0iyUfJIWO4YrFNCrod9HFRACSkjXbiDUC89fLhpcP/6z3CqLO4jXmkhtVMnZ6qj6GI4A", "supplementary": { + "hex": "70736274ff01fb0402000000010204020000000104010201050102010601002207033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28210366cfc7fdce06e08ed49b1b3952b8d151a8f7e075fe5f6dd58dd68f9dadeeca942208033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28405eab8b086d4850fe9d1c9f961a91f997b61ca8d0850afc06a78bdf3c749ef54050e692b53fb5b086e5e78793f01e76d3747f89e3177a7feff6f8c1617f1b06e300010e20fd2df4f58b5abf9b91ff1a1e43e2e3523f50c6aa19d5c22360141ec48c9a8021010f040000000001011f400d0300000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf47304402200a2be646d1a9ea5c154d9423429ac90997dff4f4d142269fe60bc76fc44e361c022008035aeacfe78265fa5fa2536a7cccea85decf86dc19895218e00c408d60c3b00101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000011004feffffff221d02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df4715102103fbd173d9c48d58c5022426d05278bca17b9a8e2282666901a1b00b9e04b79949221e02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df47151040c05da410487cfaec378febe6af5005e3ae6c86236818b0e55b214017eb5073edef40179575b5dcdaa9063491ac8b83fd0624d4177a4d2dd4994c4640d6b8ccde00010e2084d42f29bf5b0f4ac8c1e06c8a0134b533f82c0a01f7ee4e1352a404c75afb2e010f040000000001011f400d030000000000160014a692511c079575bf3756dabc56ad71d4284a690e220202f5b59fa5e492221ebf55ba78ad442605beae95166ba1eba3250d0bbaac7e2edc483045022100d5cdd930e6369707eb6786f5abc2f4d0e815b78726562dad03556919b6d0223802205f3346cf50a02c5c89a49ca1496a15f504e3dfa615d0d3c82062d27192d2e1390101030401000000220602f5b59fa5e492221ebf55ba78ad442605beae95166ba1eba3250d0bbaac7e2edc080000008001000000011004feffffff221d02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df4715102103a6a89b1b986a995533e17bed64500b541bb0d739071efe2ae2b7efb0a0ca6bcf221e02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df47151040c34a6a2940bbe9a7356c1cc6ffe358dd4441db58897cba99c212eb75285e7da1eca11c792c97a380493345ab224de9d94c2b36ee8526ae23528171a3231de73300010308905f0100000000000104225120b12809be114e5163949953b3bef86e316d170c6736654dd46a91bdbe44bc5510010942033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28031266581e3e841cbb94de62ea735583a232c4c888fa6edef2ec2f870789fc1dd400010308905f01000000000001042251207b6b024e8489569f20bfba01fdbc9899e71930155c1e20e878920694f9b1a60801094202a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510024a48d76e20d40bcf5f2e1a5c3ffeb3dc2a8b3b88d79a486d54c9d9eaa8fa188e00", "inputs": [ { "input_index": 0, @@ -910,13 +972,15 @@ "sp_v0_info": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510024a48d76e20d40bcf5f2e1a5c3ffeb3dc2a8b3b88d79a486d54c9d9eaa8fa188e", "script": "51207b6b024e8489569f20bfba01fdbc9899e71930155c1e20e878920694f9b1a608" } - ] + ], + "task": "sign" } }, { "description": "can finalize: one input / one sp output with both global and per-input ECDH shares", - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAIgcDM2HT/3LzTmtOenvvluW4FR5mqXmtznU8OcWDy+V2bSghAwoYubtBmbiTMOsX+O5ax4bghT3NLzzN8XRLl85O3gU+IggDM2HT/3LzTmtOenvvluW4FR5mqXmtznU8OcWDy+V2bShAJ/uQxdYceOMRUgD/0YPSjQq0g4BiyVQZNMZBbUJnzjG9QofpNZRSwIF68O9NUM/1eENrDSj57Y8ht5pEdkCAjgH7BAIAAAAAAQEfQA0DAAAAAAAWABQeKteHLTKUE6Vt8JaL4zgiJ4MWOyICAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/SDBFAiEAyFvlr5bhqKf1YcXDSFBg36YAz/htqrTzO6OY5lBittkCIBPq0/BHmz/uJrpIh+BRh2ZjzRP8fmHmDS6WBkIym0HkAQEDBAEAAAAiBgLIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvwgAAACAAAAAAAEOIP0t9PWLWr+bkf8aHkPi41I/UMaqGdXCI2AUHsSMmoAhAQ8EAAAAAAEQBP7///8iHQMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKCEDChi5u0GZuJMw6xf47lrHhuCFPc0vPM3xdEuXzk7eBT4iHgMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKEAAE4PUZhvocl7ykEj0jJEfifXzQxfXwMCsxg72XxtSv/96ltgzm2Jd+Dq6tXqic+3NmjXHlNrLschhFxuyZwdfAAEDCJBfAQAAAAAAAQQiUSAqcL4BPYeh6B6gH736DPH/CNUqaNGMExqMyWAfhKagrAEJQgMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKAMSZlgePoQcu5TeYupzVYOiMsTIiPpu3vLsL4cHifwd1AA=", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBACIHAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oIQMKGLm7QZm4kzDrF/juWseG4IU9zS88zfF0S5fOTt4FPiIIAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oQCf7kMXWHHjjEVIA/9GD0o0KtIOAYslUGTTGQW1CZ84xvUKH6TWUUsCBevDvTVDP9XhDaw0o+e2PIbeaRHZAgI4AAQ4g/S309Ytav5uR/xoeQ+LjUj9QxqoZ1cIjYBQexIyagCEBDwQAAAAAAQEfQA0DAAAAAAAWABQeKteHLTKUE6Vt8JaL4zgiJ4MWOyICAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/SDBFAiEAyFvlr5bhqKf1YcXDSFBg36YAz/htqrTzO6OY5lBittkCIBPq0/BHmz/uJrpIh+BRh2ZjzRP8fmHmDS6WBkIym0HkAQEDBAEAAAAiBgLIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvwgAAACAAAAAAAEQBP7///8iHQMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKCEDChi5u0GZuJMw6xf47lrHhuCFPc0vPM3xdEuXzk7eBT4iHgMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKEAAE4PUZhvocl7ykEj0jJEfifXzQxfXwMCsxg72XxtSv/96ltgzm2Jd+Dq6tXqic+3NmjXHlNrLschhFxuyZwdfAAEDCJBfAQAAAAAAAQQiUSAqcL4BPYeh6B6gH736DPH/CNUqaNGMExqMyWAfhKagrAEJQgMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKAMSZlgePoQcu5TeYupzVYOiMsTIiPpu3vLsL4cHifwd1AA=", "supplementary": { + "hex": "70736274ff01fb0402000000010204020000000104010101050101010601002207033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d2821030a18b9bb4199b89330eb17f8ee5ac786e0853dcd2f3ccdf1744b97ce4ede053e2208033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d284027fb90c5d61c78e3115200ffd183d28d0ab4838062c9541934c6416d4267ce31bd4287e9359452c0817af0ef4d50cff578436b0d28f9ed8f21b79a447640808e00010e20fd2df4f58b5abf9b91ff1a1e43e2e3523f50c6aa19d5c22360141ec48c9a8021010f040000000001011f400d0300000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf483045022100c85be5af96e1a8a7f561c5c3485060dfa600cff86daab4f33ba398e65062b6d9022013ead3f0479b3fee26ba4887e051876663cd13fc7e61e60d2e960642329b41e40101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000011004feffffff221d033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d2821030a18b9bb4199b89330eb17f8ee5ac786e0853dcd2f3ccdf1744b97ce4ede053e221e033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d2840001383d4661be8725ef29048f48c911f89f5f34317d7c0c0acc60ef65f1b52bfff7a96d8339b625df83abab57aa273edcd9a35c794dacbb1c861171bb267075f00010308905f01000000000001042251202a70be013d87a1e81ea01fbdfa0cf1ff08d52a68d18c131a8cc9601f84a6a0ac010942033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28031266581e3e841cbb94de62ea735583a232c4c888fa6edef2ec2f870789fc1dd400", "inputs": [ { "input_index": 0, @@ -945,13 +1009,15 @@ "sp_v0_info": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28031266581e3e841cbb94de62ea735583a232c4c888fa6edef2ec2f870789fc1dd4", "script": "51202a70be013d87a1e81ea01fbdfa0cf1ff08d52a68d18c131a8cc9601f84a6a0ac" } - ] + ], + "task": "sign" } }, { "description": "can finalize: three sp outputs (different scan keys) with multiple global ECDH shares", - "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQMBBgEAIgcCqfH6wsxFdoTzPekAc/4g0iyUfJIWO4YrFNCrod9HFRAhAsLZ32DuaaWoZgTdmmKCwi744sknbabllaVGPzcare4kIgcDM2HT/3LzTmtOenvvluW4FR5mqXmtznU8OcWDy+V2bSghAtx9LsrFaLARUXW6PNVJb/TEttkJQi28yuuPJS+lT4vQIgcDjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGwhAnC+9cBqmoVfxjv/K9C+LXADPIILYVNBPI1u2lHyWhspIggCqfH6wsxFdoTzPekAc/4g0iyUfJIWO4YrFNCrod9HFRBA7IJCv3tYgc7gYFZsfxPMR+RxDImiZFjCAwGzAx5IFzvAvqAWgNM3XrXoBhGrDVCLHkmrtXGxh4AyquSfCwL30iIIAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oQOpDRw5eG+MpG0igvLU/VZUsZIYOdjXvulADzK3td90SjiFml7D1I74hfsaHUHeXzM68XNlDYq8bRtgDZCvV+UAiCAOO0yIOczRPkeLTM5Hj4Wkds52vBuQjfhl+0NAHvycobEAb3+VO1KKgb/+bAAmuTj2A/EdhZHWv3yEkTP48bRBN8kdBqHVRTXhlT7nKERjm0+VS84+Mq6NVLoMzxQG/DL0/AfsEAgAAAAABAR8goQcAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQC42QsRZqzXY8+uqHOJGaBPRdBVbSvLD2Z/C6PEGO5f2QIgI64RGn6itGrUpKOIKuT++973rl0BtM22H1aXmv9SahgBIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiDUQOda/N1TGlkeN6vSbkryvw9v8uGRgwI1Yej8VxOPSgEPBAAAAAABEAT+////AAEBH6CGAQAAAAAAFgAUNyH6c8IwXLL4joSJLWvWuXcmHmoiAgJDoNQOneCIJ5QWF1K65CupCVJ4QgnwY0MPCvJWNUqFu0gwRQIhAJfXTGL5WdOu1bnHpXDy1zyq0MCrseRy1E/UxirCYuS5AiAX2VXEZF+Fr+z2aKPQRlXWdZPyNXYrGm9SKYcXYECqoAEiBgJDoNQOneCIJ5QWF1K65CupCVJ4QgnwY0MPCvJWNUqFuwgAAACAAQAAAAEOIOdsAXEIOkxftK/i9tYfAKRzAbnQH40uR3gKt1QuN3wIAQ8EAAAAAAEQBP7///8AAQMIkF8BAAAAAAABBCJRIE6KUf3Rq9Uk/FLWkolTgu5u3MSNN3228eZRXyNALkgnAQlCAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oAxJmWB4+hBy7lN5i6nNVg6IyxMiI+m7e8uwvhweJ/B3UAAEDCJBfAQAAAAAAAQQiUSB+MV8kXPlXXxNDwxcP/O42rUbTO1ZfCji5lDx8AqzXawEJQgKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVEAJKSNduINQLz18uGlw//rPcKos7iNeaSG1UydnqqPoYjgABAwiQXwEAAAAAAAEEIlEgPK1PnUbiURy2iCuvYOjtgGIgsUFRPWkE2s0r6qE3w5UBCUIDjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGwD+BRzhEyddMkh/xelr0ELYzc0jXr7/3OJG8XLDLJMsMAA", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEDAQYBACIHAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQIQLC2d9g7mmlqGYE3ZpigsIu+OLJJ22m5ZWlRj83Gq3uJCIHAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oIQLcfS7KxWiwEVF1ujzVSW/0xLbZCUItvMrrjyUvpU+L0CIHA47TIg5zNE+R4tMzkePhaR2zna8G5CN+GX7Q0Ae/JyhsIQJwvvXAapqFX8Y7/yvQvi1wAzyCC2FTQTyNbtpR8lobKSIIAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQQOyCQr97WIHO4GBWbH8TzEfkcQyJomRYwgMBswMeSBc7wL6gFoDTN1616AYRqw1Qix5Jq7VxsYeAMqrknwsC99IiCAMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKEDqQ0cOXhvjKRtIoLy1P1WVLGSGDnY177pQA8yt7XfdEo4hZpew9SO+IX7Gh1B3l8zOvFzZQ2KvG0bYA2Qr1flAIggDjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGxAG9/lTtSioG//mwAJrk49gPxHYWR1r98hJEz+PG0QTfJHQah1UU14ZU+5yhEY5tPlUvOPjKujVS6DM8UBvwy9PwABDiDUQOda/N1TGlkeN6vSbkryvw9v8uGRgwI1Yej8VxOPSgEPBAAAAAABAR8goQcAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQC42QsRZqzXY8+uqHOJGaBPRdBVbSvLD2Z/C6PEGO5f2QIgI64RGn6itGrUpKOIKuT++973rl0BtM22H1aXmv9SahgBIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////AAEOIOdsAXEIOkxftK/i9tYfAKRzAbnQH40uR3gKt1QuN3wIAQ8EAAAAAAEBH6CGAQAAAAAAFgAUNyH6c8IwXLL4joSJLWvWuXcmHmoiAgJDoNQOneCIJ5QWF1K65CupCVJ4QgnwY0MPCvJWNUqFu0gwRQIhAJfXTGL5WdOu1bnHpXDy1zyq0MCrseRy1E/UxirCYuS5AiAX2VXEZF+Fr+z2aKPQRlXWdZPyNXYrGm9SKYcXYECqoAEiBgJDoNQOneCIJ5QWF1K65CupCVJ4QgnwY0MPCvJWNUqFuwgAAACAAQAAAAEQBP7///8AAQMIkF8BAAAAAAABBCJRIE6KUf3Rq9Uk/FLWkolTgu5u3MSNN3228eZRXyNALkgnAQlCAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oAxJmWB4+hBy7lN5i6nNVg6IyxMiI+m7e8uwvhweJ/B3UAAEDCJBfAQAAAAAAAQQiUSB+MV8kXPlXXxNDwxcP/O42rUbTO1ZfCji5lDx8AqzXawEJQgKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVEAJKSNduINQLz18uGlw//rPcKos7iNeaSG1UydnqqPoYjgABAwiQXwEAAAAAAAEEIlEgPK1PnUbiURy2iCuvYOjtgGIgsUFRPWkE2s0r6qE3w5UBCUIDjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGwD+BRzhEyddMkh/xelr0ELYzc0jXr7/3OJG8XLDLJMsMAA", "supplementary": { + "hex": "70736274ff01fb040200000001020402000000010401020105010301060100220702a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df4715102102c2d9df60ee69a5a86604dd9a6282c22ef8e2c9276da6e595a5463f371aadee242207033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d282102dc7d2ecac568b0115175ba3cd5496ff4c4b6d909422dbccaeb8f252fa54f8bd02207038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c210270bef5c06a9a855fc63bff2bd0be2d70033c820b6153413c8d6eda51f25a1b29220802a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df47151040ec8242bf7b5881cee060566c7f13cc47e4710c89a26458c20301b3031e48173bc0bea01680d3375eb5e80611ab0d508b1e49abb571b1878032aae49f0b02f7d22208033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d2840ea43470e5e1be3291b48a0bcb53f55952c64860e7635efba5003ccaded77dd128e216697b0f523be217ec687507797cccebc5cd94362af1b46d803642bd5f9402208038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c401bdfe54ed4a2a06fff9b0009ae4e3d80fc47616475afdf21244cfe3c6d104df24741a875514d78654fb9ca1118e6d3e552f38f8caba3552e8333c501bf0cbd3f00010e20d440e75afcdd531a591e37abd26e4af2bf0f6ff2e19183023561e8fc57138f4a010f040000000001011f20a10700000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf483045022100b8d90b1166acd763cfaea8738919a04f45d0556d2bcb0f667f0ba3c418ee5fd9022023ae111a7ea2b46ad4a4a3882ae4fefbdef7ae5d01b4cdb61f56979aff526a1801220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000011004feffffff00010e20e76c0171083a4c5fb4afe2f6d61f00a47301b9d01f8d2e47780ab7542e377c08010f040000000001011fa0860100000000001600143721fa73c2305cb2f88e84892d6bd6b977261e6a22020243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb48304502210097d74c62f959d3aed5b9c7a570f2d73caad0c0abb1e472d44fd4c62ac262e4b9022017d955c4645f85afecf668a3d04655d67593f235762b1a6f522987176040aaa00122060243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb080000008001000000011004feffffff00010308905f01000000000001042251204e8a51fdd1abd524fc52d692895382ee6edcc48d377db6f1e6515f23402e4827010942033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28031266581e3e841cbb94de62ea735583a232c4c888fa6edef2ec2f870789fc1dd400010308905f01000000000001042251207e315f245cf9575f1343c3170ffcee36ad46d33b565f0a38b9943c7c02acd76b01094202a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510024a48d76e20d40bcf5f2e1a5c3ffeb3dc2a8b3b88d79a486d54c9d9eaa8fa188e00010308905f01000000000001042251203cad4f9d46e2511cb6882baf60e8ed806220b141513d6904dacd2beaa137c395010942038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c03f81473844c9d74c921ff17a5af410b6337348d7afbff73891bc5cb0cb24cb0c000", "inputs": [ { "input_index": 0, @@ -1014,13 +1080,15 @@ "sp_v0_info": "038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c03f81473844c9d74c921ff17a5af410b6337348d7afbff73891bc5cb0cb24cb0c0", "script": "51203cad4f9d46e2511cb6882baf60e8ed806220b141513d6904dacd2beaa137c395" } - ] + ], + "task": "sign" } }, { "description": "can finalize: one P2WPKH input / two mixed outputs - labeled sp output and BIP 32 change", - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQIBBgEAAfsEAgAAAAABAR8goQcAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9GMEMCIHcTD90bfOCOxkvITdaflmuTJVdETA9hMOK+XNqEia5EAh938mc1PdR7+Nrf+wdHBtYIqIWc7eTcyYzYZ3xl0LWsAQEDBAEAAAAiBgLIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvwgAAACAAAAAAAEOINRA51r83VMaWR43q9JuSvK/D2/y4ZGDAjVh6PxXE49KAQ8EAAAAAAEQBP7///8iHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCED7KT/Ebco4uD2DOYiKUOm/1W52V9ie/mpnQhLyHLVClsiHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaECKE7OYVUX3K9bolxSuuQmz41SoQqm7i1bNDt7SHfihmVmLMSKKSeC9fpXOEFP3xbKKy1Q6aHB2AOPOiYIu4yAhAAEDCKCGAQAAAAAAAQQiUSCy11CmDsTQW9LCInHwj+IbAOJxHTgjBIu5ZaIrxBc9LwEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaAPqjyKL4rcW2s3vyygQByh08ApHb1wHvQUZFxJsxks97wEKBAEAAAAAIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8MAAAAAAAAAAAAAAABAQMIcPMFAAAAAAABBBYAFDjBjzXdgGPjgKcP/rT5j/TvNIF3AA==", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQECAQYBAAABDiDUQOda/N1TGlkeN6vSbkryvw9v8uGRgwI1Yej8VxOPSgEPBAAAAAABAR8goQcAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9GMEMCIHcTD90bfOCOxkvITdaflmuTJVdETA9hMOK+XNqEia5EAh938mc1PdR7+Nrf+wdHBtYIqIWc7eTcyYzYZ3xl0LWsAQEDBAEAAAAiBgLIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvwgAAACAAAAAAAEQBP7///8iHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCED7KT/Ebco4uD2DOYiKUOm/1W52V9ie/mpnQhLyHLVClsiHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaECKE7OYVUX3K9bolxSuuQmz41SoQqm7i1bNDt7SHfihmVmLMSKKSeC9fpXOEFP3xbKKy1Q6aHB2AOPOiYIu4yAhAAEDCKCGAQAAAAAAAQQiUSCy11CmDsTQW9LCInHwj+IbAOJxHTgjBIu5ZaIrxBc9LwEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaAPqjyKL4rcW2s3vyygQByh08ApHb1wHvQUZFxJsxks97wEKBAEAAAAAAQMIcPMFAAAAAAABBBYAFDjBjzXdgGPjgKcP/rT5j/TvNIF3IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8MAAAAAAAAAAAAAAABAA==", "supplementary": { + "hex": "70736274ff01fb04020000000102040200000001040101010501020106010000010e20d440e75afcdd531a591e37abd26e4af2bf0f6ff2e19183023561e8fc57138f4a010f040000000001011f20a10700000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf463043022077130fdd1b7ce08ec64bc84dd69f966b932557444c0f6130e2be5cda8489ae44021f77f267353dd47bf8dadffb074706d608a8859cede4dcc98cd8677c65d0b5ac0101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee3202100010308a0860100000000000104225120b2d750a60ec4d05bd2c22271f08fe21b00e2711d3823048bb965a22bc4173d2f010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe06803ea8f228be2b716dacdefcb2810072874f00a476f5c07bd051917126cc64b3def010a04010000000001030870f3050000000000010416001438c18f35dd8063e380a70ffeb4f98ff4ef348177220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf0c00000000000000000000000100", "inputs": [ { "input_index": 0, @@ -1056,13 +1124,15 @@ "amount": 390000, "script": "001438c18f35dd8063e380a70ffeb4f98ff4ef348177" } - ] + ], + "task": "sign" } }, { "description": "can finalize: one input / two sp outputs - output 0 has no label / output 1 uses label=0 convention for sp change", - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQIBBgEAAfsEAgAAAAABAR/gkwQAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIFB2CeL9erskEbcJ/ZjL+pgC0nxcDrLBEMLU8/EJ61yYAiBeYmSIxVqzZbFYt+8gUlTszHEFFvbNOzksUNGJgWmDsQEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiDXHS3QFsrGYSyer5hVH2eAhRu3czlByBTq+trO3jDcPQEPBAAAAAABEAT+////Ih0CXw7Bs42ZhKfrYvFb5AMCBBDxQu301p42P1YVr9Kmts0hA84eNnXZDZkmSfqd2xH5AlSbs7AvVvbonMCgTIuMN92UIh0Ci3kOCYf96fDRI5jra+MMc3Z5PGR4ZaKgLy78lg2WZWghAlWBv6pzMVb2uY5xom9w/XazZ4ZJ9isfxed7jpq45hBQIh4CXw7Bs42ZhKfrYvFb5AMCBBDxQu301p42P1YVr9Kmts1ADolhPR9rJTbbj6kkIA2zpvjvyhciVWTVaxEuUIZbTTAuBY+m9hwp4jZqSnJp1FVaXGHWVVnb+/rJ4urf5TY31SIeAot5DgmH/enw0SOY62vjDHN2eTxkeGWioC8u/JYNlmVoQHlAgZ626fJYwVg4fApkzBb1F8fvRAkSLM6qlPTi/1N2xCR7/BcNmyY7Dj0ga2aMh+lLNN7q+gCheSsEeteIdbsAAQMIoIYBAAAAAAABBCJRIBM/6m8cjln0UbKW1K2xPs7sf8M9vFNq5NY3WropOE+LAQlCAot5DgmH/enw0SOY62vjDHN2eTxkeGWioC8u/JYNlmVoA7RDRzNcY/UF5V4mirKA8xi0pqoUSS/zecNmih9U74ybAAEDCDDmAgAAAAAAAQQiUSBgK8NLBuQ1Rvh+VIKxETqr+cn+KSUJmpItXCPYS7zqxgEJQgJfDsGzjZmEp+ti8VvkAwIEEPFC7fTWnjY/VhWv0qa2zQLOCzIZpapd+PIc45PpYs3afVFUbaTTXDjtAYilludg8wEKBAAAAAAA", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQECAQYBAAABDiDXHS3QFsrGYSyer5hVH2eAhRu3czlByBTq+trO3jDcPQEPBAAAAAABAR/gkwQAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIFB2CeL9erskEbcJ/ZjL+pgC0nxcDrLBEMLU8/EJ61yYAiBeYmSIxVqzZbFYt+8gUlTszHEFFvbNOzksUNGJgWmDsQEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0CXw7Bs42ZhKfrYvFb5AMCBBDxQu301p42P1YVr9Kmts0hA84eNnXZDZkmSfqd2xH5AlSbs7AvVvbonMCgTIuMN92UIh0Ci3kOCYf96fDRI5jra+MMc3Z5PGR4ZaKgLy78lg2WZWghAlWBv6pzMVb2uY5xom9w/XazZ4ZJ9isfxed7jpq45hBQIh4CXw7Bs42ZhKfrYvFb5AMCBBDxQu301p42P1YVr9Kmts1ADolhPR9rJTbbj6kkIA2zpvjvyhciVWTVaxEuUIZbTTAuBY+m9hwp4jZqSnJp1FVaXGHWVVnb+/rJ4urf5TY31SIeAot5DgmH/enw0SOY62vjDHN2eTxkeGWioC8u/JYNlmVoQHlAgZ626fJYwVg4fApkzBb1F8fvRAkSLM6qlPTi/1N2xCR7/BcNmyY7Dj0ga2aMh+lLNN7q+gCheSsEeteIdbsAAQMIoIYBAAAAAAABBCJRIBM/6m8cjln0UbKW1K2xPs7sf8M9vFNq5NY3WropOE+LAQlCAot5DgmH/enw0SOY62vjDHN2eTxkeGWioC8u/JYNlmVoA7RDRzNcY/UF5V4mirKA8xi0pqoUSS/zecNmih9U74ybAAEDCDDmAgAAAAAAAQQiUSBgK8NLBuQ1Rvh+VIKxETqr+cn+KSUJmpItXCPYS7zqxgEJQgJfDsGzjZmEp+ti8VvkAwIEEPFC7fTWnjY/VhWv0qa2zQLOCzIZpapd+PIc45PpYs3afVFUbaTTXDjtAYilludg8wEKBAAAAAAA", "supplementary": { + "hex": "70736274ff01fb04020000000102040200000001040101010501020106010000010e20d71d2dd016cac6612c9eaf98551f6780851bb7733941c814eafadacede30dc3d010f040000000001011fe0930400000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf4730440220507609e2fd7abb2411b709fd98cbfa9802d27c5c0eb2c110c2d4f3f109eb5c9802205e626488c55ab365b158b7ef205254eccc710516f6cd3b392c50d189816983b10101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000011004feffffff221d025f0ec1b38d9984a7eb62f15be403020410f142edf4d69e363f5615afd2a6b6cd2103ce1e3675d90d992649fa9ddb11f902549bb3b02f56f6e89cc0a04c8b8c37dd94221d028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d96656821025581bfaa733156f6b98e71a26f70fd76b3678649f62b1fc5e77b8e9ab8e61050221e025f0ec1b38d9984a7eb62f15be403020410f142edf4d69e363f5615afd2a6b6cd400e89613d1f6b2536db8fa924200db3a6f8efca17225564d56b112e50865b4d302e058fa6f61c29e2366a4a7269d4555a5c61d65559dbfbfac9e2eadfe53637d5221e028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d966568407940819eb6e9f258c158387c0a64cc16f517c7ef4409122cceaa94f4e2ff5376c4247bfc170d9b263b0e3d206b668c87e94b34deeafa00a1792b047ad78875bb00010308a0860100000000000104225120133fea6f1c8e59f451b296d4adb13eceec7fc33dbc536ae4d6375aba29384f8b010942028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d96656803b44347335c63f505e55e268ab280f318b4a6aa14492ff379c3668a1f54ef8c9b0001030830e60200000000000104225120602bc34b06e43546f87e5482b1113aabf9c9fe2925099a922d5c23d84bbceac6010942025f0ec1b38d9984a7eb62f15be403020410f142edf4d69e363f5615afd2a6b6cd02ce0b3219a5aa5df8f21ce393e962cdda7d51546da4d35c38ed0188a596e760f3010a040000000000", "inputs": [ { "input_index": 0, @@ -1105,57 +1175,15 @@ "sp_v0_label": 0, "script": "5120602bc34b06e43546f87e5482b1113aabf9c9fe2925099a922d5c23d84bbceac6" } - ] - } - }, - { - "description": "can finalize: two sp outputs - output 0 uses label=3 / output 1 uses label=1", - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQIBBgEAAfsEAgAAAAABAR/gkwQAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQDZJbO/p1XneLxjndqLedHNDt2LpWCdfZLLHzJ9banHkQIgFXaZjOtRHGsMQla9SjGh3cNAEDNdyZq7TBmbyhEV5PIBAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g1x0t0BbKxmEsnq+YVR9ngIUbt3M5QcgU6vrazt4w3D0BDwQAAAAAARAE/v///yIdAot5DgmH/enw0SOY62vjDHN2eTxkeGWioC8u/JYNlmVoIQJVgb+qczFW9rmOcaJvcP12s2eGSfYrH8Xne46auOYQUCIeAot5DgmH/enw0SOY62vjDHN2eTxkeGWioC8u/JYNlmVoQHlAgZ626fJYwVg4fApkzBb1F8fvRAkSLM6qlPTi/1N2xCR7/BcNmyY7Dj0ga2aMh+lLNN7q+gCheSsEeteIdbsAAQMIoIYBAAAAAAABBCJRIBPSHod1uahNrA4VjbAnhGU9Fr1/sv3Qw+Wjq6KVgWLGAQlCAot5DgmH/enw0SOY62vjDHN2eTxkeGWioC8u/JYNlmVoAu+oIvCuW/9HHRN09ozClt/pcxrzh2/50ThqMLAf/pwQAQoEAwAAAAABAwgw5gIAAAAAAAEEIlEg3h2DrBUJUvALticyRSb2WFv4fjk4CIFK2VYmY5+H+rcBCUICi3kOCYf96fDRI5jra+MMc3Z5PGR4ZaKgLy78lg2WZWgD1DFYje5hqzo5clspnDdC3Gaghh3s9ZG0I7DlJwcPgjQBCgQBAAAAAA==", - "supplementary": { - "inputs": [ - { - "input_index": 0, - "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", - "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "3ddc30decedafaea14c8413973b71b8580671f5598af9e2c61c6ca16d02d1dd7", - "prevout_index": 0, - "amount": 300000, - "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01e0930400000000001600141e2ad7872d329413a56df0968be338222783163b00000000", - "witness_utxo": "e0930400000000001600141e2ad7872d329413a56df0968be338222783163b", - "sequence": 4294967294, - "signed": true - } ], - "sp_proofs": [ - { - "scan_key": "028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d966568", - "ecdh_share": "025581bfaa733156f6b98e71a26f70fd76b3678649f62b1fc5e77b8e9ab8e61050", - "dleq_proof": "7940819eb6e9f258c158387c0a64cc16f517c7ef4409122cceaa94f4e2ff5376c4247bfc170d9b263b0e3d206b668c87e94b34deeafa00a1792b047ad78875bb", - "input_index": 0 - } - ], - "outputs": [ - { - "output_index": 0, - "amount": 100000, - "sp_v0_info": "028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d96656802efa822f0ae5bff471d1374f68cc296dfe9731af3876ff9d1386a30b01ffe9c10", - "sp_v0_label": 3, - "script": "512013d21e8775b9a84dac0e158db02784653d16bd7fb2fdd0c3e5a3aba2958162c6" - }, - { - "output_index": 1, - "amount": 190000, - "sp_v0_info": "028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d96656803d431588dee61ab3a39725b299c3742dc66a0861decf591b423b0e527070f8234", - "sp_v0_label": 1, - "script": "5120de1d83ac150952f00bb627324526f6585bf87e393808814ad95626639f87fab7" - } - ] + "task": "sign" } }, { - "description": "can finalize: three labeled sp outputs (same scan key) - k assigned by lexicographic code order, not output index", - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQQBBgEAAfsEAgAAAAABAR+AGgYAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQCETtmM8YHVKfxkiglfbVPircDEwSMyChfNxQUn7aoyVwIgaPox6uw1Qu5x0FpEPsML+NyyJhyEv9LMl7vq6ZJpYp4BAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4gcOBrhlWVxMJzHTP1pq0oD7hwNVRmYpiAyl3NjpAH4ZoBDwQAAAAAARAE/v///yIdAot5DgmH/enw0SOY62vjDHN2eTxkeGWioC8u/JYNlmVoIQJVgb+qczFW9rmOcaJvcP12s2eGSfYrH8Xne46auOYQUCIeAot5DgmH/enw0SOY62vjDHN2eTxkeGWioC8u/JYNlmVoQHlAgZ626fJYwVg4fApkzBb1F8fvRAkSLM6qlPTi/1N2xCR7/BcNmyY7Dj0ga2aMh+lLNN7q+gCheSsEeteIdbsAAQMIoIYBAAAAAAABBCJRIJPaXrkneTYjgSVQ+GmdZjtxlvDMnUiEWLtoH+srb/y6AQlCAot5DgmH/enw0SOY62vjDHN2eTxkeGWioC8u/JYNlmVoA9QxWI3uYas6OXJbKZw3QtxmoIYd7PWRtCOw5ScHD4I0AQoEAQAAAAABAwighgEAAAAAAAEEIlEg9OMGNuSPanr+mE+gslRbJX6q6MqhbsSBk9s0iSaVh1sBCUICi3kOCYf96fDRI5jra+MMc3Z5PGR4ZaKgLy78lg2WZWgDIZOtDIdfrFJDc4AikAp3JMYXXdrJlEFlqrRXqt+cTzwBCgQCAAAAAAEDCKCGAQAAAAAAAQQiUSCGOyN7vyTS6f5I4im0Hh4KYPO5s8eCeXJrcqYFAWh14AEJQgKLeQ4Jh/3p8NEjmOtr4wxzdnk8ZHhloqAvLvyWDZZlaAMWwyp3CNHuEMhsTASy75yG3jAzxOzK2QptA0tTHnE1awEKBAQAAAAAAQMIkF8BAAAAAAABBCJRIHnvVoij+n/vw5InRVsfHC8IxwCHQk1qAPhMMUIayo2kAA==", + "description": "can finalize: three sp outputs (same scan key) - output 0 uses label=1, outputs 1 and 2 uses label=2 (same spend key)", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEDAQYBAAABDiBw4GuGVZXEwnMdM/WmrSgPuHA1VGZimIDKXc2OkAfhmgEPBAAAAAABAR+AGgYAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQCUWfs0hcwTRkOekp3AdPHTla2+gwarlNndhIFCaNDsOAIgOAjuJjqIA6Fy5rMVCyyiJMlhF6GfDplTlH+lICupcGUBAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdAot5DgmH/enw0SOY62vjDHN2eTxkeGWioC8u/JYNlmVoIQJVgb+qczFW9rmOcaJvcP12s2eGSfYrH8Xne46auOYQUCIeAot5DgmH/enw0SOY62vjDHN2eTxkeGWioC8u/JYNlmVoQHlAgZ626fJYwVg4fApkzBb1F8fvRAkSLM6qlPTi/1N2xCR7/BcNmyY7Dj0ga2aMh+lLNN7q+gCheSsEeteIdbsAAQMIoYYBAAAAAAABBCJRIJPaXrkneTYjgSVQ+GmdZjtxlvDMnUiEWLtoH+srb/y6AQlCAot5DgmH/enw0SOY62vjDHN2eTxkeGWioC8u/JYNlmVoA9QxWI3uYas6OXJbKZw3QtxmoIYd7PWRtCOw5ScHD4I0AQoEAQAAAAABAwgy5gIAAAAAAAEEIlEg/euuKHi5JCPRfXT0zBQOHpmABZeNccGDE5KAQF4w5AYBCUICi3kOCYf96fDRI5jra+MMc3Z5PGR4ZaKgLy78lg2WZWgDIZOtDIdfrFJDc4AikAp3JMYXXdrJlEFlqrRXqt+cTzwBCgQCAAAAAAEDCKKGAQAAAAAAAQQiUSD04wY25I9qev6YT6CyVFslfqroyqFuxIGT2zSJJpWHWwEJQgKLeQ4Jh/3p8NEjmOtr4wxzdnk8ZHhloqAvLvyWDZZlaAMhk60Mh1+sUkNzgCKQCnckxhdd2smUQWWqtFeq35xPPAEKBAIAAAAA", "supplementary": { + "hex": "70736274ff01fb04020000000102040200000001040101010501030106010000010e2070e06b865595c4c2731d33f5a6ad280fb870355466629880ca5dcd8e9007e19a010f040000000001011f801a0600000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf4830450221009459fb3485cc1346439e929dc074f1d395adbe8306ab94d9dd84814268d0ec3802203808ee263a8803a172e6b3150b2ca224c96117a19f0e9953947fa5202ba970650101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000011004feffffff221d028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d96656821025581bfaa733156f6b98e71a26f70fd76b3678649f62b1fc5e77b8e9ab8e61050221e028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d966568407940819eb6e9f258c158387c0a64cc16f517c7ef4409122cceaa94f4e2ff5376c4247bfc170d9b263b0e3d206b668c87e94b34deeafa00a1792b047ad78875bb00010308a186010000000000010422512093da5eb927793623812550f8699d663b7196f0cc9d488458bb681feb2b6ffcba010942028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d96656803d431588dee61ab3a39725b299c3742dc66a0861decf591b423b0e527070f8234010a04010000000001030832e60200000000000104225120fdebae2878b92423d17d74f4cc140e1e998005978d71c183139280405e30e406010942028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d966568032193ad0c875fac5243738022900a7724c6175ddac9944165aab457aadf9c4f3c010a040200000000010308a2860100000000000104225120f4e30636e48f6a7afe984fa0b2545b257eaae8caa16ec48193db34892695875b010942028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d966568032193ad0c875fac5243738022900a7724c6175ddac9944165aab457aadf9c4f3c010a040200000000", "inputs": [ { "input_index": 0, @@ -1181,37 +1209,34 @@ "outputs": [ { "output_index": 0, - "amount": 100000, + "amount": 100001, "sp_v0_info": "028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d96656803d431588dee61ab3a39725b299c3742dc66a0861decf591b423b0e527070f8234", "sp_v0_label": 1, "script": "512093da5eb927793623812550f8699d663b7196f0cc9d488458bb681feb2b6ffcba" }, { "output_index": 1, - "amount": 100000, + "amount": 190002, "sp_v0_info": "028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d966568032193ad0c875fac5243738022900a7724c6175ddac9944165aab457aadf9c4f3c", "sp_v0_label": 2, - "script": "5120f4e30636e48f6a7afe984fa0b2545b257eaae8caa16ec48193db34892695875b" + "script": "5120fdebae2878b92423d17d74f4cc140e1e998005978d71c183139280405e30e406" }, { "output_index": 2, - "amount": 100000, - "sp_v0_info": "028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d9665680316c32a7708d1ee10c86c4c04b2ef9c86de3033c4eccad90a6d034b531e71356b", - "sp_v0_label": 4, - "script": "5120863b237bbf24d2e9fe48e229b41e1e0a60f3b9b3c78279726b72a605016875e0" - }, - { - "output_index": 3, - "amount": 90000, - "script": "512079ef5688a3fa7fefc39227455b1f1c2f08c70087424d6a00f84c31421aca8da4" + "amount": 100002, + "sp_v0_info": "028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d966568032193ad0c875fac5243738022900a7724c6175ddac9944165aab457aadf9c4f3c", + "sp_v0_label": 2, + "script": "5120f4e30636e48f6a7afe984fa0b2545b257eaae8caa16ec48193db34892695875b" } - ] + ], + "task": "sign" } }, { "description": "can finalize: two inputs using per-input ECDH shares - only eligible inputs contribute shares (P2SH excluded)", - "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIHX/+DN7oavaEJzJjnIcVUgz9mY0VLyglR21zhcuA3LjAiAFXY5F4lr2Gu+QPcbwd9LpuW0Ut5Op7+w5K5bqn1Hf7gEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAFMCAAAAAUDm+qYSaPF6EBAdYlU1gogq5IWL7hM2PbgP3ygfgl/8AAAAAAD/////AfBJAgAAAAAAF6kU9F+MyiaOwm5LvomRcPE4JQ189V6HAAAAAAEER1IhAod8oC8UQFm9gtAOGzma43T3ilLO96HKN/KNeIs0DS95IQNMh6RIcvXh8AbTTYigCVkoK9RTXnR3w9aMMWWZHqGzllKuAQ4g0iImLyaHKbt8hMVYEppdaYYYXO9TXsFJwN9g3UqSwgQBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQJii2i2RG5qhwJZc9k6+xlOQgoQ86HMs4rdgtRkqJSkKCIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQMIkF8BAAAAAAABBCJRIBZV0TJCpxR530ke2cObPHWqWxzY0Ba/jLNUp013dB3eAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEBAQYBAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIHX/+DN7oavaEJzJjnIcVUgz9mY0VLyglR21zhcuA3LjAiAFXY5F4lr2Gu+QPcbwd9LpuW0Ut5Op7+w5K5bqn1Hf7gEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABDiDSIiYvJocpu3yExVgSml1phhhc71NewUnA32DdSpLCBAEPBAAAAAABAFMCAAAAAUDm+qYSaPF6EBAdYlU1gogq5IWL7hM2PbgP3ygfgl/8AAAAAAD/////AfBJAgAAAAAAF6kU9F+MyiaOwm5LvomRcPE4JQ189V6HAAAAAAEER1IhAod8oC8UQFm9gtAOGzma43T3ilLO96HKN/KNeIs0DS95IQNMh6RIcvXh8AbTTYigCVkoK9RTXnR3w9aMMWWZHqGzllKuARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQJii2i2RG5qhwJZc9k6+xlOQgoQ86HMs4rdgtRkqJSkKCIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQMIkF8BAAAAAAABBCJRIBZV0TJCpxR530ke2cObPHWqWxzY0Ba/jLNUp013dB3eAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", "supplementary": { + "hex": "70736274ff01fb04020000000102040200000001040102010501010106010000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f040000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf473044022075fff8337ba1abda109cc98e721c554833f6663454bca0951db5ce172e0372e30220055d8e45e25af61aef903dc6f077d2e9b96d14b793a9efec392b96ea9f51dfee0101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee3202100010e20d222262f268729bb7c84c558129a5d6986185cef535ec149c0df60dd4a92c204010f0400000000010053020000000140e6faa61268f17a10101d62553582882ae4858bee13363db80fdf281f825ffc0000000000ffffffff01f04902000000000017a914f45f8cca268ec26e4bbe899170f138250d7cf55e8700000000010447522102877ca02f144059bd82d00e1b399ae374f78a52cef7a1ca37f28d788b340d2f7921034c87a44872f5e1f006d34d88a00959282bd4535e7477c3d68c3165991ea1b39652ae011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682102628b68b6446e6a87025973d93afb194e420a10f3a1ccb38add82d464a894a428221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010308905f01000000000001042251201655d13242a71479df491ed9c39b3c75aa5b1cd8d016bf8cb354a74d77741dde010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, @@ -1252,13 +1277,15 @@ "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", "script": "51201655d13242a71479df491ed9c39b3c75aa5b1cd8d016bf8cb354a74d77741dde" } - ] + ], + "task": "sign" } }, { "description": "can finalize: two inputs using global ECDH share - only eligible inputs contribute shares (P2SH excluded)", - "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAIgcCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIggCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAJDBHnS2hMQoCTSqrjkx7Sdds1R9F7oEnwVmwOTpnW291xYHr49CBfdrzu1mM/XoCLxqH7UeWZPa5R6R9tZQcsgH7BAIAAAAAAQEfoIYBAAAAAAAWABQeKteHLTKUE6Vt8JaL4zgiJ4MWOyICAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/RzBEAiB1//gze6Gr2hCcyY5yHFVIM/ZmNFS8oJUdtc4XLgNy4wIgBV2OReJa9hrvkD3G8HfS6bltFLeTqe/sOSuW6p9R3+4BIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABEAT+////AAEAUwIAAAABQOb6phJo8XoQEB1iVTWCiCrkhYvuEzY9uA/fKB+CX/wAAAAAAP////8B8EkCAAAAAAAXqRT0X4zKJo7Cbku+iZFw8TglDXz1XocAAAAAAQRHUiECh3ygLxRAWb2C0A4bOZrjdPeKUs73oco38o14izQNL3khA0yHpEhy9eHwBtNNiKAJWSgr1FNedHfD1owxZZkeobOWUq4BDiDSIiYvJocpu3yExVgSml1phhhc71NewUnA32DdSpLCBAEPBAAAAAABEAT+////AAEDCJBfAQAAAAAAAQQiUSAWVdEyQqcUed9JHtnDmzx1qlsc2NAWv4yzVKdNd3Qd3gEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEBAQYBACIHAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIIAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQCQwR50toTEKAk0qq45Me0nXbNUfRe6BJ8FZsDk6Z1tvdcWB6+PQgX3a87tZjP16Ai8ah+1HlmT2uUekfbWUHLIAAQ4g907dH3W0uz5ddJwVv9tmNI9oBam01F/u4aLiAfUDu3EBDwQAAAAAAQEfoIYBAAAAAAAWABQeKteHLTKUE6Vt8JaL4zgiJ4MWOyICAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/RzBEAiB1//gze6Gr2hCcyY5yHFVIM/ZmNFS8oJUdtc4XLgNy4wIgBV2OReJa9hrvkD3G8HfS6bltFLeTqe/sOSuW6p9R3+4BIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////AAEOINIiJi8mhym7fITFWBKaXWmGGFzvU17BScDfYN1KksIEAQ8EAAAAAAEAUwIAAAABQOb6phJo8XoQEB1iVTWCiCrkhYvuEzY9uA/fKB+CX/wAAAAAAP////8B8EkCAAAAAAAXqRT0X4zKJo7Cbku+iZFw8TglDXz1XocAAAAAAQRHUiECh3ygLxRAWb2C0A4bOZrjdPeKUs73oco38o14izQNL3khA0yHpEhy9eHwBtNNiKAJWSgr1FNedHfD1owxZZkeobOWUq4BEAT+////AAEDCJBfAQAAAAAAAQQiUSAWVdEyQqcUed9JHtnDmzx1qlsc2NAWv4yzVKdNd3Qd3gEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", "supplementary": { + "hex": "70736274ff01fb0402000000010204020000000104010201050101010601002207027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b2208027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068402430479d2da1310a024d2aab8e4c7b49d76cd51f45ee8127c159b0393a675b6f75c581ebe3d0817ddaf3bb598cfd7a022f1a87ed479664f6b947a47db5941cb200010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f040000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf473044022075fff8337ba1abda109cc98e721c554833f6663454bca0951db5ce172e0372e30220055d8e45e25af61aef903dc6f077d2e9b96d14b793a9efec392b96ea9f51dfee01220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000011004feffffff00010e20d222262f268729bb7c84c558129a5d6986185cef535ec149c0df60dd4a92c204010f0400000000010053020000000140e6faa61268f17a10101d62553582882ae4858bee13363db80fdf281f825ffc0000000000ffffffff01f04902000000000017a914f45f8cca268ec26e4bbe899170f138250d7cf55e8700000000010447522102877ca02f144059bd82d00e1b399ae374f78a52cef7a1ca37f28d788b340d2f7921034c87a44872f5e1f006d34d88a00959282bd4535e7477c3d68c3165991ea1b39652ae011004feffffff00010308905f01000000000001042251201655d13242a71479df491ed9c39b3c75aa5b1cd8d016bf8cb354a74d77741dde010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, @@ -1298,13 +1325,15 @@ "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", "script": "51201655d13242a71479df491ed9c39b3c75aa5b1cd8d016bf8cb354a74d77741dde" } - ] + ], + "task": "sign" } }, { "description": "can finalize: two mixed input types - only eligible inputs contribute ECDH shares (NUMS internal key excluded)", - "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAAfsEAgAAAAABASsQJwAAAAAAACJRIFCSm3TBoElUt4tLYDXpel4HiloPKOyW1Ue/7prOgDrAAQ4gYBe1kA+Yvp46bX2crTkCjOrT9SE5p6HZ7FdpPr5smqMBDwQAAAAAARAE/v///wEXIFCSm3TBoElUt4tLYDXpel4HiloPKOyW1Ue/7prOgDrAAAEBH6CGAQAAAAAAFgAUNyH6c8IwXLL4joSJLWvWuXcmHmoiAgJDoNQOneCIJ5QWF1K65CupCVJ4QgnwY0MPCvJWNUqFu0gwRQIhAO0WpquzlGlzstbNkuuIIEIYnLRxCQgyQW7wr3v6HSWoAiA1FLIzGTu4Yav6kSdimxf0vM37oWNLD/S2liY86GL7RQEBAwQBAAAAIgYCQ6DUDp3giCeUFhdSuuQrqQlSeEIJ8GNDDwryVjVKhbsIAAAAgAEAAAABDiDnbAFxCDpMX7Sv4vbWHwCkcwG50B+NLkd4CrdULjd8CAEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghAuV6etywGNj7MVToDBS5elCZS0I1aEHqn8ExcGFEAOY3Ih4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhA9/o4HeILO0WcbkJsYhPUF1MI8kgqROMyhCMmJNTa/Vcymb868WqzAsViY2OjfUSHB/fnoevqBke8zUhiA7srpgABAwgcJQAAAAAAAAEEIlEgPyxAG2oKe3La4XJhY5bRV7fyUUpeQT24CXc2wsuWezYBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEBAQYBAAABDiBgF7WQD5i+njptfZytOQKM6tP1ITmnodnsV2k+vmyaowEPBAAAAAABASsQJwAAAAAAACJRIFCSm3TBoElUt4tLYDXpel4HiloPKOyW1Ue/7prOgDrAARAE/v///wEXIFCSm3TBoElUt4tLYDXpel4HiloPKOyW1Ue/7prOgDrAAAEOIOdsAXEIOkxftK/i9tYfAKRzAbnQH40uR3gKt1QuN3wIAQ8EAAAAAAEBH6CGAQAAAAAAFgAUNyH6c8IwXLL4joSJLWvWuXcmHmoiAgJDoNQOneCIJ5QWF1K65CupCVJ4QgnwY0MPCvJWNUqFu0gwRQIhAO0WpquzlGlzstbNkuuIIEIYnLRxCQgyQW7wr3v6HSWoAiA1FLIzGTu4Yav6kSdimxf0vM37oWNLD/S2liY86GL7RQEBAwQBAAAAIgYCQ6DUDp3giCeUFhdSuuQrqQlSeEIJ8GNDDwryVjVKhbsIAAAAgAEAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghAuV6etywGNj7MVToDBS5elCZS0I1aEHqn8ExcGFEAOY3Ih4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhA9/o4HeILO0WcbkJsYhPUF1MI8kgqROMyhCMmJNTa/Vcymb868WqzAsViY2OjfUSHB/fnoevqBke8zUhiA7srpgABAwgcJQAAAAAAAAEEIlEgPyxAG2oKe3La4XJhY5bRV7fyUUpeQT24CXc2wsuWezYBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", "supplementary": { + "hex": "70736274ff01fb04020000000102040200000001040102010501010106010000010e206017b5900f98be9e3a6d7d9cad39028cead3f52139a7a1d9ec57693ebe6c9aa3010f040000000001012b102700000000000022512050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0011004feffffff01172050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac000010e20e76c0171083a4c5fb4afe2f6d61f00a47301b9d01f8d2e47780ab7542e377c08010f040000000001011fa0860100000000001600143721fa73c2305cb2f88e84892d6bd6b977261e6a22020243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb483045022100ed16a6abb3946973b2d6cd92eb882042189cb471090832416ef0af7bfa1d25a802203514b233193bb861abfa9127629b17f4bccdfba1634b0ff4b696263ce862fb45010103040100000022060243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb080000008001000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682102e57a7adcb018d8fb3154e80c14b97a50994b42356841ea9fc13170614400e637221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe06840f7fa381de20b3b459c6e426c6213d4175308f2482a44e33284232624d4dafd573299bf3af16ab302c5626363a37d448707f7e7a1ebea0647bccd486203bb2ba6000103081c2500000000000001042251203f2c401b6a0a7b72dae172616396d157b7f2514a5e413db8097736c2cb967b36010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, @@ -1346,13 +1375,15 @@ "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", "script": "51203f2c401b6a0a7b72dae172616396d157b7f2514a5e413db8097736c2cb967b36" } - ] + ], + "task": "sign" } }, { "description": "can finalize: three sp outputs (same scan key) - each output has distinct k value", - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQQBBgEAAfsEAgAAAAABAR+AGgYAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIH2bvrz6uqFt0Kqa+PjltDT3VIfbiiHm1QtEnjAT9WsrAiAlq8iYSKvhCgxaq6TPG5n553yKIkS2xy6zrFdRfncXuAEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiBw4GuGVZXEwnMdM/WmrSgPuHA1VGZimIDKXc2OkAfhmgEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwighgEAAAAAAAEEIlEgpL1hojWVPFX7Ib8SF+ZZlw+BcVUweVNwtqhuui4/buABCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkAAQMIoIYBAAAAAAABBCJRIEZ7FHQz3K03MqLFl4fZe6tlntq7U2+lo3EHQLVhS4t1AQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AAEDCKCGAQAAAAAAAQQiUSCkZ5TVNLTq9lSGWuFY2oR7xga4HYq3jhMySv5KWUnbhQEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQABAwiQXwEAAAAAAAEEIlEgee9WiKP6f+/DkidFWx8cLwjHAIdCTWoA+EwxQhrKjaQA", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEEAQYBAAABDiBw4GuGVZXEwnMdM/WmrSgPuHA1VGZimIDKXc2OkAfhmgEPBAAAAAABAR+AGgYAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIH2bvrz6uqFt0Kqa+PjltDT3VIfbiiHm1QtEnjAT9WsrAiAlq8iYSKvhCgxaq6TPG5n553yKIkS2xy6zrFdRfncXuAEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwighgEAAAAAAAEEIlEgpL1hojWVPFX7Ib8SF+ZZlw+BcVUweVNwtqhuui4/buABCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkAAQMIoIYBAAAAAAABBCJRIEZ7FHQz3K03MqLFl4fZe6tlntq7U2+lo3EHQLVhS4t1AQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AAEDCKCGAQAAAAAAAQQiUSCkZ5TVNLTq9lSGWuFY2oR7xga4HYq3jhMySv5KWUnbhQEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQABAwiQXwEAAAAAAAEEIlEgee9WiKP6f+/DkidFWx8cLwjHAIdCTWoA+EwxQhrKjaQA", "supplementary": { + "hex": "70736274ff01fb04020000000102040200000001040101010501040106010000010e2070e06b865595c4c2731d33f5a6ad280fb870355466629880ca5dcd8e9007e19a010f040000000001011f801a0600000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf47304402207d9bbebcfabaa16dd0aa9af8f8e5b434f75487db8a21e6d50b449e3013f56b2b022025abc89848abe10a0c5aaba4cf1b99f9e77c8a2244b6c72eb3ac57517e7717b80101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee3202100010308a0860100000000000104225120a4bd61a235953c55fb21bf1217e659970f81715530795370b6a86eba2e3f6ee0010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900010308a0860100000000000104225120467b147433dcad3732a2c59787d97bab659edabb536fa5a3710740b5614b8b75010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900010308a0860100000000000104225120a46794d534b4eaf654865ae158da847bc606b81d8ab78e13324afe4a5949db85010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900010308905f010000000000010422512079ef5688a3fa7fefc39227455b1f1c2f08c70087424d6a00f84c31421aca8da400", "inputs": [ { "input_index": 0, @@ -1399,13 +1430,15 @@ "amount": 90000, "script": "512079ef5688a3fa7fefc39227455b1f1c2f08c70087424d6a00f84c31421aca8da4" } - ] + ], + "task": "sign" } }, { "description": "can finalize: three sp outputs (same scan key) / two regular outputs - k values assigned independently of output index", - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQYBBgEAAfsEAgAAAAABAR8goQcAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCICcgzDtRc5g6XoCKbBZuU04tEOEjpGhrAqg+sdM9G3B6AiBdslMBO2N4nLRYrOIxjHkT9mvR6OIXHye1MrEw+uWDNQEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiDUQOda/N1TGlkeN6vSbkryvw9v8uGRgwI1Yej8VxOPSgEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwighgEAAAAAAAEEIlEgcjuJtcY4edW50HowRRu91I43rAOOZvcm83ykCrJkq3IBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkAAQMIUMMAAAAAAAABBCJRIJxqPSOBjoIO0dDP3rljZXyOwyd7fZuGXHjXVX9d7daiAAEDCKCGAQAAAAAAAQQiUSCvFHbuA/XpiJDsVJYDYaxJHFbjCpPrKYD8MiuYN6dYugEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQABAwhQwwAAAAAAAAEEIlEgee9WiKP6f+/DkidFWx8cLwjHAIdCTWoA+EwxQhrKjaQAAQMIoIYBAAAAAAABBCJRIJ5nNdGxGWsLGu/g5NEOytKTdJZLn1mSBdF8qrYcp4VFAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AAEDCMgsAQAAAAAAAQQiUSBvxQb4BSqfWoqpuZDV6ZT0ld3tbUe6xEyqza3Y2Jkc0AA=", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEGAQYBAAABDiDUQOda/N1TGlkeN6vSbkryvw9v8uGRgwI1Yej8VxOPSgEPBAAAAAABAR8goQcAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCICcgzDtRc5g6XoCKbBZuU04tEOEjpGhrAqg+sdM9G3B6AiBdslMBO2N4nLRYrOIxjHkT9mvR6OIXHye1MrEw+uWDNQEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwighgEAAAAAAAEEIlEgcjuJtcY4edW50HowRRu91I43rAOOZvcm83ykCrJkq3IBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkAAQMIUMMAAAAAAAABBCJRIJxqPSOBjoIO0dDP3rljZXyOwyd7fZuGXHjXVX9d7daiAAEDCKCGAQAAAAAAAQQiUSCvFHbuA/XpiJDsVJYDYaxJHFbjCpPrKYD8MiuYN6dYugEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQABAwhQwwAAAAAAAAEEIlEgee9WiKP6f+/DkidFWx8cLwjHAIdCTWoA+EwxQhrKjaQAAQMIoIYBAAAAAAABBCJRIJ5nNdGxGWsLGu/g5NEOytKTdJZLn1mSBdF8qrYcp4VFAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AAEDCMgsAQAAAAAAAQQiUSBvxQb4BSqfWoqpuZDV6ZT0ld3tbUe6xEyqza3Y2Jkc0AA=", "supplementary": { + "hex": "70736274ff01fb04020000000102040200000001040101010501060106010000010e20d440e75afcdd531a591e37abd26e4af2bf0f6ff2e19183023561e8fc57138f4a010f040000000001011f20a10700000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf47304402202720cc3b5173983a5e808a6c166e534e2d10e123a4686b02a83eb1d33d1b707a02205db253013b63789cb458ace2318c7913f66bd1e8e2171f27b532b130fae583350101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee3202100010308a0860100000000000104225120723b89b5c63879d5b9d07a30451bbdd48e37ac038e66f726f37ca40ab264ab72010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce0390001030850c300000000000001042251209c6a3d23818e820ed1d0cfdeb963657c8ec3277b7d9b865c78d7557f5dedd6a200010308a0860100000000000104225120af1476ee03f5e98890ec54960361ac491c56e30a93eb2980fc322b9837a758ba010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce0390001030850c3000000000000010422512079ef5688a3fa7fefc39227455b1f1c2f08c70087424d6a00f84c31421aca8da400010308a08601000000000001042251209e6735d1b1196b0b1aefe0e4d10ecad29374964b9f599205d17caab61ca78545010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900010308c82c01000000000001042251206fc506f8052a9f5a8aa9b990d5e994f495dded6d47bac44caacdadd8d8991cd000", "inputs": [ { "input_index": 0, @@ -1462,120 +1495,15 @@ "amount": 77000, "script": "51206fc506f8052a9f5a8aa9b990d5e994f495dded6d47bac44caacdadd8d8991cd0" } - ] - } - }, - { - "description": "can finalize: P2WPKH with decoy BIP32_DERIVATION before the matching key", - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIG9hTKsWyAwmppZy4viq5wvAiLUgLqne/2rOeM2n+2JyAiAQVYeP/VlnUGDrYKAL+jNMnLJB+6EoTBEkkNEA2ex8LgEBAwQBAAAAIgYCpRa89dF+FVVFALBtY95Srqd8dFqTvkLq2/Sunj4dEqAIAAAAgP8AAAAiBgLIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvwgAAACAAAAAAAEOIPdO3R91tLs+XXScFb/bZjSPaAWptNRf7uGi4gH1A7txAQ8EAAAAAAEQBP7///8iHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCED7KT/Ebco4uD2DOYiKUOm/1W52V9ie/mpnQhLyHLVClsiHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaECKE7OYVUX3K9bolxSuuQmz41SoQqm7i1bNDt7SHfihmVmLMSKKSeC9fpXOEFP3xbKKy1Q6aHB2AOPOiYIu4yAhAAEDCBhzAQAAAAAAAQQiUSBkb0lMoLubzq0UuNt+TGlEVh+vIy58zMNr3VhpX3SRWQEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", - "supplementary": { - "inputs": [ - { - "input_index": 0, - "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", - "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", - "prevout_index": 0, - "amount": 100000, - "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", - "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", - "sequence": 4294967294, - "signed": true - } - ], - "sp_proofs": [ - { - "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", - "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", - "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", - "input_index": 0 - } - ], - "outputs": [ - { - "output_index": 0, - "amount": 95000, - "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", - "script": "5120646f494ca0bb9bcead14b8db7e4c6944561faf232e7cccc36bdd58695f749159" - } - ] - } - }, - { - "description": "can finalize: P2PKH with decoy BIP32_DERIVATION before the matching key", - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAFUCAAAAAfTCEtWu0ef2/2M/LOCcZHxXvt2TAxTZjed1A9WOlAszAAAAAAD/////AaCGAQAAAAAAGXapFB4q14ctMpQTpW3wlovjOCIngxY7iKwAAAAAIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQCKz65hp7Ug/wQxkrbclMyEJpEkQIMSdkyI3dldqY0pVQIgIIfDsRj5aZKk2iQTz/6RcPJQ4n48FMtd7z5jjDDX6oABAQMEAQAAACIGAqUWvPXRfhVVRQCwbWPeUq6nfHRak75C6tv0rp4+HRKgCAAAAID/AAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiBSJ0jrF3ZNKMpJSBXsjUnn0w1SvHNCLHyG63TjlwVylAEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEg4UDSh7RbRs1OqvpDdwYVcLq+g9G4vJUKdKn+oJIz16YBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", - "supplementary": { - "inputs": [ - { - "input_index": 0, - "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", - "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "94720597e374eb867c2c4273bc520dd3e7498dec154849ca284d7617eb482752", - "prevout_index": 0, - "amount": 100000, - "non_witness_utxo": "0200000001f4c212d5aed1e7f6ff633f2ce09c647c57bedd930314d98de77503d58e940b330000000000ffffffff01a0860100000000001976a9141e2ad7872d329413a56df0968be338222783163b88ac00000000", - "sequence": 4294967294, - "signed": true - } - ], - "sp_proofs": [ - { - "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", - "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", - "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", - "input_index": 0 - } ], - "outputs": [ - { - "output_index": 0, - "amount": 95000, - "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", - "script": "5120e140d287b45b46cd4eaafa4377061570babe83d1b8bc950a74a9fea09233d7a6" - } - ] - } - }, - { - "description": "can finalize: P2SH-P2WPKH with decoy BIP32_DERIVATION before the matching key", - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAFMCAAAAAa0yiGinxhSdpSUXfZUerAPh/iyT6DzlNGVjrZNjwndMAAAAAAD/////AaCGAQAAAAAAF6kU1JxxjCdjjcMGkgbmNVqpXZ1duKWHAAAAAAEBIKCGAQAAAAAAF6kU1JxxjCdjjcMGkgbmNVqpXZ1duKWHIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIFBuSluOMYyBrd9OR3Ekc0Wn5JubCy7y8tHyslkj1IWiAiAlJe9tm34eaBzNTTivDPyzNKKgc3+gfalxSAq06ezHBgEBAwQBAAAAAQQWABQeKteHLTKUE6Vt8JaL4zgiJ4MWOyIGAqUWvPXRfhVVRQCwbWPeUq6nfHRak75C6tv0rp4+HRKgCAAAAID/AAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiBfVGsxp4xGbEWT3iMOmTvJk1ue7NTSp39zulVcUkIDhQEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEgKV0FbmDiskmZ/sNpyGa9XoHA09MFqZ7rUSB0qfd8cFMBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", - "supplementary": { - "inputs": [ - { - "input_index": 0, - "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", - "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "850342525c55ba737fa7d2d4ec9e5b93c93b990e23de93456c468ca7316b545f", - "prevout_index": 0, - "amount": 100000, - "non_witness_utxo": "0200000001ad328868a7c6149da525177d951eac03e1fe2c93e83ce5346563ad9363c2774c0000000000ffffffff01a08601000000000017a914d49c718c27638dc3069206e6355aa95d9d5db8a58700000000", - "witness_utxo": "a08601000000000017a914d49c718c27638dc3069206e6355aa95d9d5db8a587", - "sequence": 4294967294, - "signed": true - } - ], - "sp_proofs": [ - { - "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", - "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", - "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", - "input_index": 0 - } - ], - "outputs": [ - { - "output_index": 0, - "amount": 95000, - "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", - "script": "5120295d056e60e2b24999fec369c866bd5e81c0d3d305a99eeb512074a9f77c7053" - } - ] + "task": "sign" } }, { "description": "in progress: two P2TR inputs, neither is signed", - "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAAfsEAgAAAAABAStADQMAAAAAACJRIMgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/AQMEAQAAAAEOIOJh+vHI4yk0OVQtKlp35brqbxAwWLwV/LJyqNqQxuPNAQ8EAAAAAAEQBP7///8BFyDIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvyIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQErECcAAAAAAAAiUSBDoNQOneCIJ5QWF1K65CupCVJ4QgnwY0MPCvJWNUqFuwEDBAEAAAABDiCIKHQ5bbf1J6fjPTRao7j7VR+MxUUp+Du85P11q+G6yQEPBAAAAAABEAT+////ARcgQ6DUDp3giCeUFhdSuuQrqQlSeEIJ8GNDDwryVjVKhbsiHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCEC5Xp63LAY2PsxVOgMFLl6UJlLQjVoQeqfwTFwYUQA5jciHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaED3+jgd4gs7RZxuQmxiE9QXUwjySCpE4zKEIyYk1Nr9VzKZvzrxarMCxWJjY6N9RIcH9+eh6+oGR7zNSGIDuyumAAEDCLj5AgAAAAAAAQQiUSDuvwDmhUt84x4LCQCf5zbeTa0t0Hk6nrKLDm+jAO2+FAEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEBAQYBAAABDiDiYfrxyOMpNDlULSpad+W66m8QMFi8FfyycqjakMbjzQEPBAAAAAABAStADQMAAAAAACJRIMgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/AQMEAQAAAAEQBP7///8BFyDIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvyIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQ4giCh0OW239Sen4z00WqO4+1UfjMVFKfg7vOT9davhuskBDwQAAAAAAQErECcAAAAAAAAiUSBDoNQOneCIJ5QWF1K65CupCVJ4QgnwY0MPCvJWNUqFuwEDBAEAAAABEAT+////ARcgQ6DUDp3giCeUFhdSuuQrqQlSeEIJ8GNDDwryVjVKhbsiHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCEC5Xp63LAY2PsxVOgMFLl6UJlLQjVoQeqfwTFwYUQA5jciHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaED3+jgd4gs7RZxuQmxiE9QXUwjySCpE4zKEIyYk1Nr9VzKZvzrxarMCxWJjY6N9RIcH9+eh6+oGR7zNSGIDuyumAAEDCLj5AgAAAAAAAQQiUSDuvwDmhUt84x4LCQCf5zbeTa0t0Hk6nrKLDm+jAO2+FAEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", "supplementary": { + "hex": "70736274ff01fb04020000000102040200000001040102010501010106010000010e20e261faf1c8e3293439542d2a5a77e5baea6f103058bc15fcb272a8da90c6e3cd010f040000000001012b400d030000000000225120c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf01030401000000011004feffffff011720c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee3202100010e20882874396db7f527a7e33d345aa3b8fb551f8cc54529f83bbce4fd75abe1bac9010f040000000001012b102700000000000022512043a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb01030401000000011004feffffff01172043a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682102e57a7adcb018d8fb3154e80c14b97a50994b42356841ea9fc13170614400e637221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe06840f7fa381de20b3b459c6e426c6213d4175308f2482a44e33284232624d4dafd573299bf3af16ab302c5626363a37d448707f7e7a1ebea0647bccd486203bb2ba600010308b8f90200000000000104225120eebf00e6854b7ce31e0b09009fe736de4dad2dd0793a9eb28b0e6fa300edbe14010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, @@ -1623,13 +1551,15 @@ "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", "script": "5120eebf00e6854b7ce31e0b09009fe736de4dad2dd0793a9eb28b0e6fa300edbe14" } - ] + ], + "task": "fail_sign" } }, { "description": "in progress: one P2TR input / one sp output with no ECDH shares when PSBT_OUT_SCRIPT field is not set", - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABASughgEAAAAAACJRIMgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/AQ4go8Kr7b6RMdXjhleFYNR+NopA2asmCdsgpHnDBLBkU2wBDwQAAAAAARAE/v///wEXIMgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/AAEDCBhzAQAAAAAAAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiCjwqvtvpEx1eOGV4Vg1H42ikDZqyYJ2yCkecMEsGRTbAEPBAAAAAABASughgEAAAAAACJRIMgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/ARAE/v///wEXIMgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/AAEDCBhzAQAAAAAAAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", "supplementary": { + "hex": "70736274ff01fb04020000000102040200000001040101010501010106010000010e20a3c2abedbe9131d5e386578560d47e368a40d9ab2609db20a479c304b064536c010f040000000001012ba086010000000000225120c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf011004feffffff011720c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf000103081873010000000000010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, @@ -1651,13 +1581,15 @@ "amount": 95000, "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039" } - ] + ], + "task": "fail_sign" } }, { "description": "in progress: two inputs / one sp output, input 1 missing ECDH share when PSBT_OUT_SCRIPT field is not set", - "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7AQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g907dH3W0uz5ddJwVv9tmNI9oBam01F/u4aLiAfUDu3EBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQEf8EkCAAAAAAAWABQ3IfpzwjBcsviOhIkta9a5dyYeaiIGAkOg1A6d4IgnlBYXUrrkK6kJUnhCCfBjQw8K8lY1SoW7CAAAAIABAAAAAQ4gSQv/chrf7ISJdgPfb7uyrbjEZTqaQrLW0VICyiQN4LEBDwQAAAAAARAE/v///wABAwhADQMAAAAAAAEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEBAQYBAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7AQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQ4gSQv/chrf7ISJdgPfb7uyrbjEZTqaQrLW0VICyiQN4LEBDwQAAAAAAQEf8EkCAAAAAAAWABQ3IfpzwjBcsviOhIkta9a5dyYeaiIGAkOg1A6d4IgnlBYXUrrkK6kJUnhCCfBjQw8K8lY1SoW7CAAAAIABAAAAARAE/v///wABAwhADQMAAAAAAAEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", "supplementary": { + "hex": "70736274ff01fb04020000000102040200000001040102010501010106010000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f040000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b01030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee3202100010e20490bff721adfec84897603df6fbbb2adb8c4653a9a42b2d6d15202ca240de0b1010f040000000001011ff0490200000000001600143721fa73c2305cb2f88e84892d6bd6b977261e6a22060243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb080000008001000000011004feffffff00010308400d030000000000010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, @@ -1698,13 +1630,15 @@ "amount": 200000, "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039" } - ] + ], + "task": "fail_sign" } }, { "description": "in progress: one input / two sp outputs, input 0 missing ECDH share for output 0 when PSBT_OUT_SCRIPT field is not set", - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQIBBgEAAfsEAgAAAAABAR9ADQMAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7AQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g/S309Ytav5uR/xoeQ+LjUj9QxqoZ1cIjYBQexIyagCEBDwQAAAAAARAE/v///yIdA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsIQMJH9SAORd/RNe3npYWiEnGLrP4eADEZ2fFCo84+Y79FSIeA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsQL4acjrvVeiYG5lZmpvBKzj4froBWMxwZokPImnK3kY7dzQal9KScZZNAcAkHMMi/VOQwpuZFg+CbzKTZYmMvwIAAQMIkF8BAAAAAAABCUIDZR0sBz/LAqTYLdpT8dUB13oDUGZnmFRkc7ISa2zRp94D8nDgpWMhg7arAQdOh35oANsA9cfF0vr7to+cKNSFRSQAAQMIkF8BAAAAAAABBCJRIGMlBrk4zY0hMZ/eTlk5KyP5juuXb0OS1jPxg+Iut/qxAQlCA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsAuDEwYe3IV+ZfISFp1tFkbbChHe5WhEjuZaSLTFUhgv4AA==", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQECAQYBAAABDiD9LfT1i1q/m5H/Gh5D4uNSP1DGqhnVwiNgFB7EjJqAIQEPBAAAAAABAR9ADQMAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7AQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsIQMJH9SAORd/RNe3npYWiEnGLrP4eADEZ2fFCo84+Y79FSIeA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsQL4acjrvVeiYG5lZmpvBKzj4froBWMxwZokPImnK3kY7dzQal9KScZZNAcAkHMMi/VOQwpuZFg+CbzKTZYmMvwIAAQMIkF8BAAAAAAABCUIDZR0sBz/LAqTYLdpT8dUB13oDUGZnmFRkc7ISa2zRp94D8nDgpWMhg7arAQdOh35oANsA9cfF0vr7to+cKNSFRSQAAQMIkF8BAAAAAAABBCJRIGMlBrk4zY0hMZ/eTlk5KyP5juuXb0OS1jPxg+Iut/qxAQlCA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsAuDEwYe3IV+ZfISFp1tFkbbChHe5WhEjuZaSLTFUhgv4AA==", "supplementary": { + "hex": "70736274ff01fb04020000000102040200000001040101010501020106010000010e20fd2df4f58b5abf9b91ff1a1e43e2e3523f50c6aa19d5c22360141ec48c9a8021010f040000000001011f400d0300000000001600141e2ad7872d329413a56df0968be338222783163b01030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000011004feffffff221d0352d78c41390032ad91816a697fc740d8eb909cf04d70885264b051f2385e25ec2103091fd48039177f44d7b79e96168849c62eb3f87800c46767c50a8f38f98efd15221e0352d78c41390032ad91816a697fc740d8eb909cf04d70885264b051f2385e25ec40be1a723aef55e8981b99599a9bc12b38f87eba0158cc7066890f2269cade463b77341a97d29271964d01c0241cc322fd5390c29b99160f826f329365898cbf0200010308905f01000000000001094203651d2c073fcb02a4d82dda53f1d501d77a0350666798546473b2126b6cd1a7de03f270e0a5632183b6ab01074e877e6800db00f5c7c5d2fafbb68f9c28d485452400010308905f0100000000000104225120632506b938cd8d21319fde4e59392b23f98eeb976f4392d633f183e22eb7fab10109420352d78c41390032ad91816a697fc740d8eb909cf04d70885264b051f2385e25ec02e0c4c187b7215f997c8485a75b4591b6c28477b95a1123b996922d3154860bf800", "inputs": [ { "input_index": 0, @@ -1739,13 +1673,15 @@ "sp_v0_info": "0352d78c41390032ad91816a697fc740d8eb909cf04d70885264b051f2385e25ec02e0c4c187b7215f997c8485a75b4591b6c28477b95a1123b996922d3154860bf8", "script": "5120632506b938cd8d21319fde4e59392b23f98eeb976f4392d633f183e22eb7fab1" } - ] + ], + "task": "fail_sign" } }, { "description": "in progress: large PSBT with nine mixed inputs / six outputs - some inputs signed", - "psbt": "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", + "psbt": "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", "supplementary": { + "hex": "70736274ff01fb04020000000102040200000001040109010501060106010000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f040000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf483045022100cfb1211e5838c6b05d05b197102f2dae59338491f70fa2e333c9fda0bb2eb79b02202b8de3141576c69c53171239c4852b0303179952628049be6eecad55052c070d0101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000011004feffffff221d02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df4715102103fbd173d9c48d58c5022426d05278bca17b9a8e2282666901a1b00b9e04b79949221d033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d2821030a18b9bb4199b89330eb17f8ee5ac786e0853dcd2f3ccdf1744b97ce4ede053e221d038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c21037372d179f4f628da82ccbd4e4217bdb0809f1417c9abeaa35fa805d48ad6554c221e02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df47151040c05da410487cfaec378febe6af5005e3ae6c86236818b0e55b214017eb5073edef40179575b5dcdaa9063491ac8b83fd0624d4177a4d2dd4994c4640d6b8ccde221e033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d2840001383d4661be8725ef29048f48c911f89f5f34317d7c0c0acc60ef65f1b52bfff7a96d8339b625df83abab57aa273edcd9a35c794dacbb1c861171bb267075f221e038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c40a6872d4eb119fe2af70953f752a22236b54a3b57f70e511f10bd8b42ff56b5acf6365093c480ea9f13776784945b59318ac2927d915aae244cfb683f4188a3a700010e20bcd485a709cb25d13463a1832db2194c6c9d9fe72b9699f4fe42c82bed93d326010f040000000001011fa086010000000000160014a692511c079575bf3756dabc56ad71d4284a690e220202f5b59fa5e492221ebf55ba78ad442605beae95166ba1eba3250d0bbaac7e2edc483045022100bbb0b0843e6aea07d18dcda22093ba73367983b15933bdf84300f60debca950d022050e5f0f5538f7149e48fcde427357bc12af0e7f18608a23659cf891727aabb8c0101030401000000220602f5b59fa5e492221ebf55ba78ad442605beae95166ba1eba3250d0bbaac7e2edc080000008001000000011004feffffff221d02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df4715102103a6a89b1b986a995533e17bed64500b541bb0d739071efe2ae2b7efb0a0ca6bcf221d033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d282102f6ae7b8aac9a0f9c9f04eab484062172df2e38d9f2f6ec31b404bb5a286aabf0221d038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c2102b1d3ed2fa4bc316a08eb1485fa75ed7dd54ca7a9ae18d0c4a17da93f30c385d5221e02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df47151040c34a6a2940bbe9a7356c1cc6ffe358dd4441db58897cba99c212eb75285e7da1eca11c792c97a380493345ab224de9d94c2b36ee8526ae23528171a3231de733221e033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d2840334aced8106ebaa4287daca56cca26795f2d2a739784cf6b734da3370757f499e120c0e40be40436cd74c4ef26905706f52fa7fa6e8e76451e8583783051a843221e038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c40d841a373ad2896b972b8cfea1634ff14a30f80d84cfd6ef18893397b8f346c80519c9b161a72244d0e9b64e5436c98ce9dd4e17a0728fc997b5c7bcf39cecb6800010e20a29d7767440275ca532af6091f0a5c56329895020d3b0bd88aff43b41320239c010f040000000001011fa086010000000000160014d4dc903f7116602ee358ec8edf3284e6ff0294e3220202655ef5daf05d28d1ca73ba8e211300db2b70416737183e0fa8c355ee4c1cbac6483045022100cc6550f0d334f78d183fea10a7cb74f46f29504d91d28fdfad0e705e1b7ff0e702206e1bfebb555d39ef55a6439dfb5bc575794ffde9c90eb66d020a6a77c53d30550101030401000000220602655ef5daf05d28d1ca73ba8e211300db2b70416737183e0fa8c355ee4c1cbac6080000008002000000011004feffffff221d02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df4715102103df706ff26d672fe50c6f56a2ca1e7174e75055c920bbd337e1a7d6bf2826f6dc221d033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d282103bfb86253beb96f58b8c469e442cfcf9f78a5413a95423be8e686764f2fa7bd3f221d038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c21038604aa8cff309dddf49b1f366f89c269616587fc41db608540f9431536f6646f221e02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df47151040fd2e8c22b9b672d3bb9e26d4b6da2dc3f125455a969fd8e2b2c1ba791076ad71b38c01f9218c3d6776fd895d2f3067484996d85e268390c2b433e6c4b21891f1221e033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d284052dffbf0095f29b1de24c9d68d549d1c54bce6900454fe37fd10f5c903dfee85f7bad8a72ada8e52cd9092f51d9e90b5a7e4f36ca04df98e77fbad1347305bc7221e038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c4093e1e5d4888bc1cfe02eecfa9dea144ead84f23a10fc1a301103c1e56393527b63417c6c4a5af45359ff8b6e179af73978e4d62e862eedd2a286f5278e4cb34000010e201e7fcee7bee58da88197c40959a62e0603809ade35137493df2cfa8f855304bb010f040000000001011fa086010000000000160014fb6d08dfb14f001dc98cf17c4d7322b07bf0754f22020303a0f4528d264e8e95256634b94414e2748f72962704fe57e8b0a2cc44d2383d473044022008bbd83c008e6d14e74aa91defcc9d06bf59a78efab643411f3e0399e2e2ac14022006e16d93d20da92f1d36413a08e78d0dd5195fe1ceca6d978870055c84d854b5010103040100000022060303a0f4528d264e8e95256634b94414e2748f72962704fe57e8b0a2cc44d2383d080000008003000000011004feffffff221d02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df47151021038029998c73c2b139db75557ec3011ec65ecd212447963006571852a3e92289cc221d033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d282102980bac7264e14bf820cc435b69a78df726c177eb026f1b81b52de811272f58eb221d038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c2103a27d9f1fa53e43f70835a6990954b78a35f747066f7b82b4a9ea82e8bb5e06a6221e02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df47151040381ce3c1ac9fc7f6a51536456252984768e8fbd014070239f4cb13b16793c74cc5ed677c8a7eacc173e988d353a3f289c7e2141db7a4b4145c5499ec837f36ae221e033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d284038e03463b6450dbd051065a812a6f2631087f7951e46ac84e66da811755717c093180e4d49827b8c097ca7093fe92d393f95a5d7ad849a41802dc4e4558abde9221e038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c40732aa0957a9db2c759e39aca5d0167ef13d2a34a43c812e9cc9d712d458f7b2285da7511eb16f61f9600d20be4e94dfdd2bc3ae37fd943fc34947dfc3fdc679700010e20d3115addfefba31ddf71ab5567d435cc58f4806d45fa865a8b070ec9f8741907010f040000000001011fa0860100000000001600140b1845f4c80dabe2c5dc8a567fbe410a78e486c8220203a8911beb5a48fe119cb015088cf0c3a118cf026772448972d1b70c764ac5941247304402204d1af28490d64b249307a5fa046ad7d0cc698919841a1c631724604e3b933690022024793fc6be7b0a23d3edd2ff71f79be44f597d043eb369a1d6ca9291584bafc30101030401000000220603a8911beb5a48fe119cb015088cf0c3a118cf026772448972d1b70c764ac59412080000008004000000011004feffffff221d02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df4715102102bef4738c6f327f1724b1407988959cdf2bd19210894bfd043535b61138270818221d033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d2821027eb7c1c4afcd7e62ab6ad3d2ba2733a3745220641f91903ebfe7bcc5dbdc6b5d221d038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c2103ca88bcdb6d1f5291e90c75d3da601a8bd29991eabbf7f94b2f39483e3858c9a1221e02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510400a584927102820b7b6cad6bcfb031a23a37312ad87d23f1cb5a8359be2d5ff39b6a2a2fe37cd0d53ee347f13e6b3525769b2e789f0699cb985588eac2daf10dd221e033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d284077b1572336d9bd4e2f73411eb8f6a96235a130f444cbeb07a489f447921e37489d71fd3db28a0bbaa35b88c37b7579ecdbf6ce1638700db81dfc86bf79cd1be7221e038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c405d0de8a27f0d528802cf3354a1af507bcf0fed419da641c9c0807cd754e07af8790b511c705d5fbf63305ab22afe0497facf070b5afeafcee3a690054776775600010e2090936b5863dffd85c2b8c76cd221a8deeafd52bedb0342e09652da2385b5d70d010f040000000001012ba086010000000000225120d155713c520ce2d8276164215d659ab623c5f7306f8652c1756e26833e886e0101030401000000011004feffffff011720d155713c520ce2d8276164215d659ab623c5f7306f8652c1756e26833e886e01221d02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df47151021024f2a15a4b15a6b78f0a632fc7fdf112929f64bd4dd14f67a63cf4fb8f325a204221d033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d282103802b69b360da4585512b1cf967b184010226d75ce5b762e77a0128bcb068ccbb221d038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c2102407615505ecbdea881312504eef6f4681a26316ef73d33537a7fd793f4658ea9221e02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510408f223de27986dd8792a03d9d5b662323e8697830ebabb67363881fe72c86482ae61a09268d083b8354cfc2bad35c148eeb291af622dd460634606332af1b8297221e033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d2840103ae05c10e43298376c3fee1dc5f0d04389f4f20af49346d48ead324d615d6f28fca0a318445130ea56a862019b2de0c2637db3c418c0b074b58548ae8b20c9221e038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c40f055990738544d099b159290e7f5442cb91226260174aa9d8c1c8310b7cb01ce2b94cc5d2b8fdf81667e02fb796db0e5c27877de0d41a2a0e709b01445baf29600010e20f87911fa033a02ce17f2963603ce60575db73b9a97477d481f7232d9f0a4e123010f040000000001012ba086010000000000225120d00e15fb626a7efee85c5bce676d636b6048914e9a34ace0b4cbc44bc948077a01030401000000011004feffffff011720d00e15fb626a7efee85c5bce676d636b6048914e9a34ace0b4cbc44bc948077a221d02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df4715102102153fcdfe96ae70363fd1542646d309c2132b8325540e3dd7f88e37f9796079a6221d033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d2821020faa3a0c31ae7695e769546e30aa782abd31fb681b970a13aa35cc21dfd13800221d038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c2103f313f8f475eb01e3cecbc0eaac2f726d29032c6ff7c3ad6cc3bf8bb10186527c221e02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510404320e9f60fd3c2a6f737aace546c23b0c7d76e84159c0ad289c1df4c0f8a500e51209f296f9d7d223a1d292bd41d266faacb1be843becf4b706eb15dba702806221e033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d2840e4074a6ec893eab806d5df9a74ed257e785ff378643dbaa7933c7813a7b5f6c90ca82b62539f39b38c2c72fe5cf81c22a5e641f673644f6c486b3db577464463221e038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c403b29e12cf693f272139f74452f2bccc2bcd07432dce8fb107354c1458a12a47c8544d2d6ca1e33bce0578b6508cf8a5934673f9fc435a5f84a22a54b5adcbcfc00010e20b6368bbc330cddfe9e2550edb7dfc15ae74cac9bcc7d967fe81e6f27f8597b1d010f04000000000100530200000001fea14f3d169b2b0400db14996221b31182bb9e86ca169e91b9c7bd93f9c73e880000000000ffffffff01a08601000000000017a9140df101357f73e6658500cf56f3a132d7bb8afbdd8700000000010120a08601000000000017a9140df101357f73e6658500cf56f3a132d7bb8afbdd872202020500f167cf669e7dac39e6aecda1f28c66b78ec7097eefef25d54f7be785e7f64730440220675318791a1743ceef915ca50525b5871cb6f1182d2c7134981937730b523be6022002409d795216233c3656d659c876c3c06277fa09902e57cf4e517532a87f4e1701010304010000000104160014c6bc8105ec6db60c4da53ac35cda204069e90e8a2206020500f167cf669e7dac39e6aecda1f28c66b78ec7097eefef25d54f7be785e7f6080000008007000000011004feffffff221d02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df4715102102fe7841cddfb46fdb2ca9bde56c9558c2d1b36121665659080224e24031438408221d033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d2821026f027b235a7593ca8943c6d7b7e37d92eab339617f7f0c344106c58dd0cbc6aa221d038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c21020611450c6c1944ecdecb78f61816c767fba4368f21f7e9b169779c76f23cf4cc221e02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df4715104088072551662c3eebee545f188b8dafc682973a2f218e7ca07fc8e42ff57a1134630449fd703177d7a12d0c9ced024844dc1b9e0ecad67587dd5c479431b36a1a221e033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d284016b58148f7baff783e4310f185503fe92417dba43b966c83a2184322cb1f20424cb9d040ae6a1aea4e7444bdc786258a975644ce1a0195564c2b9fc3c606a292221e038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c404ab36bdd69eb1cd0d4b0aeae403dce4db5228c5ba3a291dc725de23382d1736d265d7bc33f83690a5ca5609719f19e81952d4c8d5e288fd0cb8c6411104b80a300010e2003bceba5379d73daeafe677972b03dcf7ef30b7f10eaa83ad04bc0bf00d8b2f7010f040000000001005502000000012a34ac1b0db77a8198c1e29002cc47bbfcd6ed830960304d2c9a3ab548486b5d0000000000ffffffff01a0860100000000001976a914569bf311e68a383767b43f83042dfabe60093ede88ac00000000220203199d2f155f32ebb167aeb0ccca6e5afb7340898df1b7ab9936500f6d4391902a473044022007f37a98a7ea09f615449a3f800df2ec55c23311ce2b1a451716e39e79d1f12d022050f55e799e2be3d670bc66a68ec96223e0d1ee39602e468db2cc7b25c87aa6e00101030401000000220603199d2f155f32ebb167aeb0ccca6e5afb7340898df1b7ab9936500f6d4391902a080000008008000000011004feffffff221d02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df4715102102f3c175b08b207637616aa74e67baac1a1807c94bce70800f76f5b17b52c0082d221d033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d282102fa1ced932598a27fa28410b955ea67479b5a4033b69f2c99e4e26767bba0a556221d038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c210300e0fd1710dc56ad7c173aa9141d731577009bc3dffcba8576a48e77ab34d970221e02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df4715104099225658fede7a8c2437eb3821bdc9d3700abc896e8b6dcef84e29347b78bc2b03e6da33836e4f40767390c36644ce016b36b1d546963540fa51d0b0407db6d7221e033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d2840a0948c517d70976c0e39ca67abf19e7217040dbe172bb96534133e6ffa3941c1659416f540662b7561efb70064b4d71a9b17b63bc563f630db4422f273e0df12221e038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c40ee0aaa65ca73ccc547b31c2b7ed2ae31a4f4ccdaea73f2add24630d608ede9aea5d808688186ebca42b877efab13f35e60f210d4f620602f850fc0731c201e9100010308307500000000000001042251201afa5d88188cef9b91b3f1002b11e0f9e94ad3981978c4d12a0605564c081233010942033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28031266581e3e841cbb94de62ea735583a232c4c888fa6edef2ec2f870789fc1dd40001030830750000000000000104225120cabf7e4a0de424ec9bbadd7f7242cce7673e1701f49d6a19a97055da332b1324010942033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28031266581e3e841cbb94de62ea735583a232c4c888fa6edef2ec2f870789fc1dd400010308204e00000000000001042251204aadc9e0a590d21e0c19cb2024f27140f9b19c2a1282d50ea7c5f45eb03fd4a201094202a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510024a48d76e20d40bcf5f2e1a5c3ffeb3dc2a8b3b88d79a486d54c9d9eaa8fa188e00010308204e00000000000001042251202fa43700ea1d28fd7ad4dcb332b3e5e5a0d8cb54258f6661c4de0377d72804e501094202a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510024a48d76e20d40bcf5f2e1a5c3ffeb3dc2a8b3b88d79a486d54c9d9eaa8fa188e000103081027000000000000010422512051986faee319436b51b38409c1b300f4396e2b32e3cc9a12ae2a4be135da6f6e010942038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c03f81473844c9d74c921ff17a5af410b6337348d7afbff73891bc5cb0cb24cb0c00001030850c300000000000001042251206fc506f8052a9f5a8aa9b990d5e994f495dded6d47bac44caacdadd8d8991cd000", "inputs": [ { "input_index": 0, @@ -2055,145 +1991,83 @@ "amount": 50000, "script": "51206fc506f8052a9f5a8aa9b990d5e994f495dded6d47bac44caacdadd8d8991cd0" } - ] - } - } - ], - "workflows": [ - { - "step": "created", - "description": "Creator produces an empty PSBT v2", - "supplementary": {}, - "expected": { - "psbt": "cHNidP8BAgQCAAAAAQQBAAEFAQABBgEDAfsEAgAAAAA=" + ], + "task": "fail_sign" } }, { - "step": "constructed", - "description": "Constructor adds inputs and SP outputs (no ECDH yet)", + "description": "can finalize: P2WPKH with decoy BIP32_DERIVATION before the matching key", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIG9hTKsWyAwmppZy4viq5wvAiLUgLqne/2rOeM2n+2JyAiAQVYeP/VlnUGDrYKAL+jNMnLJB+6EoTBEkkNEA2ex8LgEBAwQBAAAAIgYCpRa89dF+FVVFALBtY95Srqd8dFqTvkLq2/Sunj4dEqAIAAAAgP8AAAAiBgLIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvwgAAACAAAAAAAEQBP7///8iHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCED7KT/Ebco4uD2DOYiKUOm/1W52V9ie/mpnQhLyHLVClsiHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaECKE7OYVUX3K9bolxSuuQmz41SoQqm7i1bNDt7SHfihmVmLMSKKSeC9fpXOEFP3xbKKy1Q6aHB2AOPOiYIu4yAhAAEDCBhzAQAAAAAAAQQiUSBkb0lMoLubzq0UuNt+TGlEVh+vIy58zMNr3VhpX3SRWQEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", "supplementary": { - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEDAfsEAgAAAAABDiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEPBAAAAAAAAQMIAAAAAAAAAAAA", + "hex": "70736274ff01fb04020000000102040200000001040101010501010106010000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f040000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf47304402206f614cab16c80c26a69672e2f8aae70bc088b5202ea9deff6ace78cda7fb627202201055878ffd59675060eb60a00bfa334c9cb241fba1284c112490d100d9ec7c2e0101030401000000220602a516bcf5d17e15554500b06d63de52aea77c745a93be42eadbf4ae9e3e1d12a00800000080ff000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee320210001030818730100000000000104225120646f494ca0bb9bcead14b8db7e4c6944561faf232e7cccc36bdd58695f749159010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, - "prevout_txid": "6244422c1833da958781dacfc349368ab886650033514ba7c773691a5da057ab", + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", "prevout_index": 0, - "sequence": 4294967294 + "amount": 100000, + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", + "input_index": 0 } ], "outputs": [ { "output_index": 0, - "amount": 90000, - "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039" + "amount": 95000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "5120646f494ca0bb9bcead14b8db7e4c6944561faf232e7cccc36bdd58695f749159" } - ] - }, - "expected": { - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEDAfsEAgAAAAABAR+ghgEAAAAAABYAFMFaMn8CdS4U7n3BlH5Fe7aOmXikAQ4gq1egXRppc8enS1EzAGWGuIo2ScPP2oGHldozGCxCRGIBDwQAAAAAARAE/v///wABAwiQXwEAAAAAAAEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", - "unique_id": "541c997611395ccf867da76839dd0da75f2a5ead4ce22eef2c0d987544368266" + ], + "task": "deserialize" } }, { - "step": "updated", - "description": "Updater adds UTXO/pubkey data plus ECDH shares and DLEQ proofs", + "description": "can finalize: P2PKH with decoy BIP32_DERIVATION before the matching key", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiBSJ0jrF3ZNKMpJSBXsjUnn0w1SvHNCLHyG63TjlwVylAEPBAAAAAABAFUCAAAAAfTCEtWu0ef2/2M/LOCcZHxXvt2TAxTZjed1A9WOlAszAAAAAAD/////AaCGAQAAAAAAGXapFB4q14ctMpQTpW3wlovjOCIngxY7iKwAAAAAIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQCKz65hp7Ug/wQxkrbclMyEJpEkQIMSdkyI3dldqY0pVQIgIIfDsRj5aZKk2iQTz/6RcPJQ4n48FMtd7z5jjDDX6oABAQMEAQAAACIGAqUWvPXRfhVVRQCwbWPeUq6nfHRak75C6tv0rp4+HRKgCAAAAID/AAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEg4UDSh7RbRs1OqvpDdwYVcLq+g9G4vJUKdKn+oJIz16YBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", "supplementary": { - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEDAfsEAgAAAAABAR+ghgEAAAAAABYAFMFaMn8CdS4U7n3BlH5Fe7aOmXikAQ4gq1egXRppc8enS1EzAGWGuIo2ScPP2oGHldozGCxCRGIBDwQAAAAAARAE/v///wABAwiQXwEAAAAAAAEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "hex": "70736274ff01fb04020000000102040200000001040101010501010106010000010e20522748eb17764d28ca494815ec8d49e7d30d52bc73422c7c86eb74e397057294010f04000000000100550200000001f4c212d5aed1e7f6ff633f2ce09c647c57bedd930314d98de77503d58e940b330000000000ffffffff01a0860100000000001976a9141e2ad7872d329413a56df0968be338222783163b88ac00000000220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf4830450221008acfae61a7b520ff043192b6dc94cc84269124408312764c88ddd95da98d295502202087c3b118f96992a4da2413cffe9170f250e27e3c14cb5def3e638c30d7ea800101030401000000220602a516bcf5d17e15554500b06d63de52aea77c745a93be42eadbf4ae9e3e1d12a00800000080ff000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee320210001030818730100000000000104225120e140d287b45b46cd4eaafa4377061570babe83d1b8bc950a74a9fea09233d7a6010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, - "public_key": "0356c51fd2d03d6907ec025384e68ee2329f1e48dabb18144a959fc6a67425e245", - "prevout_txid": "6244422c1833da958781dacfc349368ab886650033514ba7c773691a5da057ab", + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "94720597e374eb867c2c4273bc520dd3e7498dec154849ca284d7617eb482752", "prevout_index": 0, "amount": 100000, - "witness_utxo": "a086010000000000160014c15a327f02752e14ee7dc1947e457bb68e9978a4", - "sequence": 4294967294 + "non_witness_utxo": "0200000001f4c212d5aed1e7f6ff633f2ce09c647c57bedd930314d98de77503d58e940b330000000000ffffffff01a0860100000000001976a9141e2ad7872d329413a56df0968be338222783163b88ac00000000", + "sequence": 4294967294, + "signed": true } ], "sp_proofs": [ { "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", - "ecdh_share": "034e54f4dff2bb9cee30e30e93bdbff7508b1f11085f2b794731b680f4d7c71642", - "dleq_proof": "f3eb7de65597bcf0b182396aae454ba61f5633e7ceae3c9a1ad2b9f1a5fe81826ed402b27a2d28c933f50111c715c0afca99af088aad9690f31ee970a2a0842a" + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", + "input_index": 0 } ], "outputs": [ { "output_index": 0, - "amount": 90000, - "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039" - } - ] - }, - "expected": { - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEDAfsEAgAAAAABAR+ghgEAAAAAABYAFMFaMn8CdS4U7n3BlH5Fe7aOmXikIgYDVsUf0tA9aQfsAlOE5o7iMp8eSNq7GBRKlZ/GpnQl4kUEAAAAAAEOIKtXoF0aaXPHp0tRMwBlhriKNknDz9qBh5XaMxgsQkRiAQ8EAAAAAAEQBP7///8iHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCEDTlT03/K7nO4w4w6Tvb/3UIsfEQhfK3lHMbaA9NfHFkIiHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaEAtPzykoyXOiOFG75KyWIqahljrU3l0nB7OaDK5ObNoabNWz+GGhg3J8Om3M9Fkvdp4EriHDkBvYoM6fROVLjMRAAEDCJBfAQAAAAAAAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", - "unique_id": "541c997611395ccf867da76839dd0da75f2a5ead4ce22eef2c0d987544368266" - } - }, - { - "step": "sp_finalized", - "description": "SP Output Finalizer computes the silent payment output scripts", - "supplementary": { - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEDAfsEAgAAAAABAR+ghgEAAAAAABYAFMFaMn8CdS4U7n3BlH5Fe7aOmXikIgYDVsUf0tA9aQfsAlOE5o7iMp8eSNq7GBRKlZ/GpnQl4kUEAAAAAAEOIKtXoF0aaXPHp0tRMwBlhriKNknDz9qBh5XaMxgsQkRiAQ8EAAAAAAEQBP7///8iHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCEDTlT03/K7nO4w4w6Tvb/3UIsfEQhfK3lHMbaA9NfHFkIiHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaEAtPzykoyXOiOFG75KyWIqahljrU3l0nB7OaDK5ObNoabNWz+GGhg3J8Om3M9Fkvdp4EriHDkBvYoM6fROVLjMRAAEDCJBfAQAAAAAAAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", - "outputs": [ - { - "output_index": 0, - "amount": 90000, + "amount": 95000, "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", - "script": "5120aa55e2357f08a95293e2e28f9bfedb2f7f1af12c7419a2bb15b79b923c9f5d04" - } - ] - }, - "expected": { - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFMFaMn8CdS4U7n3BlH5Fe7aOmXikIgYDVsUf0tA9aQfsAlOE5o7iMp8eSNq7GBRKlZ/GpnQl4kUEAAAAAAEOIKtXoF0aaXPHp0tRMwBlhriKNknDz9qBh5XaMxgsQkRiAQ8EAAAAAAEQBP7///8iHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCEDTlT03/K7nO4w4w6Tvb/3UIsfEQhfK3lHMbaA9NfHFkIiHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaEAtPzykoyXOiOFG75KyWIqahljrU3l0nB7OaDK5ObNoabNWz+GGhg3J8Om3M9Fkvdp4EriHDkBvYoM6fROVLjMRAAEDCJBfAQAAAAAAAQQiUSCqVeI1fwipUpPi4o+b/tsvfxrxLHQZorsVt5uSPJ9dBAEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", - "unique_id": "541c997611395ccf867da76839dd0da75f2a5ead4ce22eef2c0d987544368266" - } - }, - { - "step": "signed", - "description": "Signer signs the eligible inputs", - "supplementary": { - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFMFaMn8CdS4U7n3BlH5Fe7aOmXikIgYDVsUf0tA9aQfsAlOE5o7iMp8eSNq7GBRKlZ/GpnQl4kUEAAAAAAEOIKtXoF0aaXPHp0tRMwBlhriKNknDz9qBh5XaMxgsQkRiAQ8EAAAAAAEQBP7///8iHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCEDTlT03/K7nO4w4w6Tvb/3UIsfEQhfK3lHMbaA9NfHFkIiHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaEAtPzykoyXOiOFG75KyWIqahljrU3l0nB7OaDK5ObNoabNWz+GGhg3J8Om3M9Fkvdp4EriHDkBvYoM6fROVLjMRAAEDCJBfAQAAAAAAAQQiUSCqVeI1fwipUpPi4o+b/tsvfxrxLHQZorsVt5uSPJ9dBAEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", - "inputs": [ - { - "input_index": 0, - "private_key": "e8a1d3762682c9f559441aa519b61c269d59210cdb9a59ac37f5d83a6f725015", - "signed": true - } - ] - }, - "expected": { - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFMFaMn8CdS4U7n3BlH5Fe7aOmXikIgIDVsUf0tA9aQfsAlOE5o7iMp8eSNq7GBRKlZ/GpnQl4kVHMEQCIGAUx1TZpeshKb1hh+8lRn9ZpgkuEze7li5arLlNMqnfAiBZFLtCV9tnbvdefmsXbuZRFJTifFPN8ibm9owXrCI7yAEiBgNWxR/S0D1pB+wCU4TmjuIynx5I2rsYFEqVn8amdCXiRQQAAAAAAQ4gq1egXRppc8enS1EzAGWGuIo2ScPP2oGHldozGCxCRGIBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQNOVPTf8ruc7jDjDpO9v/dQix8RCF8reUcxtoD018cWQiIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQC0/PKSjJc6I4UbvkrJYipqGWOtTeXScHs5oMrk5s2hps1bP4YaGDcnw6bcz0WS92ngSuIcOQG9igzp9E5UuMxEAAQMIkF8BAAAAAAABBCJRIKpV4jV/CKlSk+Lij5v+2y9/GvEsdBmiuxW3m5I8n10EAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", - "unique_id": "541c997611395ccf867da76839dd0da75f2a5ead4ce22eef2c0d987544368266" - } - }, - { - "step": "finalized", - "description": "Input Finalizer builds the final scriptwitness", - "supplementary": { - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFMFaMn8CdS4U7n3BlH5Fe7aOmXikIgIDVsUf0tA9aQfsAlOE5o7iMp8eSNq7GBRKlZ/GpnQl4kVHMEQCIGAUx1TZpeshKb1hh+8lRn9ZpgkuEze7li5arLlNMqnfAiBZFLtCV9tnbvdefmsXbuZRFJTifFPN8ibm9owXrCI7yAEiBgNWxR/S0D1pB+wCU4TmjuIynx5I2rsYFEqVn8amdCXiRQQAAAAAAQ4gq1egXRppc8enS1EzAGWGuIo2ScPP2oGHldozGCxCRGIBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQNOVPTf8ruc7jDjDpO9v/dQix8RCF8reUcxtoD018cWQiIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQC0/PKSjJc6I4UbvkrJYipqGWOtTeXScHs5oMrk5s2hps1bP4YaGDcnw6bcz0WS92ngSuIcOQG9igzp9E5UuMxEAAQMIkF8BAAAAAAABBCJRIKpV4jV/CKlSk+Lij5v+2y9/GvEsdBmiuxW3m5I8n10EAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", - "inputs": [ - { - "input_index": 0, - "signed": true + "script": "5120e140d287b45b46cd4eaafa4377061570babe83d1b8bc950a74a9fea09233d7a6" } - ] - }, - "expected": { - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFMFaMn8CdS4U7n3BlH5Fe7aOmXikAQhrAkcwRAIgYBTHVNml6yEpvWGH7yVGf1mmCS4TN7uWLlqsuU0yqd8CIFkUu0JX22du915+axdu5lEUlOJ8U83yJub2jBesIjvIASEDVsUf0tA9aQfsAlOE5o7iMp8eSNq7GBRKlZ/GpnQl4kUBDiCrV6BdGmlzx6dLUTMAZYa4ijZJw8/agYeV2jMYLEJEYgEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA05U9N/yu5zuMOMOk72/91CLHxEIXyt5RzG2gPTXxxZCIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhALT88pKMlzojhRu+SsliKmoZY61N5dJwezmgyuTmzaGmzVs/hhoYNyfDptzPRZL3aeBK4hw5Ab2KDOn0TlS4zEQABAwiQXwEAAAAAAAEEIlEgqlXiNX8IqVKT4uKPm/7bL38a8Sx0GaK7FbebkjyfXQQBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", - "unique_id": "541c997611395ccf867da76839dd0da75f2a5ead4ce22eef2c0d987544368266" - } - }, - { - "step": "transaction", - "description": "Extractor produces the raw transaction", - "supplementary": { - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFMFaMn8CdS4U7n3BlH5Fe7aOmXikAQhrAkcwRAIgYBTHVNml6yEpvWGH7yVGf1mmCS4TN7uWLlqsuU0yqd8CIFkUu0JX22du915+axdu5lEUlOJ8U83yJub2jBesIjvIASEDVsUf0tA9aQfsAlOE5o7iMp8eSNq7GBRKlZ/GpnQl4kUBDiCrV6BdGmlzx6dLUTMAZYa4ijZJw8/agYeV2jMYLEJEYgEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA05U9N/yu5zuMOMOk72/91CLHxEIXyt5RzG2gPTXxxZCIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhALT88pKMlzojhRu+SsliKmoZY61N5dJwezmgyuTmzaGmzVs/hhoYNyfDptzPRZL3aeBK4hw5Ab2KDOn0TlS4zEQABAwiQXwEAAAAAAAEEIlEgqlXiNX8IqVKT4uKPm/7bL38a8Sx0GaK7FbebkjyfXQQBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA" - }, - "expected": { - "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFMFaMn8CdS4U7n3BlH5Fe7aOmXikAQhrAkcwRAIgYBTHVNml6yEpvWGH7yVGf1mmCS4TN7uWLlqsuU0yqd8CIFkUu0JX22du915+axdu5lEUlOJ8U83yJub2jBesIjvIASEDVsUf0tA9aQfsAlOE5o7iMp8eSNq7GBRKlZ/GpnQl4kUBDiCrV6BdGmlzx6dLUTMAZYa4ijZJw8/agYeV2jMYLEJEYgEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA05U9N/yu5zuMOMOk72/91CLHxEIXyt5RzG2gPTXxxZCIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhALT88pKMlzojhRu+SsliKmoZY61N5dJwezmgyuTmzaGmzVs/hhoYNyfDptzPRZL3aeBK4hw5Ab2KDOn0TlS4zEQABAwiQXwEAAAAAAAEEIlEgqlXiNX8IqVKT4uKPm/7bL38a8Sx0GaK7FbebkjyfXQQBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", - "unique_id": "541c997611395ccf867da76839dd0da75f2a5ead4ce22eef2c0d987544368266", - "tx": "02000000000101ab57a05d1a6973c7a74b5133006586b88a3649c3cfda818795da33182c4244620000000000feffffff01905f010000000000225120aa55e2357f08a95293e2e28f9bfedb2f7f1af12c7419a2bb15b79b923c9f5d040247304402206014c754d9a5eb2129bd6187ef25467f59a6092e1337bb962e5aacb94d32a9df02205914bb4257db676ef75e7e6b176ee6511494e27c53cdf226e6f68c17ac223bc801210356c51fd2d03d6907ec025384e68ee2329f1e48dabb18144a959fc6a67425e24500000000" + ], + "task": "deserialize" } } ] From 6fc4630beadb175803b103ee8ed98152db31f886 Mon Sep 17 00:00:00 2001 From: Jasper van Gelder Date: Tue, 23 Jun 2026 16:17:55 +0200 Subject: [PATCH 23/26] chore(psbtv2): Cleanup redundant code - Created reusable taggedChallenge/tagged hash function (can be replaced with bitcoinJs tagged hash if needed) - Added verifyDleq proof for external use to prevent recalculation of points. --- packages/caravan-psbt/src/psbtv2/dleq.test.ts | 1 - packages/caravan-psbt/src/psbtv2/dleq.ts | 124 ++++++++++-------- packages/caravan-psbt/src/psbtv2/functions.ts | 6 + .../caravan-psbt/src/psbtv2/silentpayment.ts | 27 +--- 4 files changed, 75 insertions(+), 83 deletions(-) diff --git a/packages/caravan-psbt/src/psbtv2/dleq.test.ts b/packages/caravan-psbt/src/psbtv2/dleq.test.ts index 482a78ec1c..364d69b58a 100644 --- a/packages/caravan-psbt/src/psbtv2/dleq.test.ts +++ b/packages/caravan-psbt/src/psbtv2/dleq.test.ts @@ -6,7 +6,6 @@ import { multiplyCompressedPoint, verifyDLEQProof, } from "./dleq"; -import { verifySilentPaymentDLEQProof } from "./silentpayment"; function hex(s: string): Buffer { return Buffer.from(s, "hex"); } diff --git a/packages/caravan-psbt/src/psbtv2/dleq.ts b/packages/caravan-psbt/src/psbtv2/dleq.ts index 516f030c16..24cdb381a2 100644 --- a/packages/caravan-psbt/src/psbtv2/dleq.ts +++ b/packages/caravan-psbt/src/psbtv2/dleq.ts @@ -1,9 +1,8 @@ import { randomBytes } from "crypto"; - import { secp256k1 } from "@noble/curves/secp256k1"; -import { sha256 } from "@noble/hashes/sha256"; import { bytesToNumberBE, numberToBytesBE } from "@noble/curves/abstract/utils"; import { mod } from "@noble/curves/abstract/modular"; +import { taggedHash } from "./functions"; export type ProjectivePoint = InstanceType; @@ -11,11 +10,6 @@ const N = secp256k1.CURVE.n; const G = secp256k1.ProjectivePoint.BASE; const ZERO = secp256k1.ProjectivePoint.ZERO; -function taggedHash(tag: string, msg: Buffer): Buffer { - const tagHash = Buffer.from(sha256(Buffer.from(tag, "utf8"))); - return Buffer.from(sha256(Buffer.concat([tagHash, tagHash, msg]))); -} - function scalarFromPrivateKey(bytes: Buffer, context: string): bigint { if (!secp256k1.utils.isValidPrivateKey(bytes)) { throw new Error(`${context}: invalid secp256k1 scalar.`); @@ -58,7 +52,7 @@ function pointFromCompressed(bytes: Buffer): ProjectivePoint { return secp256k1.ProjectivePoint.fromHex(bytes); } -function pointToCompressedBytes(point: typeof G): Buffer { +function pointToCompressedBytes(point: ProjectivePoint): Buffer { if (point.equals(ZERO)) { throw new Error("Cannot serialize point at infinity."); } @@ -88,6 +82,28 @@ export function multiplyCompressedPoint( return Buffer.from(result.toRawBytes(true)); } +function getTaggedChallenge( + A: ProjectivePoint, + B: ProjectivePoint, + C: ProjectivePoint, + R1: ProjectivePoint, + R2: ProjectivePoint, + m: Buffer, +): Buffer { + return taggedHash( + "BIP0374/challenge", + Buffer.concat([ + pointToCompressedBytes(A), + pointToCompressedBytes(B), + pointToCompressedBytes(C), + pointToCompressedBytes(G), + pointToCompressedBytes(R1), + pointToCompressedBytes(R2), + m, + ]), + ); +} + export function generateDLEQProof({ secret, basePoint, @@ -113,7 +129,6 @@ export function generateDLEQProof({ } const ABytes = Buffer.from(A.toRawBytes(true)); - const BBytes = Buffer.from(B.toRawBytes(true)); const CBytes = Buffer.from(C.toRawBytes(true)); const t = xor32(secret, taggedHash("BIP0374/aux", auxRand)); @@ -136,21 +151,7 @@ export function generateDLEQProof({ throw new Error("BIP374 nonce produced point at infinity."); } - const R1Bytes = Buffer.from(R1.toRawBytes(true)); - const R2Bytes = Buffer.from(R2.toRawBytes(true)); - - const eBytes = taggedHash( - "BIP0374/challenge", - Buffer.concat([ - ABytes, - BBytes, - CBytes, - Buffer.from(G.toRawBytes(true)), - R1Bytes, - R2Bytes, - m, - ]), - ); + const eBytes = getTaggedChallenge(A, B, C, R1, R2, m); const e = bytesToNumberBE(eBytes); const s = mod(k + mod(e, N) * a, N); @@ -158,10 +159,10 @@ export function generateDLEQProof({ const proof = Buffer.concat([eBytes, Buffer.from(numberToBytesBE(s, 32))]); if ( - !verifyDLEQProof({ - publicKey: ABytes, - basePoint, - result: CBytes, + !verifyDLEQProofForPoints({ + A, + B, + C, proof, message, }) @@ -172,16 +173,16 @@ export function generateDLEQProof({ return proof; } -export function verifyDLEQProof({ - publicKey, - basePoint, - result, +function verifyDLEQProofForPoints({ + A, + B, + C, proof, message, }: { - publicKey: Buffer; - basePoint: Buffer; - result: Buffer; + A: ProjectivePoint; + B: ProjectivePoint; + C: ProjectivePoint; proof: Buffer; message?: Buffer; }): boolean { @@ -189,17 +190,6 @@ export function verifyDLEQProof({ return false; } - let A: ProjectivePoint; - let B: ProjectivePoint; - let C: ProjectivePoint; - try { - A = pointFromCompressed(publicKey); - B = pointFromCompressed(basePoint); - C = pointFromCompressed(result); - } catch { - return false; - } - const eBytes = proof.subarray(0, 32); const sBytes = proof.subarray(32, 64); @@ -226,18 +216,36 @@ export function verifyDLEQProof({ } catch { return false; } - const expectedE = taggedHash( - "BIP0374/challenge", - Buffer.concat([ - pointToCompressedBytes(A), - pointToCompressedBytes(B), - pointToCompressedBytes(C), - pointToCompressedBytes(G), - pointToCompressedBytes(R1), - pointToCompressedBytes(R2), - m, - ]), - ); + + const expectedE = getTaggedChallenge(A, B, C, R1, R2, m); return expectedE.equals(eBytes); } + +export function verifyDLEQProof({ + publicKey, + basePoint, + result, + proof, + message, +}: { + publicKey: Buffer; + basePoint: Buffer; + result: Buffer; + proof: Buffer; + message?: Buffer; +}): boolean { + let A: ProjectivePoint; + let B: ProjectivePoint; + let C: ProjectivePoint; + + try { + A = pointFromCompressed(publicKey); + B = pointFromCompressed(basePoint); + C = pointFromCompressed(result); + } catch { + return false; + } + + return verifyDLEQProofForPoints({ A, B, C, proof, message }); +} diff --git a/packages/caravan-psbt/src/psbtv2/functions.ts b/packages/caravan-psbt/src/psbtv2/functions.ts index d52f3f3b09..d53cda4441 100644 --- a/packages/caravan-psbt/src/psbtv2/functions.ts +++ b/packages/caravan-psbt/src/psbtv2/functions.ts @@ -1,5 +1,6 @@ import { BufferReader, BufferWriter } from "bufio"; import { validateBIP32Path } from "@caravan/bitcoin"; +import { sha256 } from "@noble/hashes/sha2"; import { PSBT_MAGIC_BYTES } from "../constants"; import { Key, Value, NonUniqueKeyTypeValue, KeyType } from "./types"; import { @@ -142,3 +143,8 @@ export function getPsbtVersionNumber(psbt: string | Buffer): number { readAndSetKeyPairs(map, br); return map.get(KeyType.PSBT_GLOBAL_VERSION)?.readUInt32LE(0) || 0; } + +export function taggedHash(tag: string, msg: Buffer): Buffer { + const tagHash = Buffer.from(sha256(Buffer.from(tag, "utf8"))); + return Buffer.from(sha256(Buffer.concat([tagHash, tagHash, msg]))); +} diff --git a/packages/caravan-psbt/src/psbtv2/silentpayment.ts b/packages/caravan-psbt/src/psbtv2/silentpayment.ts index b3701e3e3f..079248bb81 100644 --- a/packages/caravan-psbt/src/psbtv2/silentpayment.ts +++ b/packages/caravan-psbt/src/psbtv2/silentpayment.ts @@ -11,6 +11,7 @@ import { secp256k1, schnorr } from "@noble/curves/secp256k1"; import { createHash } from "crypto"; import { script } from "bitcoinjs-lib-v6"; +import { taggedHash } from "./functions"; const CURVE_ORDER = secp256k1.CURVE.n; const { bytesToNumberBE } = schnorr.utils; @@ -185,28 +186,6 @@ function assertValidScalar(value: bigint, name: string): void { } } -// ── Tagged hash ──────────────────────────────────────────────────────────── - -/** - * Computes a BIP340 tagged hash. - * - * ``` - * taggedHash(tag, data) = SHA256(SHA256(tag) || SHA256(tag) || data) - * ``` - * - * @param tag - ASCII tag string, e.g. `"BIP0352/Inputs"`. - * @param data - Arbitrary data to hash. - * @returns 32-byte hash buffer. - */ -export function bip352TaggedHash(tag: string, data: Buffer): Buffer { - const tagHash = createHash("sha256").update(tag).digest(); - return createHash("sha256") - .update(tagHash) - .update(tagHash) - .update(data) - .digest(); -} - // ── Eligible input indices ───────────────────────────────────────────────── function readWitnessUtxoScript(witnessUtxo: Buffer): Buffer { @@ -516,7 +495,7 @@ export function computeInputHash( } const sorted = [...outpoints].sort(Buffer.compare); const data = Buffer.concat([sorted[0], combinedPubkey]); - return bip352TaggedHash("BIP0352/Inputs", data); + return taggedHash("BIP0352/Inputs", data); } // ── Output script derivation ─────────────────────────────────────────────── @@ -563,7 +542,7 @@ export function deriveSilentPaymentOutput( // tweak_k = taggedHash("BIP0352/SharedSecret", ecdhSecret_compressed || k_be32) const kBuf = Buffer.allocUnsafe(4); kBuf.writeUInt32BE(k, 0); - const tweak = bip352TaggedHash( + const tweak = taggedHash( "BIP0352/SharedSecret", Buffer.concat([ecdhSecretBytes, kBuf]), ); From 0275c92e87fb3d7bda09223214cbbdace0f6db90 Mon Sep 17 00:00:00 2001 From: Jasper van Gelder Date: Tue, 23 Jun 2026 17:25:30 +0200 Subject: [PATCH 24/26] chore(psbtv2): Revert PSBT_OUT_SCRIPT changes Instead of returning an empty string, throw error and handle it. --- .../src/psbtv2/psbtv2-bip375.test.ts | 19 ++++++-- packages/caravan-psbt/src/psbtv2/psbtv2.ts | 43 +++++++++++-------- 2 files changed, 41 insertions(+), 21 deletions(-) diff --git a/packages/caravan-psbt/src/psbtv2/psbtv2-bip375.test.ts b/packages/caravan-psbt/src/psbtv2/psbtv2-bip375.test.ts index 0276affca4..454ff01730 100644 --- a/packages/caravan-psbt/src/psbtv2/psbtv2-bip375.test.ts +++ b/packages/caravan-psbt/src/psbtv2/psbtv2-bip375.test.ts @@ -52,7 +52,6 @@ describe("BIP375 invalid vectors", () => { }); // ── Valid vectors ────────────────────────────────────────────────────────── - describe("BIP375 valid vectors", () => { test.each(bip375Vectors.valid)("$description", ({ psbt, supplementary }) => { const p = new PsbtV2(psbt); @@ -62,12 +61,24 @@ describe("BIP375 valid vectors", () => { // ── Output checks ────────────────────────────────────────────────────── for (const output of supplementary.outputs ?? []) { - // Output script - if (output.script) { + const outputMap = p.outputMaps[output.output_index]; + expect(outputMap, `output ${output.output_index} exists`).toBeDefined(); + + if ( + "script" in output && + output.script !== null && + output.script !== undefined + ) { + const script = outputMap.get(KeyType.PSBT_OUT_SCRIPT); expect( - p.PSBT_OUT_SCRIPT[output.output_index], + script?.toString("hex"), `output ${output.output_index} script`, ).toBe(output.script); + } else { + expect( + outputMap.has(KeyType.PSBT_OUT_SCRIPT), + `output ${output.output_index} should not have PSBT_OUT_SCRIPT`, + ).toBe(false); } // SP V0 info (bscan || bspend): only check unlabeled outputs. diff --git a/packages/caravan-psbt/src/psbtv2/psbtv2.ts b/packages/caravan-psbt/src/psbtv2/psbtv2.ts index 232ef3d285..d882829736 100644 --- a/packages/caravan-psbt/src/psbtv2/psbtv2.ts +++ b/packages/caravan-psbt/src/psbtv2/psbtv2.ts @@ -41,6 +41,7 @@ import { verifySilentPaymentDLEQProof, } from "src/psbtv2/silentpayment"; import { ProjectivePoint } from "src/psbtv2/dleq"; + /** * The PsbtV2 class is intended to represent an easily modifiable and * serializable psbt of version 2 conforming to BIP0174. Getters exist for all @@ -475,12 +476,17 @@ export class PsbtV2 extends PsbtV2Maps { return indices; } - get PSBT_OUT_SCRIPT(): string[] { - return this.outputMaps.map((map) => { + get PSBT_OUT_SCRIPT() { + const indices: string[] = []; + for (const map of this.outputMaps) { const value = map.get(KeyType.PSBT_OUT_SCRIPT); - if (!value) return ""; - return value.toString("hex"); - }); + if (!value) { + // This should never happen, but it can't be gracefully handled. + throw Error("PSBT_OUT_SCRIPT not set for an output"); + } + indices.push(value.toString("hex")); + } + return indices; } get PSBT_OUT_TAP_INTERNAL_KEY() { @@ -677,13 +683,11 @@ export class PsbtV2 extends PsbtV2Maps { this.PSBT_IN_POR_COMMITMENT[i] || this.PSBT_IN_TAP_KEY_SIG[i] || this.PSBT_IN_TAP_INTERNAL_KEY[i] || - this.PSBT_IN_TAP_MERKLE_ROOT[i] || - // Numbers + this.PSBT_IN_TAP_MERKLE_ROOT[i] || // Numbers this.PSBT_IN_SIGHASH_TYPE[i] !== null || this.PSBT_IN_SEQUENCE[i] !== null || this.PSBT_IN_REQUIRED_TIME_LOCKTIME[i] !== null || - this.PSBT_IN_REQUIRED_HEIGHT_LOCKTIME[i] !== null || - // Arrays of non-unique keytype values + this.PSBT_IN_REQUIRED_HEIGHT_LOCKTIME[i] !== null || // Arrays of non-unique keytype values this.PSBT_IN_PARTIAL_SIG[i].filter((el) => el !== null).length > 0 || this.PSBT_IN_BIP32_DERIVATION[i].filter((el) => el !== null).length > 0 || @@ -823,8 +827,11 @@ export class PsbtV2 extends PsbtV2Maps { throw Error("PsbtV2 input is missing PSBT_OUT_AMOUNT"); } } - for (const [i, script] of this.PSBT_OUT_SCRIPT.entries()) { - if (!script && !this.outputMaps[i].has(KeyType.PSBT_OUT_SP_V0_INFO)) { + for (let i = 0; i < this.outputMaps.length; i++) { + if ( + !this.hasNonEmptyOutputScript(i) && + !this.outputMaps[i].has(KeyType.PSBT_OUT_SP_V0_INFO) + ) { throw Error( `PsbtV2 output ${i} is missing PSBT_OUT_SCRIPT and has no ` + "PSBT_OUT_SP_V0_INFO. An output must have one or both per BIP375.", @@ -844,6 +851,11 @@ export class PsbtV2 extends PsbtV2Maps { this.validateSilentPayments(); } + private hasNonEmptyOutputScript(outputIndex: number): boolean { + const script = this.outputMaps[outputIndex]?.get(KeyType.PSBT_OUT_SCRIPT); + return !!script && script.length > 0; + } + private getSilentPaymentInputDescriptors(): SPInputDescriptor[] { return this.inputMaps.map((map, i) => { const outputIndex = map.get(KeyType.PSBT_IN_OUTPUT_INDEX); @@ -881,9 +893,8 @@ export class PsbtV2 extends PsbtV2Maps { continue; } - if (onlyWithScripts) { - const script = this.outputMaps[i].get(KeyType.PSBT_OUT_SCRIPT); - if (!script || script.length === 0) continue; + if (onlyWithScripts && !this.hasNonEmptyOutputScript(i)) { + continue; } entries.push({ outputIndex: i, ...info }); @@ -1667,9 +1678,7 @@ export class PsbtV2 extends PsbtV2Maps { if (!pubkey || !sig) { throw Error( - `PsbtV2.addPartialSig() missing argument ${ - (!pubkey && "pubkey") || (!sig && "sig") - }`, + `PsbtV2.addPartialSig() missing argument ${(!pubkey && "pubkey") || (!sig && "sig")}`, ); } From 5a122304292aa7bfe335bba8ecf29e51c5d91c10 Mon Sep 17 00:00:00 2001 From: Jasper van Gelder Date: Tue, 23 Jun 2026 17:51:10 +0200 Subject: [PATCH 25/26] chore(psbtv2): Improve missing warning Previously removed to much readded previous out. --- packages/caravan-psbt/src/psbtv2/psbtv2maps.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/caravan-psbt/src/psbtv2/psbtv2maps.ts b/packages/caravan-psbt/src/psbtv2/psbtv2maps.ts index 5ccbda2933..116e822706 100644 --- a/packages/caravan-psbt/src/psbtv2/psbtv2maps.ts +++ b/packages/caravan-psbt/src/psbtv2/psbtv2maps.ts @@ -232,7 +232,7 @@ export class PsbtConversionMaps extends PsbtV2Maps { !this.outputMaps[i].has(KeyType.PSBT_OUT_AMOUNT) ) { console.warn( - `Output ${i} is missing SP_INFO, script or amount. Skipping.`, + `Output ${i} is missing SP_INFO, previous out script or amount. Skipping.`, ); continue; } From e1a6b39d1d3271988421dd0c00a3e9c93db674ce Mon Sep 17 00:00:00 2001 From: Jasper van Gelder Date: Thu, 16 Jul 2026 23:18:34 +0200 Subject: [PATCH 26/26] chore(psbtv2): Cleanup and remove dead code Removed unused functions, merged if statements and reused existing functions. --- packages/caravan-psbt/src/psbtv2/dleq.test.ts | 1 + packages/caravan-psbt/src/psbtv2/dleq.ts | 4 +- .../src/psbtv2/psbtv2-bip375.test.ts | 12 +- packages/caravan-psbt/src/psbtv2/psbtv2.ts | 129 +++++++++--------- .../caravan-psbt/src/psbtv2/silentpayment.ts | 34 +---- 5 files changed, 75 insertions(+), 105 deletions(-) diff --git a/packages/caravan-psbt/src/psbtv2/dleq.test.ts b/packages/caravan-psbt/src/psbtv2/dleq.test.ts index 364d69b58a..c67e3048eb 100644 --- a/packages/caravan-psbt/src/psbtv2/dleq.test.ts +++ b/packages/caravan-psbt/src/psbtv2/dleq.test.ts @@ -6,6 +6,7 @@ import { multiplyCompressedPoint, verifyDLEQProof, } from "./dleq"; + function hex(s: string): Buffer { return Buffer.from(s, "hex"); } diff --git a/packages/caravan-psbt/src/psbtv2/dleq.ts b/packages/caravan-psbt/src/psbtv2/dleq.ts index 24cdb381a2..b50fe67693 100644 --- a/packages/caravan-psbt/src/psbtv2/dleq.ts +++ b/packages/caravan-psbt/src/psbtv2/dleq.ts @@ -128,8 +128,8 @@ export function generateDLEQProof({ throw new Error("BIP374 proof generation produced point at infinity."); } - const ABytes = Buffer.from(A.toRawBytes(true)); - const CBytes = Buffer.from(C.toRawBytes(true)); + const ABytes = pointToCompressedBytes(A); + const CBytes = pointToCompressedBytes(C); const t = xor32(secret, taggedHash("BIP0374/aux", auxRand)); diff --git a/packages/caravan-psbt/src/psbtv2/psbtv2-bip375.test.ts b/packages/caravan-psbt/src/psbtv2/psbtv2-bip375.test.ts index 454ff01730..c62639904a 100644 --- a/packages/caravan-psbt/src/psbtv2/psbtv2-bip375.test.ts +++ b/packages/caravan-psbt/src/psbtv2/psbtv2-bip375.test.ts @@ -7,6 +7,7 @@ import { PsbtV2 } from "./psbtv2"; import bip375Vectors from "../fixtures/bip375_vectors.json"; import { KeyType } from "src/psbtv2/types"; import { secp256k1 } from "@noble/curves/secp256k1"; +import { hash160 } from "@caravan/bitcoin"; function hex(s: string): Buffer { return Buffer.from(s, "hex"); @@ -21,16 +22,7 @@ function pubkeyFromSecret(secret: Buffer): Buffer { } function p2wpkhScript(pubkey: Buffer): Buffer { - // Test-only: use a fixed valid witness program derived from pubkey bytes. - // If the repo already has address/script helpers, prefer those. - const h = Buffer.from( - require("crypto") - .createHash("ripemd160") - .update(require("crypto").createHash("sha256").update(pubkey).digest()) - .digest(), - ); - - return Buffer.concat([Buffer.from([0x00, 0x14]), h]); + return Buffer.concat([Buffer.from([0x00, 0x14]), hash160(pubkey)]); } // ── Invalid vectors ──────────────────────────────────────────────────────── diff --git a/packages/caravan-psbt/src/psbtv2/psbtv2.ts b/packages/caravan-psbt/src/psbtv2/psbtv2.ts index d882829736..2ac02a1798 100644 --- a/packages/caravan-psbt/src/psbtv2/psbtv2.ts +++ b/packages/caravan-psbt/src/psbtv2/psbtv2.ts @@ -600,12 +600,9 @@ export class PsbtV2 extends PsbtV2Maps { return false; } - // Per BIP375: if SP outputs are present, all must have a computed - // PSBT_OUT_SCRIPT before signing is permitted. - if (this.hasSilentPaymentOutputs && !this.hasAllSPOutputScripts) { - return false; - } - return true; + // For non-SP transactions this is vacuously true. For SP transactions, + // every SP output must have a non-empty PSBT_OUT_SCRIPT before signing. + return this.hasAllSPOutputScripts; } /** @@ -967,7 +964,7 @@ export class PsbtV2 extends PsbtV2Maps { ); if (!pubkeyBytes) { - continue; + return null; } const point = secp256k1.ProjectivePoint.fromHex(pubkeyBytes); @@ -1135,28 +1132,28 @@ export class PsbtV2 extends PsbtV2Maps { `PsbtV2 output ${i} has PSBT_OUT_SP_V0_LABEL but no PSBT_OUT_SP_V0_INFO.`, ); } - if (spInfo) { assertValidSPV0Info(spInfo, i); + } else { + continue; } - if (!spInfo && !script) { - throw Error( - `PsbtV2 output ${i} is missing PSBT_OUT_SCRIPT and has no ` + - "PSBT_OUT_SP_V0_INFO. An output must have one or both per BIP375.", - ); - } - - if (spInfo && script && script.length === 0) { + if ( + outputMap.has(KeyType.PSBT_OUT_SCRIPT) && + !this.hasNonEmptyOutputScript(i) + ) { throw Error(`PsbtV2 output ${i} has empty PSBT_OUT_SCRIPT.`); } - if (spInfo && script && script.length > 0) { - if (this.PSBT_GLOBAL_TX_MODIFIABLE.length > 0) { - throw Error( - "PSBT_OUT_SCRIPT set for silent payment output but PSBT_GLOBAL_TX_MODIFIABLE is not zeroed.", - ); - } + if ( + spInfo && + script && + script.length > 0 && + this.PSBT_GLOBAL_TX_MODIFIABLE.length > 0 + ) { + throw Error( + "PSBT_OUT_SCRIPT set for silent payment output but PSBT_GLOBAL_TX_MODIFIABLE is not zeroed.", + ); } } @@ -1547,21 +1544,12 @@ export class PsbtV2 extends PsbtV2Maps { if (silentPayment) { const { bscan, bspend, label } = silentPayment; - assertValidBscan(bscan); - assertValidBspend(bspend); - // Value: bscan || bspend, 66 bytes — no version prefix in field value. - const spBw = new BufferWriter(); - spBw.writeBytes(bscan); - spBw.writeBytes(bspend); - map.set(KeyType.PSBT_OUT_SP_V0_INFO, spBw.render()); + const outputIndex = this.outputMaps.length; + + this.setOutputSPInfoOnMap(map, bscan, bspend); if (label !== undefined) { - if (!Number.isInteger(label) || label < 0 || label > 0xffffffff) { - throw Error(`label must be a uint32 (0–${0xffffffff}), got ${label}`); - } - const labelBw = new BufferWriter(); - labelBw.writeU32(label); - map.set(KeyType.PSBT_OUT_SP_V0_LABEL, labelBw.render()); + this.setOutputSPLabelOnMap(map, outputIndex, label); } } @@ -1861,40 +1849,62 @@ export class PsbtV2 extends PsbtV2Maps { } // ── Per-output SP methods ───────────────────────────────────────────────── - - public addOutputSPInfo( - outputIndex: number, + private setOutputSPInfoOnMap( + map: Map, bscan: Buffer, bspend: Buffer, ): void { - if (outputIndex < 0 || outputIndex >= this.outputMaps.length) { - throw new Error( - `outputIndex ${outputIndex} out of range (${this.outputMaps.length} outputs)`, - ); - } assertValidBscan(bscan); assertValidBspend(bspend); + const bw = new BufferWriter(); bw.writeBytes(bscan); bw.writeBytes(bspend); - this.outputMaps[outputIndex].set(KeyType.PSBT_OUT_SP_V0_INFO, bw.render()); + map.set(KeyType.PSBT_OUT_SP_V0_INFO, bw.render()); } - public addOutputSPLabel(outputIndex: number, label: number): void { - if (outputIndex < 0 || outputIndex >= this.outputMaps.length) { + private setOutputSPLabelOnMap( + map: Map, + outputIndex: number, + label: number, + ): void { + if (!map.has(KeyType.PSBT_OUT_SP_V0_INFO)) { + throw new Error( + `Output ${outputIndex} has no SP info. Call setOutputSPInfo first.`, + ); + } + + assertValidLabel(label, outputIndex); + + const bw = new BufferWriter(); + bw.writeU32(label); + map.set(KeyType.PSBT_OUT_SP_V0_LABEL, bw.render()); + } + + public setOutputSPInfo( + outputIndex: number, + bscan: Buffer, + bspend: Buffer, + ): void { + const map = this.outputMaps[outputIndex]; + + if (!map) { throw new Error( `outputIndex ${outputIndex} out of range (${this.outputMaps.length} outputs)`, ); } - if (!this.outputMaps[outputIndex].has(KeyType.PSBT_OUT_SP_V0_INFO)) { + this.setOutputSPInfoOnMap(map, bscan, bspend); + } + + public setOutputSPLabel(outputIndex: number, label: number): void { + const map = this.outputMaps[outputIndex]; + + if (!map) { throw new Error( - `Output ${outputIndex} has no SP info. Call addOutputSPInfo first.`, + `outputIndex ${outputIndex} out of range (${this.outputMaps.length} outputs)`, ); } - assertValidLabel(label, outputIndex); - const bw = new BufferWriter(); - bw.writeU32(label); - this.outputMaps[outputIndex].set(KeyType.PSBT_OUT_SP_V0_LABEL, bw.render()); + this.setOutputSPLabelOnMap(map, outputIndex, label); } /** @@ -2233,12 +2243,11 @@ export class PsbtV2 extends PsbtV2Maps { * Per BIP375: the Signer must not add a signature until this is true. */ get hasAllSPOutputScripts(): boolean { - return this.outputMaps.every((map) => { - if (!map.has(KeyType.PSBT_OUT_SP_V0_INFO)) return true; - - const script = map.get(KeyType.PSBT_OUT_SCRIPT); - return !!script && script.length > 0; - }); + return this.outputMaps.every( + (map, i) => + !map.has(KeyType.PSBT_OUT_SP_V0_INFO) || + this.hasNonEmptyOutputScript(i), + ); } /** @@ -2357,10 +2366,6 @@ export class PsbtV2 extends PsbtV2Maps { const contributing = this.getContributingInputsForSilentPayments(); const inputHash = this.computeSilentPaymentInputHash(contributing); - if (!inputHash) { - throw new Error("Could not extract public keys from eligible inputs."); - } - // ── Step 2: Group SP outputs by Bscan, sort within groups ────────────── const scanKeyGroups = this.getSilentPaymentOutputGroups(); diff --git a/packages/caravan-psbt/src/psbtv2/silentpayment.ts b/packages/caravan-psbt/src/psbtv2/silentpayment.ts index 079248bb81..3c7637b20e 100644 --- a/packages/caravan-psbt/src/psbtv2/silentpayment.ts +++ b/packages/caravan-psbt/src/psbtv2/silentpayment.ts @@ -9,14 +9,13 @@ */ import { secp256k1, schnorr } from "@noble/curves/secp256k1"; -import { createHash } from "crypto"; -import { script } from "bitcoinjs-lib-v6"; +import { script, Transaction } from "bitcoinjs-lib-v6"; import { taggedHash } from "./functions"; const CURVE_ORDER = secp256k1.CURVE.n; const { bytesToNumberBE } = schnorr.utils; const { OPS } = script; -import { Transaction } from "bitcoinjs-lib-v6"; +import { hash160 } from "@caravan/bitcoin"; import { generateDLEQProof, multiplyCompressedPoint, @@ -91,28 +90,6 @@ export function assertValidBscan(bscan: Buffer): void { assertValidCompressedPoint(bscan, "bscan"); } -export function parseSilentPaymentScanKeyData( - key: string, - keyType: string, - context: string, -): Buffer { - const scanKey = key.slice(keyType.length); - if (!/^[0-9a-fA-F]+$/.test(scanKey)) { - throw new Error(`${context} scan keydata must be hex encoded.`); - } - const bscan = Buffer.from(scanKey, "hex"); - assertValidBscan(bscan); - return bscan; -} - -export function scanKeyHexFromBIP375Key( - key: string, - keyType: string, - context: string, -): string { - return parseSilentPaymentScanKeyData(key, keyType, context).toString("hex"); -} - /** * Asserts that a spend public key is a valid 33-byte compressed point. * @@ -173,7 +150,7 @@ export function assertValidLabel(m: number, outputIndex: number): void { } export function assertValidOutputK(k: number, outputIndex: number): void { - if (!Number.isInteger(k) || k < 0 || k > 2323) { + if (!Number.isInteger(k) || k < 0 || k >= 2323) { throw new Error( `Silent payment recipient index should be 0 < k < 2323 (Kmax) but was at output ${outputIndex}: ${k}`, ); @@ -375,11 +352,6 @@ export function getTaprootOutputKeyFromWitnessUtxo( return Buffer.concat([Buffer.from([0x02]), scriptPubKey.subarray(2, 34)]); } -function hash160(buffer: Buffer): Buffer { - const sha = createHash("sha256").update(buffer).digest(); - return createHash("ripemd160").update(sha).digest(); -} - export function getSilentPaymentPubkeyFromInputDescriptor( input: SPInputDescriptor, candidatePubkeys: Buffer[],