Skip to content

Commit 52148d8

Browse files
committed
fix(p2sp): Function signature and output fixes
Some outputs wernt matching what we expected them to be.
1 parent d6f3297 commit 52148d8

File tree

3 files changed

+19
-28
lines changed

3 files changed

+19
-28
lines changed

src/esm/payments/p2sp.js

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,9 @@ export const findSmallestOutpoint = inputs =>
7171
*/
7272
export const serOutpointLE = (txidHexBE, vout) => {
7373
const out = new Uint8Array(36);
74-
const txidLE = tools.fromHex(txidHexBE);
75-
if (txidLE.length !== 32) throw new Error('txid must be 32 bytes');
76-
txidLE.reverse(); // BE -> LE
77-
out.set(txidLE, 0);
74+
if (txidHexBE.length !== 32) throw new Error('txid must be 32 bytes');
75+
txidHexBE.reverse(); // BE -> LE
76+
out.set(txidHexBE, 0);
7877
writeUInt32(out, 32, vout >>> 0, 'le');
7978
return out;
8079
};
@@ -273,8 +272,7 @@ export function calculateSharedSecret(
273272
throw new Error('summedSenderPrivkey was not provided?');
274273
const Si = ecc.pointMultiply(scanPubkey, inputHash, true);
275274
if (!Si) throw new Error('pointMultiply(B_scan, ih) failed');
276-
let S;
277-
S = ecc.pointMultiply(Si, summedSenderPrivkey, true);
275+
const S = ecc.pointMultiply(Si, summedSenderPrivkey, true);
278276
if (!S) throw new Error('pointMultiply(Si, summedSenderPrivkey) failed');
279277
else return S;
280278
}
@@ -287,8 +285,7 @@ export function calculateSharedSecret(
287285
* @returns input_hash tweak
288286
*/
289287
export function calculateT_k(S, k) {
290-
if (!S) return null;
291-
let t_k = taggedHash('BIP0352/SharedSecret', tools.concat([S, ser32BE(k)]));
288+
const t_k = taggedHash('BIP0352/SharedSecret', tools.concat([S, ser32BE(k)]));
292289
return hashToTweak(t_k);
293290
}
294291
/**
@@ -313,6 +310,7 @@ export function calculateP_k(spendPubKey, t_k) {
313310
export function deriveOutput(S, spendPubkey, k) {
314311
// t_k = H_tag(SharedSecret, ser_P(S) || ser32BE(k)) -> reduce mod n
315312
const t_k = calculateT_k(S, k);
313+
if (!t_k) throw new Error('t_k: failed');
316314
// P_k = B_spend + t_k·G (compressed) -> x-only for P2TR
317315
const P_k = calculateP_k(spendPubkey, t_k);
318316
const P_xOnly = toXOnly(P_k);
@@ -355,7 +353,6 @@ export function generateLabelAndAddress(B_scan, B_spend, label) {
355353
* Scans a transaction's inputs and outputs to find any silent payments for the receiver.
356354
* @param receiverScanPrivkey - b_scan
357355
* @param receiverSpendPrivkey - b_spend
358-
* @param smallestOutpoint
359356
* @param inputHashTweak
360357
* @param summedSenderPubkey - A_sum
361358
* @param outputsToCheck - array of hex xOnly encoded outputs to check
@@ -364,7 +361,6 @@ export function generateLabelAndAddress(B_scan, B_spend, label) {
364361
export function scanForSilentPayments(
365362
receiverScanPrivkey,
366363
receiverSpendPrivkey,
367-
smallestOutpoint,
368364
inputHashTweak,
369365
summedSenderPubkey,
370366
outputsToCheck,

test/integration/silentpayment.spec.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import {
1414
encodeSilentPaymentAddress,
1515
findSmallestOutpoint,
1616
modN32,
17-
generateLabelAndAddress,
1817
scanForSilentPayments,
1918
} from '../../ts_src/payments/p2sp.js';
2019
import { Input } from '../../ts_src/transaction.js';
@@ -35,7 +34,7 @@ interface TestInput {
3534
txinwitness: string;
3635
prevout: {
3736
scriptPubKey: {
38-
hex: String;
37+
hex: string;
3938
};
4039
};
4140
private_key?: string;
@@ -82,7 +81,7 @@ interface Recipient {
8281
interface RecipientOutput {
8382
priv_key_tweak: string;
8483
pub_key: string;
85-
signature: String;
84+
signature: string;
8685
}
8786

8887
// ================================================================
@@ -315,7 +314,7 @@ function runSenderCase(tc: Sender) {
315314

316315
// -------- 2) a_sum with Taproot-only odd-Y conditional negation --------
317316
// 2) a_sum = Σ negated (mod n) via tiny-secp
318-
let aSum: Uint8Array = calculateSumA(inputPrivKeyTuples);
317+
const aSum: Uint8Array = calculateSumA(inputPrivKeyTuples);
319318

320319
// (optional) fixture check stays the same
321320
if (expected.input_private_key_sum) {
@@ -446,7 +445,6 @@ function runReceiverCase(tc: Recipient) {
446445
const foundScanned = scanForSilentPayments(
447446
b_scan,
448447
b_spend,
449-
outpointL,
450448
inputHashTweak,
451449
A_sum_point,
452450
outputsToCheck,

ts_src/payments/p2sp.ts

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import { bech32m } from 'bech32';
88
// Explicitly import the Payment type for clarity
99
import { Payment, PaymentOpts } from './index';
1010
import * as lazy from './lazy';
11-
import * as payments from './index.ts';
1211
import { taggedHash } from '../crypto';
1312
import { Input } from '../transaction';
1413

@@ -90,12 +89,11 @@ export const findSmallestOutpoint = (inputs: Array<Input>) =>
9089
* @param vout - output index
9190
* @returns the serialized little endian encoded output
9291
*/
93-
export const serOutpointLE = (txidHexBE: string, vout: number) => {
92+
export const serOutpointLE = (txidHexBE: Uint8Array, vout: number) => {
9493
const out = new Uint8Array(36);
95-
const txidLE = tools.fromHex(txidHexBE);
96-
if (txidLE.length !== 32) throw new Error('txid must be 32 bytes');
97-
txidLE.reverse(); // BE -> LE
98-
out.set(txidLE, 0);
94+
if (txidHexBE.length !== 32) throw new Error('txid must be 32 bytes');
95+
txidHexBE.reverse(); // BE -> LE
96+
out.set(txidHexBE, 0);
9997
writeUInt32(out, 32, vout >>> 0, 'le');
10098
return out;
10199
};
@@ -395,9 +393,10 @@ export function deriveOutput(
395393
S: Uint8Array,
396394
spendPubkey: Uint8Array,
397395
k: number,
398-
): { pub_key: Uint8Array; tweak_key } {
396+
): { pub_key: Uint8Array; tweak_key: Uint8Array } {
399397
// t_k = H_tag(SharedSecret, ser_P(S) || ser32BE(k)) -> reduce mod n
400398
const t_k: Uint8Array<ArrayBufferLike> | null = calculateT_k(S, k);
399+
if (!t_k) throw new Error('t_k: failed');
401400

402401
// P_k = B_spend + t_k·G (compressed) -> x-only for P2TR
403402
const P_k: Uint8Array<ArrayBufferLike> = calculateP_k(spendPubkey, t_k);
@@ -453,7 +452,6 @@ export function generateLabelAndAddress(
453452
* Scans a transaction's inputs and outputs to find any silent payments for the receiver.
454453
* @param receiverScanPrivkey - b_scan
455454
* @param receiverSpendPrivkey - b_spend
456-
* @param smallestOutpoint
457455
* @param inputHashTweak
458456
* @param summedSenderPubkey - A_sum
459457
* @param outputsToCheck - array of hex xOnly encoded outputs to check
@@ -462,20 +460,19 @@ export function generateLabelAndAddress(
462460
export function scanForSilentPayments(
463461
receiverScanPrivkey: Uint8Array,
464462
receiverSpendPrivkey: Uint8Array,
465-
smallestOutpoint: Uint8Array,
466463
inputHashTweak: Uint8Array,
467464
summedSenderPubkey: Uint8Array,
468465
outputsToCheck: Set<string>,
469-
labelNonces: Array<Uint8Array> = Array.from([]),
466+
labelNonces: Array<number> = Array.from([]),
470467
): {
471468
priv_key_tweak: Uint8Array;
472469
pub_key: Uint8Array;
473-
labelNonce?: Uint8Array;
470+
labelNonce?: number;
474471
}[] {
475472
let foundPayments: {
476473
priv_key_tweak: Uint8Array;
477474
pub_key: Uint8Array;
478-
labelNonce?: Uint8Array;
475+
labelNonce?: number;
479476
}[] = [];
480477

481478
// G
@@ -529,7 +526,7 @@ function performScan(
529526
outputsToCheck: Set<string>,
530527
labelScalar: Uint8Array | null, // L (or null for base)
531528
): { priv_key_tweak: Uint8Array; pub_key: Uint8Array }[] {
532-
const found: { payment: Payment; t: Uint8Array; P_xonly: Uint8Array }[] = [];
529+
const found: { priv_key_tweak: Uint8Array; pub_key: Uint8Array }[] = [];
533530

534531
for (let k = 0; k < outputsToCheck.size; k++) {
535532
const derivedOutput = deriveOutput(S, receiverSpendPubkey, k);

0 commit comments

Comments
 (0)