From 62282920063446e403315385e28a7e2d59ce87cf Mon Sep 17 00:00:00 2001 From: Egge Date: Tue, 3 Dec 2024 22:19:41 +0100 Subject: [PATCH] added advanced p2pk --- src/CashuWallet.ts | 29 +++++++++++++++++++++-------- src/model/BlindingData.ts | 33 +++++++++++++++++++++++++++------ 2 files changed, 48 insertions(+), 14 deletions(-) diff --git a/src/CashuWallet.ts b/src/CashuWallet.ts index 66cc8578..163aec17 100644 --- a/src/CashuWallet.ts +++ b/src/CashuWallet.ts @@ -252,6 +252,7 @@ class CashuWallet { privkey?: string; requireDleq?: boolean; blindingData?: Array; + p2pk?: { pubkey: string; locktime?: number; refundKeys?: Array }; } ): Promise> { if (typeof token === 'string') { @@ -272,7 +273,8 @@ class CashuWallet { options?.counter, options?.pubkey, options?.privkey, - options?.blindingData ? { keep: options.blindingData, send: [] } : undefined + options?.blindingData ? { keep: options.blindingData, send: [] } : undefined, + options?.p2pk ); const { signatures } = await this.mint.swap(swapTransaction.payload); return swapTransaction.blindingData.map((d, i) => d.toProof(signatures[i], keys)); @@ -310,6 +312,7 @@ class CashuWallet { keep?: Array; send?: Array; }; + p2pk?: { pubkey: string; locktime?: number; refundKeys?: Array }; } ): Promise { if (options?.includeDleq) { @@ -492,6 +495,7 @@ class CashuWallet { keep?: Array; send?: Array; }; + p2pk?: { pubkey: string; locktime?: number; refundKeys?: Array }; } ): Promise { if (!options) options = {}; @@ -562,7 +566,8 @@ class CashuWallet { options?.counter, options?.pubkey, options?.privkey, - options?.customBlindingData + options?.customBlindingData, + options?.p2pk ); const { signatures } = await this.mint.swap(swapTransaction.payload); const swapProofs = swapTransaction.blindingData.map((d, i) => d.toProof(signatures[i], keyset)); @@ -662,6 +667,7 @@ class CashuWallet { proofsWeHave?: Array; counter?: number; pubkey?: string; + p2pk?: { pubkey: string; locktime?: number; refundKeys?: Array }; } ): Promise> { const keyset = await this.getKeys(options?.keysetId); @@ -682,7 +688,8 @@ class CashuWallet { keyset, options?.counter, options?.pubkey, - options?.outputAmounts?.keepAmounts + options?.outputAmounts?.keepAmounts, + options?.p2pk ); const mintPayload: MintPayload = { outputs: blindingData.map((d) => d.blindedMessage), @@ -790,7 +797,8 @@ class CashuWallet { customBlindingData?: { keep?: Array; send?: Array; - } + }, + p2pk?: { pubkey: string; locktime?: number; refundKeys?: Array } ): SwapTransaction { const totalAmount = proofsToSend.reduce((total: number, curr: Proof) => total + curr.amount, 0); if (outputAmounts && outputAmounts.sendAmounts && !outputAmounts.keepAmounts) { @@ -811,7 +819,8 @@ class CashuWallet { keyset, counter, pubkey, - outputAmounts?.keepAmounts + outputAmounts?.keepAmounts, + p2pk ); } @@ -823,7 +832,8 @@ class CashuWallet { keyset, counter, pubkey, - outputAmounts?.sendAmounts + outputAmounts?.sendAmounts, + p2pk ); } @@ -1045,11 +1055,12 @@ class CashuWallet { keyset: MintKeys, counter?: number, pubkey?: string, - outputAmounts?: Array + outputAmounts?: Array, + p2pk?: { pubkey: string; locktime?: number; refundKeys?: Array } ): Array { let blindingData: Array; if (pubkey) { - blindingData = BlindingData.createP2PKData(pubkey, amount, keyset, outputAmounts); + blindingData = BlindingData.createP2PKData({ pubkey }, amount, keyset, outputAmounts); } else if (counter || counter === 0) { if (!this._seed) { throw new Error('cannot create deterministic messages without seed'); @@ -1061,6 +1072,8 @@ class CashuWallet { keyset, outputAmounts ); + } else if (p2pk) { + blindingData = BlindingData.createP2PKData(p2pk, amount, keyset); } else { blindingData = BlindingData.createRandomData(amount, keyset, outputAmounts); } diff --git a/src/model/BlindingData.ts b/src/model/BlindingData.ts index 6ea90555..bd3c6cd8 100644 --- a/src/model/BlindingData.ts +++ b/src/model/BlindingData.ts @@ -1,6 +1,4 @@ -import { createP2PKsecret } from '@cashu/crypto/modules/client/NUT11'; import { - Keys, MintKeys, Proof, SerializedBlindedMessage, @@ -64,17 +62,40 @@ export class BlindingData { } static createP2PKData( - pubkey: string, + p2pk: { pubkey: string; locktime?: number; refundKeys?: Array }, amount: number, keyset: MintKeys, customSplit?: Array ) { const amounts = splitAmount(amount, keyset.keys, customSplit); - return amounts.map((a) => this._createP2PKData(pubkey, a, keyset.id)); + return amounts.map((a) => + this._createP2PKData(p2pk.pubkey, a, keyset.id, p2pk.locktime, p2pk.refundKeys) + ); } - private static _createP2PKData(pubkey: string, amount: number, keysetId: string) { - const secretBytes = createP2PKsecret(pubkey); + private static _createP2PKData( + pubkey: string, + amount: number, + keysetId: string, + locktime?: number, + refundKeys?: Array + ) { + const newSecret: [string, { nonce: string; data: string; tags: Array }] = [ + 'P2PK', + { + nonce: bytesToHex(randomBytes(32)), + data: pubkey, + tags: [] + } + ]; + if (locktime) { + newSecret[1].tags.push(['locktime', locktime]); + } + if (refundKeys) { + newSecret[1].tags.push(['refund', refundKeys]); + } + const parsed = JSON.stringify(newSecret); + const secretBytes = new TextEncoder().encode(parsed); const { r, B_ } = blindMessage(secretBytes); return new BlindingData( new BlindedMessage(amount, B_, keysetId).getSerializedBlindedMessage(),