@buildonspark/spark-sdk 0.2.3 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/dist/{chunk-PTRXJS7Q.js → chunk-TVUMSHWA.js} +1 -1
- package/dist/{chunk-PLLJIZC3.js → chunk-W4ZRBSWM.js} +2298 -778
- package/dist/{chunk-CDLETEDT.js → chunk-WAQKYSDI.js} +13 -1
- package/dist/{client-CGTRS23n.d.ts → client-BF4cn8F4.d.ts} +15 -3
- package/dist/{client-CcYzmpmj.d.cts → client-KhNkrXz4.d.cts} +15 -3
- package/dist/debug.cjs +2282 -762
- package/dist/debug.d.cts +17 -4
- package/dist/debug.d.ts +17 -4
- package/dist/debug.js +2 -2
- package/dist/graphql/objects/index.cjs +13 -1
- package/dist/graphql/objects/index.d.cts +2 -2
- package/dist/graphql/objects/index.d.ts +2 -2
- package/dist/graphql/objects/index.js +1 -1
- package/dist/index.cjs +2283 -752
- package/dist/index.d.cts +189 -8
- package/dist/index.d.ts +189 -8
- package/dist/index.js +29 -3
- package/dist/index.node.cjs +2387 -753
- package/dist/index.node.d.cts +9 -189
- package/dist/index.node.d.ts +9 -189
- package/dist/index.node.js +131 -3
- package/dist/native/index.cjs +2283 -752
- package/dist/native/index.d.cts +95 -30
- package/dist/native/index.d.ts +95 -30
- package/dist/native/index.js +2284 -767
- package/dist/{spark-wallet-CxcGPXRB.d.ts → spark-wallet-C1Tr_VKI.d.ts} +31 -25
- package/dist/{spark-wallet-DJJm19BP.d.cts → spark-wallet-DG3x2obf.d.cts} +31 -25
- package/dist/spark-wallet.node-CGxoeCpH.d.ts +13 -0
- package/dist/spark-wallet.node-CN9LoB_O.d.cts +13 -0
- package/dist/tests/test-utils.cjs +570 -73
- package/dist/tests/test-utils.d.cts +11 -11
- package/dist/tests/test-utils.d.ts +11 -11
- package/dist/tests/test-utils.js +53 -16
- package/dist/types/index.cjs +13 -1
- package/dist/types/index.d.cts +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.js +1 -1
- package/dist/{xchain-address-Bh9w1SeC.d.ts → xchain-address-BHu6CpZC.d.ts} +54 -7
- package/dist/{xchain-address-SZ7dkVUE.d.cts → xchain-address-HBr6isnc.d.cts} +54 -7
- package/package.json +1 -1
- package/src/graphql/client.ts +8 -0
- package/src/graphql/mutations/CompleteLeavesSwap.ts +9 -1
- package/src/graphql/mutations/RequestSwapLeaves.ts +4 -0
- package/src/graphql/objects/CompleteLeavesSwapInput.ts +34 -34
- package/src/graphql/objects/LeavesSwapRequest.ts +4 -0
- package/src/graphql/objects/RequestLeavesSwapInput.ts +48 -47
- package/src/graphql/objects/SwapLeaf.ts +40 -32
- package/src/graphql/objects/UserLeafInput.ts +24 -0
- package/src/graphql/objects/UserRequest.ts +4 -0
- package/src/index.node.ts +1 -1
- package/src/native/index.ts +4 -5
- package/src/services/coop-exit.ts +171 -36
- package/src/services/deposit.ts +471 -74
- package/src/services/lightning.ts +18 -5
- package/src/services/signing.ts +162 -50
- package/src/services/transfer.ts +950 -384
- package/src/services/tree-creation.ts +342 -121
- package/src/spark-wallet/spark-wallet.node.ts +71 -66
- package/src/spark-wallet/spark-wallet.ts +405 -153
- package/src/tests/integration/coop-exit.test.ts +3 -8
- package/src/tests/integration/deposit.test.ts +3 -3
- package/src/tests/integration/lightning.test.ts +521 -466
- package/src/tests/integration/swap.test.ts +559 -307
- package/src/tests/integration/transfer.test.ts +625 -623
- package/src/tests/integration/wallet.test.ts +2 -2
- package/src/tests/integration/watchtower.test.ts +211 -0
- package/src/tests/test-utils.ts +63 -14
- package/src/tests/utils/test-faucet.ts +4 -2
- package/src/utils/adaptor-signature.ts +15 -5
- package/src/utils/fetch.ts +75 -0
- package/src/utils/mempool.ts +9 -4
- package/src/utils/transaction.ts +388 -26
package/dist/index.cjs
CHANGED
|
@@ -1290,7 +1290,10 @@ __export(index_exports, {
|
|
|
1290
1290
|
AuthenticationError: () => AuthenticationError,
|
|
1291
1291
|
ConfigurationError: () => ConfigurationError,
|
|
1292
1292
|
DEFAULT_FEE_SATS: () => DEFAULT_FEE_SATS,
|
|
1293
|
+
DIRECT_TIMELOCK_OFFSET: () => DIRECT_TIMELOCK_OFFSET,
|
|
1293
1294
|
DefaultSparkSigner: () => DefaultSparkSigner,
|
|
1295
|
+
INITIAL_DIRECT_SEQUENCE: () => INITIAL_DIRECT_SEQUENCE,
|
|
1296
|
+
INITIAL_SEQUENCE: () => INITIAL_SEQUENCE,
|
|
1294
1297
|
InternalValidationError: () => InternalValidationError,
|
|
1295
1298
|
KeyDerivationType: () => KeyDerivationType,
|
|
1296
1299
|
LRC_WALLET_NETWORK: () => LRC_WALLET_NETWORK,
|
|
@@ -1303,6 +1306,8 @@ __export(index_exports, {
|
|
|
1303
1306
|
RPCError: () => RPCError,
|
|
1304
1307
|
SparkSDKError: () => SparkSDKError,
|
|
1305
1308
|
SparkWallet: () => SparkWallet,
|
|
1309
|
+
TEST_UNILATERAL_DIRECT_SEQUENCE: () => TEST_UNILATERAL_DIRECT_SEQUENCE,
|
|
1310
|
+
TEST_UNILATERAL_SEQUENCE: () => TEST_UNILATERAL_SEQUENCE,
|
|
1306
1311
|
TaprootOutputKeysGenerator: () => TaprootOutputKeysGenerator,
|
|
1307
1312
|
TaprootSparkSigner: () => TaprootSparkSigner,
|
|
1308
1313
|
TokenTransactionService: () => TokenTransactionService,
|
|
@@ -1322,13 +1327,21 @@ __export(index_exports, {
|
|
|
1322
1327
|
constructFeeBumpTx: () => constructFeeBumpTx,
|
|
1323
1328
|
constructUnilateralExitFeeBumpPackages: () => constructUnilateralExitFeeBumpPackages,
|
|
1324
1329
|
constructUnilateralExitTxs: () => constructUnilateralExitTxs,
|
|
1330
|
+
createConnectorRefundTransactions: () => createConnectorRefundTransactions,
|
|
1331
|
+
createLeafNodeTx: () => createLeafNodeTx,
|
|
1332
|
+
createNodeTx: () => createNodeTx,
|
|
1333
|
+
createNodeTxs: () => createNodeTxs,
|
|
1325
1334
|
createRefundTx: () => createRefundTx,
|
|
1335
|
+
createRefundTxs: () => createRefundTxs,
|
|
1336
|
+
createRootTx: () => createRootTx,
|
|
1326
1337
|
createSigningCommitment: () => createSigningCommitment,
|
|
1327
1338
|
createSigningNonce: () => createSigningNonce,
|
|
1339
|
+
createSplitTx: () => createSplitTx,
|
|
1328
1340
|
decodeBech32mTokenIdentifier: () => decodeBech32mTokenIdentifier,
|
|
1329
1341
|
decodeBytesToSigningCommitment: () => decodeBytesToSigningCommitment,
|
|
1330
1342
|
decodeBytesToSigningNonce: () => decodeBytesToSigningNonce,
|
|
1331
1343
|
decodeSparkAddress: () => decodeSparkAddress,
|
|
1344
|
+
doesLeafNeedRefresh: () => doesLeafNeedRefresh,
|
|
1332
1345
|
encodeBech32mTokenIdentifier: () => encodeBech32mTokenIdentifier,
|
|
1333
1346
|
encodeSigningCommitmentToBytes: () => encodeSigningCommitmentToBytes,
|
|
1334
1347
|
encodeSigningNonceToBytes: () => encodeSigningNonceToBytes,
|
|
@@ -16203,13 +16216,24 @@ function applyAdaptorToSignature(pubkey, hash, signature, adaptorPrivateKeyBytes
|
|
|
16203
16216
|
const adaptorPrivateKey = (0, import_utils4.bytesToNumberBE)(adaptorPrivateKeyBytes);
|
|
16204
16217
|
const newS = (0, import_modular.mod)(sBigInt + adaptorPrivateKey, import_secp256k12.secp256k1.CURVE.n);
|
|
16205
16218
|
const newSig = new Uint8Array([...r, ...(0, import_utils4.numberToBytesBE)(newS, 32)]);
|
|
16206
|
-
|
|
16207
|
-
|
|
16219
|
+
try {
|
|
16220
|
+
if (import_secp256k12.schnorr.verify(newSig, hash, pubkey)) {
|
|
16221
|
+
return newSig;
|
|
16222
|
+
}
|
|
16223
|
+
} catch (e) {
|
|
16224
|
+
console.error("[applyAdaptorToSignature] Addition verification failed:", e);
|
|
16208
16225
|
}
|
|
16209
16226
|
const altS = (0, import_modular.mod)(sBigInt - adaptorPrivateKey, import_secp256k12.secp256k1.CURVE.n);
|
|
16210
16227
|
const altSig = new Uint8Array([...r, ...(0, import_utils4.numberToBytesBE)(altS, 32)]);
|
|
16211
|
-
|
|
16212
|
-
|
|
16228
|
+
try {
|
|
16229
|
+
if (import_secp256k12.schnorr.verify(altSig, hash, pubkey)) {
|
|
16230
|
+
return altSig;
|
|
16231
|
+
}
|
|
16232
|
+
} catch (e) {
|
|
16233
|
+
console.error(
|
|
16234
|
+
"[applyAdaptorToSignature] Subtraction verification failed:",
|
|
16235
|
+
e
|
|
16236
|
+
);
|
|
16213
16237
|
}
|
|
16214
16238
|
throw new Error("Cannot apply adaptor to signature");
|
|
16215
16239
|
}
|
|
@@ -17103,7 +17127,11 @@ var SwapLeafFromJson = (obj) => {
|
|
|
17103
17127
|
return {
|
|
17104
17128
|
leafId: obj["swap_leaf_leaf_id"],
|
|
17105
17129
|
rawUnsignedRefundTransaction: obj["swap_leaf_raw_unsigned_refund_transaction"],
|
|
17106
|
-
adaptorSignedSignature: obj["swap_leaf_adaptor_signed_signature"]
|
|
17130
|
+
adaptorSignedSignature: obj["swap_leaf_adaptor_signed_signature"],
|
|
17131
|
+
directRawUnsignedRefundTransaction: obj["swap_leaf_direct_raw_unsigned_refund_transaction"],
|
|
17132
|
+
directAdaptorSignedSignature: obj["swap_leaf_direct_adaptor_signed_signature"],
|
|
17133
|
+
directFromCpfpRawUnsignedRefundTransaction: obj["swap_leaf_direct_from_cpfp_raw_unsigned_refund_transaction"],
|
|
17134
|
+
directFromCpfpAdaptorSignedSignature: obj["swap_leaf_direct_from_cpfp_adaptor_signed_signature"]
|
|
17107
17135
|
};
|
|
17108
17136
|
};
|
|
17109
17137
|
|
|
@@ -17358,6 +17386,10 @@ fragment LeavesSwapRequestFragment on LeavesSwapRequest {
|
|
|
17358
17386
|
swap_leaf_leaf_id: leaf_id
|
|
17359
17387
|
swap_leaf_raw_unsigned_refund_transaction: raw_unsigned_refund_transaction
|
|
17360
17388
|
swap_leaf_adaptor_signed_signature: adaptor_signed_signature
|
|
17389
|
+
swap_leaf_direct_raw_unsigned_refund_transaction: direct_raw_unsigned_refund_transaction
|
|
17390
|
+
swap_leaf_direct_adaptor_signed_signature: direct_adaptor_signed_signature
|
|
17391
|
+
swap_leaf_direct_from_cpfp_raw_unsigned_refund_transaction: direct_from_cpfp_raw_unsigned_refund_transaction
|
|
17392
|
+
swap_leaf_direct_from_cpfp_adaptor_signed_signature: direct_from_cpfp_adaptor_signed_signature
|
|
17361
17393
|
}
|
|
17362
17394
|
}`;
|
|
17363
17395
|
|
|
@@ -17704,6 +17736,10 @@ fragment UserRequestFragment on UserRequest {
|
|
|
17704
17736
|
swap_leaf_leaf_id: leaf_id
|
|
17705
17737
|
swap_leaf_raw_unsigned_refund_transaction: raw_unsigned_refund_transaction
|
|
17706
17738
|
swap_leaf_adaptor_signed_signature: adaptor_signed_signature
|
|
17739
|
+
swap_leaf_direct_raw_unsigned_refund_transaction: direct_raw_unsigned_refund_transaction
|
|
17740
|
+
swap_leaf_direct_adaptor_signed_signature: direct_adaptor_signed_signature
|
|
17741
|
+
swap_leaf_direct_from_cpfp_raw_unsigned_refund_transaction: direct_from_cpfp_raw_unsigned_refund_transaction
|
|
17742
|
+
swap_leaf_direct_from_cpfp_adaptor_signed_signature: direct_from_cpfp_adaptor_signed_signature
|
|
17707
17743
|
}
|
|
17708
17744
|
}
|
|
17709
17745
|
... on LightningReceiveRequest {
|
|
@@ -17829,18 +17865,40 @@ function mapTransferToWalletTransfer(proto, identityPublicKey) {
|
|
|
17829
17865
|
};
|
|
17830
17866
|
}
|
|
17831
17867
|
|
|
17868
|
+
// src/utils/fetch.ts
|
|
17869
|
+
init_buffer();
|
|
17870
|
+
var fetchImpl = typeof window !== "undefined" && window.fetch ? window.fetch.bind(window) : globalThis.fetch ? globalThis.fetch : null;
|
|
17871
|
+
var Headers = globalThis.Headers ?? null;
|
|
17872
|
+
var getFetch = () => {
|
|
17873
|
+
if (!fetchImpl) {
|
|
17874
|
+
throw new Error(
|
|
17875
|
+
"Fetch implementation is not set. Please set it using setFetch()."
|
|
17876
|
+
);
|
|
17877
|
+
}
|
|
17878
|
+
if (!Headers) {
|
|
17879
|
+
throw new Error(
|
|
17880
|
+
"Headers implementation is not set. Please set it using setFetch()."
|
|
17881
|
+
);
|
|
17882
|
+
}
|
|
17883
|
+
return {
|
|
17884
|
+
fetch: fetchImpl,
|
|
17885
|
+
Headers
|
|
17886
|
+
};
|
|
17887
|
+
};
|
|
17888
|
+
|
|
17832
17889
|
// src/utils/mempool.ts
|
|
17833
17890
|
async function getLatestDepositTxId(address2) {
|
|
17891
|
+
const { fetch: fetch2, Headers: Headers2 } = getFetch();
|
|
17834
17892
|
const network = getNetworkFromAddress(address2);
|
|
17835
17893
|
const baseUrl = network === BitcoinNetwork_default.REGTEST ? getElectrsUrl("REGTEST") : getElectrsUrl("MAINNET");
|
|
17836
|
-
const headers =
|
|
17894
|
+
const headers = new Headers2();
|
|
17837
17895
|
if (network === BitcoinNetwork_default.REGTEST) {
|
|
17838
17896
|
const auth = btoa(
|
|
17839
17897
|
`${ELECTRS_CREDENTIALS.username}:${ELECTRS_CREDENTIALS.password}`
|
|
17840
17898
|
);
|
|
17841
|
-
headers
|
|
17899
|
+
headers.set("Authorization", `Basic ${auth}`);
|
|
17842
17900
|
}
|
|
17843
|
-
const response = await
|
|
17901
|
+
const response = await fetch2(`${baseUrl}/address/${address2}/txs`, {
|
|
17844
17902
|
headers
|
|
17845
17903
|
});
|
|
17846
17904
|
const addressTxs = await response.json();
|
|
@@ -17857,14 +17915,15 @@ async function getLatestDepositTxId(address2) {
|
|
|
17857
17915
|
return null;
|
|
17858
17916
|
}
|
|
17859
17917
|
async function isTxBroadcast(txid, baseUrl, network) {
|
|
17860
|
-
const
|
|
17918
|
+
const { fetch: fetch2, Headers: Headers2 } = getFetch();
|
|
17919
|
+
const headers = new Headers2();
|
|
17861
17920
|
if (network === 3 /* REGTEST */) {
|
|
17862
17921
|
const auth = btoa(
|
|
17863
17922
|
`${ELECTRS_CREDENTIALS.username}:${ELECTRS_CREDENTIALS.password}`
|
|
17864
17923
|
);
|
|
17865
|
-
headers
|
|
17924
|
+
headers.set("Authorization", `Basic ${auth}`);
|
|
17866
17925
|
}
|
|
17867
|
-
const response = await
|
|
17926
|
+
const response = await fetch2(`${baseUrl}/tx/${txid}`, {
|
|
17868
17927
|
headers
|
|
17869
17928
|
});
|
|
17870
17929
|
const tx = await response.json();
|
|
@@ -18335,7 +18394,14 @@ function getTransferPackageSigningPayload(transferID, transferPackage) {
|
|
|
18335
18394
|
// src/utils/transaction.ts
|
|
18336
18395
|
init_buffer();
|
|
18337
18396
|
var import_btc_signer = require("@scure/btc-signer");
|
|
18397
|
+
var INITIAL_TIMELOCK = 2e3;
|
|
18398
|
+
var TEST_UNILATERAL_TIMELOCK = 100;
|
|
18338
18399
|
var TIME_LOCK_INTERVAL = 100;
|
|
18400
|
+
var DIRECT_TIMELOCK_OFFSET = 50;
|
|
18401
|
+
var INITIAL_SEQUENCE = 1 << 30 | INITIAL_TIMELOCK;
|
|
18402
|
+
var INITIAL_DIRECT_SEQUENCE = 1 << 30 | INITIAL_TIMELOCK + DIRECT_TIMELOCK_OFFSET;
|
|
18403
|
+
var TEST_UNILATERAL_SEQUENCE = 1 << 30 | TEST_UNILATERAL_TIMELOCK;
|
|
18404
|
+
var TEST_UNILATERAL_DIRECT_SEQUENCE = 1 << 30 | TEST_UNILATERAL_TIMELOCK + DIRECT_TIMELOCK_OFFSET;
|
|
18339
18405
|
var ESTIMATED_TX_SIZE = 191;
|
|
18340
18406
|
var DEFAULT_SATS_PER_VBYTE = 5;
|
|
18341
18407
|
var DEFAULT_FEE_SATS = ESTIMATED_TX_SIZE * DEFAULT_SATS_PER_VBYTE;
|
|
@@ -18345,29 +18411,270 @@ function maybeApplyFee(amount) {
|
|
|
18345
18411
|
}
|
|
18346
18412
|
return amount;
|
|
18347
18413
|
}
|
|
18348
|
-
function
|
|
18349
|
-
const
|
|
18414
|
+
function createRootTx(depositOutPoint, depositTxOut) {
|
|
18415
|
+
const cpfpRootTx = new import_btc_signer.Transaction({
|
|
18416
|
+
version: 3,
|
|
18417
|
+
allowUnknownOutputs: true
|
|
18418
|
+
});
|
|
18419
|
+
cpfpRootTx.addInput(depositOutPoint);
|
|
18420
|
+
cpfpRootTx.addOutput(depositTxOut);
|
|
18421
|
+
cpfpRootTx.addOutput(getEphemeralAnchorOutput());
|
|
18422
|
+
const directRootTx = new import_btc_signer.Transaction({
|
|
18423
|
+
version: 3,
|
|
18424
|
+
allowUnknownOutputs: true
|
|
18425
|
+
});
|
|
18426
|
+
directRootTx.addInput(depositOutPoint);
|
|
18427
|
+
directRootTx.addOutput({
|
|
18428
|
+
script: depositTxOut.script,
|
|
18429
|
+
amount: maybeApplyFee(depositTxOut.amount ?? 0n)
|
|
18430
|
+
});
|
|
18431
|
+
return [cpfpRootTx, directRootTx];
|
|
18432
|
+
}
|
|
18433
|
+
function createSplitTx(parentOutPoint, childTxOuts) {
|
|
18434
|
+
const cpfpSplitTx = new import_btc_signer.Transaction({
|
|
18435
|
+
version: 3,
|
|
18436
|
+
allowUnknownOutputs: true
|
|
18437
|
+
});
|
|
18438
|
+
cpfpSplitTx.addInput(parentOutPoint);
|
|
18439
|
+
for (const txOut of childTxOuts) {
|
|
18440
|
+
cpfpSplitTx.addOutput(txOut);
|
|
18441
|
+
}
|
|
18442
|
+
cpfpSplitTx.addOutput(getEphemeralAnchorOutput());
|
|
18443
|
+
const directSplitTx = new import_btc_signer.Transaction({
|
|
18444
|
+
version: 3,
|
|
18445
|
+
allowUnknownOutputs: true
|
|
18446
|
+
});
|
|
18447
|
+
directSplitTx.addInput(parentOutPoint);
|
|
18448
|
+
let totalOutputAmount = 0n;
|
|
18449
|
+
for (const txOut of childTxOuts) {
|
|
18450
|
+
totalOutputAmount += txOut.amount ?? 0n;
|
|
18451
|
+
}
|
|
18452
|
+
if (totalOutputAmount > BigInt(DEFAULT_FEE_SATS)) {
|
|
18453
|
+
const feeRatio = Number(DEFAULT_FEE_SATS) / Number(totalOutputAmount);
|
|
18454
|
+
for (const txOut of childTxOuts) {
|
|
18455
|
+
const adjustedAmount = BigInt(
|
|
18456
|
+
Math.floor(Number(txOut.amount ?? 0n) * (1 - feeRatio))
|
|
18457
|
+
);
|
|
18458
|
+
directSplitTx.addOutput({
|
|
18459
|
+
script: txOut.script,
|
|
18460
|
+
amount: adjustedAmount
|
|
18461
|
+
});
|
|
18462
|
+
}
|
|
18463
|
+
} else {
|
|
18464
|
+
for (const txOut of childTxOuts) {
|
|
18465
|
+
directSplitTx.addOutput(txOut);
|
|
18466
|
+
}
|
|
18467
|
+
}
|
|
18468
|
+
return [cpfpSplitTx, directSplitTx];
|
|
18469
|
+
}
|
|
18470
|
+
function createNodeTx({
|
|
18471
|
+
txOut,
|
|
18472
|
+
parentOutPoint,
|
|
18473
|
+
applyFee,
|
|
18474
|
+
includeAnchor
|
|
18475
|
+
}) {
|
|
18476
|
+
const nodeTx = new import_btc_signer.Transaction({
|
|
18477
|
+
version: 3,
|
|
18478
|
+
allowUnknownOutputs: true
|
|
18479
|
+
});
|
|
18480
|
+
nodeTx.addInput(parentOutPoint);
|
|
18481
|
+
if (applyFee) {
|
|
18482
|
+
nodeTx.addOutput({
|
|
18483
|
+
script: txOut.script,
|
|
18484
|
+
amount: maybeApplyFee(txOut.amount ?? 0n)
|
|
18485
|
+
});
|
|
18486
|
+
} else {
|
|
18487
|
+
nodeTx.addOutput(txOut);
|
|
18488
|
+
}
|
|
18489
|
+
if (includeAnchor) {
|
|
18490
|
+
nodeTx.addOutput(getEphemeralAnchorOutput());
|
|
18491
|
+
}
|
|
18492
|
+
return nodeTx;
|
|
18493
|
+
}
|
|
18494
|
+
function createNodeTxs(txOut, txIn, directTxIn) {
|
|
18495
|
+
const cpfpNodeTx = createNodeTx({
|
|
18496
|
+
txOut,
|
|
18497
|
+
parentOutPoint: txIn,
|
|
18498
|
+
includeAnchor: true
|
|
18499
|
+
});
|
|
18500
|
+
let directNodeTx;
|
|
18501
|
+
if (directTxIn) {
|
|
18502
|
+
directNodeTx = createNodeTx({
|
|
18503
|
+
txOut,
|
|
18504
|
+
parentOutPoint: directTxIn,
|
|
18505
|
+
includeAnchor: false,
|
|
18506
|
+
applyFee: true
|
|
18507
|
+
});
|
|
18508
|
+
}
|
|
18509
|
+
return { cpfpNodeTx, directNodeTx };
|
|
18510
|
+
}
|
|
18511
|
+
function createLeafNodeTx(sequence, directSequence, parentOutPoint, txOut, shouldCalculateFee) {
|
|
18512
|
+
const cpfpLeafTx = new import_btc_signer.Transaction({
|
|
18513
|
+
version: 3,
|
|
18514
|
+
allowUnknownOutputs: true
|
|
18515
|
+
});
|
|
18516
|
+
cpfpLeafTx.addInput({
|
|
18517
|
+
...parentOutPoint,
|
|
18518
|
+
sequence
|
|
18519
|
+
});
|
|
18520
|
+
cpfpLeafTx.addOutput(txOut);
|
|
18521
|
+
cpfpLeafTx.addOutput(getEphemeralAnchorOutput());
|
|
18522
|
+
const directLeafTx = new import_btc_signer.Transaction({
|
|
18523
|
+
version: 3,
|
|
18524
|
+
allowUnknownOutputs: true
|
|
18525
|
+
});
|
|
18526
|
+
directLeafTx.addInput({
|
|
18527
|
+
...parentOutPoint,
|
|
18528
|
+
sequence: directSequence
|
|
18529
|
+
});
|
|
18530
|
+
const amountSats = txOut.amount ?? 0n;
|
|
18531
|
+
let outputAmount = amountSats;
|
|
18532
|
+
if (shouldCalculateFee) {
|
|
18533
|
+
outputAmount = maybeApplyFee(amountSats);
|
|
18534
|
+
}
|
|
18535
|
+
directLeafTx.addOutput({
|
|
18536
|
+
script: txOut.script,
|
|
18537
|
+
amount: outputAmount
|
|
18538
|
+
});
|
|
18539
|
+
return [cpfpLeafTx, directLeafTx];
|
|
18540
|
+
}
|
|
18541
|
+
function createRefundTx({
|
|
18542
|
+
sequence,
|
|
18543
|
+
input,
|
|
18544
|
+
amountSats,
|
|
18545
|
+
receivingPubkey,
|
|
18546
|
+
network,
|
|
18547
|
+
shouldCalculateFee,
|
|
18548
|
+
includeAnchor
|
|
18549
|
+
}) {
|
|
18550
|
+
const refundTx = new import_btc_signer.Transaction({
|
|
18350
18551
|
version: 3,
|
|
18351
18552
|
allowUnknownOutputs: true
|
|
18352
18553
|
});
|
|
18353
|
-
|
|
18354
|
-
...
|
|
18554
|
+
refundTx.addInput({
|
|
18555
|
+
...input,
|
|
18355
18556
|
sequence
|
|
18356
18557
|
});
|
|
18357
18558
|
const refundPkScript = getP2TRScriptFromPublicKey(receivingPubkey, network);
|
|
18358
|
-
|
|
18559
|
+
let outputAmount = amountSats;
|
|
18560
|
+
if (shouldCalculateFee) {
|
|
18561
|
+
outputAmount = maybeApplyFee(amountSats);
|
|
18562
|
+
}
|
|
18563
|
+
refundTx.addOutput({
|
|
18359
18564
|
script: refundPkScript,
|
|
18565
|
+
amount: outputAmount
|
|
18566
|
+
});
|
|
18567
|
+
if (includeAnchor) {
|
|
18568
|
+
refundTx.addOutput(getEphemeralAnchorOutput());
|
|
18569
|
+
}
|
|
18570
|
+
return refundTx;
|
|
18571
|
+
}
|
|
18572
|
+
function createRefundTxs({
|
|
18573
|
+
sequence,
|
|
18574
|
+
directSequence,
|
|
18575
|
+
input,
|
|
18576
|
+
directInput,
|
|
18577
|
+
amountSats,
|
|
18578
|
+
receivingPubkey,
|
|
18579
|
+
network
|
|
18580
|
+
}) {
|
|
18581
|
+
const cpfpRefundTx = createRefundTx({
|
|
18582
|
+
sequence,
|
|
18583
|
+
input,
|
|
18584
|
+
amountSats,
|
|
18585
|
+
receivingPubkey,
|
|
18586
|
+
network,
|
|
18587
|
+
shouldCalculateFee: false,
|
|
18588
|
+
includeAnchor: true
|
|
18589
|
+
});
|
|
18590
|
+
let directRefundTx;
|
|
18591
|
+
let directFromCpfpRefundTx;
|
|
18592
|
+
if (directSequence && directInput) {
|
|
18593
|
+
directRefundTx = createRefundTx({
|
|
18594
|
+
sequence: directSequence,
|
|
18595
|
+
input: directInput,
|
|
18596
|
+
amountSats,
|
|
18597
|
+
receivingPubkey,
|
|
18598
|
+
network,
|
|
18599
|
+
shouldCalculateFee: true,
|
|
18600
|
+
includeAnchor: false
|
|
18601
|
+
});
|
|
18602
|
+
directFromCpfpRefundTx = createRefundTx({
|
|
18603
|
+
sequence: directSequence,
|
|
18604
|
+
input,
|
|
18605
|
+
amountSats,
|
|
18606
|
+
receivingPubkey,
|
|
18607
|
+
network,
|
|
18608
|
+
shouldCalculateFee: true,
|
|
18609
|
+
includeAnchor: false
|
|
18610
|
+
});
|
|
18611
|
+
} else if (directInput && !directSequence) {
|
|
18612
|
+
throw new ValidationError(
|
|
18613
|
+
"directSequence must be provided if directInput is",
|
|
18614
|
+
{
|
|
18615
|
+
field: "directSequence",
|
|
18616
|
+
value: directSequence
|
|
18617
|
+
}
|
|
18618
|
+
);
|
|
18619
|
+
}
|
|
18620
|
+
return { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx };
|
|
18621
|
+
}
|
|
18622
|
+
function createConnectorRefundTransactions(sequence, cpfpNodeOutPoint, directNodeOutPoint, connectorOutput, amountSats, receiverPubKey, network, shouldCalculateFee) {
|
|
18623
|
+
const cpfpRefundTx = new import_btc_signer.Transaction({
|
|
18624
|
+
version: 3,
|
|
18625
|
+
allowUnknownOutputs: true
|
|
18626
|
+
});
|
|
18627
|
+
cpfpRefundTx.addInput({
|
|
18628
|
+
...cpfpNodeOutPoint,
|
|
18629
|
+
sequence
|
|
18630
|
+
});
|
|
18631
|
+
cpfpRefundTx.addInput(connectorOutput);
|
|
18632
|
+
const receiverScript = getP2TRScriptFromPublicKey(receiverPubKey, network);
|
|
18633
|
+
cpfpRefundTx.addOutput({
|
|
18634
|
+
script: receiverScript,
|
|
18360
18635
|
amount: amountSats
|
|
18361
18636
|
});
|
|
18362
|
-
|
|
18363
|
-
|
|
18637
|
+
const directRefundTx = new import_btc_signer.Transaction({
|
|
18638
|
+
version: 3,
|
|
18639
|
+
allowUnknownOutputs: true
|
|
18640
|
+
});
|
|
18641
|
+
directRefundTx.addInput({
|
|
18642
|
+
...directNodeOutPoint,
|
|
18643
|
+
sequence
|
|
18644
|
+
});
|
|
18645
|
+
directRefundTx.addInput(connectorOutput);
|
|
18646
|
+
let outputAmount = amountSats;
|
|
18647
|
+
if (shouldCalculateFee) {
|
|
18648
|
+
outputAmount = maybeApplyFee(amountSats);
|
|
18649
|
+
}
|
|
18650
|
+
directRefundTx.addOutput({
|
|
18651
|
+
script: receiverScript,
|
|
18652
|
+
amount: outputAmount
|
|
18653
|
+
});
|
|
18654
|
+
const directFromCpfpTx = new import_btc_signer.Transaction({
|
|
18655
|
+
version: 3,
|
|
18656
|
+
allowUnknownOutputs: true
|
|
18657
|
+
});
|
|
18658
|
+
directFromCpfpTx.addInput({
|
|
18659
|
+
...cpfpNodeOutPoint,
|
|
18660
|
+
sequence
|
|
18661
|
+
});
|
|
18662
|
+
directFromCpfpTx.addInput(connectorOutput);
|
|
18663
|
+
directFromCpfpTx.addOutput({
|
|
18664
|
+
script: receiverScript,
|
|
18665
|
+
amount: outputAmount
|
|
18666
|
+
});
|
|
18667
|
+
return [cpfpRefundTx, directRefundTx, directFromCpfpTx];
|
|
18364
18668
|
}
|
|
18365
18669
|
function getCurrentTimelock(currSequence) {
|
|
18366
18670
|
return (currSequence || 0) & 65535;
|
|
18367
18671
|
}
|
|
18368
18672
|
function getTransactionSequence(currSequence) {
|
|
18369
18673
|
const timelock = getCurrentTimelock(currSequence);
|
|
18370
|
-
return
|
|
18674
|
+
return {
|
|
18675
|
+
nextSequence: 1 << 30 | timelock,
|
|
18676
|
+
nextDirectSequence: 1 << 30 | timelock + DIRECT_TIMELOCK_OFFSET
|
|
18677
|
+
};
|
|
18371
18678
|
}
|
|
18372
18679
|
function checkIfValidSequence(currSequence) {
|
|
18373
18680
|
const TIME_LOCK_ACTIVE = (currSequence || 0) & 2147483648;
|
|
@@ -18385,24 +18692,32 @@ function checkIfValidSequence(currSequence) {
|
|
|
18385
18692
|
});
|
|
18386
18693
|
}
|
|
18387
18694
|
}
|
|
18388
|
-
function
|
|
18695
|
+
function doesLeafNeedRefresh(currSequence, isNodeTx) {
|
|
18389
18696
|
const currentTimelock = getCurrentTimelock(currSequence);
|
|
18390
|
-
|
|
18391
|
-
|
|
18392
|
-
return {
|
|
18393
|
-
nextSequence: 1 << 30 | nextTimelock,
|
|
18394
|
-
needRefresh: true
|
|
18395
|
-
};
|
|
18697
|
+
if (isNodeTx) {
|
|
18698
|
+
return currentTimelock === 0;
|
|
18396
18699
|
}
|
|
18397
|
-
|
|
18700
|
+
return currentTimelock <= 100;
|
|
18701
|
+
}
|
|
18702
|
+
function getNextTransactionSequence(currSequence, isNodeTx) {
|
|
18703
|
+
const currentTimelock = getCurrentTimelock(currSequence);
|
|
18704
|
+
const nextTimelock = currentTimelock - TIME_LOCK_INTERVAL;
|
|
18705
|
+
if (isNodeTx && nextTimelock < 0) {
|
|
18398
18706
|
throw new ValidationError("timelock interval is less than 0", {
|
|
18399
18707
|
field: "nextTimelock",
|
|
18400
|
-
value: nextTimelock
|
|
18708
|
+
value: nextTimelock,
|
|
18709
|
+
expected: "Non-negative timelock interval"
|
|
18710
|
+
});
|
|
18711
|
+
} else if (!isNodeTx && nextTimelock <= 0) {
|
|
18712
|
+
throw new ValidationError("timelock interval is less than or equal to 0", {
|
|
18713
|
+
field: "nextTimelock",
|
|
18714
|
+
value: nextTimelock,
|
|
18715
|
+
expected: "Timelock greater than 0"
|
|
18401
18716
|
});
|
|
18402
18717
|
}
|
|
18403
18718
|
return {
|
|
18404
18719
|
nextSequence: 1 << 30 | nextTimelock,
|
|
18405
|
-
|
|
18720
|
+
nextDirectSequence: 1 << 30 | nextTimelock + DIRECT_TIMELOCK_OFFSET
|
|
18406
18721
|
};
|
|
18407
18722
|
}
|
|
18408
18723
|
function getEphemeralAnchorOutput() {
|
|
@@ -18931,7 +19246,7 @@ init_buffer();
|
|
|
18931
19246
|
var import_core8 = require("@lightsparkdev/core");
|
|
18932
19247
|
var isReactNative = typeof navigator !== "undefined" && navigator.product === "ReactNative";
|
|
18933
19248
|
var isBun = globalThis.Bun !== void 0;
|
|
18934
|
-
var packageVersion = true ? "0.2.
|
|
19249
|
+
var packageVersion = true ? "0.2.4" : "unknown";
|
|
18935
19250
|
var baseEnvStr = "unknown";
|
|
18936
19251
|
if (isBun) {
|
|
18937
19252
|
const bunVersion = "version" in globalThis.Bun ? globalThis.Bun.version : "unknown-version";
|
|
@@ -19642,10 +19957,18 @@ init_buffer();
|
|
|
19642
19957
|
var CompleteLeavesSwap = `
|
|
19643
19958
|
mutation CompleteLeavesSwap(
|
|
19644
19959
|
$adaptor_secret_key: String!
|
|
19960
|
+
$direct_adaptor_secret_key: String!
|
|
19961
|
+
$direct_from_cpfp_adaptor_secret_key: String!
|
|
19645
19962
|
$user_outbound_transfer_external_id: UUID!
|
|
19646
19963
|
$leaves_swap_request_id: ID!
|
|
19647
19964
|
) {
|
|
19648
|
-
complete_leaves_swap(input: {
|
|
19965
|
+
complete_leaves_swap(input: {
|
|
19966
|
+
adaptor_secret_key: $adaptor_secret_key,
|
|
19967
|
+
direct_adaptor_secret_key: $direct_adaptor_secret_key,
|
|
19968
|
+
direct_from_cpfp_adaptor_secret_key: $direct_from_cpfp_adaptor_secret_key,
|
|
19969
|
+
user_outbound_transfer_external_id: $user_outbound_transfer_external_id,
|
|
19970
|
+
leaves_swap_request_id: $leaves_swap_request_id
|
|
19971
|
+
}) {
|
|
19649
19972
|
request {
|
|
19650
19973
|
...LeavesSwapRequestFragment
|
|
19651
19974
|
}
|
|
@@ -19776,6 +20099,8 @@ init_buffer();
|
|
|
19776
20099
|
var RequestSwapLeaves = `
|
|
19777
20100
|
mutation RequestSwapLeaves(
|
|
19778
20101
|
$adaptor_pubkey: PublicKey!
|
|
20102
|
+
$direct_adaptor_pubkey: PublicKey
|
|
20103
|
+
$direct_from_cpfp_adaptor_pubkey: PublicKey
|
|
19779
20104
|
$total_amount_sats: Long!
|
|
19780
20105
|
$target_amount_sats: Long!
|
|
19781
20106
|
$fee_sats: Long!
|
|
@@ -19785,6 +20110,8 @@ var RequestSwapLeaves = `
|
|
|
19785
20110
|
) {
|
|
19786
20111
|
request_leaves_swap(input: {
|
|
19787
20112
|
adaptor_pubkey: $adaptor_pubkey
|
|
20113
|
+
direct_adaptor_pubkey: $direct_adaptor_pubkey
|
|
20114
|
+
direct_from_cpfp_adaptor_pubkey: $direct_from_cpfp_adaptor_pubkey
|
|
19788
20115
|
total_amount_sats: $total_amount_sats
|
|
19789
20116
|
target_amount_sats: $target_amount_sats
|
|
19790
20117
|
fee_sats: $fee_sats
|
|
@@ -20293,6 +20620,8 @@ var SspClient = class {
|
|
|
20293
20620
|
}
|
|
20294
20621
|
async requestLeaveSwap({
|
|
20295
20622
|
adaptorPubkey,
|
|
20623
|
+
directAdaptorPubkey,
|
|
20624
|
+
directFromCpfpAdaptorPubkey,
|
|
20296
20625
|
totalAmountSats,
|
|
20297
20626
|
targetAmountSats,
|
|
20298
20627
|
feeSats,
|
|
@@ -20304,6 +20633,8 @@ var SspClient = class {
|
|
|
20304
20633
|
queryPayload: RequestSwapLeaves,
|
|
20305
20634
|
variables: {
|
|
20306
20635
|
adaptor_pubkey: adaptorPubkey,
|
|
20636
|
+
direct_adaptor_pubkey: directAdaptorPubkey,
|
|
20637
|
+
direct_from_cpfp_adaptor_pubkey: directFromCpfpAdaptorPubkey,
|
|
20307
20638
|
total_amount_sats: totalAmountSats,
|
|
20308
20639
|
target_amount_sats: targetAmountSats,
|
|
20309
20640
|
fee_sats: feeSats,
|
|
@@ -20322,6 +20653,8 @@ var SspClient = class {
|
|
|
20322
20653
|
}
|
|
20323
20654
|
async completeLeaveSwap({
|
|
20324
20655
|
adaptorSecretKey,
|
|
20656
|
+
directAdaptorSecretKey,
|
|
20657
|
+
directFromCpfpAdaptorSecretKey,
|
|
20325
20658
|
userOutboundTransferExternalId,
|
|
20326
20659
|
leavesSwapRequestId
|
|
20327
20660
|
}) {
|
|
@@ -20329,6 +20662,8 @@ var SspClient = class {
|
|
|
20329
20662
|
queryPayload: CompleteLeavesSwap,
|
|
20330
20663
|
variables: {
|
|
20331
20664
|
adaptor_secret_key: adaptorSecretKey,
|
|
20665
|
+
direct_adaptor_secret_key: directAdaptorSecretKey,
|
|
20666
|
+
direct_from_cpfp_adaptor_secret_key: directFromCpfpAdaptorSecretKey,
|
|
20332
20667
|
user_outbound_transfer_external_id: userOutboundTransferExternalId,
|
|
20333
20668
|
leaves_swap_request_id: leavesSwapRequestId
|
|
20334
20669
|
},
|
|
@@ -24493,11 +24828,7 @@ var import_sha28 = require("@noble/hashes/sha2");
|
|
|
24493
24828
|
var import_btc_signer2 = require("@scure/btc-signer");
|
|
24494
24829
|
var ecies2 = __toESM(require("eciesjs"), 1);
|
|
24495
24830
|
var import_uuidv72 = require("uuidv7");
|
|
24496
|
-
var INITIAL_TIME_LOCK = 2e3;
|
|
24497
24831
|
var DEFAULT_EXPIRY_TIME = 10 * 60 * 1e3;
|
|
24498
|
-
function initialSequence() {
|
|
24499
|
-
return 1 << 30 | INITIAL_TIME_LOCK;
|
|
24500
|
-
}
|
|
24501
24832
|
function getSigningJobProto(signingJob) {
|
|
24502
24833
|
return {
|
|
24503
24834
|
signingPublicKey: signingJob.signingPublicKey,
|
|
@@ -24514,12 +24845,14 @@ var BaseTransferService = class {
|
|
|
24514
24845
|
this.connectionManager = connectionManager;
|
|
24515
24846
|
this.signingService = signingService;
|
|
24516
24847
|
}
|
|
24517
|
-
async sendTransferTweakKey(transfer, leaves,
|
|
24848
|
+
async sendTransferTweakKey(transfer, leaves, cpfpRefundSignatureMap, directRefundSignatureMap, directFromCpfpRefundSignatureMap) {
|
|
24518
24849
|
const keyTweakInputMap = await this.prepareSendTransferKeyTweaks(
|
|
24519
24850
|
transfer.id,
|
|
24520
24851
|
transfer.receiverIdentityPublicKey,
|
|
24521
24852
|
leaves,
|
|
24522
|
-
|
|
24853
|
+
cpfpRefundSignatureMap,
|
|
24854
|
+
directRefundSignatureMap,
|
|
24855
|
+
directFromCpfpRefundSignatureMap
|
|
24523
24856
|
);
|
|
24524
24857
|
let updatedTransfer;
|
|
24525
24858
|
const coordinatorOperator = this.config.getSigningOperators()[this.config.getCoordinatorIdentifier()];
|
|
@@ -24557,13 +24890,26 @@ var BaseTransferService = class {
|
|
|
24557
24890
|
}
|
|
24558
24891
|
return updatedTransfer;
|
|
24559
24892
|
}
|
|
24560
|
-
async deliverTransferPackage(transfer, leaves,
|
|
24893
|
+
async deliverTransferPackage(transfer, leaves, cpfpRefundSignatureMap, directRefundSignatureMap, directFromCpfpRefundSignatureMap) {
|
|
24561
24894
|
const keyTweakInputMap = await this.prepareSendTransferKeyTweaks(
|
|
24562
24895
|
transfer.id,
|
|
24563
24896
|
transfer.receiverIdentityPublicKey,
|
|
24564
24897
|
leaves,
|
|
24565
|
-
|
|
24898
|
+
cpfpRefundSignatureMap,
|
|
24899
|
+
directRefundSignatureMap,
|
|
24900
|
+
directFromCpfpRefundSignatureMap
|
|
24566
24901
|
);
|
|
24902
|
+
for (const [key, operator] of Object.entries(
|
|
24903
|
+
this.config.getSigningOperators()
|
|
24904
|
+
)) {
|
|
24905
|
+
const tweaks = keyTweakInputMap.get(key);
|
|
24906
|
+
if (!tweaks) {
|
|
24907
|
+
throw new ValidationError("No tweaks for operator", {
|
|
24908
|
+
field: "operator",
|
|
24909
|
+
value: key
|
|
24910
|
+
});
|
|
24911
|
+
}
|
|
24912
|
+
}
|
|
24567
24913
|
const transferPackage = await this.prepareTransferPackage(
|
|
24568
24914
|
transfer.id,
|
|
24569
24915
|
keyTweakInputMap,
|
|
@@ -24589,6 +24935,8 @@ var BaseTransferService = class {
|
|
|
24589
24935
|
transferID,
|
|
24590
24936
|
receiverIdentityPubkey,
|
|
24591
24937
|
leaves,
|
|
24938
|
+
/* @__PURE__ */ new Map(),
|
|
24939
|
+
/* @__PURE__ */ new Map(),
|
|
24592
24940
|
/* @__PURE__ */ new Map()
|
|
24593
24941
|
);
|
|
24594
24942
|
const transferPackage = await this.prepareTransferPackage(
|
|
@@ -24602,7 +24950,7 @@ var BaseTransferService = class {
|
|
|
24602
24950
|
);
|
|
24603
24951
|
let response;
|
|
24604
24952
|
try {
|
|
24605
|
-
response = await sparkClient.
|
|
24953
|
+
response = await sparkClient.start_transfer_v2({
|
|
24606
24954
|
transferId: transferID,
|
|
24607
24955
|
ownerIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),
|
|
24608
24956
|
receiverIdentityPublicKey: receiverIdentityPubkey,
|
|
@@ -24631,12 +24979,22 @@ var BaseTransferService = class {
|
|
|
24631
24979
|
nodes.push(leaf.leaf.id);
|
|
24632
24980
|
}
|
|
24633
24981
|
const signingCommitments = await sparkClient.get_signing_commitments({
|
|
24634
|
-
nodeIds: nodes
|
|
24982
|
+
nodeIds: nodes,
|
|
24983
|
+
count: 3
|
|
24635
24984
|
});
|
|
24636
|
-
const
|
|
24985
|
+
const {
|
|
24986
|
+
cpfpLeafSigningJobs,
|
|
24987
|
+
directLeafSigningJobs,
|
|
24988
|
+
directFromCpfpLeafSigningJobs
|
|
24989
|
+
} = await this.signingService.signRefunds(
|
|
24637
24990
|
leaves,
|
|
24638
|
-
|
|
24639
|
-
|
|
24991
|
+
receiverIdentityPubkey,
|
|
24992
|
+
signingCommitments.signingCommitments.slice(0, leaves.length),
|
|
24993
|
+
signingCommitments.signingCommitments.slice(
|
|
24994
|
+
leaves.length,
|
|
24995
|
+
2 * leaves.length
|
|
24996
|
+
),
|
|
24997
|
+
signingCommitments.signingCommitments.slice(2 * leaves.length)
|
|
24640
24998
|
);
|
|
24641
24999
|
const encryptedKeyTweaks = {};
|
|
24642
25000
|
for (const [key, value] of keyTweakInputMap) {
|
|
@@ -24656,12 +25014,11 @@ var BaseTransferService = class {
|
|
|
24656
25014
|
encryptedKeyTweaks[key] = Uint8Array.from(encryptedProto);
|
|
24657
25015
|
}
|
|
24658
25016
|
const transferPackage = {
|
|
24659
|
-
leavesToSend:
|
|
25017
|
+
leavesToSend: cpfpLeafSigningJobs,
|
|
24660
25018
|
keyTweakPackage: encryptedKeyTweaks,
|
|
24661
25019
|
userSignature: new Uint8Array(),
|
|
24662
|
-
|
|
24663
|
-
|
|
24664
|
-
directFromCpfpLeavesToSend: []
|
|
25020
|
+
directLeavesToSend: directLeafSigningJobs,
|
|
25021
|
+
directFromCpfpLeavesToSend: directFromCpfpLeafSigningJobs
|
|
24665
25022
|
};
|
|
24666
25023
|
const transferPackageSigningPayload = getTransferPackageSigningPayload(
|
|
24667
25024
|
transferID,
|
|
@@ -24721,7 +25078,7 @@ var BaseTransferService = class {
|
|
|
24721
25078
|
}
|
|
24722
25079
|
return updatedTransfer;
|
|
24723
25080
|
}
|
|
24724
|
-
async signRefunds(leafDataMap, operatorSigningResults,
|
|
25081
|
+
async signRefunds(leafDataMap, operatorSigningResults, cpfpAdaptorPubKey, directAdaptorPubKey, directFromCpfpAdaptorPubKey) {
|
|
24725
25082
|
const nodeSignatures = [];
|
|
24726
25083
|
for (const operatorSigningResult of operatorSigningResults) {
|
|
24727
25084
|
const leafData = leafDataMap.get(operatorSigningResult.leafId);
|
|
@@ -24736,54 +25093,120 @@ var BaseTransferService = class {
|
|
|
24736
25093
|
`Output not found for leaf ${operatorSigningResult.leafId}`
|
|
24737
25094
|
);
|
|
24738
25095
|
}
|
|
24739
|
-
const
|
|
25096
|
+
const cpfpRefundTxSighash = getSigHashFromTx(
|
|
25097
|
+
leafData.refundTx,
|
|
25098
|
+
0,
|
|
25099
|
+
txOutput
|
|
25100
|
+
);
|
|
24740
25101
|
const publicKey = await this.config.signer.getPublicKeyFromDerivation(
|
|
24741
25102
|
leafData.keyDerivation
|
|
24742
25103
|
);
|
|
24743
|
-
const
|
|
24744
|
-
message:
|
|
25104
|
+
const cpfpUserSignature = await this.config.signer.signFrost({
|
|
25105
|
+
message: cpfpRefundTxSighash,
|
|
24745
25106
|
publicKey,
|
|
24746
25107
|
keyDerivation: leafData.keyDerivation,
|
|
24747
25108
|
selfCommitment: leafData.signingNonceCommitment,
|
|
24748
25109
|
statechainCommitments: operatorSigningResult.refundTxSigningResult?.signingNonceCommitments,
|
|
24749
|
-
adaptorPubKey,
|
|
25110
|
+
adaptorPubKey: cpfpAdaptorPubKey,
|
|
24750
25111
|
verifyingKey: operatorSigningResult.verifyingKey
|
|
24751
25112
|
});
|
|
24752
|
-
const
|
|
24753
|
-
message:
|
|
25113
|
+
const cpfpRefundAggregate = await this.config.signer.aggregateFrost({
|
|
25114
|
+
message: cpfpRefundTxSighash,
|
|
24754
25115
|
statechainSignatures: operatorSigningResult.refundTxSigningResult?.signatureShares,
|
|
24755
25116
|
statechainPublicKeys: operatorSigningResult.refundTxSigningResult?.publicKeys,
|
|
24756
25117
|
verifyingKey: operatorSigningResult.verifyingKey,
|
|
24757
25118
|
statechainCommitments: operatorSigningResult.refundTxSigningResult?.signingNonceCommitments,
|
|
24758
25119
|
selfCommitment: leafData.signingNonceCommitment,
|
|
24759
25120
|
publicKey,
|
|
24760
|
-
selfSignature:
|
|
24761
|
-
adaptorPubKey
|
|
25121
|
+
selfSignature: cpfpUserSignature,
|
|
25122
|
+
adaptorPubKey: cpfpAdaptorPubKey
|
|
24762
25123
|
});
|
|
25124
|
+
let directRefundAggregate;
|
|
25125
|
+
let directFromCpfpRefundAggregate;
|
|
25126
|
+
if (leafData.directTx) {
|
|
25127
|
+
const directTxOutput = leafData.directTx.getOutput(0);
|
|
25128
|
+
if (leafData.directRefundTx) {
|
|
25129
|
+
const directRefundTxSighash = getSigHashFromTx(
|
|
25130
|
+
leafData.directRefundTx,
|
|
25131
|
+
0,
|
|
25132
|
+
directTxOutput
|
|
25133
|
+
);
|
|
25134
|
+
const directUserSignature = await this.config.signer.signFrost({
|
|
25135
|
+
message: directRefundTxSighash,
|
|
25136
|
+
publicKey,
|
|
25137
|
+
keyDerivation: leafData.keyDerivation,
|
|
25138
|
+
selfCommitment: leafData.directSigningNonceCommitment,
|
|
25139
|
+
statechainCommitments: operatorSigningResult.directRefundTxSigningResult?.signingNonceCommitments,
|
|
25140
|
+
adaptorPubKey: directAdaptorPubKey,
|
|
25141
|
+
verifyingKey: operatorSigningResult.verifyingKey
|
|
25142
|
+
});
|
|
25143
|
+
directRefundAggregate = await this.config.signer.aggregateFrost({
|
|
25144
|
+
message: directRefundTxSighash,
|
|
25145
|
+
statechainSignatures: operatorSigningResult.directRefundTxSigningResult?.signatureShares,
|
|
25146
|
+
statechainPublicKeys: operatorSigningResult.directRefundTxSigningResult?.publicKeys,
|
|
25147
|
+
verifyingKey: operatorSigningResult.verifyingKey,
|
|
25148
|
+
statechainCommitments: operatorSigningResult.directRefundTxSigningResult?.signingNonceCommitments,
|
|
25149
|
+
selfCommitment: leafData.directSigningNonceCommitment,
|
|
25150
|
+
publicKey,
|
|
25151
|
+
selfSignature: directUserSignature,
|
|
25152
|
+
adaptorPubKey: directAdaptorPubKey
|
|
25153
|
+
});
|
|
25154
|
+
}
|
|
25155
|
+
if (leafData.directFromCpfpRefundTx) {
|
|
25156
|
+
const directFromCpfpRefundTxSighash = getSigHashFromTx(
|
|
25157
|
+
leafData.directFromCpfpRefundTx,
|
|
25158
|
+
0,
|
|
25159
|
+
txOutput
|
|
25160
|
+
);
|
|
25161
|
+
const directFromCpfpUserSignature = await this.config.signer.signFrost({
|
|
25162
|
+
message: directFromCpfpRefundTxSighash,
|
|
25163
|
+
publicKey,
|
|
25164
|
+
keyDerivation: leafData.keyDerivation,
|
|
25165
|
+
selfCommitment: leafData.directFromCpfpRefundSigningNonceCommitment,
|
|
25166
|
+
statechainCommitments: operatorSigningResult.directFromCpfpRefundTxSigningResult?.signingNonceCommitments,
|
|
25167
|
+
adaptorPubKey: directFromCpfpAdaptorPubKey,
|
|
25168
|
+
verifyingKey: operatorSigningResult.verifyingKey
|
|
25169
|
+
});
|
|
25170
|
+
directFromCpfpRefundAggregate = await this.config.signer.aggregateFrost({
|
|
25171
|
+
message: directFromCpfpRefundTxSighash,
|
|
25172
|
+
statechainSignatures: operatorSigningResult.directFromCpfpRefundTxSigningResult?.signatureShares,
|
|
25173
|
+
statechainPublicKeys: operatorSigningResult.directFromCpfpRefundTxSigningResult?.publicKeys,
|
|
25174
|
+
verifyingKey: operatorSigningResult.verifyingKey,
|
|
25175
|
+
statechainCommitments: operatorSigningResult.directFromCpfpRefundTxSigningResult?.signingNonceCommitments,
|
|
25176
|
+
selfCommitment: leafData.directFromCpfpRefundSigningNonceCommitment,
|
|
25177
|
+
publicKey,
|
|
25178
|
+
selfSignature: directFromCpfpUserSignature,
|
|
25179
|
+
adaptorPubKey: directFromCpfpAdaptorPubKey
|
|
25180
|
+
});
|
|
25181
|
+
}
|
|
25182
|
+
}
|
|
24763
25183
|
nodeSignatures.push({
|
|
24764
25184
|
nodeId: operatorSigningResult.leafId,
|
|
24765
|
-
refundTxSignature: refundAggregate,
|
|
24766
25185
|
nodeTxSignature: new Uint8Array(),
|
|
24767
|
-
// TODO: Add direct refund signature
|
|
24768
25186
|
directNodeTxSignature: new Uint8Array(),
|
|
24769
|
-
|
|
24770
|
-
|
|
25187
|
+
refundTxSignature: cpfpRefundAggregate,
|
|
25188
|
+
directRefundTxSignature: directRefundAggregate ?? new Uint8Array(),
|
|
25189
|
+
directFromCpfpRefundTxSignature: directFromCpfpRefundAggregate ?? new Uint8Array()
|
|
24771
25190
|
});
|
|
24772
25191
|
}
|
|
24773
25192
|
return nodeSignatures;
|
|
24774
25193
|
}
|
|
24775
|
-
async prepareSendTransferKeyTweaks(transferID, receiverIdentityPubkey, leaves,
|
|
25194
|
+
async prepareSendTransferKeyTweaks(transferID, receiverIdentityPubkey, leaves, cpfpRefundSignatureMap, directRefundSignatureMap, directFromCpfpRefundSignatureMap) {
|
|
24776
25195
|
const receiverEciesPubKey = ecies2.PublicKey.fromHex(
|
|
24777
25196
|
(0, import_utils14.bytesToHex)(receiverIdentityPubkey)
|
|
24778
25197
|
);
|
|
24779
25198
|
const leavesTweaksMap = /* @__PURE__ */ new Map();
|
|
24780
25199
|
for (const leaf of leaves) {
|
|
24781
|
-
const
|
|
25200
|
+
const cpfpRefundSignature = cpfpRefundSignatureMap.get(leaf.leaf.id);
|
|
25201
|
+
const directRefundSignature = directRefundSignatureMap.get(leaf.leaf.id);
|
|
25202
|
+
const directFromCpfpRefundSignature = directFromCpfpRefundSignatureMap.get(leaf.leaf.id);
|
|
24782
25203
|
const leafTweaksMap = await this.prepareSingleSendTransferKeyTweak(
|
|
24783
25204
|
transferID,
|
|
24784
25205
|
leaf,
|
|
24785
25206
|
receiverEciesPubKey,
|
|
24786
|
-
|
|
25207
|
+
cpfpRefundSignature,
|
|
25208
|
+
directRefundSignature,
|
|
25209
|
+
directFromCpfpRefundSignature
|
|
24787
25210
|
);
|
|
24788
25211
|
for (const [identifier, leafTweak] of leafTweaksMap) {
|
|
24789
25212
|
leavesTweaksMap.set(identifier, [
|
|
@@ -24794,7 +25217,7 @@ var BaseTransferService = class {
|
|
|
24794
25217
|
}
|
|
24795
25218
|
return leavesTweaksMap;
|
|
24796
25219
|
}
|
|
24797
|
-
async prepareSingleSendTransferKeyTweak(transferID, leaf, receiverEciesPubKey,
|
|
25220
|
+
async prepareSingleSendTransferKeyTweak(transferID, leaf, receiverEciesPubKey, cpfpRefundSignature, directRefundSignature, directFromCpfpRefundSignature) {
|
|
24798
25221
|
const signingOperators = this.config.getSigningOperators();
|
|
24799
25222
|
const { shares, secretCipher } = await this.config.signer.subtractSplitAndEncrypt({
|
|
24800
25223
|
first: leaf.keyDerivation,
|
|
@@ -24842,10 +25265,9 @@ var BaseTransferService = class {
|
|
|
24842
25265
|
pubkeySharesTweak: Object.fromEntries(pubkeySharesTweak),
|
|
24843
25266
|
secretCipher,
|
|
24844
25267
|
signature,
|
|
24845
|
-
refundSignature:
|
|
24846
|
-
|
|
24847
|
-
|
|
24848
|
-
directFromCpfpRefundSignature: new Uint8Array()
|
|
25268
|
+
refundSignature: cpfpRefundSignature ?? new Uint8Array(),
|
|
25269
|
+
directRefundSignature: directRefundSignature ?? new Uint8Array(),
|
|
25270
|
+
directFromCpfpRefundSignature: directFromCpfpRefundSignature ?? new Uint8Array()
|
|
24849
25271
|
});
|
|
24850
25272
|
}
|
|
24851
25273
|
return leafTweaksMap;
|
|
@@ -24875,7 +25297,12 @@ var TransferService = class extends BaseTransferService {
|
|
|
24875
25297
|
* Deprecated in v0.1.32
|
|
24876
25298
|
*/
|
|
24877
25299
|
async sendTransfer(leaves, receiverIdentityPubkey) {
|
|
24878
|
-
const {
|
|
25300
|
+
const {
|
|
25301
|
+
transfer,
|
|
25302
|
+
signatureMap,
|
|
25303
|
+
directSignatureMap,
|
|
25304
|
+
directFromCpfpSignatureMap
|
|
25305
|
+
} = await this.sendTransferSignRefund(
|
|
24879
25306
|
leaves,
|
|
24880
25307
|
receiverIdentityPubkey,
|
|
24881
25308
|
new Date(Date.now() + DEFAULT_EXPIRY_TIME)
|
|
@@ -24883,7 +25310,9 @@ var TransferService = class extends BaseTransferService {
|
|
|
24883
25310
|
const transferWithTweakedKeys = await this.sendTransferTweakKey(
|
|
24884
25311
|
transfer,
|
|
24885
25312
|
leaves,
|
|
24886
|
-
signatureMap
|
|
25313
|
+
signatureMap,
|
|
25314
|
+
directSignatureMap,
|
|
25315
|
+
directFromCpfpSignatureMap
|
|
24887
25316
|
);
|
|
24888
25317
|
return transferWithTweakedKeys;
|
|
24889
25318
|
}
|
|
@@ -24987,7 +25416,13 @@ var TransferService = class extends BaseTransferService {
|
|
|
24987
25416
|
return transferResp.transfers[0];
|
|
24988
25417
|
}
|
|
24989
25418
|
async sendTransferSignRefund(leaves, receiverIdentityPubkey, expiryTime) {
|
|
24990
|
-
const {
|
|
25419
|
+
const {
|
|
25420
|
+
transfer,
|
|
25421
|
+
signatureMap,
|
|
25422
|
+
directSignatureMap,
|
|
25423
|
+
directFromCpfpSignatureMap,
|
|
25424
|
+
leafDataMap
|
|
25425
|
+
} = await this.sendTransferSignRefundInternal(
|
|
24991
25426
|
leaves,
|
|
24992
25427
|
receiverIdentityPubkey,
|
|
24993
25428
|
expiryTime,
|
|
@@ -24996,11 +25431,19 @@ var TransferService = class extends BaseTransferService {
|
|
|
24996
25431
|
return {
|
|
24997
25432
|
transfer,
|
|
24998
25433
|
signatureMap,
|
|
25434
|
+
directSignatureMap,
|
|
25435
|
+
directFromCpfpSignatureMap,
|
|
24999
25436
|
leafDataMap
|
|
25000
25437
|
};
|
|
25001
25438
|
}
|
|
25002
25439
|
async startSwapSignRefund(leaves, receiverIdentityPubkey, expiryTime) {
|
|
25003
|
-
const {
|
|
25440
|
+
const {
|
|
25441
|
+
transfer,
|
|
25442
|
+
signatureMap,
|
|
25443
|
+
directSignatureMap,
|
|
25444
|
+
directFromCpfpSignatureMap,
|
|
25445
|
+
leafDataMap
|
|
25446
|
+
} = await this.sendTransferSignRefundInternal(
|
|
25004
25447
|
leaves,
|
|
25005
25448
|
receiverIdentityPubkey,
|
|
25006
25449
|
expiryTime,
|
|
@@ -25009,31 +25452,45 @@ var TransferService = class extends BaseTransferService {
|
|
|
25009
25452
|
return {
|
|
25010
25453
|
transfer,
|
|
25011
25454
|
signatureMap,
|
|
25455
|
+
directSignatureMap,
|
|
25456
|
+
directFromCpfpSignatureMap,
|
|
25012
25457
|
leafDataMap
|
|
25013
25458
|
};
|
|
25014
25459
|
}
|
|
25015
|
-
async counterSwapSignRefund(leaves, receiverIdentityPubkey, expiryTime,
|
|
25460
|
+
async counterSwapSignRefund(leaves, receiverIdentityPubkey, expiryTime, cpfpAdaptorPubKey, directAdaptorPubKey, directFromCpfpAdaptorPubKey) {
|
|
25016
25461
|
return this.sendTransferSignRefundInternal(
|
|
25017
25462
|
leaves,
|
|
25018
25463
|
receiverIdentityPubkey,
|
|
25019
25464
|
expiryTime,
|
|
25020
25465
|
true,
|
|
25021
|
-
|
|
25466
|
+
cpfpAdaptorPubKey,
|
|
25467
|
+
directAdaptorPubKey,
|
|
25468
|
+
directFromCpfpAdaptorPubKey
|
|
25022
25469
|
);
|
|
25023
25470
|
}
|
|
25024
|
-
async sendTransferSignRefundInternal(leaves, receiverIdentityPubkey, expiryTime, forSwap,
|
|
25471
|
+
async sendTransferSignRefundInternal(leaves, receiverIdentityPubkey, expiryTime, forSwap, cpfpAdaptorPubKey, directAdaptorPubKey, directFromCpfpAdaptorPubKey) {
|
|
25025
25472
|
const transferId = (0, import_uuidv72.uuidv7)();
|
|
25026
25473
|
const leafDataMap = /* @__PURE__ */ new Map();
|
|
25027
25474
|
for (const leaf of leaves) {
|
|
25028
25475
|
const signingNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
25476
|
+
const directSigningNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
25477
|
+
const directFromCpfpRefundSigningNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
25029
25478
|
const tx = getTxFromRawTxBytes(leaf.leaf.nodeTx);
|
|
25030
25479
|
const refundTx = getTxFromRawTxBytes(leaf.leaf.refundTx);
|
|
25480
|
+
const directTx = leaf.leaf.directTx.length > 0 ? getTxFromRawTxBytes(leaf.leaf.directTx) : void 0;
|
|
25481
|
+
const directRefundTx = leaf.leaf.directRefundTx.length > 0 ? getTxFromRawTxBytes(leaf.leaf.directRefundTx) : void 0;
|
|
25482
|
+
const directFromCpfpRefundTx = leaf.leaf.directFromCpfpRefundTx.length > 0 ? getTxFromRawTxBytes(leaf.leaf.directFromCpfpRefundTx) : void 0;
|
|
25031
25483
|
leafDataMap.set(leaf.leaf.id, {
|
|
25032
25484
|
keyDerivation: leaf.keyDerivation,
|
|
25033
25485
|
receivingPubkey: receiverIdentityPubkey,
|
|
25034
25486
|
signingNonceCommitment,
|
|
25487
|
+
directSigningNonceCommitment,
|
|
25035
25488
|
tx,
|
|
25489
|
+
directTx,
|
|
25036
25490
|
refundTx,
|
|
25491
|
+
directRefundTx,
|
|
25492
|
+
directFromCpfpRefundTx,
|
|
25493
|
+
directFromCpfpRefundSigningNonceCommitment,
|
|
25037
25494
|
vout: leaf.leaf.vout
|
|
25038
25495
|
});
|
|
25039
25496
|
}
|
|
@@ -25046,8 +25503,8 @@ var TransferService = class extends BaseTransferService {
|
|
|
25046
25503
|
);
|
|
25047
25504
|
let response;
|
|
25048
25505
|
try {
|
|
25049
|
-
if (
|
|
25050
|
-
response = await sparkClient.
|
|
25506
|
+
if (cpfpAdaptorPubKey !== void 0 || directAdaptorPubKey !== void 0 || directFromCpfpAdaptorPubKey !== void 0) {
|
|
25507
|
+
response = await sparkClient.counter_leaf_swap_v2({
|
|
25051
25508
|
transfer: {
|
|
25052
25509
|
transferId,
|
|
25053
25510
|
leavesToSend: signingJobs,
|
|
@@ -25056,10 +25513,12 @@ var TransferService = class extends BaseTransferService {
|
|
|
25056
25513
|
expiryTime
|
|
25057
25514
|
},
|
|
25058
25515
|
swapId: (0, import_uuidv72.uuidv7)(),
|
|
25059
|
-
adaptorPublicKey:
|
|
25516
|
+
adaptorPublicKey: cpfpAdaptorPubKey,
|
|
25517
|
+
directAdaptorPublicKey: directAdaptorPubKey,
|
|
25518
|
+
directFromCpfpAdaptorPublicKey: directFromCpfpAdaptorPubKey
|
|
25060
25519
|
});
|
|
25061
25520
|
} else if (forSwap) {
|
|
25062
|
-
response = await sparkClient.
|
|
25521
|
+
response = await sparkClient.start_leaf_swap_v2({
|
|
25063
25522
|
transferId,
|
|
25064
25523
|
leavesToSend: signingJobs,
|
|
25065
25524
|
ownerIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),
|
|
@@ -25067,7 +25526,7 @@ var TransferService = class extends BaseTransferService {
|
|
|
25067
25526
|
expiryTime
|
|
25068
25527
|
});
|
|
25069
25528
|
} else {
|
|
25070
|
-
response = await sparkClient.
|
|
25529
|
+
response = await sparkClient.start_transfer_v2({
|
|
25071
25530
|
transferId,
|
|
25072
25531
|
leavesToSend: signingJobs,
|
|
25073
25532
|
ownerIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),
|
|
@@ -25084,15 +25543,29 @@ var TransferService = class extends BaseTransferService {
|
|
|
25084
25543
|
const signatures = await this.signRefunds(
|
|
25085
25544
|
leafDataMap,
|
|
25086
25545
|
response.signingResults,
|
|
25087
|
-
|
|
25546
|
+
cpfpAdaptorPubKey,
|
|
25547
|
+
directAdaptorPubKey,
|
|
25548
|
+
directFromCpfpAdaptorPubKey
|
|
25088
25549
|
);
|
|
25089
|
-
const
|
|
25550
|
+
const cpfpSignatureMap = /* @__PURE__ */ new Map();
|
|
25551
|
+
const directSignatureMap = /* @__PURE__ */ new Map();
|
|
25552
|
+
const directFromCpfpSignatureMap = /* @__PURE__ */ new Map();
|
|
25090
25553
|
for (const signature of signatures) {
|
|
25091
|
-
|
|
25554
|
+
cpfpSignatureMap.set(signature.nodeId, signature.refundTxSignature);
|
|
25555
|
+
directSignatureMap.set(
|
|
25556
|
+
signature.nodeId,
|
|
25557
|
+
signature.directRefundTxSignature
|
|
25558
|
+
);
|
|
25559
|
+
directFromCpfpSignatureMap.set(
|
|
25560
|
+
signature.nodeId,
|
|
25561
|
+
signature.directFromCpfpRefundTxSignature
|
|
25562
|
+
);
|
|
25092
25563
|
}
|
|
25093
25564
|
return {
|
|
25094
25565
|
transfer: response.transfer,
|
|
25095
|
-
signatureMap,
|
|
25566
|
+
signatureMap: cpfpSignatureMap,
|
|
25567
|
+
directSignatureMap,
|
|
25568
|
+
directFromCpfpSignatureMap,
|
|
25096
25569
|
leafDataMap,
|
|
25097
25570
|
signingResults: response.signingResults
|
|
25098
25571
|
};
|
|
@@ -25105,38 +25578,68 @@ var TransferService = class extends BaseTransferService {
|
|
|
25105
25578
|
throw new Error(`Leaf data not found for leaf ${leaf.leaf.id}`);
|
|
25106
25579
|
}
|
|
25107
25580
|
const nodeTx = getTxFromRawTxBytes(leaf.leaf.nodeTx);
|
|
25108
|
-
const
|
|
25581
|
+
const cpfpNodeOutPoint = {
|
|
25109
25582
|
txid: (0, import_utils14.hexToBytes)(getTxId(nodeTx)),
|
|
25110
25583
|
index: 0
|
|
25111
25584
|
};
|
|
25585
|
+
let directNodeTx;
|
|
25586
|
+
let directNodeOutPoint;
|
|
25587
|
+
if (leaf.leaf.directTx.length > 0) {
|
|
25588
|
+
directNodeTx = getTxFromRawTxBytes(leaf.leaf.directTx);
|
|
25589
|
+
directNodeOutPoint = {
|
|
25590
|
+
txid: (0, import_utils14.hexToBytes)(getTxId(directNodeTx)),
|
|
25591
|
+
index: 0
|
|
25592
|
+
};
|
|
25593
|
+
}
|
|
25112
25594
|
const currRefundTx = getTxFromRawTxBytes(leaf.leaf.refundTx);
|
|
25113
|
-
const
|
|
25595
|
+
const sequence = currRefundTx.getInput(0).sequence;
|
|
25596
|
+
if (!sequence) {
|
|
25597
|
+
throw new ValidationError("Invalid refund transaction", {
|
|
25598
|
+
field: "sequence",
|
|
25599
|
+
value: currRefundTx.getInput(0),
|
|
25600
|
+
expected: "Non-null sequence"
|
|
25601
|
+
});
|
|
25602
|
+
}
|
|
25603
|
+
const { nextSequence, nextDirectSequence } = isForClaim ? getTransactionSequence(sequence) : getNextTransactionSequence(sequence);
|
|
25114
25604
|
const amountSats = currRefundTx.getOutput(0).amount;
|
|
25115
25605
|
if (amountSats === void 0) {
|
|
25116
25606
|
throw new Error("Amount not found in signRefunds");
|
|
25117
25607
|
}
|
|
25118
|
-
const
|
|
25119
|
-
nextSequence,
|
|
25120
|
-
|
|
25608
|
+
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } = createRefundTxs({
|
|
25609
|
+
sequence: nextSequence,
|
|
25610
|
+
directSequence: nextDirectSequence,
|
|
25611
|
+
input: cpfpNodeOutPoint,
|
|
25612
|
+
directInput: directNodeOutPoint,
|
|
25121
25613
|
amountSats,
|
|
25122
|
-
refundSigningData.receivingPubkey,
|
|
25123
|
-
this.config.getNetwork()
|
|
25614
|
+
receivingPubkey: refundSigningData.receivingPubkey,
|
|
25615
|
+
network: this.config.getNetwork()
|
|
25616
|
+
});
|
|
25617
|
+
refundSigningData.refundTx = cpfpRefundTx;
|
|
25618
|
+
refundSigningData.directRefundTx = directRefundTx;
|
|
25619
|
+
refundSigningData.directFromCpfpRefundTx = directFromCpfpRefundTx;
|
|
25620
|
+
const cpfpRefundNonceCommitmentProto = refundSigningData.signingNonceCommitment;
|
|
25621
|
+
const directRefundNonceCommitmentProto = refundSigningData.directSigningNonceCommitment;
|
|
25622
|
+
const directFromCpfpRefundNonceCommitmentProto = refundSigningData.directFromCpfpRefundSigningNonceCommitment;
|
|
25623
|
+
const signingPublicKey = await this.config.signer.getPublicKeyFromDerivation(
|
|
25624
|
+
refundSigningData.keyDerivation
|
|
25124
25625
|
);
|
|
25125
|
-
refundSigningData.refundTx = refundTx;
|
|
25126
|
-
const refundNonceCommitmentProto = refundSigningData.signingNonceCommitment;
|
|
25127
25626
|
signingJobs.push({
|
|
25128
25627
|
leafId: leaf.leaf.id,
|
|
25129
25628
|
refundTxSigningJob: {
|
|
25130
|
-
signingPublicKey
|
|
25131
|
-
|
|
25132
|
-
|
|
25133
|
-
rawTx: refundTx.toBytes(),
|
|
25134
|
-
signingNonceCommitment: refundNonceCommitmentProto.commitment
|
|
25629
|
+
signingPublicKey,
|
|
25630
|
+
rawTx: cpfpRefundTx.toBytes(),
|
|
25631
|
+
signingNonceCommitment: cpfpRefundNonceCommitmentProto.commitment
|
|
25135
25632
|
},
|
|
25136
|
-
|
|
25137
|
-
|
|
25138
|
-
|
|
25139
|
-
|
|
25633
|
+
directRefundTxSigningJob: directRefundTx ? {
|
|
25634
|
+
signingPublicKey,
|
|
25635
|
+
rawTx: directRefundTx.toBytes(),
|
|
25636
|
+
signingNonceCommitment: directRefundNonceCommitmentProto.commitment
|
|
25637
|
+
} : void 0,
|
|
25638
|
+
directFromCpfpRefundTxSigningJob: directFromCpfpRefundTx ? {
|
|
25639
|
+
signingPublicKey,
|
|
25640
|
+
rawTx: directFromCpfpRefundTx.toBytes(),
|
|
25641
|
+
signingNonceCommitment: directFromCpfpRefundNonceCommitmentProto.commitment
|
|
25642
|
+
} : void 0
|
|
25140
25643
|
});
|
|
25141
25644
|
}
|
|
25142
25645
|
return signingJobs;
|
|
@@ -25257,13 +25760,17 @@ var TransferService = class extends BaseTransferService {
|
|
|
25257
25760
|
const leafDataMap = /* @__PURE__ */ new Map();
|
|
25258
25761
|
for (const leafKey of leafKeys) {
|
|
25259
25762
|
const tx = getTxFromRawTxBytes(leafKey.leaf.nodeTx);
|
|
25763
|
+
const directTx = leafKey.leaf.directTx.length > 0 ? getTxFromRawTxBytes(leafKey.leaf.directTx) : void 0;
|
|
25260
25764
|
leafDataMap.set(leafKey.leaf.id, {
|
|
25261
25765
|
keyDerivation: leafKey.newKeyDerivation,
|
|
25262
25766
|
receivingPubkey: await this.config.signer.getPublicKeyFromDerivation(
|
|
25263
25767
|
leafKey.newKeyDerivation
|
|
25264
25768
|
),
|
|
25265
25769
|
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
25770
|
+
directSigningNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
25771
|
+
directFromCpfpRefundSigningNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
25266
25772
|
tx,
|
|
25773
|
+
directTx,
|
|
25267
25774
|
vout: leafKey.leaf.vout
|
|
25268
25775
|
});
|
|
25269
25776
|
}
|
|
@@ -25285,7 +25792,7 @@ var TransferService = class extends BaseTransferService {
|
|
|
25285
25792
|
}
|
|
25286
25793
|
}
|
|
25287
25794
|
try {
|
|
25288
|
-
resp = await sparkClient.
|
|
25795
|
+
resp = await sparkClient.claim_transfer_sign_refunds_v2({
|
|
25289
25796
|
transferId: transfer.id,
|
|
25290
25797
|
ownerIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),
|
|
25291
25798
|
signingJobs
|
|
@@ -25300,7 +25807,7 @@ var TransferService = class extends BaseTransferService {
|
|
|
25300
25807
|
this.config.getCoordinatorAddress()
|
|
25301
25808
|
);
|
|
25302
25809
|
try {
|
|
25303
|
-
return await sparkClient.
|
|
25810
|
+
return await sparkClient.finalize_node_signatures_v2({
|
|
25304
25811
|
intent: 1 /* TRANSFER */,
|
|
25305
25812
|
nodeSignatures
|
|
25306
25813
|
});
|
|
@@ -25339,109 +25846,134 @@ var TransferService = class extends BaseTransferService {
|
|
|
25339
25846
|
throw new Error(`Error querying pending transfers by sender: ${error}`);
|
|
25340
25847
|
}
|
|
25341
25848
|
}
|
|
25342
|
-
async
|
|
25343
|
-
if (nodes.length === 0) {
|
|
25344
|
-
throw Error("no nodes to refresh");
|
|
25345
|
-
}
|
|
25849
|
+
async refreshTimelockNodesInternal(node, parentNode, useTestUnilateralSequence) {
|
|
25346
25850
|
const signingJobs = [];
|
|
25347
|
-
const
|
|
25348
|
-
|
|
25349
|
-
|
|
25350
|
-
|
|
25351
|
-
|
|
25352
|
-
|
|
25353
|
-
|
|
25354
|
-
|
|
25355
|
-
|
|
25356
|
-
|
|
25357
|
-
|
|
25358
|
-
|
|
25359
|
-
|
|
25360
|
-
|
|
25361
|
-
|
|
25362
|
-
|
|
25363
|
-
|
|
25364
|
-
|
|
25365
|
-
|
|
25366
|
-
|
|
25367
|
-
|
|
25368
|
-
|
|
25369
|
-
|
|
25370
|
-
newTx.addOutput(additionalOutput);
|
|
25371
|
-
}
|
|
25372
|
-
}
|
|
25373
|
-
if (i === 0) {
|
|
25374
|
-
const currSequence = input.sequence;
|
|
25375
|
-
newTx.addInput({
|
|
25376
|
-
...input,
|
|
25377
|
-
sequence: getNextTransactionSequence(currSequence).nextSequence
|
|
25378
|
-
});
|
|
25379
|
-
} else {
|
|
25380
|
-
newTx.addInput({
|
|
25381
|
-
...input,
|
|
25382
|
-
sequence: initialSequence(),
|
|
25383
|
-
txid: newNodeTxs[i - 1]?.id
|
|
25384
|
-
});
|
|
25385
|
-
}
|
|
25386
|
-
signingJobs.push({
|
|
25387
|
-
signingPublicKey: await this.config.signer.getPublicKeyFromDerivation({
|
|
25388
|
-
type: "leaf" /* LEAF */,
|
|
25389
|
-
path: node.id
|
|
25390
|
-
}),
|
|
25391
|
-
rawTx: newTx.toBytes(),
|
|
25392
|
-
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment()
|
|
25851
|
+
const parentNodeTx = getTxFromRawTxBytes(parentNode.nodeTx);
|
|
25852
|
+
const parentNodeOutput = parentNodeTx.getOutput(0);
|
|
25853
|
+
if (!parentNodeOutput) {
|
|
25854
|
+
throw Error("Could not get parent node output");
|
|
25855
|
+
}
|
|
25856
|
+
const nodeTx = getTxFromRawTxBytes(node.nodeTx);
|
|
25857
|
+
const nodeInput = nodeTx.getInput(0);
|
|
25858
|
+
const nodeOutput = nodeTx.getOutput(0);
|
|
25859
|
+
if (!nodeOutput) {
|
|
25860
|
+
throw Error("Could not get node output");
|
|
25861
|
+
}
|
|
25862
|
+
let directNodeTx;
|
|
25863
|
+
let directNodeInput;
|
|
25864
|
+
if (node.directTx.length > 0) {
|
|
25865
|
+
directNodeTx = getTxFromRawTxBytes(node.directTx);
|
|
25866
|
+
directNodeInput = directNodeTx.getInput(0);
|
|
25867
|
+
}
|
|
25868
|
+
const currSequence = nodeInput.sequence;
|
|
25869
|
+
if (!currSequence) {
|
|
25870
|
+
throw new ValidationError("Invalid node transaction", {
|
|
25871
|
+
field: "sequence",
|
|
25872
|
+
value: nodeInput,
|
|
25873
|
+
expected: "Non-null sequence"
|
|
25393
25874
|
});
|
|
25394
|
-
newNodeTxs[i] = newTx;
|
|
25395
25875
|
}
|
|
25396
|
-
|
|
25397
|
-
|
|
25398
|
-
|
|
25876
|
+
let { nextSequence, nextDirectSequence } = getNextTransactionSequence(
|
|
25877
|
+
currSequence,
|
|
25878
|
+
true
|
|
25879
|
+
);
|
|
25880
|
+
const output = {
|
|
25881
|
+
script: parentNodeOutput.script,
|
|
25882
|
+
amount: parentNodeOutput.amount
|
|
25883
|
+
};
|
|
25884
|
+
const newNodeInput = {
|
|
25885
|
+
txid: nodeInput.txid,
|
|
25886
|
+
index: nodeInput.index,
|
|
25887
|
+
sequence: useTestUnilateralSequence ? TEST_UNILATERAL_SEQUENCE : nextSequence
|
|
25888
|
+
};
|
|
25889
|
+
const newDirectInput = directNodeTx && directNodeInput ? {
|
|
25890
|
+
txid: directNodeInput.txid,
|
|
25891
|
+
index: directNodeInput.index,
|
|
25892
|
+
sequence: useTestUnilateralSequence ? TEST_UNILATERAL_DIRECT_SEQUENCE : nextDirectSequence
|
|
25893
|
+
} : void 0;
|
|
25894
|
+
const { cpfpNodeTx, directNodeTx: newDirectNodeTx } = createNodeTxs(
|
|
25895
|
+
output,
|
|
25896
|
+
newNodeInput,
|
|
25897
|
+
newDirectInput
|
|
25898
|
+
);
|
|
25899
|
+
const newCpfpNodeOutput = cpfpNodeTx.getOutput(0);
|
|
25900
|
+
if (!newCpfpNodeOutput) {
|
|
25901
|
+
throw Error("Could not get new cpfp node output");
|
|
25399
25902
|
}
|
|
25400
|
-
const
|
|
25401
|
-
const
|
|
25402
|
-
|
|
25403
|
-
|
|
25903
|
+
const newDirectNodeOutput = newDirectNodeTx?.getOutput(0);
|
|
25904
|
+
const signingPublicKey = await this.config.signer.getPublicKeyFromDerivation({
|
|
25905
|
+
type: "leaf" /* LEAF */,
|
|
25906
|
+
path: node.id
|
|
25404
25907
|
});
|
|
25405
|
-
|
|
25406
|
-
|
|
25407
|
-
|
|
25408
|
-
|
|
25409
|
-
|
|
25410
|
-
|
|
25411
|
-
amount: originalRefundOutput.amount
|
|
25908
|
+
signingJobs.push({
|
|
25909
|
+
signingPublicKey,
|
|
25910
|
+
rawTx: cpfpNodeTx.toBytes(),
|
|
25911
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
25912
|
+
type: "node",
|
|
25913
|
+
parentTxOut: parentNodeOutput
|
|
25412
25914
|
});
|
|
25413
|
-
|
|
25414
|
-
|
|
25415
|
-
|
|
25416
|
-
|
|
25417
|
-
|
|
25418
|
-
|
|
25419
|
-
|
|
25420
|
-
|
|
25421
|
-
throw Error("refund tx doesn't have input");
|
|
25915
|
+
if (newDirectNodeTx) {
|
|
25916
|
+
signingJobs.push({
|
|
25917
|
+
signingPublicKey,
|
|
25918
|
+
rawTx: newDirectNodeTx.toBytes(),
|
|
25919
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
25920
|
+
type: "directNode",
|
|
25921
|
+
parentTxOut: parentNodeOutput
|
|
25922
|
+
});
|
|
25422
25923
|
}
|
|
25423
|
-
|
|
25424
|
-
|
|
25924
|
+
const newCpfpRefundOutPoint = {
|
|
25925
|
+
txid: (0, import_utils14.hexToBytes)(getTxId(cpfpNodeTx)),
|
|
25926
|
+
index: 0
|
|
25927
|
+
};
|
|
25928
|
+
let newDirectRefundOutPoint;
|
|
25929
|
+
if (newDirectNodeTx) {
|
|
25930
|
+
newDirectRefundOutPoint = {
|
|
25931
|
+
txid: (0, import_utils14.hexToBytes)(getTxId(newDirectNodeTx)),
|
|
25932
|
+
index: 0
|
|
25933
|
+
};
|
|
25425
25934
|
}
|
|
25426
|
-
|
|
25427
|
-
|
|
25428
|
-
|
|
25429
|
-
|
|
25430
|
-
|
|
25431
|
-
|
|
25432
|
-
|
|
25935
|
+
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } = createRefundTxs({
|
|
25936
|
+
sequence: INITIAL_SEQUENCE,
|
|
25937
|
+
directSequence: INITIAL_DIRECT_SEQUENCE,
|
|
25938
|
+
input: newCpfpRefundOutPoint,
|
|
25939
|
+
directInput: newDirectRefundOutPoint,
|
|
25940
|
+
amountSats: nodeOutput.amount,
|
|
25941
|
+
receivingPubkey: await this.config.signer.getPublicKeyFromDerivation({
|
|
25433
25942
|
type: "leaf" /* LEAF */,
|
|
25434
|
-
path:
|
|
25943
|
+
path: node.id
|
|
25435
25944
|
}),
|
|
25436
|
-
|
|
25437
|
-
|
|
25438
|
-
|
|
25439
|
-
|
|
25945
|
+
network: this.config.getNetwork()
|
|
25946
|
+
});
|
|
25947
|
+
signingJobs.push({
|
|
25948
|
+
signingPublicKey,
|
|
25949
|
+
rawTx: cpfpRefundTx.toBytes(),
|
|
25950
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
25951
|
+
type: "cpfp",
|
|
25952
|
+
parentTxOut: newCpfpNodeOutput
|
|
25953
|
+
});
|
|
25954
|
+
if (directRefundTx && newDirectNodeOutput) {
|
|
25955
|
+
signingJobs.push({
|
|
25956
|
+
signingPublicKey,
|
|
25957
|
+
rawTx: directRefundTx.toBytes(),
|
|
25958
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
25959
|
+
type: "direct",
|
|
25960
|
+
parentTxOut: newDirectNodeOutput
|
|
25961
|
+
});
|
|
25962
|
+
}
|
|
25963
|
+
if (directFromCpfpRefundTx && newCpfpNodeOutput) {
|
|
25964
|
+
signingJobs.push({
|
|
25965
|
+
signingPublicKey,
|
|
25966
|
+
rawTx: directFromCpfpRefundTx.toBytes(),
|
|
25967
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
25968
|
+
type: "directFromCpfp",
|
|
25969
|
+
parentTxOut: newCpfpNodeOutput
|
|
25970
|
+
});
|
|
25971
|
+
}
|
|
25440
25972
|
const sparkClient = await this.connectionManager.createSparkClient(
|
|
25441
25973
|
this.config.getCoordinatorAddress()
|
|
25442
25974
|
);
|
|
25443
|
-
const response = await sparkClient.
|
|
25444
|
-
leafId:
|
|
25975
|
+
const response = await sparkClient.refresh_timelock_v2({
|
|
25976
|
+
leafId: node.id,
|
|
25445
25977
|
ownerIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),
|
|
25446
25978
|
signingJobs: signingJobs.map(getSigningJobProto)
|
|
25447
25979
|
});
|
|
@@ -25451,45 +25983,27 @@ var TransferService = class extends BaseTransferService {
|
|
|
25451
25983
|
);
|
|
25452
25984
|
}
|
|
25453
25985
|
let nodeSignatures = [];
|
|
25454
|
-
let
|
|
25455
|
-
let
|
|
25456
|
-
let
|
|
25457
|
-
|
|
25458
|
-
|
|
25986
|
+
let leafCpfpSignature;
|
|
25987
|
+
let leafDirectSignature;
|
|
25988
|
+
let cpfpRefundSignature;
|
|
25989
|
+
let directRefundSignature;
|
|
25990
|
+
let directFromCpfpRefundSignature;
|
|
25991
|
+
for (const [i, signingResult] of response.signingResults.entries()) {
|
|
25459
25992
|
const signingJob = signingJobs[i];
|
|
25460
25993
|
if (!signingJob || !signingResult) {
|
|
25461
25994
|
throw Error("Signing job does not exist");
|
|
25462
25995
|
}
|
|
25463
|
-
if (!signingJob.signingNonceCommitment) {
|
|
25464
|
-
throw Error("nonce commitment does not exist");
|
|
25465
|
-
}
|
|
25466
25996
|
const rawTx = getTxFromRawTxBytes(signingJob.rawTx);
|
|
25467
|
-
|
|
25468
|
-
|
|
25469
|
-
|
|
25470
|
-
if (i === nodes.length) {
|
|
25471
|
-
nodeId = nodes[i - 1]?.id;
|
|
25472
|
-
parentTx = newNodeTxs[i - 1];
|
|
25473
|
-
vout = 0;
|
|
25474
|
-
} else if (i === 0) {
|
|
25475
|
-
nodeId = nodes[i]?.id;
|
|
25476
|
-
parentTx = getTxFromRawTxBytes(parentNode.nodeTx);
|
|
25477
|
-
vout = nodes[i]?.vout;
|
|
25478
|
-
} else {
|
|
25479
|
-
nodeId = nodes[i]?.id;
|
|
25480
|
-
parentTx = newNodeTxs[i - 1];
|
|
25481
|
-
vout = nodes[i]?.vout;
|
|
25997
|
+
const txOut = signingJob.parentTxOut;
|
|
25998
|
+
if (!txOut) {
|
|
25999
|
+
throw Error("Could not get tx out");
|
|
25482
26000
|
}
|
|
25483
|
-
if (!parentTx || !nodeId || vout === void 0) {
|
|
25484
|
-
throw Error("Could not parse signing results");
|
|
25485
|
-
}
|
|
25486
|
-
const txOut = parentTx.getOutput(vout);
|
|
25487
26001
|
const rawTxSighash = getSigHashFromTx(rawTx, 0, txOut);
|
|
25488
26002
|
const userSignature = await this.config.signer.signFrost({
|
|
25489
26003
|
message: rawTxSighash,
|
|
25490
26004
|
keyDerivation: {
|
|
25491
26005
|
type: "leaf" /* LEAF */,
|
|
25492
|
-
path:
|
|
26006
|
+
path: node.id
|
|
25493
26007
|
},
|
|
25494
26008
|
publicKey: signingJob.signingPublicKey,
|
|
25495
26009
|
verifyingKey: signingResult.verifyingKey,
|
|
@@ -25508,41 +26022,35 @@ var TransferService = class extends BaseTransferService {
|
|
|
25508
26022
|
selfSignature: userSignature,
|
|
25509
26023
|
adaptorPubKey: new Uint8Array()
|
|
25510
26024
|
});
|
|
25511
|
-
if (
|
|
25512
|
-
|
|
25513
|
-
|
|
25514
|
-
|
|
25515
|
-
|
|
25516
|
-
|
|
25517
|
-
|
|
25518
|
-
|
|
25519
|
-
|
|
25520
|
-
|
|
25521
|
-
} else if (i === nodes.length) {
|
|
25522
|
-
refundSignature = signature;
|
|
25523
|
-
} else if (i === nodes.length - 1) {
|
|
25524
|
-
leafNodeId = nodeId;
|
|
25525
|
-
leafSignature = signature;
|
|
26025
|
+
if (signingJob.type === "node") {
|
|
26026
|
+
leafCpfpSignature = signature;
|
|
26027
|
+
} else if (signingJob.type === "directNode") {
|
|
26028
|
+
leafDirectSignature = signature;
|
|
26029
|
+
} else if (signingJob.type === "cpfp") {
|
|
26030
|
+
cpfpRefundSignature = signature;
|
|
26031
|
+
} else if (signingJob.type === "direct") {
|
|
26032
|
+
directRefundSignature = signature;
|
|
26033
|
+
} else if (signingJob.type === "directFromCpfp") {
|
|
26034
|
+
directFromCpfpRefundSignature = signature;
|
|
25526
26035
|
}
|
|
25527
26036
|
}
|
|
25528
|
-
if (!leafSignature || !refundSignature || !leafNodeId) {
|
|
25529
|
-
throw Error("leaf or refund signature does not exist");
|
|
25530
|
-
}
|
|
25531
26037
|
nodeSignatures.push({
|
|
25532
|
-
nodeId:
|
|
25533
|
-
nodeTxSignature:
|
|
25534
|
-
|
|
25535
|
-
|
|
25536
|
-
|
|
25537
|
-
|
|
25538
|
-
directFromCpfpRefundTxSignature: new Uint8Array()
|
|
26038
|
+
nodeId: node.id,
|
|
26039
|
+
nodeTxSignature: leafCpfpSignature || new Uint8Array(),
|
|
26040
|
+
directNodeTxSignature: leafDirectSignature || new Uint8Array(),
|
|
26041
|
+
refundTxSignature: cpfpRefundSignature || new Uint8Array(),
|
|
26042
|
+
directRefundTxSignature: directRefundSignature || new Uint8Array(),
|
|
26043
|
+
directFromCpfpRefundTxSignature: directFromCpfpRefundSignature || new Uint8Array()
|
|
25539
26044
|
});
|
|
25540
|
-
const result = await sparkClient.
|
|
26045
|
+
const result = await sparkClient.finalize_node_signatures_v2({
|
|
25541
26046
|
intent: 3 /* REFRESH */,
|
|
25542
26047
|
nodeSignatures
|
|
25543
26048
|
});
|
|
25544
26049
|
return result;
|
|
25545
26050
|
}
|
|
26051
|
+
async refreshTimelockNodes(node, parentNode) {
|
|
26052
|
+
return await this.refreshTimelockNodesInternal(node, parentNode);
|
|
26053
|
+
}
|
|
25546
26054
|
async extendTimelock(node) {
|
|
25547
26055
|
const nodeTx = getTxFromRawTxBytes(node.nodeTx);
|
|
25548
26056
|
const refundTx = getTxFromRawTxBytes(node.refundTx);
|
|
@@ -25551,7 +26059,10 @@ var TransferService = class extends BaseTransferService {
|
|
|
25551
26059
|
txid: (0, import_utils14.hexToBytes)(getTxId(nodeTx)),
|
|
25552
26060
|
index: 0
|
|
25553
26061
|
};
|
|
25554
|
-
const {
|
|
26062
|
+
const {
|
|
26063
|
+
nextSequence: newNodeSequence,
|
|
26064
|
+
nextDirectSequence: newDirectNodeSequence
|
|
26065
|
+
} = getNextTransactionSequence(refundSequence);
|
|
25555
26066
|
const newNodeTx = new import_btc_signer2.Transaction({
|
|
25556
26067
|
version: 3,
|
|
25557
26068
|
allowUnknownOutputs: true
|
|
@@ -25564,81 +26075,122 @@ var TransferService = class extends BaseTransferService {
|
|
|
25564
26075
|
newNodeTx.addOutput({
|
|
25565
26076
|
script: originalOutput.script,
|
|
25566
26077
|
amount: originalOutput.amount
|
|
25567
|
-
// feeReducedAmount,
|
|
25568
26078
|
});
|
|
25569
26079
|
newNodeTx.addOutput(getEphemeralAnchorOutput());
|
|
25570
|
-
|
|
26080
|
+
let newDirectNodeTx;
|
|
26081
|
+
if (node.directTx.length > 0) {
|
|
26082
|
+
newDirectNodeTx = new import_btc_signer2.Transaction({
|
|
26083
|
+
version: 3,
|
|
26084
|
+
allowUnknownOutputs: true
|
|
26085
|
+
});
|
|
26086
|
+
newDirectNodeTx.addInput({
|
|
26087
|
+
...newNodeOutPoint,
|
|
26088
|
+
sequence: newDirectNodeSequence
|
|
26089
|
+
});
|
|
26090
|
+
newDirectNodeTx.addOutput({
|
|
26091
|
+
script: originalOutput.script,
|
|
26092
|
+
amount: maybeApplyFee(originalOutput.amount)
|
|
26093
|
+
});
|
|
26094
|
+
}
|
|
26095
|
+
const newCpfpRefundOutPoint = {
|
|
25571
26096
|
txid: (0, import_utils14.hexToBytes)(getTxId(newNodeTx)),
|
|
25572
26097
|
index: 0
|
|
25573
26098
|
};
|
|
26099
|
+
let newDirectRefundOutPoint;
|
|
26100
|
+
if (newDirectNodeTx) {
|
|
26101
|
+
newDirectRefundOutPoint = {
|
|
26102
|
+
txid: (0, import_utils14.hexToBytes)(getTxId(newDirectNodeTx)),
|
|
26103
|
+
index: 0
|
|
26104
|
+
};
|
|
26105
|
+
}
|
|
25574
26106
|
const amountSats = refundTx.getOutput(0).amount;
|
|
25575
26107
|
if (amountSats === void 0) {
|
|
25576
26108
|
throw new Error("Amount not found in extendTimelock");
|
|
25577
26109
|
}
|
|
25578
|
-
const
|
|
26110
|
+
const signingPublicKey = await this.config.signer.getPublicKeyFromDerivation({
|
|
25579
26111
|
type: "leaf" /* LEAF */,
|
|
25580
26112
|
path: node.id
|
|
25581
26113
|
});
|
|
25582
|
-
const
|
|
25583
|
-
|
|
25584
|
-
|
|
26114
|
+
const {
|
|
26115
|
+
cpfpRefundTx: newCpfpRefundTx,
|
|
26116
|
+
directRefundTx: newDirectRefundTx,
|
|
26117
|
+
directFromCpfpRefundTx: newDirectFromCpfpRefundTx
|
|
26118
|
+
} = createRefundTxs({
|
|
26119
|
+
sequence: INITIAL_SEQUENCE,
|
|
26120
|
+
directSequence: INITIAL_DIRECT_SEQUENCE,
|
|
26121
|
+
input: newCpfpRefundOutPoint,
|
|
26122
|
+
directInput: newDirectRefundOutPoint,
|
|
25585
26123
|
amountSats,
|
|
25586
|
-
|
|
25587
|
-
|
|
25588
|
-
|
|
25589
|
-
)
|
|
26124
|
+
receivingPubkey: signingPublicKey,
|
|
26125
|
+
network: this.config.getNetwork()
|
|
26126
|
+
});
|
|
26127
|
+
if (!newCpfpRefundTx) {
|
|
26128
|
+
throw new ValidationError(
|
|
26129
|
+
"Failed to create refund transactions in extendTimelock"
|
|
26130
|
+
);
|
|
26131
|
+
}
|
|
25590
26132
|
const nodeSighash = getSigHashFromTx(newNodeTx, 0, nodeTx.getOutput(0));
|
|
25591
|
-
const
|
|
25592
|
-
|
|
26133
|
+
const directNodeSighash = newDirectNodeTx ? getSigHashFromTx(newDirectNodeTx, 0, nodeTx.getOutput(0)) : void 0;
|
|
26134
|
+
const cpfpRefundSighash = getSigHashFromTx(
|
|
26135
|
+
newCpfpRefundTx,
|
|
25593
26136
|
0,
|
|
25594
26137
|
newNodeTx.getOutput(0)
|
|
25595
26138
|
);
|
|
26139
|
+
const directRefundSighash = newDirectNodeTx && newDirectRefundTx ? getSigHashFromTx(newDirectRefundTx, 0, newDirectNodeTx.getOutput(0)) : void 0;
|
|
26140
|
+
const directFromCpfpRefundSighash = newDirectFromCpfpRefundTx ? getSigHashFromTx(newDirectFromCpfpRefundTx, 0, newNodeTx.getOutput(0)) : void 0;
|
|
25596
26141
|
const newNodeSigningJob = {
|
|
25597
|
-
signingPublicKey
|
|
26142
|
+
signingPublicKey,
|
|
25598
26143
|
rawTx: newNodeTx.toBytes(),
|
|
25599
26144
|
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment()
|
|
25600
26145
|
};
|
|
25601
|
-
const
|
|
25602
|
-
signingPublicKey
|
|
25603
|
-
rawTx:
|
|
26146
|
+
const newDirectNodeSigningJob = newDirectNodeTx ? {
|
|
26147
|
+
signingPublicKey,
|
|
26148
|
+
rawTx: newDirectNodeTx.toBytes(),
|
|
26149
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment()
|
|
26150
|
+
} : void 0;
|
|
26151
|
+
const newCpfpRefundSigningJob = {
|
|
26152
|
+
signingPublicKey,
|
|
26153
|
+
rawTx: newCpfpRefundTx.toBytes(),
|
|
25604
26154
|
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment()
|
|
25605
26155
|
};
|
|
26156
|
+
const newDirectRefundSigningJob = newDirectRefundTx ? {
|
|
26157
|
+
signingPublicKey,
|
|
26158
|
+
rawTx: newDirectRefundTx.toBytes(),
|
|
26159
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment()
|
|
26160
|
+
} : void 0;
|
|
26161
|
+
const newDirectFromCpfpRefundSigningJob = newDirectFromCpfpRefundTx ? {
|
|
26162
|
+
signingPublicKey,
|
|
26163
|
+
rawTx: newDirectFromCpfpRefundTx.toBytes(),
|
|
26164
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment()
|
|
26165
|
+
} : void 0;
|
|
25606
26166
|
const sparkClient = await this.connectionManager.createSparkClient(
|
|
25607
26167
|
this.config.getCoordinatorAddress()
|
|
25608
26168
|
);
|
|
25609
|
-
const response = await sparkClient.
|
|
26169
|
+
const response = await sparkClient.extend_leaf_v2({
|
|
25610
26170
|
leafId: node.id,
|
|
25611
26171
|
ownerIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),
|
|
25612
26172
|
nodeTxSigningJob: getSigningJobProto(newNodeSigningJob),
|
|
25613
|
-
|
|
26173
|
+
directNodeTxSigningJob: newDirectNodeSigningJob ? getSigningJobProto(newDirectNodeSigningJob) : void 0,
|
|
26174
|
+
refundTxSigningJob: getSigningJobProto(newCpfpRefundSigningJob),
|
|
26175
|
+
directRefundTxSigningJob: newDirectRefundSigningJob ? getSigningJobProto(newDirectRefundSigningJob) : void 0,
|
|
26176
|
+
directFromCpfpRefundTxSigningJob: newDirectFromCpfpRefundSigningJob ? getSigningJobProto(newDirectFromCpfpRefundSigningJob) : void 0
|
|
25614
26177
|
});
|
|
25615
26178
|
if (!response.nodeTxSigningResult || !response.refundTxSigningResult) {
|
|
25616
26179
|
throw new Error("Signing result does not exist");
|
|
25617
26180
|
}
|
|
26181
|
+
const keyDerivation = {
|
|
26182
|
+
type: "leaf" /* LEAF */,
|
|
26183
|
+
path: node.id
|
|
26184
|
+
};
|
|
25618
26185
|
const nodeUserSig = await this.config.signer.signFrost({
|
|
25619
26186
|
message: nodeSighash,
|
|
25620
|
-
keyDerivation
|
|
25621
|
-
|
|
25622
|
-
path: node.id
|
|
25623
|
-
},
|
|
25624
|
-
publicKey: signingPubKey,
|
|
26187
|
+
keyDerivation,
|
|
26188
|
+
publicKey: signingPublicKey,
|
|
25625
26189
|
verifyingKey: response.nodeTxSigningResult.verifyingKey,
|
|
25626
26190
|
selfCommitment: newNodeSigningJob.signingNonceCommitment,
|
|
25627
26191
|
statechainCommitments: response.nodeTxSigningResult.signingResult?.signingNonceCommitments,
|
|
25628
26192
|
adaptorPubKey: new Uint8Array()
|
|
25629
26193
|
});
|
|
25630
|
-
const refundUserSig = await this.config.signer.signFrost({
|
|
25631
|
-
message: refundSighash,
|
|
25632
|
-
keyDerivation: {
|
|
25633
|
-
type: "leaf" /* LEAF */,
|
|
25634
|
-
path: node.id
|
|
25635
|
-
},
|
|
25636
|
-
publicKey: signingPubKey,
|
|
25637
|
-
verifyingKey: response.refundTxSigningResult.verifyingKey,
|
|
25638
|
-
selfCommitment: newRefundSigningJob.signingNonceCommitment,
|
|
25639
|
-
statechainCommitments: response.refundTxSigningResult.signingResult?.signingNonceCommitments,
|
|
25640
|
-
adaptorPubKey: new Uint8Array()
|
|
25641
|
-
});
|
|
25642
26194
|
const nodeSig = await this.config.signer.aggregateFrost({
|
|
25643
26195
|
message: nodeSighash,
|
|
25644
26196
|
statechainSignatures: response.nodeTxSigningResult.signingResult?.signatureShares,
|
|
@@ -25646,122 +26198,253 @@ var TransferService = class extends BaseTransferService {
|
|
|
25646
26198
|
verifyingKey: response.nodeTxSigningResult.verifyingKey,
|
|
25647
26199
|
statechainCommitments: response.nodeTxSigningResult.signingResult?.signingNonceCommitments,
|
|
25648
26200
|
selfCommitment: newNodeSigningJob.signingNonceCommitment,
|
|
25649
|
-
publicKey:
|
|
26201
|
+
publicKey: signingPublicKey,
|
|
25650
26202
|
selfSignature: nodeUserSig,
|
|
25651
26203
|
adaptorPubKey: new Uint8Array()
|
|
25652
26204
|
});
|
|
25653
|
-
|
|
25654
|
-
|
|
26205
|
+
let directNodeSig;
|
|
26206
|
+
if (directNodeSighash && newDirectNodeSigningJob && response.directNodeTxSigningResult) {
|
|
26207
|
+
const directNodeUserSig = await this.config.signer.signFrost({
|
|
26208
|
+
message: directNodeSighash,
|
|
26209
|
+
keyDerivation,
|
|
26210
|
+
publicKey: signingPublicKey,
|
|
26211
|
+
verifyingKey: response.directNodeTxSigningResult.verifyingKey,
|
|
26212
|
+
selfCommitment: newDirectNodeSigningJob.signingNonceCommitment,
|
|
26213
|
+
statechainCommitments: response.directNodeTxSigningResult.signingResult?.signingNonceCommitments,
|
|
26214
|
+
adaptorPubKey: new Uint8Array()
|
|
26215
|
+
});
|
|
26216
|
+
directNodeSig = await this.config.signer.aggregateFrost({
|
|
26217
|
+
message: directNodeSighash,
|
|
26218
|
+
statechainSignatures: response.directNodeTxSigningResult.signingResult?.signatureShares,
|
|
26219
|
+
statechainPublicKeys: response.directNodeTxSigningResult.signingResult?.publicKeys,
|
|
26220
|
+
verifyingKey: response.directNodeTxSigningResult.verifyingKey,
|
|
26221
|
+
statechainCommitments: response.directNodeTxSigningResult.signingResult?.signingNonceCommitments,
|
|
26222
|
+
selfCommitment: newDirectNodeSigningJob.signingNonceCommitment,
|
|
26223
|
+
publicKey: signingPublicKey,
|
|
26224
|
+
selfSignature: directNodeUserSig,
|
|
26225
|
+
adaptorPubKey: new Uint8Array()
|
|
26226
|
+
});
|
|
26227
|
+
}
|
|
26228
|
+
const cpfpRefundUserSig = await this.config.signer.signFrost({
|
|
26229
|
+
message: cpfpRefundSighash,
|
|
26230
|
+
keyDerivation,
|
|
26231
|
+
publicKey: signingPublicKey,
|
|
26232
|
+
verifyingKey: response.refundTxSigningResult.verifyingKey,
|
|
26233
|
+
selfCommitment: newCpfpRefundSigningJob.signingNonceCommitment,
|
|
26234
|
+
statechainCommitments: response.refundTxSigningResult.signingResult?.signingNonceCommitments,
|
|
26235
|
+
adaptorPubKey: new Uint8Array()
|
|
26236
|
+
});
|
|
26237
|
+
const cpfpRefundSig = await this.config.signer.aggregateFrost({
|
|
26238
|
+
message: cpfpRefundSighash,
|
|
25655
26239
|
statechainSignatures: response.refundTxSigningResult.signingResult?.signatureShares,
|
|
25656
26240
|
statechainPublicKeys: response.refundTxSigningResult.signingResult?.publicKeys,
|
|
25657
26241
|
verifyingKey: response.refundTxSigningResult.verifyingKey,
|
|
25658
26242
|
statechainCommitments: response.refundTxSigningResult.signingResult?.signingNonceCommitments,
|
|
25659
|
-
selfCommitment:
|
|
25660
|
-
publicKey:
|
|
25661
|
-
selfSignature:
|
|
26243
|
+
selfCommitment: newCpfpRefundSigningJob.signingNonceCommitment,
|
|
26244
|
+
publicKey: signingPublicKey,
|
|
26245
|
+
selfSignature: cpfpRefundUserSig,
|
|
25662
26246
|
adaptorPubKey: new Uint8Array()
|
|
25663
26247
|
});
|
|
25664
|
-
|
|
26248
|
+
let directRefundSig;
|
|
26249
|
+
if (directRefundSighash && newDirectRefundSigningJob && response.directRefundTxSigningResult) {
|
|
26250
|
+
const directRefundUserSig = await this.config.signer.signFrost({
|
|
26251
|
+
message: directRefundSighash,
|
|
26252
|
+
keyDerivation,
|
|
26253
|
+
publicKey: signingPublicKey,
|
|
26254
|
+
verifyingKey: response.directRefundTxSigningResult.verifyingKey,
|
|
26255
|
+
selfCommitment: newDirectRefundSigningJob.signingNonceCommitment,
|
|
26256
|
+
statechainCommitments: response.directRefundTxSigningResult.signingResult?.signingNonceCommitments,
|
|
26257
|
+
adaptorPubKey: new Uint8Array()
|
|
26258
|
+
});
|
|
26259
|
+
directRefundSig = await this.config.signer.aggregateFrost({
|
|
26260
|
+
message: directRefundSighash,
|
|
26261
|
+
statechainSignatures: response.directRefundTxSigningResult.signingResult?.signatureShares,
|
|
26262
|
+
statechainPublicKeys: response.directRefundTxSigningResult.signingResult?.publicKeys,
|
|
26263
|
+
verifyingKey: response.directRefundTxSigningResult.verifyingKey,
|
|
26264
|
+
statechainCommitments: response.directRefundTxSigningResult.signingResult?.signingNonceCommitments,
|
|
26265
|
+
selfCommitment: newDirectRefundSigningJob.signingNonceCommitment,
|
|
26266
|
+
publicKey: signingPublicKey,
|
|
26267
|
+
selfSignature: directRefundUserSig,
|
|
26268
|
+
adaptorPubKey: new Uint8Array()
|
|
26269
|
+
});
|
|
26270
|
+
}
|
|
26271
|
+
let directFromCpfpRefundSig;
|
|
26272
|
+
if (directFromCpfpRefundSighash && newDirectFromCpfpRefundSigningJob && response.directFromCpfpRefundTxSigningResult) {
|
|
26273
|
+
const directFromCpfpRefundUserSig = await this.config.signer.signFrost({
|
|
26274
|
+
message: directFromCpfpRefundSighash,
|
|
26275
|
+
keyDerivation,
|
|
26276
|
+
publicKey: signingPublicKey,
|
|
26277
|
+
verifyingKey: response.directFromCpfpRefundTxSigningResult.verifyingKey,
|
|
26278
|
+
selfCommitment: newDirectFromCpfpRefundSigningJob.signingNonceCommitment,
|
|
26279
|
+
statechainCommitments: response.directFromCpfpRefundTxSigningResult.signingResult?.signingNonceCommitments,
|
|
26280
|
+
adaptorPubKey: new Uint8Array()
|
|
26281
|
+
});
|
|
26282
|
+
directFromCpfpRefundSig = await this.config.signer.aggregateFrost({
|
|
26283
|
+
message: directFromCpfpRefundSighash,
|
|
26284
|
+
statechainSignatures: response.directFromCpfpRefundTxSigningResult.signingResult?.signatureShares,
|
|
26285
|
+
statechainPublicKeys: response.directFromCpfpRefundTxSigningResult.signingResult?.publicKeys,
|
|
26286
|
+
verifyingKey: response.directFromCpfpRefundTxSigningResult.verifyingKey,
|
|
26287
|
+
statechainCommitments: response.directFromCpfpRefundTxSigningResult.signingResult?.signingNonceCommitments,
|
|
26288
|
+
selfCommitment: newDirectFromCpfpRefundSigningJob.signingNonceCommitment,
|
|
26289
|
+
publicKey: signingPublicKey,
|
|
26290
|
+
selfSignature: directFromCpfpRefundUserSig,
|
|
26291
|
+
adaptorPubKey: new Uint8Array()
|
|
26292
|
+
});
|
|
26293
|
+
}
|
|
26294
|
+
return await sparkClient.finalize_node_signatures_v2({
|
|
25665
26295
|
intent: 4 /* EXTEND */,
|
|
25666
26296
|
nodeSignatures: [
|
|
25667
26297
|
{
|
|
25668
26298
|
nodeId: response.leafId,
|
|
25669
26299
|
nodeTxSignature: nodeSig,
|
|
25670
|
-
|
|
26300
|
+
directNodeTxSignature: directNodeSig,
|
|
26301
|
+
refundTxSignature: cpfpRefundSig,
|
|
26302
|
+
directRefundTxSignature: directRefundSig,
|
|
26303
|
+
directFromCpfpRefundTxSignature: directFromCpfpRefundSig
|
|
25671
26304
|
}
|
|
25672
26305
|
]
|
|
25673
26306
|
});
|
|
25674
26307
|
}
|
|
25675
|
-
async
|
|
26308
|
+
async testonly_expireTimeLockNodeTx(node, parentNode) {
|
|
26309
|
+
return await this.refreshTimelockNodesInternal(node, parentNode, true);
|
|
26310
|
+
}
|
|
26311
|
+
async testonly_expireTimeLockRefundtx(node) {
|
|
25676
26312
|
const nodeTx = getTxFromRawTxBytes(node.nodeTx);
|
|
25677
|
-
const
|
|
25678
|
-
const
|
|
25679
|
-
const
|
|
25680
|
-
const
|
|
26313
|
+
const directNodeTx = node.directTx.length > 0 ? getTxFromRawTxBytes(node.directTx) : void 0;
|
|
26314
|
+
const cpfpRefundTx = getTxFromRawTxBytes(node.refundTx);
|
|
26315
|
+
const currSequence = cpfpRefundTx.getInput(0).sequence || 0;
|
|
26316
|
+
const currTimelock = getCurrentTimelock(currSequence);
|
|
26317
|
+
if (currTimelock <= 100) {
|
|
26318
|
+
throw new ValidationError("Cannot expire timelock below 100", {
|
|
26319
|
+
field: "currTimelock",
|
|
26320
|
+
value: currTimelock,
|
|
26321
|
+
expected: "Timelock greater than 100"
|
|
26322
|
+
});
|
|
26323
|
+
}
|
|
26324
|
+
const nextSequence = TEST_UNILATERAL_SEQUENCE;
|
|
26325
|
+
const nextDirectSequence = TEST_UNILATERAL_SEQUENCE + DIRECT_TIMELOCK_OFFSET;
|
|
26326
|
+
const nodeOutput = nodeTx.getOutput(0);
|
|
26327
|
+
if (!nodeOutput) {
|
|
26328
|
+
throw Error("Could not get node output");
|
|
26329
|
+
}
|
|
26330
|
+
const keyDerivation = {
|
|
25681
26331
|
type: "leaf" /* LEAF */,
|
|
25682
26332
|
path: node.id
|
|
25683
|
-
}
|
|
25684
|
-
const
|
|
25685
|
-
|
|
25686
|
-
|
|
25687
|
-
|
|
25688
|
-
|
|
25689
|
-
|
|
25690
|
-
|
|
26333
|
+
};
|
|
26334
|
+
const signingPublicKey = await this.config.signer.getPublicKeyFromDerivation(keyDerivation);
|
|
26335
|
+
const cpfpRefundOutPoint = {
|
|
26336
|
+
txid: (0, import_utils14.hexToBytes)(getTxId(nodeTx)),
|
|
26337
|
+
index: 0
|
|
26338
|
+
};
|
|
26339
|
+
let directRefundOutPoint;
|
|
26340
|
+
if (directNodeTx) {
|
|
26341
|
+
directRefundOutPoint = {
|
|
26342
|
+
txid: (0, import_utils14.hexToBytes)(getTxId(directNodeTx)),
|
|
26343
|
+
index: 0
|
|
26344
|
+
};
|
|
25691
26345
|
}
|
|
25692
|
-
|
|
25693
|
-
|
|
25694
|
-
|
|
26346
|
+
const {
|
|
26347
|
+
cpfpRefundTx: newCpfpRefundTx,
|
|
26348
|
+
directRefundTx: newDirectRefundTx,
|
|
26349
|
+
directFromCpfpRefundTx: newDirectFromCpfpRefundTx
|
|
26350
|
+
} = createRefundTxs({
|
|
26351
|
+
sequence: nextSequence,
|
|
26352
|
+
directSequence: nextDirectSequence,
|
|
26353
|
+
input: cpfpRefundOutPoint,
|
|
26354
|
+
directInput: directRefundOutPoint,
|
|
26355
|
+
amountSats: nodeOutput.amount,
|
|
26356
|
+
receivingPubkey: signingPublicKey,
|
|
26357
|
+
network: this.config.getNetwork()
|
|
25695
26358
|
});
|
|
25696
|
-
|
|
25697
|
-
|
|
25698
|
-
|
|
25699
|
-
|
|
25700
|
-
|
|
26359
|
+
const signingJobs = [];
|
|
26360
|
+
signingJobs.push({
|
|
26361
|
+
signingPublicKey,
|
|
26362
|
+
rawTx: newCpfpRefundTx.toBytes(),
|
|
26363
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
26364
|
+
type: "cpfp",
|
|
26365
|
+
parentTxOut: nodeOutput
|
|
26366
|
+
});
|
|
26367
|
+
const directNodeTxOut = directNodeTx?.getOutput(0);
|
|
26368
|
+
if (newDirectRefundTx && directNodeTxOut) {
|
|
26369
|
+
signingJobs.push({
|
|
26370
|
+
signingPublicKey,
|
|
26371
|
+
rawTx: newDirectRefundTx.toBytes(),
|
|
26372
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
26373
|
+
type: "direct",
|
|
26374
|
+
parentTxOut: directNodeTxOut
|
|
26375
|
+
});
|
|
25701
26376
|
}
|
|
25702
|
-
|
|
25703
|
-
|
|
25704
|
-
|
|
26377
|
+
if (newDirectFromCpfpRefundTx) {
|
|
26378
|
+
signingJobs.push({
|
|
26379
|
+
signingPublicKey,
|
|
26380
|
+
rawTx: newDirectFromCpfpRefundTx.toBytes(),
|
|
26381
|
+
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment(),
|
|
26382
|
+
type: "directFromCpfp",
|
|
26383
|
+
parentTxOut: nodeOutput
|
|
26384
|
+
});
|
|
25705
26385
|
}
|
|
25706
|
-
newRefundTx.addInput({
|
|
25707
|
-
...refundTxInput,
|
|
25708
|
-
sequence: nextSequence
|
|
25709
|
-
});
|
|
25710
|
-
const refundSigningJob = {
|
|
25711
|
-
signingPublicKey: signingPubKey,
|
|
25712
|
-
rawTx: newRefundTx.toBytes(),
|
|
25713
|
-
signingNonceCommitment: await this.config.signer.getRandomSigningCommitment()
|
|
25714
|
-
};
|
|
25715
26386
|
const sparkClient = await this.connectionManager.createSparkClient(
|
|
25716
26387
|
this.config.getCoordinatorAddress()
|
|
25717
26388
|
);
|
|
25718
|
-
const response = await sparkClient.
|
|
26389
|
+
const response = await sparkClient.refresh_timelock_v2({
|
|
25719
26390
|
leafId: node.id,
|
|
25720
26391
|
ownerIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),
|
|
25721
|
-
signingJobs:
|
|
26392
|
+
signingJobs: signingJobs.map(getSigningJobProto)
|
|
25722
26393
|
});
|
|
25723
|
-
if (response.signingResults.length !==
|
|
26394
|
+
if (response.signingResults.length !== signingJobs.length) {
|
|
25724
26395
|
throw Error(
|
|
25725
|
-
`Expected
|
|
26396
|
+
`Expected ${signingJobs.length} signing results, got ${response.signingResults.length}`
|
|
25726
26397
|
);
|
|
25727
26398
|
}
|
|
25728
|
-
|
|
25729
|
-
|
|
25730
|
-
|
|
26399
|
+
let cpfpRefundSignature;
|
|
26400
|
+
let directRefundSignature;
|
|
26401
|
+
let directFromCpfpRefundSignature;
|
|
26402
|
+
for (const [i, signingJob] of signingJobs.entries()) {
|
|
26403
|
+
const signingResult = response.signingResults[i];
|
|
26404
|
+
if (!signingResult) {
|
|
26405
|
+
throw Error("Signing result does not exist");
|
|
26406
|
+
}
|
|
26407
|
+
const rawTx = getTxFromRawTxBytes(signingJob.rawTx);
|
|
26408
|
+
const txOut = signingJob.parentTxOut;
|
|
26409
|
+
const rawTxSighash = getSigHashFromTx(rawTx, 0, txOut);
|
|
26410
|
+
const userSignature = await this.config.signer.signFrost({
|
|
26411
|
+
message: rawTxSighash,
|
|
26412
|
+
keyDerivation,
|
|
26413
|
+
publicKey: signingPublicKey,
|
|
26414
|
+
verifyingKey: signingResult.verifyingKey,
|
|
26415
|
+
selfCommitment: signingJob.signingNonceCommitment,
|
|
26416
|
+
statechainCommitments: signingResult.signingResult?.signingNonceCommitments,
|
|
26417
|
+
adaptorPubKey: new Uint8Array()
|
|
26418
|
+
});
|
|
26419
|
+
const signature = await this.config.signer.aggregateFrost({
|
|
26420
|
+
message: rawTxSighash,
|
|
26421
|
+
statechainSignatures: signingResult.signingResult?.signatureShares,
|
|
26422
|
+
statechainPublicKeys: signingResult.signingResult?.publicKeys,
|
|
26423
|
+
verifyingKey: signingResult.verifyingKey,
|
|
26424
|
+
statechainCommitments: signingResult.signingResult?.signingNonceCommitments,
|
|
26425
|
+
selfCommitment: signingJob.signingNonceCommitment,
|
|
26426
|
+
publicKey: signingPublicKey,
|
|
26427
|
+
selfSignature: userSignature,
|
|
26428
|
+
adaptorPubKey: new Uint8Array()
|
|
26429
|
+
});
|
|
26430
|
+
if (signingJob.type === "cpfp") {
|
|
26431
|
+
cpfpRefundSignature = signature;
|
|
26432
|
+
} else if (signingJob.type === "direct") {
|
|
26433
|
+
directRefundSignature = signature;
|
|
26434
|
+
} else if (signingJob.type === "directFromCpfp") {
|
|
26435
|
+
directFromCpfpRefundSignature = signature;
|
|
26436
|
+
}
|
|
25731
26437
|
}
|
|
25732
|
-
const
|
|
25733
|
-
const txOut = nodeTx.getOutput(0);
|
|
25734
|
-
const rawTxSighash = getSigHashFromTx(rawTx, 0, txOut);
|
|
25735
|
-
const userSignature = await this.config.signer.signFrost({
|
|
25736
|
-
message: rawTxSighash,
|
|
25737
|
-
keyDerivation: {
|
|
25738
|
-
type: "leaf" /* LEAF */,
|
|
25739
|
-
path: node.id
|
|
25740
|
-
},
|
|
25741
|
-
publicKey: signingPubKey,
|
|
25742
|
-
verifyingKey: signingResult.verifyingKey,
|
|
25743
|
-
selfCommitment: refundSigningJob.signingNonceCommitment,
|
|
25744
|
-
statechainCommitments: signingResult.signingResult?.signingNonceCommitments,
|
|
25745
|
-
adaptorPubKey: new Uint8Array()
|
|
25746
|
-
});
|
|
25747
|
-
const signature = await this.config.signer.aggregateFrost({
|
|
25748
|
-
message: rawTxSighash,
|
|
25749
|
-
statechainSignatures: signingResult.signingResult?.signatureShares,
|
|
25750
|
-
statechainPublicKeys: signingResult.signingResult?.publicKeys,
|
|
25751
|
-
verifyingKey: signingResult.verifyingKey,
|
|
25752
|
-
statechainCommitments: signingResult.signingResult?.signingNonceCommitments,
|
|
25753
|
-
selfCommitment: refundSigningJob.signingNonceCommitment,
|
|
25754
|
-
publicKey: signingPubKey,
|
|
25755
|
-
selfSignature: userSignature,
|
|
25756
|
-
adaptorPubKey: new Uint8Array()
|
|
25757
|
-
});
|
|
25758
|
-
const result = await sparkClient.finalize_node_signatures({
|
|
26438
|
+
const result = await sparkClient.finalize_node_signatures_v2({
|
|
25759
26439
|
intent: 3 /* REFRESH */,
|
|
25760
26440
|
nodeSignatures: [
|
|
25761
26441
|
{
|
|
25762
26442
|
nodeId: node.id,
|
|
25763
26443
|
nodeTxSignature: new Uint8Array(),
|
|
25764
|
-
|
|
26444
|
+
directNodeTxSignature: new Uint8Array(),
|
|
26445
|
+
refundTxSignature: cpfpRefundSignature,
|
|
26446
|
+
directRefundTxSignature: directRefundSignature,
|
|
26447
|
+
directFromCpfpRefundTxSignature: directFromCpfpRefundSignature
|
|
25765
26448
|
}
|
|
25766
26449
|
]
|
|
25767
26450
|
});
|
|
@@ -25780,7 +26463,12 @@ var CoopExitService = class extends BaseTransferService {
|
|
|
25780
26463
|
connectorOutputs,
|
|
25781
26464
|
receiverPubKey
|
|
25782
26465
|
}) {
|
|
25783
|
-
const {
|
|
26466
|
+
const {
|
|
26467
|
+
transfer,
|
|
26468
|
+
signaturesMap,
|
|
26469
|
+
directSignaturesMap,
|
|
26470
|
+
directFromCpfpSignaturesMap
|
|
26471
|
+
} = await this.signCoopExitRefunds(
|
|
25784
26472
|
leaves,
|
|
25785
26473
|
exitTxId,
|
|
25786
26474
|
connectorOutputs,
|
|
@@ -25789,34 +26477,81 @@ var CoopExitService = class extends BaseTransferService {
|
|
|
25789
26477
|
const transferTweak = await this.deliverTransferPackage(
|
|
25790
26478
|
transfer,
|
|
25791
26479
|
leaves,
|
|
25792
|
-
signaturesMap
|
|
26480
|
+
signaturesMap,
|
|
26481
|
+
directSignaturesMap,
|
|
26482
|
+
directFromCpfpSignaturesMap
|
|
25793
26483
|
);
|
|
25794
|
-
return {
|
|
25795
|
-
|
|
25796
|
-
|
|
25797
|
-
|
|
25798
|
-
|
|
25799
|
-
|
|
25800
|
-
|
|
25801
|
-
|
|
26484
|
+
return {
|
|
26485
|
+
transfer: transferTweak,
|
|
26486
|
+
signaturesMap,
|
|
26487
|
+
directSignaturesMap,
|
|
26488
|
+
directFromCpfpSignaturesMap
|
|
26489
|
+
};
|
|
26490
|
+
}
|
|
26491
|
+
createConnectorRefundTransactions(sequence, directSequence, cpfpNodeOutPoint, directNodeOutPoint, connectorOutput, amountSats, receiverPubKey) {
|
|
26492
|
+
const cpfpRefundTx = new import_btc_signer3.Transaction();
|
|
26493
|
+
if (!cpfpNodeOutPoint.txid || cpfpNodeOutPoint.index === void 0) {
|
|
26494
|
+
throw new ValidationError("Invalid CPFP node outpoint", {
|
|
26495
|
+
field: "cpfpNodeOutPoint",
|
|
26496
|
+
value: { txid: cpfpNodeOutPoint.txid, index: cpfpNodeOutPoint.index },
|
|
25802
26497
|
expected: "Both txid and index must be defined"
|
|
25803
26498
|
});
|
|
25804
26499
|
}
|
|
25805
|
-
|
|
25806
|
-
txid:
|
|
25807
|
-
index:
|
|
26500
|
+
cpfpRefundTx.addInput({
|
|
26501
|
+
txid: cpfpNodeOutPoint.txid,
|
|
26502
|
+
index: cpfpNodeOutPoint.index,
|
|
25808
26503
|
sequence
|
|
25809
26504
|
});
|
|
25810
|
-
|
|
26505
|
+
cpfpRefundTx.addInput(connectorOutput);
|
|
25811
26506
|
const receiverScript = getP2TRScriptFromPublicKey(
|
|
25812
26507
|
receiverPubKey,
|
|
25813
26508
|
this.config.getNetwork()
|
|
25814
26509
|
);
|
|
25815
|
-
|
|
26510
|
+
cpfpRefundTx.addOutput({
|
|
25816
26511
|
script: receiverScript,
|
|
25817
26512
|
amount: amountSats
|
|
25818
26513
|
});
|
|
25819
|
-
|
|
26514
|
+
let directRefundTx;
|
|
26515
|
+
let directFromCpfpRefundTx;
|
|
26516
|
+
if (directNodeOutPoint) {
|
|
26517
|
+
if (!directNodeOutPoint.txid || directNodeOutPoint.index === void 0) {
|
|
26518
|
+
throw new ValidationError("Invalid direct node outpoint", {
|
|
26519
|
+
field: "directNodeOutPoint",
|
|
26520
|
+
value: {
|
|
26521
|
+
txid: directNodeOutPoint.txid,
|
|
26522
|
+
index: directNodeOutPoint.index
|
|
26523
|
+
},
|
|
26524
|
+
expected: "Both txid and index must be defined"
|
|
26525
|
+
});
|
|
26526
|
+
}
|
|
26527
|
+
directRefundTx = new import_btc_signer3.Transaction();
|
|
26528
|
+
directRefundTx.addInput({
|
|
26529
|
+
txid: directNodeOutPoint.txid,
|
|
26530
|
+
index: directNodeOutPoint.index,
|
|
26531
|
+
sequence: directSequence
|
|
26532
|
+
});
|
|
26533
|
+
directRefundTx.addInput(connectorOutput);
|
|
26534
|
+
directRefundTx.addOutput({
|
|
26535
|
+
script: receiverScript,
|
|
26536
|
+
amount: maybeApplyFee(amountSats)
|
|
26537
|
+
});
|
|
26538
|
+
directFromCpfpRefundTx = new import_btc_signer3.Transaction();
|
|
26539
|
+
directFromCpfpRefundTx.addInput({
|
|
26540
|
+
txid: cpfpNodeOutPoint.txid,
|
|
26541
|
+
index: cpfpNodeOutPoint.index,
|
|
26542
|
+
sequence: directSequence
|
|
26543
|
+
});
|
|
26544
|
+
directFromCpfpRefundTx.addInput(connectorOutput);
|
|
26545
|
+
directFromCpfpRefundTx.addOutput({
|
|
26546
|
+
script: receiverScript,
|
|
26547
|
+
amount: maybeApplyFee(amountSats)
|
|
26548
|
+
});
|
|
26549
|
+
}
|
|
26550
|
+
return {
|
|
26551
|
+
cpfpRefundTx,
|
|
26552
|
+
directRefundTx,
|
|
26553
|
+
directFromCpfpRefundTx
|
|
26554
|
+
};
|
|
25820
26555
|
}
|
|
25821
26556
|
async signCoopExitRefunds(leaves, exitTxId, connectorOutputs, receiverPubKey) {
|
|
25822
26557
|
if (leaves.length !== connectorOutputs.length) {
|
|
@@ -25852,39 +26587,67 @@ var CoopExitService = class extends BaseTransferService {
|
|
|
25852
26587
|
});
|
|
25853
26588
|
}
|
|
25854
26589
|
const currentRefundTx = getTxFromRawTxBytes(leaf.leaf.refundTx);
|
|
25855
|
-
const
|
|
25856
|
-
|
|
25857
|
-
|
|
25858
|
-
|
|
26590
|
+
const sequence = currentRefundTx.getInput(0).sequence;
|
|
26591
|
+
if (!sequence) {
|
|
26592
|
+
throw new ValidationError("Invalid refund transaction", {
|
|
26593
|
+
field: "sequence",
|
|
26594
|
+
value: currentRefundTx.getInput(0),
|
|
26595
|
+
expected: "Non-null sequence"
|
|
26596
|
+
});
|
|
26597
|
+
}
|
|
26598
|
+
const { nextSequence, nextDirectSequence } = getNextTransactionSequence(sequence);
|
|
26599
|
+
let currentDirectRefundTx;
|
|
26600
|
+
if (leaf.leaf.directRefundTx.length > 0) {
|
|
26601
|
+
currentDirectRefundTx = getTxFromRawTxBytes(leaf.leaf.directRefundTx);
|
|
26602
|
+
}
|
|
26603
|
+
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } = this.createConnectorRefundTransactions(
|
|
25859
26604
|
nextSequence,
|
|
26605
|
+
nextDirectSequence,
|
|
25860
26606
|
currentRefundTx.getInput(0),
|
|
26607
|
+
currentDirectRefundTx?.getInput(0),
|
|
25861
26608
|
connectorOutput,
|
|
25862
26609
|
BigInt(leaf.leaf.value),
|
|
25863
26610
|
receiverPubKey
|
|
25864
26611
|
);
|
|
25865
26612
|
const signingNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
26613
|
+
const directSigningNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
26614
|
+
const directFromCpfpSigningNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
26615
|
+
const signingPublicKey = await this.config.signer.getPublicKeyFromDerivation(leaf.keyDerivation);
|
|
25866
26616
|
const signingJob = {
|
|
25867
26617
|
leafId: leaf.leaf.id,
|
|
25868
26618
|
refundTxSigningJob: {
|
|
25869
26619
|
signingPublicKey: await this.config.signer.getPublicKeyFromDerivation(
|
|
25870
26620
|
leaf.keyDerivation
|
|
25871
26621
|
),
|
|
25872
|
-
rawTx:
|
|
26622
|
+
rawTx: cpfpRefundTx.toBytes(),
|
|
25873
26623
|
signingNonceCommitment: signingNonceCommitment.commitment
|
|
25874
26624
|
},
|
|
25875
|
-
|
|
25876
|
-
|
|
25877
|
-
|
|
26625
|
+
directRefundTxSigningJob: directRefundTx ? {
|
|
26626
|
+
signingPublicKey,
|
|
26627
|
+
rawTx: directRefundTx.toBytes(),
|
|
26628
|
+
signingNonceCommitment: directSigningNonceCommitment.commitment
|
|
26629
|
+
} : void 0,
|
|
26630
|
+
directFromCpfpRefundTxSigningJob: directFromCpfpRefundTx ? {
|
|
26631
|
+
signingPublicKey,
|
|
26632
|
+
rawTx: directFromCpfpRefundTx.toBytes(),
|
|
26633
|
+
signingNonceCommitment: directFromCpfpSigningNonceCommitment.commitment
|
|
26634
|
+
} : void 0
|
|
25878
26635
|
};
|
|
25879
26636
|
signingJobs.push(signingJob);
|
|
25880
26637
|
const tx = getTxFromRawTxBytes(leaf.leaf.nodeTx);
|
|
26638
|
+
const directTx = leaf.leaf.directTx.length > 0 ? getTxFromRawTxBytes(leaf.leaf.directTx) : void 0;
|
|
25881
26639
|
leafDataMap.set(leaf.leaf.id, {
|
|
25882
26640
|
keyDerivation: leaf.keyDerivation,
|
|
25883
|
-
|
|
26641
|
+
receivingPubkey: receiverPubKey,
|
|
25884
26642
|
signingNonceCommitment,
|
|
26643
|
+
directSigningNonceCommitment,
|
|
25885
26644
|
tx,
|
|
25886
|
-
|
|
25887
|
-
|
|
26645
|
+
directTx,
|
|
26646
|
+
refundTx: cpfpRefundTx,
|
|
26647
|
+
directRefundTx,
|
|
26648
|
+
directFromCpfpRefundTx,
|
|
26649
|
+
directFromCpfpRefundSigningNonceCommitment: directFromCpfpSigningNonceCommitment,
|
|
26650
|
+
vout: leaf.leaf.vout
|
|
25888
26651
|
});
|
|
25889
26652
|
}
|
|
25890
26653
|
const sparkClient = await this.connectionManager.createSparkClient(
|
|
@@ -25892,7 +26655,7 @@ var CoopExitService = class extends BaseTransferService {
|
|
|
25892
26655
|
);
|
|
25893
26656
|
let response;
|
|
25894
26657
|
try {
|
|
25895
|
-
response = await sparkClient.
|
|
26658
|
+
response = await sparkClient.cooperative_exit_v2({
|
|
25896
26659
|
transfer: {
|
|
25897
26660
|
transferId: (0, import_uuidv73.uuidv7)(),
|
|
25898
26661
|
leavesToSend: signingJobs,
|
|
@@ -25926,10 +26689,25 @@ var CoopExitService = class extends BaseTransferService {
|
|
|
25926
26689
|
response.signingResults
|
|
25927
26690
|
);
|
|
25928
26691
|
const signaturesMap = /* @__PURE__ */ new Map();
|
|
26692
|
+
const directSignaturesMap = /* @__PURE__ */ new Map();
|
|
26693
|
+
const directFromCpfpSignaturesMap = /* @__PURE__ */ new Map();
|
|
25929
26694
|
for (const signature of signatures) {
|
|
25930
26695
|
signaturesMap.set(signature.nodeId, signature.refundTxSignature);
|
|
26696
|
+
directSignaturesMap.set(
|
|
26697
|
+
signature.nodeId,
|
|
26698
|
+
signature.directRefundTxSignature
|
|
26699
|
+
);
|
|
26700
|
+
directFromCpfpSignaturesMap.set(
|
|
26701
|
+
signature.nodeId,
|
|
26702
|
+
signature.directFromCpfpRefundTxSignature
|
|
26703
|
+
);
|
|
25931
26704
|
}
|
|
25932
|
-
return {
|
|
26705
|
+
return {
|
|
26706
|
+
transfer: response.transfer,
|
|
26707
|
+
signaturesMap,
|
|
26708
|
+
directSignaturesMap,
|
|
26709
|
+
directFromCpfpSignaturesMap
|
|
26710
|
+
};
|
|
25933
26711
|
}
|
|
25934
26712
|
};
|
|
25935
26713
|
|
|
@@ -25938,10 +26716,8 @@ init_buffer();
|
|
|
25938
26716
|
var import_secp256k110 = require("@noble/curves/secp256k1");
|
|
25939
26717
|
var import_sha29 = require("@noble/hashes/sha2");
|
|
25940
26718
|
var import_utils15 = require("@noble/hashes/utils");
|
|
25941
|
-
var btc5 = __toESM(require("@scure/btc-signer"), 1);
|
|
25942
26719
|
var import_btc_signer4 = require("@scure/btc-signer");
|
|
25943
26720
|
var import_utils16 = require("@scure/btc-signer/utils");
|
|
25944
|
-
var INITIAL_TIME_LOCK2 = 2e3;
|
|
25945
26721
|
var DepositService = class {
|
|
25946
26722
|
config;
|
|
25947
26723
|
connectionManager;
|
|
@@ -26059,7 +26835,6 @@ var DepositService = class {
|
|
|
26059
26835
|
depositTx,
|
|
26060
26836
|
vout
|
|
26061
26837
|
}) {
|
|
26062
|
-
const rootTx = new import_btc_signer4.Transaction({ version: 3 });
|
|
26063
26838
|
const output = depositTx.getOutput(vout);
|
|
26064
26839
|
if (!output) {
|
|
26065
26840
|
throw new ValidationError("Invalid deposit transaction output", {
|
|
@@ -26077,39 +26852,345 @@ var DepositService = class {
|
|
|
26077
26852
|
expected: "Output with script and amount"
|
|
26078
26853
|
});
|
|
26079
26854
|
}
|
|
26080
|
-
|
|
26081
|
-
|
|
26082
|
-
txid: getTxId(depositTx),
|
|
26855
|
+
const depositOutPoint = {
|
|
26856
|
+
txid: (0, import_utils15.hexToBytes)(getTxId(depositTx)),
|
|
26083
26857
|
index: vout
|
|
26084
|
-
}
|
|
26085
|
-
|
|
26858
|
+
};
|
|
26859
|
+
const depositTxOut = {
|
|
26086
26860
|
script,
|
|
26087
|
-
amount
|
|
26861
|
+
amount
|
|
26862
|
+
};
|
|
26863
|
+
const [cpfpRootTx, directRootTx] = createRootTx(
|
|
26864
|
+
depositOutPoint,
|
|
26865
|
+
depositTxOut
|
|
26866
|
+
);
|
|
26867
|
+
const cpfpRootNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
26868
|
+
const directRootNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
26869
|
+
const cpfpRootTxSighash = getSigHashFromTx(cpfpRootTx, 0, output);
|
|
26870
|
+
const directRootTxSighash = getSigHashFromTx(directRootTx, 0, output);
|
|
26871
|
+
const signingPubKey = await this.config.signer.getPublicKeyFromDerivation(keyDerivation);
|
|
26872
|
+
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } = createRefundTxs({
|
|
26873
|
+
sequence: INITIAL_SEQUENCE,
|
|
26874
|
+
directSequence: INITIAL_DIRECT_SEQUENCE,
|
|
26875
|
+
input: { txid: (0, import_utils15.hexToBytes)(getTxId(cpfpRootTx)), index: 0 },
|
|
26876
|
+
directInput: { txid: (0, import_utils15.hexToBytes)(getTxId(directRootTx)), index: 0 },
|
|
26877
|
+
amountSats: amount,
|
|
26878
|
+
receivingPubkey: signingPubKey,
|
|
26879
|
+
network: this.config.getNetwork()
|
|
26088
26880
|
});
|
|
26089
|
-
|
|
26090
|
-
const
|
|
26091
|
-
const
|
|
26092
|
-
const
|
|
26093
|
-
|
|
26094
|
-
|
|
26095
|
-
|
|
26096
|
-
|
|
26097
|
-
|
|
26881
|
+
const cpfpRefundNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
26882
|
+
const directRefundNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
26883
|
+
const directFromCpfpRefundNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
26884
|
+
const cpfpRefundTxSighash = getSigHashFromTx(
|
|
26885
|
+
cpfpRefundTx,
|
|
26886
|
+
0,
|
|
26887
|
+
cpfpRootTx.getOutput(0)
|
|
26888
|
+
);
|
|
26889
|
+
if (!directRefundTx || !directFromCpfpRefundTx) {
|
|
26890
|
+
throw new ValidationError(
|
|
26891
|
+
"Expected direct refund transactions for tree creation",
|
|
26892
|
+
{
|
|
26893
|
+
field: "directRefundTx",
|
|
26894
|
+
value: directRefundTx
|
|
26895
|
+
}
|
|
26896
|
+
);
|
|
26897
|
+
}
|
|
26898
|
+
const directRefundTxSighash = getSigHashFromTx(
|
|
26899
|
+
directRefundTx,
|
|
26900
|
+
0,
|
|
26901
|
+
directRootTx.getOutput(0)
|
|
26902
|
+
);
|
|
26903
|
+
const directFromCpfpRefundTxSighash = getSigHashFromTx(
|
|
26904
|
+
directFromCpfpRefundTx,
|
|
26905
|
+
0,
|
|
26906
|
+
cpfpRootTx.getOutput(0)
|
|
26907
|
+
);
|
|
26908
|
+
const sparkClient = await this.connectionManager.createSparkClient(
|
|
26909
|
+
this.config.getCoordinatorAddress()
|
|
26910
|
+
);
|
|
26911
|
+
let treeResp;
|
|
26912
|
+
try {
|
|
26913
|
+
treeResp = await sparkClient.start_deposit_tree_creation({
|
|
26914
|
+
identityPublicKey: await this.config.signer.getIdentityPublicKey(),
|
|
26915
|
+
onChainUtxo: {
|
|
26916
|
+
vout,
|
|
26917
|
+
rawTx: depositTx.toBytes(true),
|
|
26918
|
+
network: this.config.getNetworkProto()
|
|
26919
|
+
},
|
|
26920
|
+
rootTxSigningJob: {
|
|
26921
|
+
rawTx: cpfpRootTx.toBytes(),
|
|
26922
|
+
signingPublicKey: signingPubKey,
|
|
26923
|
+
signingNonceCommitment: cpfpRootNonceCommitment.commitment
|
|
26924
|
+
},
|
|
26925
|
+
refundTxSigningJob: {
|
|
26926
|
+
rawTx: cpfpRefundTx.toBytes(),
|
|
26927
|
+
signingPublicKey: signingPubKey,
|
|
26928
|
+
signingNonceCommitment: cpfpRefundNonceCommitment.commitment
|
|
26929
|
+
},
|
|
26930
|
+
directRootTxSigningJob: {
|
|
26931
|
+
rawTx: directRootTx.toBytes(),
|
|
26932
|
+
signingPublicKey: signingPubKey,
|
|
26933
|
+
signingNonceCommitment: directRootNonceCommitment.commitment
|
|
26934
|
+
},
|
|
26935
|
+
directRefundTxSigningJob: {
|
|
26936
|
+
rawTx: directRefundTx.toBytes(),
|
|
26937
|
+
signingPublicKey: signingPubKey,
|
|
26938
|
+
signingNonceCommitment: directRefundNonceCommitment.commitment
|
|
26939
|
+
},
|
|
26940
|
+
directFromCpfpRefundTxSigningJob: {
|
|
26941
|
+
rawTx: directFromCpfpRefundTx.toBytes(),
|
|
26942
|
+
signingPublicKey: signingPubKey,
|
|
26943
|
+
signingNonceCommitment: directFromCpfpRefundNonceCommitment.commitment
|
|
26944
|
+
}
|
|
26945
|
+
});
|
|
26946
|
+
} catch (error) {
|
|
26947
|
+
throw new NetworkError(
|
|
26948
|
+
"Failed to start deposit tree creation",
|
|
26949
|
+
{
|
|
26950
|
+
operation: "start_deposit_tree_creation",
|
|
26951
|
+
errorCount: 1,
|
|
26952
|
+
errors: error instanceof Error ? error.message : String(error)
|
|
26953
|
+
},
|
|
26954
|
+
error
|
|
26955
|
+
);
|
|
26956
|
+
}
|
|
26957
|
+
if (!treeResp.rootNodeSignatureShares?.verifyingKey) {
|
|
26958
|
+
throw new ValidationError("No verifying key found in tree response", {
|
|
26959
|
+
field: "verifyingKey",
|
|
26960
|
+
value: treeResp.rootNodeSignatureShares,
|
|
26961
|
+
expected: "Non-null verifying key"
|
|
26962
|
+
});
|
|
26963
|
+
}
|
|
26964
|
+
if (!treeResp.rootNodeSignatureShares.nodeTxSigningResult?.signingNonceCommitments) {
|
|
26965
|
+
throw new ValidationError(
|
|
26966
|
+
"No signing nonce commitments found in tree response",
|
|
26967
|
+
{
|
|
26968
|
+
field: "nodeTxSigningResult.signingNonceCommitments",
|
|
26969
|
+
value: treeResp.rootNodeSignatureShares.nodeTxSigningResult,
|
|
26970
|
+
expected: "Non-null signing nonce commitments"
|
|
26971
|
+
}
|
|
26972
|
+
);
|
|
26973
|
+
}
|
|
26974
|
+
if (!treeResp.rootNodeSignatureShares.refundTxSigningResult?.signingNonceCommitments) {
|
|
26975
|
+
throw new ValidationError(
|
|
26976
|
+
"No signing nonce commitments found in tree response",
|
|
26977
|
+
{
|
|
26978
|
+
field: "refundTxSigningResult.signingNonceCommitments"
|
|
26979
|
+
}
|
|
26980
|
+
);
|
|
26981
|
+
}
|
|
26982
|
+
if (!treeResp.rootNodeSignatureShares.directNodeTxSigningResult?.signingNonceCommitments) {
|
|
26983
|
+
throw new ValidationError(
|
|
26984
|
+
"No direct node signing nonce commitments found in tree response",
|
|
26985
|
+
{
|
|
26986
|
+
field: "directNodeTxSigningResult.signingNonceCommitments"
|
|
26987
|
+
}
|
|
26988
|
+
);
|
|
26989
|
+
}
|
|
26990
|
+
if (!treeResp.rootNodeSignatureShares.directRefundTxSigningResult?.signingNonceCommitments) {
|
|
26991
|
+
throw new ValidationError(
|
|
26992
|
+
"No direct refund signing nonce commitments found in tree response",
|
|
26993
|
+
{
|
|
26994
|
+
field: "directRefundTxSigningResult.signingNonceCommitments"
|
|
26995
|
+
}
|
|
26996
|
+
);
|
|
26997
|
+
}
|
|
26998
|
+
if (!treeResp.rootNodeSignatureShares.directFromCpfpRefundTxSigningResult?.signingNonceCommitments) {
|
|
26999
|
+
throw new ValidationError(
|
|
27000
|
+
"No direct from CPFP refund signing nonce commitments found in tree response",
|
|
27001
|
+
{
|
|
27002
|
+
field: "directFromCpfpRefundTxSigningResult.signingNonceCommitments"
|
|
27003
|
+
}
|
|
27004
|
+
);
|
|
27005
|
+
}
|
|
27006
|
+
if (!(0, import_utils16.equalBytes)(treeResp.rootNodeSignatureShares.verifyingKey, verifyingKey)) {
|
|
27007
|
+
throw new ValidationError("Verifying key mismatch", {
|
|
27008
|
+
field: "verifyingKey",
|
|
27009
|
+
value: treeResp.rootNodeSignatureShares.verifyingKey,
|
|
27010
|
+
expected: verifyingKey
|
|
27011
|
+
});
|
|
27012
|
+
}
|
|
27013
|
+
const cpfpRootSignature = await this.config.signer.signFrost({
|
|
27014
|
+
message: cpfpRootTxSighash,
|
|
27015
|
+
publicKey: signingPubKey,
|
|
27016
|
+
keyDerivation,
|
|
27017
|
+
verifyingKey,
|
|
27018
|
+
selfCommitment: cpfpRootNonceCommitment,
|
|
27019
|
+
statechainCommitments: treeResp.rootNodeSignatureShares.nodeTxSigningResult.signingNonceCommitments,
|
|
27020
|
+
adaptorPubKey: new Uint8Array()
|
|
26098
27021
|
});
|
|
27022
|
+
const directRootSignature = await this.config.signer.signFrost({
|
|
27023
|
+
message: directRootTxSighash,
|
|
27024
|
+
publicKey: signingPubKey,
|
|
27025
|
+
keyDerivation,
|
|
27026
|
+
verifyingKey,
|
|
27027
|
+
selfCommitment: directRootNonceCommitment,
|
|
27028
|
+
statechainCommitments: treeResp.rootNodeSignatureShares.directNodeTxSigningResult.signingNonceCommitments,
|
|
27029
|
+
adaptorPubKey: new Uint8Array()
|
|
27030
|
+
});
|
|
27031
|
+
const cpfpRefundSignature = await this.config.signer.signFrost({
|
|
27032
|
+
message: cpfpRefundTxSighash,
|
|
27033
|
+
publicKey: signingPubKey,
|
|
27034
|
+
keyDerivation,
|
|
27035
|
+
verifyingKey: treeResp.rootNodeSignatureShares.verifyingKey,
|
|
27036
|
+
selfCommitment: cpfpRefundNonceCommitment,
|
|
27037
|
+
statechainCommitments: treeResp.rootNodeSignatureShares.refundTxSigningResult.signingNonceCommitments,
|
|
27038
|
+
adaptorPubKey: new Uint8Array()
|
|
27039
|
+
});
|
|
27040
|
+
const directRefundSignature = await this.config.signer.signFrost({
|
|
27041
|
+
message: directRefundTxSighash,
|
|
27042
|
+
publicKey: signingPubKey,
|
|
27043
|
+
keyDerivation,
|
|
27044
|
+
verifyingKey: treeResp.rootNodeSignatureShares.verifyingKey,
|
|
27045
|
+
selfCommitment: directRefundNonceCommitment,
|
|
27046
|
+
statechainCommitments: treeResp.rootNodeSignatureShares.directRefundTxSigningResult.signingNonceCommitments,
|
|
27047
|
+
adaptorPubKey: new Uint8Array()
|
|
27048
|
+
});
|
|
27049
|
+
const directFromCpfpRefundSignature = await this.config.signer.signFrost({
|
|
27050
|
+
message: directFromCpfpRefundTxSighash,
|
|
27051
|
+
publicKey: signingPubKey,
|
|
27052
|
+
keyDerivation,
|
|
27053
|
+
verifyingKey: treeResp.rootNodeSignatureShares.verifyingKey,
|
|
27054
|
+
selfCommitment: directFromCpfpRefundNonceCommitment,
|
|
27055
|
+
statechainCommitments: treeResp.rootNodeSignatureShares.directFromCpfpRefundTxSigningResult.signingNonceCommitments,
|
|
27056
|
+
adaptorPubKey: new Uint8Array()
|
|
27057
|
+
});
|
|
27058
|
+
const cpfpRootAggregate = await this.config.signer.aggregateFrost({
|
|
27059
|
+
message: cpfpRootTxSighash,
|
|
27060
|
+
statechainSignatures: treeResp.rootNodeSignatureShares.nodeTxSigningResult.signatureShares,
|
|
27061
|
+
statechainPublicKeys: treeResp.rootNodeSignatureShares.nodeTxSigningResult.publicKeys,
|
|
27062
|
+
verifyingKey: treeResp.rootNodeSignatureShares.verifyingKey,
|
|
27063
|
+
statechainCommitments: treeResp.rootNodeSignatureShares.nodeTxSigningResult.signingNonceCommitments,
|
|
27064
|
+
selfCommitment: cpfpRootNonceCommitment,
|
|
27065
|
+
publicKey: signingPubKey,
|
|
27066
|
+
selfSignature: cpfpRootSignature,
|
|
27067
|
+
adaptorPubKey: new Uint8Array()
|
|
27068
|
+
});
|
|
27069
|
+
const directRootAggregate = await this.config.signer.aggregateFrost({
|
|
27070
|
+
message: directRootTxSighash,
|
|
27071
|
+
statechainSignatures: treeResp.rootNodeSignatureShares.directNodeTxSigningResult.signatureShares,
|
|
27072
|
+
statechainPublicKeys: treeResp.rootNodeSignatureShares.directNodeTxSigningResult.publicKeys,
|
|
27073
|
+
verifyingKey: treeResp.rootNodeSignatureShares.verifyingKey,
|
|
27074
|
+
statechainCommitments: treeResp.rootNodeSignatureShares.directNodeTxSigningResult.signingNonceCommitments,
|
|
27075
|
+
selfCommitment: directRootNonceCommitment,
|
|
27076
|
+
publicKey: signingPubKey,
|
|
27077
|
+
selfSignature: directRootSignature,
|
|
27078
|
+
adaptorPubKey: new Uint8Array()
|
|
27079
|
+
});
|
|
27080
|
+
const cpfpRefundAggregate = await this.config.signer.aggregateFrost({
|
|
27081
|
+
message: cpfpRefundTxSighash,
|
|
27082
|
+
statechainSignatures: treeResp.rootNodeSignatureShares.refundTxSigningResult.signatureShares,
|
|
27083
|
+
statechainPublicKeys: treeResp.rootNodeSignatureShares.refundTxSigningResult.publicKeys,
|
|
27084
|
+
verifyingKey: treeResp.rootNodeSignatureShares.verifyingKey,
|
|
27085
|
+
statechainCommitments: treeResp.rootNodeSignatureShares.refundTxSigningResult.signingNonceCommitments,
|
|
27086
|
+
selfCommitment: cpfpRefundNonceCommitment,
|
|
27087
|
+
publicKey: signingPubKey,
|
|
27088
|
+
selfSignature: cpfpRefundSignature,
|
|
27089
|
+
adaptorPubKey: new Uint8Array()
|
|
27090
|
+
});
|
|
27091
|
+
const directRefundAggregate = await this.config.signer.aggregateFrost({
|
|
27092
|
+
message: directRefundTxSighash,
|
|
27093
|
+
statechainSignatures: treeResp.rootNodeSignatureShares.directRefundTxSigningResult.signatureShares,
|
|
27094
|
+
statechainPublicKeys: treeResp.rootNodeSignatureShares.directRefundTxSigningResult.publicKeys,
|
|
27095
|
+
verifyingKey: treeResp.rootNodeSignatureShares.verifyingKey,
|
|
27096
|
+
statechainCommitments: treeResp.rootNodeSignatureShares.directRefundTxSigningResult.signingNonceCommitments,
|
|
27097
|
+
selfCommitment: directRefundNonceCommitment,
|
|
27098
|
+
publicKey: signingPubKey,
|
|
27099
|
+
selfSignature: directRefundSignature,
|
|
27100
|
+
adaptorPubKey: new Uint8Array()
|
|
27101
|
+
});
|
|
27102
|
+
const directFromCpfpRefundAggregate = await this.config.signer.aggregateFrost({
|
|
27103
|
+
message: directFromCpfpRefundTxSighash,
|
|
27104
|
+
statechainSignatures: treeResp.rootNodeSignatureShares.directFromCpfpRefundTxSigningResult.signatureShares,
|
|
27105
|
+
statechainPublicKeys: treeResp.rootNodeSignatureShares.directFromCpfpRefundTxSigningResult.publicKeys,
|
|
27106
|
+
verifyingKey: treeResp.rootNodeSignatureShares.verifyingKey,
|
|
27107
|
+
statechainCommitments: treeResp.rootNodeSignatureShares.directFromCpfpRefundTxSigningResult.signingNonceCommitments,
|
|
27108
|
+
selfCommitment: directFromCpfpRefundNonceCommitment,
|
|
27109
|
+
publicKey: signingPubKey,
|
|
27110
|
+
selfSignature: directFromCpfpRefundSignature,
|
|
27111
|
+
adaptorPubKey: new Uint8Array()
|
|
27112
|
+
});
|
|
27113
|
+
let finalizeResp;
|
|
27114
|
+
try {
|
|
27115
|
+
finalizeResp = await sparkClient.finalize_node_signatures_v2({
|
|
27116
|
+
intent: 0 /* CREATION */,
|
|
27117
|
+
nodeSignatures: [
|
|
27118
|
+
{
|
|
27119
|
+
nodeId: treeResp.rootNodeSignatureShares.nodeId,
|
|
27120
|
+
nodeTxSignature: cpfpRootAggregate,
|
|
27121
|
+
refundTxSignature: cpfpRefundAggregate,
|
|
27122
|
+
directNodeTxSignature: directRootAggregate,
|
|
27123
|
+
directRefundTxSignature: directRefundAggregate,
|
|
27124
|
+
directFromCpfpRefundTxSignature: directFromCpfpRefundAggregate
|
|
27125
|
+
}
|
|
27126
|
+
]
|
|
27127
|
+
});
|
|
27128
|
+
} catch (error) {
|
|
27129
|
+
throw new NetworkError(
|
|
27130
|
+
"Failed to finalize node signatures",
|
|
27131
|
+
{
|
|
27132
|
+
operation: "finalize_node_signatures",
|
|
27133
|
+
errorCount: 1,
|
|
27134
|
+
errors: error instanceof Error ? error.message : String(error)
|
|
27135
|
+
},
|
|
27136
|
+
error
|
|
27137
|
+
);
|
|
27138
|
+
}
|
|
27139
|
+
return finalizeResp;
|
|
27140
|
+
}
|
|
27141
|
+
/**
|
|
27142
|
+
* @deprecated
|
|
27143
|
+
* Use createTreeRoot instead.
|
|
27144
|
+
* This is currently only used to test backwards compatibility.
|
|
27145
|
+
*/
|
|
27146
|
+
async createTreeWithoutDirectTx({
|
|
27147
|
+
keyDerivation,
|
|
27148
|
+
verifyingKey,
|
|
27149
|
+
depositTx,
|
|
27150
|
+
vout
|
|
27151
|
+
}) {
|
|
27152
|
+
const output = depositTx.getOutput(vout);
|
|
27153
|
+
if (!output) {
|
|
27154
|
+
throw new ValidationError("Invalid deposit transaction output", {
|
|
27155
|
+
field: "vout",
|
|
27156
|
+
value: vout,
|
|
27157
|
+
expected: "Valid output index"
|
|
27158
|
+
});
|
|
27159
|
+
}
|
|
27160
|
+
const script = output.script;
|
|
27161
|
+
const amount = output.amount;
|
|
27162
|
+
if (!script || !amount) {
|
|
27163
|
+
throw new ValidationError("No script or amount found in deposit tx", {
|
|
27164
|
+
field: "output",
|
|
27165
|
+
value: output,
|
|
27166
|
+
expected: "Output with script and amount"
|
|
27167
|
+
});
|
|
27168
|
+
}
|
|
27169
|
+
const depositOutPoint = {
|
|
27170
|
+
txid: (0, import_utils15.hexToBytes)(getTxId(depositTx)),
|
|
27171
|
+
index: vout
|
|
27172
|
+
};
|
|
27173
|
+
const depositTxOut = {
|
|
27174
|
+
script,
|
|
27175
|
+
amount
|
|
27176
|
+
};
|
|
27177
|
+
const [cpfpRootTx, _] = createRootTx(depositOutPoint, depositTxOut);
|
|
27178
|
+
const cpfpRootNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
27179
|
+
const cpfpRootTxSighash = getSigHashFromTx(cpfpRootTx, 0, output);
|
|
26099
27180
|
const signingPubKey = await this.config.signer.getPublicKeyFromDerivation(keyDerivation);
|
|
26100
|
-
const
|
|
26101
|
-
|
|
26102
|
-
|
|
26103
|
-
|
|
26104
|
-
|
|
26105
|
-
|
|
26106
|
-
refundTx.addOutput({
|
|
26107
|
-
script: refundPkScript,
|
|
26108
|
-
amount: outputAmount
|
|
27181
|
+
const { cpfpRefundTx } = createRefundTxs({
|
|
27182
|
+
sequence: INITIAL_SEQUENCE,
|
|
27183
|
+
input: { txid: (0, import_utils15.hexToBytes)(getTxId(cpfpRootTx)), index: 0 },
|
|
27184
|
+
amountSats: amount,
|
|
27185
|
+
receivingPubkey: signingPubKey,
|
|
27186
|
+
network: this.config.getNetwork()
|
|
26109
27187
|
});
|
|
26110
|
-
|
|
26111
|
-
const
|
|
26112
|
-
|
|
27188
|
+
const cpfpRefundNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
27189
|
+
const cpfpRefundTxSighash = getSigHashFromTx(
|
|
27190
|
+
cpfpRefundTx,
|
|
27191
|
+
0,
|
|
27192
|
+
cpfpRootTx.getOutput(0)
|
|
27193
|
+
);
|
|
26113
27194
|
const sparkClient = await this.connectionManager.createSparkClient(
|
|
26114
27195
|
this.config.getCoordinatorAddress()
|
|
26115
27196
|
);
|
|
@@ -26123,14 +27204,14 @@ var DepositService = class {
|
|
|
26123
27204
|
network: this.config.getNetworkProto()
|
|
26124
27205
|
},
|
|
26125
27206
|
rootTxSigningJob: {
|
|
26126
|
-
rawTx:
|
|
27207
|
+
rawTx: cpfpRootTx.toBytes(),
|
|
26127
27208
|
signingPublicKey: signingPubKey,
|
|
26128
|
-
signingNonceCommitment:
|
|
27209
|
+
signingNonceCommitment: cpfpRootNonceCommitment.commitment
|
|
26129
27210
|
},
|
|
26130
27211
|
refundTxSigningJob: {
|
|
26131
|
-
rawTx:
|
|
27212
|
+
rawTx: cpfpRefundTx.toBytes(),
|
|
26132
27213
|
signingPublicKey: signingPubKey,
|
|
26133
|
-
signingNonceCommitment:
|
|
27214
|
+
signingNonceCommitment: cpfpRefundNonceCommitment.commitment
|
|
26134
27215
|
}
|
|
26135
27216
|
});
|
|
26136
27217
|
} catch (error) {
|
|
@@ -26176,55 +27257,55 @@ var DepositService = class {
|
|
|
26176
27257
|
expected: verifyingKey
|
|
26177
27258
|
});
|
|
26178
27259
|
}
|
|
26179
|
-
const
|
|
26180
|
-
message:
|
|
27260
|
+
const cpfpRootSignature = await this.config.signer.signFrost({
|
|
27261
|
+
message: cpfpRootTxSighash,
|
|
26181
27262
|
publicKey: signingPubKey,
|
|
26182
27263
|
keyDerivation,
|
|
26183
27264
|
verifyingKey,
|
|
26184
|
-
selfCommitment:
|
|
27265
|
+
selfCommitment: cpfpRootNonceCommitment,
|
|
26185
27266
|
statechainCommitments: treeResp.rootNodeSignatureShares.nodeTxSigningResult.signingNonceCommitments,
|
|
26186
27267
|
adaptorPubKey: new Uint8Array()
|
|
26187
27268
|
});
|
|
26188
|
-
const
|
|
26189
|
-
message:
|
|
27269
|
+
const cpfpRefundSignature = await this.config.signer.signFrost({
|
|
27270
|
+
message: cpfpRefundTxSighash,
|
|
26190
27271
|
publicKey: signingPubKey,
|
|
26191
27272
|
keyDerivation,
|
|
26192
|
-
verifyingKey,
|
|
26193
|
-
selfCommitment:
|
|
27273
|
+
verifyingKey: treeResp.rootNodeSignatureShares.verifyingKey,
|
|
27274
|
+
selfCommitment: cpfpRefundNonceCommitment,
|
|
26194
27275
|
statechainCommitments: treeResp.rootNodeSignatureShares.refundTxSigningResult.signingNonceCommitments,
|
|
26195
27276
|
adaptorPubKey: new Uint8Array()
|
|
26196
27277
|
});
|
|
26197
|
-
const
|
|
26198
|
-
message:
|
|
27278
|
+
const cpfpRootAggregate = await this.config.signer.aggregateFrost({
|
|
27279
|
+
message: cpfpRootTxSighash,
|
|
26199
27280
|
statechainSignatures: treeResp.rootNodeSignatureShares.nodeTxSigningResult.signatureShares,
|
|
26200
27281
|
statechainPublicKeys: treeResp.rootNodeSignatureShares.nodeTxSigningResult.publicKeys,
|
|
26201
27282
|
verifyingKey: treeResp.rootNodeSignatureShares.verifyingKey,
|
|
26202
27283
|
statechainCommitments: treeResp.rootNodeSignatureShares.nodeTxSigningResult.signingNonceCommitments,
|
|
26203
|
-
selfCommitment:
|
|
27284
|
+
selfCommitment: cpfpRootNonceCommitment,
|
|
26204
27285
|
publicKey: signingPubKey,
|
|
26205
|
-
selfSignature:
|
|
27286
|
+
selfSignature: cpfpRootSignature,
|
|
26206
27287
|
adaptorPubKey: new Uint8Array()
|
|
26207
27288
|
});
|
|
26208
|
-
const
|
|
26209
|
-
message:
|
|
27289
|
+
const cpfpRefundAggregate = await this.config.signer.aggregateFrost({
|
|
27290
|
+
message: cpfpRefundTxSighash,
|
|
26210
27291
|
statechainSignatures: treeResp.rootNodeSignatureShares.refundTxSigningResult.signatureShares,
|
|
26211
27292
|
statechainPublicKeys: treeResp.rootNodeSignatureShares.refundTxSigningResult.publicKeys,
|
|
26212
27293
|
verifyingKey: treeResp.rootNodeSignatureShares.verifyingKey,
|
|
26213
27294
|
statechainCommitments: treeResp.rootNodeSignatureShares.refundTxSigningResult.signingNonceCommitments,
|
|
26214
|
-
selfCommitment:
|
|
27295
|
+
selfCommitment: cpfpRefundNonceCommitment,
|
|
26215
27296
|
publicKey: signingPubKey,
|
|
26216
|
-
selfSignature:
|
|
27297
|
+
selfSignature: cpfpRefundSignature,
|
|
26217
27298
|
adaptorPubKey: new Uint8Array()
|
|
26218
27299
|
});
|
|
26219
27300
|
let finalizeResp;
|
|
26220
27301
|
try {
|
|
26221
|
-
finalizeResp = await sparkClient.
|
|
27302
|
+
finalizeResp = await sparkClient.finalize_node_signatures_v2({
|
|
26222
27303
|
intent: 0 /* CREATION */,
|
|
26223
27304
|
nodeSignatures: [
|
|
26224
27305
|
{
|
|
26225
27306
|
nodeId: treeResp.rootNodeSignatureShares.nodeId,
|
|
26226
|
-
nodeTxSignature:
|
|
26227
|
-
refundTxSignature:
|
|
27307
|
+
nodeTxSignature: cpfpRootAggregate,
|
|
27308
|
+
refundTxSignature: cpfpRefundAggregate
|
|
26228
27309
|
}
|
|
26229
27310
|
]
|
|
26230
27311
|
});
|
|
@@ -26434,7 +27515,8 @@ var LightningService = class {
|
|
|
26434
27515
|
let signingCommitments;
|
|
26435
27516
|
try {
|
|
26436
27517
|
signingCommitments = await sparkClient.get_signing_commitments({
|
|
26437
|
-
nodeIds: leaves.map((leaf) => leaf.leaf.id)
|
|
27518
|
+
nodeIds: leaves.map((leaf) => leaf.leaf.id),
|
|
27519
|
+
count: 3
|
|
26438
27520
|
});
|
|
26439
27521
|
} catch (error) {
|
|
26440
27522
|
throw new NetworkError(
|
|
@@ -26447,10 +27529,19 @@ var LightningService = class {
|
|
|
26447
27529
|
error
|
|
26448
27530
|
);
|
|
26449
27531
|
}
|
|
26450
|
-
const
|
|
27532
|
+
const {
|
|
27533
|
+
cpfpLeafSigningJobs,
|
|
27534
|
+
directLeafSigningJobs,
|
|
27535
|
+
directFromCpfpLeafSigningJobs
|
|
27536
|
+
} = await this.signingService.signRefunds(
|
|
26451
27537
|
leaves,
|
|
26452
|
-
|
|
26453
|
-
|
|
27538
|
+
receiverIdentityPubkey,
|
|
27539
|
+
signingCommitments.signingCommitments.slice(0, leaves.length),
|
|
27540
|
+
signingCommitments.signingCommitments.slice(
|
|
27541
|
+
leaves.length,
|
|
27542
|
+
2 * leaves.length
|
|
27543
|
+
),
|
|
27544
|
+
signingCommitments.signingCommitments.slice(2 * leaves.length)
|
|
26454
27545
|
);
|
|
26455
27546
|
const transferId = (0, import_uuidv74.uuidv7)();
|
|
26456
27547
|
let bolt11String = "";
|
|
@@ -26487,7 +27578,7 @@ var LightningService = class {
|
|
|
26487
27578
|
const reason = isInboundPayment ? 1 /* REASON_RECEIVE */ : 0 /* REASON_SEND */;
|
|
26488
27579
|
let response;
|
|
26489
27580
|
try {
|
|
26490
|
-
response = await sparkClient.
|
|
27581
|
+
response = await sparkClient.initiate_preimage_swap_v2({
|
|
26491
27582
|
paymentHash,
|
|
26492
27583
|
invoiceAmount: {
|
|
26493
27584
|
invoiceAmountProof: {
|
|
@@ -26499,7 +27590,9 @@ var LightningService = class {
|
|
|
26499
27590
|
transfer: {
|
|
26500
27591
|
transferId,
|
|
26501
27592
|
ownerIdentityPublicKey: await this.config.signer.getIdentityPublicKey(),
|
|
26502
|
-
leavesToSend:
|
|
27593
|
+
leavesToSend: cpfpLeafSigningJobs,
|
|
27594
|
+
directLeavesToSend: directLeafSigningJobs,
|
|
27595
|
+
directFromCpfpLeavesToSend: directFromCpfpLeafSigningJobs,
|
|
26503
27596
|
receiverIdentityPublicKey: receiverIdentityPubkey,
|
|
26504
27597
|
expiryTime: new Date(Date.now() + 2 * 60 * 1e3)
|
|
26505
27598
|
},
|
|
@@ -28976,13 +30069,6 @@ function isTokenTransaction(tokenTransaction) {
|
|
|
28976
30069
|
init_buffer();
|
|
28977
30070
|
var import_utils20 = require("@noble/curves/abstract/utils");
|
|
28978
30071
|
var import_btc_signer5 = require("@scure/btc-signer");
|
|
28979
|
-
var INITIAL_TIME_LOCK3 = 2e3;
|
|
28980
|
-
function maybeApplyFee2(amount) {
|
|
28981
|
-
if (amount > BigInt(DEFAULT_FEE_SATS)) {
|
|
28982
|
-
return amount - BigInt(DEFAULT_FEE_SATS);
|
|
28983
|
-
}
|
|
28984
|
-
return amount;
|
|
28985
|
-
}
|
|
28986
30072
|
var TreeCreationService = class {
|
|
28987
30073
|
config;
|
|
28988
30074
|
connectionManager;
|
|
@@ -29097,7 +30183,7 @@ var TreeCreationService = class {
|
|
|
29097
30183
|
);
|
|
29098
30184
|
let response;
|
|
29099
30185
|
try {
|
|
29100
|
-
response = await sparkClient.
|
|
30186
|
+
response = await sparkClient.create_tree_v2(request);
|
|
29101
30187
|
} catch (error) {
|
|
29102
30188
|
throw new Error(`Error creating tree: ${error}`);
|
|
29103
30189
|
}
|
|
@@ -29114,7 +30200,7 @@ var TreeCreationService = class {
|
|
|
29114
30200
|
);
|
|
29115
30201
|
let finalizeResp;
|
|
29116
30202
|
try {
|
|
29117
|
-
finalizeResp = await sparkClient.
|
|
30203
|
+
finalizeResp = await sparkClient.finalize_node_signatures_v2({
|
|
29118
30204
|
nodeSignatures
|
|
29119
30205
|
});
|
|
29120
30206
|
} catch (error) {
|
|
@@ -29179,91 +30265,111 @@ var TreeCreationService = class {
|
|
|
29179
30265
|
async buildChildCreationNode(node, parentTx, vout, network) {
|
|
29180
30266
|
const internalCreationNode = {
|
|
29181
30267
|
nodeTxSigningJob: void 0,
|
|
29182
|
-
refundTxSigningJob: void 0,
|
|
29183
|
-
children: [],
|
|
29184
30268
|
directNodeTxSigningJob: void 0,
|
|
30269
|
+
refundTxSigningJob: void 0,
|
|
29185
30270
|
directRefundTxSigningJob: void 0,
|
|
29186
|
-
directFromCpfpRefundTxSigningJob: void 0
|
|
30271
|
+
directFromCpfpRefundTxSigningJob: void 0,
|
|
30272
|
+
children: []
|
|
29187
30273
|
};
|
|
29188
|
-
const tx = new import_btc_signer5.Transaction({ version: 3 });
|
|
29189
|
-
tx.addInput({
|
|
29190
|
-
txid: getTxId(parentTx),
|
|
29191
|
-
index: vout
|
|
29192
|
-
});
|
|
29193
30274
|
const parentTxOut = parentTx.getOutput(vout);
|
|
29194
30275
|
if (!parentTxOut?.script || !parentTxOut?.amount) {
|
|
29195
30276
|
throw new Error("parentTxOut is undefined");
|
|
29196
30277
|
}
|
|
29197
|
-
|
|
30278
|
+
const parentOutPoint = {
|
|
30279
|
+
txid: (0, import_utils20.hexToBytes)(getTxId(parentTx)),
|
|
30280
|
+
index: vout
|
|
30281
|
+
};
|
|
30282
|
+
const parentTxOutObj = {
|
|
29198
30283
|
script: parentTxOut.script,
|
|
29199
30284
|
amount: parentTxOut.amount
|
|
29200
|
-
|
|
29201
|
-
}
|
|
29202
|
-
|
|
29203
|
-
|
|
29204
|
-
|
|
30285
|
+
};
|
|
30286
|
+
const { cpfpNodeTx, directNodeTx } = createNodeTxs(
|
|
30287
|
+
parentTxOutObj,
|
|
30288
|
+
parentOutPoint
|
|
30289
|
+
);
|
|
30290
|
+
const cpfpNodeSigningCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
30291
|
+
const directNodeSigningCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
30292
|
+
const cpfpNodeSigningJob = {
|
|
29205
30293
|
signingPublicKey: node.signingPublicKey,
|
|
29206
|
-
rawTx:
|
|
29207
|
-
signingNonceCommitment:
|
|
30294
|
+
rawTx: cpfpNodeTx.toBytes(),
|
|
30295
|
+
signingNonceCommitment: cpfpNodeSigningCommitment.commitment
|
|
29208
30296
|
};
|
|
29209
|
-
|
|
29210
|
-
|
|
29211
|
-
|
|
30297
|
+
const directNodeSigningJob = directNodeTx ? {
|
|
30298
|
+
signingPublicKey: node.signingPublicKey,
|
|
30299
|
+
rawTx: directNodeTx.toBytes(),
|
|
30300
|
+
signingNonceCommitment: directNodeSigningCommitment.commitment
|
|
30301
|
+
} : void 0;
|
|
30302
|
+
internalCreationNode.nodeTxSigningCommitment = cpfpNodeSigningCommitment;
|
|
30303
|
+
internalCreationNode.directNodeTxSigningCommitment = directNodeSigningCommitment;
|
|
30304
|
+
internalCreationNode.nodeTxSigningJob = cpfpNodeSigningJob;
|
|
30305
|
+
internalCreationNode.directNodeTxSigningJob = directNodeSigningJob;
|
|
30306
|
+
const sequence = INITIAL_SEQUENCE;
|
|
30307
|
+
const directSequence = INITIAL_DIRECT_SEQUENCE;
|
|
29212
30308
|
const childCreationNode = {
|
|
29213
30309
|
nodeTxSigningJob: void 0,
|
|
29214
|
-
refundTxSigningJob: void 0,
|
|
29215
|
-
children: [],
|
|
29216
30310
|
directNodeTxSigningJob: void 0,
|
|
30311
|
+
refundTxSigningJob: void 0,
|
|
29217
30312
|
directRefundTxSigningJob: void 0,
|
|
29218
|
-
directFromCpfpRefundTxSigningJob: void 0
|
|
30313
|
+
directFromCpfpRefundTxSigningJob: void 0,
|
|
30314
|
+
children: []
|
|
29219
30315
|
};
|
|
29220
|
-
const
|
|
29221
|
-
|
|
29222
|
-
|
|
29223
|
-
index: 0,
|
|
29224
|
-
|
|
29225
|
-
|
|
29226
|
-
|
|
29227
|
-
|
|
29228
|
-
|
|
29229
|
-
|
|
29230
|
-
|
|
29231
|
-
childTx.addOutput(getEphemeralAnchorOutput());
|
|
29232
|
-
const childSigningNonceCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
29233
|
-
const childSigningJob = {
|
|
30316
|
+
const [cpfpLeafTx, directLeafTx] = createLeafNodeTx(
|
|
30317
|
+
sequence,
|
|
30318
|
+
directSequence,
|
|
30319
|
+
{ txid: (0, import_utils20.hexToBytes)(getTxId(cpfpNodeTx)), index: 0 },
|
|
30320
|
+
parentTxOutObj,
|
|
30321
|
+
true
|
|
30322
|
+
// shouldCalculateFee
|
|
30323
|
+
);
|
|
30324
|
+
const cpfpLeafSigningCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
30325
|
+
const directLeafSigningCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
30326
|
+
const cpfpLeafSigningJob = {
|
|
29234
30327
|
signingPublicKey: node.signingPublicKey,
|
|
29235
|
-
rawTx:
|
|
29236
|
-
signingNonceCommitment:
|
|
29237
|
-
};
|
|
29238
|
-
|
|
29239
|
-
|
|
29240
|
-
|
|
29241
|
-
|
|
29242
|
-
|
|
29243
|
-
|
|
29244
|
-
|
|
29245
|
-
|
|
29246
|
-
|
|
29247
|
-
|
|
30328
|
+
rawTx: cpfpLeafTx.toBytes(),
|
|
30329
|
+
signingNonceCommitment: cpfpLeafSigningCommitment.commitment
|
|
30330
|
+
};
|
|
30331
|
+
const directLeafSigningJob = {
|
|
30332
|
+
signingPublicKey: node.signingPublicKey,
|
|
30333
|
+
rawTx: directLeafTx.toBytes(),
|
|
30334
|
+
signingNonceCommitment: directLeafSigningCommitment.commitment
|
|
30335
|
+
};
|
|
30336
|
+
childCreationNode.nodeTxSigningCommitment = cpfpLeafSigningCommitment;
|
|
30337
|
+
childCreationNode.directNodeTxSigningCommitment = directLeafSigningCommitment;
|
|
30338
|
+
childCreationNode.nodeTxSigningJob = cpfpLeafSigningJob;
|
|
30339
|
+
childCreationNode.directNodeTxSigningJob = directLeafSigningJob;
|
|
30340
|
+
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } = createRefundTxs({
|
|
30341
|
+
sequence,
|
|
30342
|
+
directSequence,
|
|
30343
|
+
input: { txid: (0, import_utils20.hexToBytes)(getTxId(cpfpLeafTx)), index: 0 },
|
|
30344
|
+
directInput: { txid: (0, import_utils20.hexToBytes)(getTxId(directLeafTx)), index: 0 },
|
|
30345
|
+
amountSats: parentTxOut.amount,
|
|
30346
|
+
receivingPubkey: node.signingPublicKey,
|
|
29248
30347
|
network
|
|
29249
|
-
);
|
|
29250
|
-
const refundAddress = (0, import_btc_signer5.Address)(getNetwork(network)).decode(
|
|
29251
|
-
refundP2trAddress
|
|
29252
|
-
);
|
|
29253
|
-
const refundPkScript = import_btc_signer5.OutScript.encode(refundAddress);
|
|
29254
|
-
refundTx.addOutput({
|
|
29255
|
-
script: refundPkScript,
|
|
29256
|
-
amount: maybeApplyFee2(parentTxOut.amount)
|
|
29257
30348
|
});
|
|
29258
|
-
|
|
29259
|
-
const
|
|
29260
|
-
const
|
|
30349
|
+
const cpfpRefundSigningCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
30350
|
+
const directRefundSigningCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
30351
|
+
const directFromCpfpRefundSigningCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
30352
|
+
const cpfpRefundSigningJob = {
|
|
29261
30353
|
signingPublicKey: node.signingPublicKey,
|
|
29262
|
-
rawTx:
|
|
29263
|
-
signingNonceCommitment:
|
|
30354
|
+
rawTx: cpfpRefundTx.toBytes(),
|
|
30355
|
+
signingNonceCommitment: cpfpRefundSigningCommitment.commitment
|
|
29264
30356
|
};
|
|
29265
|
-
|
|
29266
|
-
|
|
30357
|
+
const directRefundSigningJob = directRefundTx ? {
|
|
30358
|
+
signingPublicKey: node.signingPublicKey,
|
|
30359
|
+
rawTx: directRefundTx.toBytes(),
|
|
30360
|
+
signingNonceCommitment: directRefundSigningCommitment.commitment
|
|
30361
|
+
} : void 0;
|
|
30362
|
+
const directFromCpfpRefundSigningJob = directFromCpfpRefundTx ? {
|
|
30363
|
+
signingPublicKey: node.signingPublicKey,
|
|
30364
|
+
rawTx: directFromCpfpRefundTx.toBytes(),
|
|
30365
|
+
signingNonceCommitment: directFromCpfpRefundSigningCommitment.commitment
|
|
30366
|
+
} : void 0;
|
|
30367
|
+
childCreationNode.refundTxSigningCommitment = cpfpRefundSigningCommitment;
|
|
30368
|
+
childCreationNode.directRefundTxSigningCommitment = directRefundSigningCommitment;
|
|
30369
|
+
childCreationNode.directFromCpfpRefundTxSigningCommitment = directFromCpfpRefundSigningCommitment;
|
|
30370
|
+
childCreationNode.refundTxSigningJob = cpfpRefundSigningJob;
|
|
30371
|
+
childCreationNode.directRefundTxSigningJob = directRefundSigningJob;
|
|
30372
|
+
childCreationNode.directFromCpfpRefundTxSigningJob = directFromCpfpRefundSigningJob;
|
|
29267
30373
|
internalCreationNode.children.push(childCreationNode);
|
|
29268
30374
|
return internalCreationNode;
|
|
29269
30375
|
}
|
|
@@ -29272,11 +30378,7 @@ var TreeCreationService = class {
|
|
|
29272
30378
|
if (!parentTxOutput?.script || !parentTxOutput?.amount) {
|
|
29273
30379
|
throw new Error("parentTxOutput is undefined");
|
|
29274
30380
|
}
|
|
29275
|
-
const
|
|
29276
|
-
rootNodeTx.addInput({
|
|
29277
|
-
txid: getTxId(parentTx),
|
|
29278
|
-
index: vout
|
|
29279
|
-
});
|
|
30381
|
+
const childTxOuts = [];
|
|
29280
30382
|
for (let i = 0; i < root.children.length; i++) {
|
|
29281
30383
|
const child = root.children[i];
|
|
29282
30384
|
if (!child || !child.address) {
|
|
@@ -29284,28 +30386,41 @@ var TreeCreationService = class {
|
|
|
29284
30386
|
}
|
|
29285
30387
|
const childAddress = (0, import_btc_signer5.Address)(getNetwork(network)).decode(child.address);
|
|
29286
30388
|
const childPkScript = import_btc_signer5.OutScript.encode(childAddress);
|
|
29287
|
-
|
|
30389
|
+
childTxOuts.push({
|
|
29288
30390
|
script: childPkScript,
|
|
29289
30391
|
amount: parentTxOutput.amount / 2n
|
|
29290
|
-
// feeAdjustedAmount / 2n,
|
|
29291
30392
|
});
|
|
29292
30393
|
}
|
|
29293
|
-
|
|
29294
|
-
|
|
29295
|
-
|
|
30394
|
+
const parentOutPoint = {
|
|
30395
|
+
txid: (0, import_utils20.hexToBytes)(getTxId(parentTx)),
|
|
30396
|
+
index: vout
|
|
30397
|
+
};
|
|
30398
|
+
const [cpfpSplitTx, directSplitTx] = createSplitTx(
|
|
30399
|
+
parentOutPoint,
|
|
30400
|
+
childTxOuts
|
|
30401
|
+
);
|
|
30402
|
+
const cpfpSplitSigningCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
30403
|
+
const directSplitSigningCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
30404
|
+
const cpfpSplitSigningJob = {
|
|
30405
|
+
signingPublicKey: root.signingPublicKey,
|
|
30406
|
+
rawTx: cpfpSplitTx.toBytes(),
|
|
30407
|
+
signingNonceCommitment: cpfpSplitSigningCommitment.commitment
|
|
30408
|
+
};
|
|
30409
|
+
const directSplitSigningJob = {
|
|
29296
30410
|
signingPublicKey: root.signingPublicKey,
|
|
29297
|
-
rawTx:
|
|
29298
|
-
signingNonceCommitment:
|
|
30411
|
+
rawTx: directSplitTx.toBytes(),
|
|
30412
|
+
signingNonceCommitment: directSplitSigningCommitment.commitment
|
|
29299
30413
|
};
|
|
29300
30414
|
const rootCreationNode = {
|
|
29301
|
-
nodeTxSigningJob:
|
|
30415
|
+
nodeTxSigningJob: cpfpSplitSigningJob,
|
|
30416
|
+
directNodeTxSigningJob: directSplitSigningJob,
|
|
29302
30417
|
refundTxSigningJob: void 0,
|
|
29303
|
-
children: [],
|
|
29304
|
-
directNodeTxSigningJob: void 0,
|
|
29305
30418
|
directRefundTxSigningJob: void 0,
|
|
29306
|
-
directFromCpfpRefundTxSigningJob: void 0
|
|
30419
|
+
directFromCpfpRefundTxSigningJob: void 0,
|
|
30420
|
+
children: []
|
|
29307
30421
|
};
|
|
29308
|
-
rootCreationNode.nodeTxSigningCommitment =
|
|
30422
|
+
rootCreationNode.nodeTxSigningCommitment = cpfpSplitSigningCommitment;
|
|
30423
|
+
rootCreationNode.directNodeTxSigningCommitment = directSplitSigningCommitment;
|
|
29309
30424
|
const leftChild = root.children[0];
|
|
29310
30425
|
const rightChild = root.children[1];
|
|
29311
30426
|
if (!leftChild || !rightChild) {
|
|
@@ -29313,13 +30428,15 @@ var TreeCreationService = class {
|
|
|
29313
30428
|
}
|
|
29314
30429
|
const leftChildCreationNode = await this.buildChildCreationNode(
|
|
29315
30430
|
leftChild,
|
|
29316
|
-
|
|
30431
|
+
cpfpSplitTx,
|
|
30432
|
+
// Use CPFP version for children
|
|
29317
30433
|
0,
|
|
29318
30434
|
network
|
|
29319
30435
|
);
|
|
29320
30436
|
const rightChildCreationNode = await this.buildChildCreationNode(
|
|
29321
30437
|
rightChild,
|
|
29322
|
-
|
|
30438
|
+
cpfpSplitTx,
|
|
30439
|
+
// Use CPFP version for children
|
|
29323
30440
|
1,
|
|
29324
30441
|
network
|
|
29325
30442
|
);
|
|
@@ -29328,19 +30445,19 @@ var TreeCreationService = class {
|
|
|
29328
30445
|
return rootCreationNode;
|
|
29329
30446
|
}
|
|
29330
30447
|
async signNodeCreation(parentTx, vout, internalNode, creationNode, creationResponseNode) {
|
|
29331
|
-
if (!creationNode.nodeTxSigningJob?.signingPublicKey || !internalNode.verificationKey) {
|
|
30448
|
+
if (!creationNode.nodeTxSigningJob?.signingPublicKey || !creationNode.directNodeTxSigningJob?.signingPublicKey || !internalNode.verificationKey) {
|
|
29332
30449
|
throw new Error("signingPublicKey or verificationKey is undefined");
|
|
29333
30450
|
}
|
|
29334
30451
|
const parentTxOutput = parentTx.getOutput(vout);
|
|
29335
30452
|
if (!parentTxOutput) {
|
|
29336
30453
|
throw new Error("parentTxOutput is undefined");
|
|
29337
30454
|
}
|
|
29338
|
-
const
|
|
29339
|
-
const
|
|
29340
|
-
let
|
|
30455
|
+
const cpfpNodeTx = getTxFromRawTxBytes(creationNode.nodeTxSigningJob.rawTx);
|
|
30456
|
+
const cpfpNodeTxSighash = getSigHashFromTx(cpfpNodeTx, 0, parentTxOutput);
|
|
30457
|
+
let cpfpNodeTxSignature = new Uint8Array();
|
|
29341
30458
|
if (creationNode.nodeTxSigningCommitment) {
|
|
29342
|
-
const
|
|
29343
|
-
message:
|
|
30459
|
+
const cpfpUserSignature = await this.config.signer.signFrost({
|
|
30460
|
+
message: cpfpNodeTxSighash,
|
|
29344
30461
|
publicKey: creationNode.nodeTxSigningJob.signingPublicKey,
|
|
29345
30462
|
keyDerivation: {
|
|
29346
30463
|
type: "leaf" /* LEAF */,
|
|
@@ -29350,30 +30467,84 @@ var TreeCreationService = class {
|
|
|
29350
30467
|
statechainCommitments: creationResponseNode.nodeTxSigningResult?.signingNonceCommitments,
|
|
29351
30468
|
verifyingKey: internalNode.verificationKey
|
|
29352
30469
|
});
|
|
29353
|
-
|
|
29354
|
-
message:
|
|
30470
|
+
cpfpNodeTxSignature = await this.config.signer.aggregateFrost({
|
|
30471
|
+
message: cpfpNodeTxSighash,
|
|
29355
30472
|
statechainSignatures: creationResponseNode.nodeTxSigningResult?.signatureShares,
|
|
29356
30473
|
statechainPublicKeys: creationResponseNode.nodeTxSigningResult?.publicKeys,
|
|
29357
30474
|
verifyingKey: internalNode.verificationKey,
|
|
29358
30475
|
statechainCommitments: creationResponseNode.nodeTxSigningResult?.signingNonceCommitments,
|
|
29359
30476
|
selfCommitment: creationNode.nodeTxSigningCommitment,
|
|
29360
|
-
selfSignature:
|
|
30477
|
+
selfSignature: cpfpUserSignature,
|
|
29361
30478
|
publicKey: internalNode.signingPublicKey
|
|
29362
30479
|
});
|
|
29363
30480
|
}
|
|
29364
|
-
|
|
29365
|
-
|
|
29366
|
-
|
|
29367
|
-
|
|
29368
|
-
|
|
29369
|
-
|
|
29370
|
-
|
|
29371
|
-
|
|
29372
|
-
|
|
29373
|
-
|
|
29374
|
-
const
|
|
29375
|
-
|
|
29376
|
-
|
|
30481
|
+
const directNodeTx = getTxFromRawTxBytes(
|
|
30482
|
+
creationNode.directNodeTxSigningJob.rawTx
|
|
30483
|
+
);
|
|
30484
|
+
const directNodeTxSighash = getSigHashFromTx(
|
|
30485
|
+
directNodeTx,
|
|
30486
|
+
0,
|
|
30487
|
+
parentTxOutput
|
|
30488
|
+
);
|
|
30489
|
+
let directNodeTxSignature = new Uint8Array();
|
|
30490
|
+
if (creationNode.directNodeTxSigningCommitment) {
|
|
30491
|
+
const directUserSignature = await this.config.signer.signFrost({
|
|
30492
|
+
message: directNodeTxSighash,
|
|
30493
|
+
publicKey: creationNode.directNodeTxSigningJob.signingPublicKey,
|
|
30494
|
+
keyDerivation: {
|
|
30495
|
+
type: "leaf" /* LEAF */,
|
|
30496
|
+
path: creationResponseNode.nodeId
|
|
30497
|
+
},
|
|
30498
|
+
selfCommitment: creationNode.directNodeTxSigningCommitment,
|
|
30499
|
+
statechainCommitments: creationResponseNode.directNodeTxSigningResult?.signingNonceCommitments,
|
|
30500
|
+
verifyingKey: internalNode.verificationKey
|
|
30501
|
+
});
|
|
30502
|
+
directNodeTxSignature = await this.config.signer.aggregateFrost({
|
|
30503
|
+
message: directNodeTxSighash,
|
|
30504
|
+
statechainSignatures: creationResponseNode.directNodeTxSigningResult?.signatureShares,
|
|
30505
|
+
statechainPublicKeys: creationResponseNode.directNodeTxSigningResult?.publicKeys,
|
|
30506
|
+
verifyingKey: internalNode.verificationKey,
|
|
30507
|
+
statechainCommitments: creationResponseNode.directNodeTxSigningResult?.signingNonceCommitments,
|
|
30508
|
+
selfCommitment: creationNode.directNodeTxSigningCommitment,
|
|
30509
|
+
selfSignature: directUserSignature,
|
|
30510
|
+
publicKey: internalNode.signingPublicKey
|
|
30511
|
+
});
|
|
30512
|
+
}
|
|
30513
|
+
let cpfpRefundTxSignature = new Uint8Array();
|
|
30514
|
+
let directRefundTxSignature = new Uint8Array();
|
|
30515
|
+
let directFromCpfpRefundTxSignature = new Uint8Array();
|
|
30516
|
+
if (creationNode.refundTxSigningCommitment && creationNode.directRefundTxSigningCommitment && creationNode.directFromCpfpRefundTxSigningCommitment) {
|
|
30517
|
+
const rawCpfpRefundTx = creationNode.refundTxSigningJob?.rawTx;
|
|
30518
|
+
const rawDirectRefundTx = creationNode.directRefundTxSigningJob?.rawTx;
|
|
30519
|
+
const rawDirectFromCpfpRefundTx = creationNode.directFromCpfpRefundTxSigningJob?.rawTx;
|
|
30520
|
+
if (!rawCpfpRefundTx || !rawDirectRefundTx || !rawDirectFromCpfpRefundTx) {
|
|
30521
|
+
throw new Error("refund transaction rawTx is undefined");
|
|
30522
|
+
}
|
|
30523
|
+
if (!creationNode.refundTxSigningJob?.signingPublicKey || !creationNode.directRefundTxSigningJob?.signingPublicKey || !creationNode.directFromCpfpRefundTxSigningJob?.signingPublicKey) {
|
|
30524
|
+
throw new Error("refund transaction signingPublicKey is undefined");
|
|
30525
|
+
}
|
|
30526
|
+
const cpfpRefundTx = getTxFromRawTxBytes(rawCpfpRefundTx);
|
|
30527
|
+
const directRefundTx = getTxFromRawTxBytes(rawDirectRefundTx);
|
|
30528
|
+
const directFromCpfpRefundTx = getTxFromRawTxBytes(
|
|
30529
|
+
rawDirectFromCpfpRefundTx
|
|
30530
|
+
);
|
|
30531
|
+
const cpfpRefundTxSighash = getSigHashFromTx(
|
|
30532
|
+
cpfpRefundTx,
|
|
30533
|
+
0,
|
|
30534
|
+
cpfpNodeTx.getOutput(0)
|
|
30535
|
+
);
|
|
30536
|
+
const directRefundTxSighash = getSigHashFromTx(
|
|
30537
|
+
directRefundTx,
|
|
30538
|
+
0,
|
|
30539
|
+
directNodeTx.getOutput(0)
|
|
30540
|
+
);
|
|
30541
|
+
const directFromCpfpRefundTxSighash = getSigHashFromTx(
|
|
30542
|
+
directFromCpfpRefundTx,
|
|
30543
|
+
0,
|
|
30544
|
+
cpfpNodeTx.getOutput(0)
|
|
30545
|
+
);
|
|
30546
|
+
const cpfpRefundUserSignature = await this.config.signer.signFrost({
|
|
30547
|
+
message: cpfpRefundTxSighash,
|
|
29377
30548
|
publicKey: creationNode.refundTxSigningJob.signingPublicKey,
|
|
29378
30549
|
keyDerivation: {
|
|
29379
30550
|
type: "leaf" /* LEAF */,
|
|
@@ -29383,27 +30554,69 @@ var TreeCreationService = class {
|
|
|
29383
30554
|
statechainCommitments: creationResponseNode.refundTxSigningResult?.signingNonceCommitments,
|
|
29384
30555
|
verifyingKey: internalNode.verificationKey
|
|
29385
30556
|
});
|
|
29386
|
-
|
|
29387
|
-
message:
|
|
30557
|
+
cpfpRefundTxSignature = await this.config.signer.aggregateFrost({
|
|
30558
|
+
message: cpfpRefundTxSighash,
|
|
29388
30559
|
statechainSignatures: creationResponseNode.refundTxSigningResult?.signatureShares,
|
|
29389
30560
|
statechainPublicKeys: creationResponseNode.refundTxSigningResult?.publicKeys,
|
|
29390
30561
|
verifyingKey: internalNode.verificationKey,
|
|
29391
30562
|
statechainCommitments: creationResponseNode.refundTxSigningResult?.signingNonceCommitments,
|
|
29392
30563
|
selfCommitment: creationNode.refundTxSigningCommitment,
|
|
29393
|
-
selfSignature:
|
|
30564
|
+
selfSignature: cpfpRefundUserSignature,
|
|
30565
|
+
publicKey: internalNode.signingPublicKey
|
|
30566
|
+
});
|
|
30567
|
+
const keyDerivation = {
|
|
30568
|
+
type: "leaf" /* LEAF */,
|
|
30569
|
+
path: creationResponseNode.nodeId
|
|
30570
|
+
};
|
|
30571
|
+
const directRefundUserSignature = await this.config.signer.signFrost({
|
|
30572
|
+
message: directRefundTxSighash,
|
|
30573
|
+
publicKey: creationNode.directRefundTxSigningJob.signingPublicKey,
|
|
30574
|
+
keyDerivation,
|
|
30575
|
+
selfCommitment: creationNode.directRefundTxSigningCommitment,
|
|
30576
|
+
statechainCommitments: creationResponseNode.directRefundTxSigningResult?.signingNonceCommitments,
|
|
30577
|
+
verifyingKey: internalNode.verificationKey
|
|
30578
|
+
});
|
|
30579
|
+
directRefundTxSignature = await this.config.signer.aggregateFrost({
|
|
30580
|
+
message: directRefundTxSighash,
|
|
30581
|
+
statechainSignatures: creationResponseNode.directRefundTxSigningResult?.signatureShares,
|
|
30582
|
+
statechainPublicKeys: creationResponseNode.directRefundTxSigningResult?.publicKeys,
|
|
30583
|
+
verifyingKey: internalNode.verificationKey,
|
|
30584
|
+
statechainCommitments: creationResponseNode.directRefundTxSigningResult?.signingNonceCommitments,
|
|
30585
|
+
selfCommitment: creationNode.directRefundTxSigningCommitment,
|
|
30586
|
+
selfSignature: directRefundUserSignature,
|
|
29394
30587
|
publicKey: internalNode.signingPublicKey
|
|
29395
30588
|
});
|
|
30589
|
+
const directFromCpfpRefundUserSignature = await this.config.signer.signFrost({
|
|
30590
|
+
message: directFromCpfpRefundTxSighash,
|
|
30591
|
+
publicKey: creationNode.directFromCpfpRefundTxSigningJob.signingPublicKey,
|
|
30592
|
+
keyDerivation,
|
|
30593
|
+
selfCommitment: creationNode.directFromCpfpRefundTxSigningCommitment,
|
|
30594
|
+
statechainCommitments: creationResponseNode.directFromCpfpRefundTxSigningResult?.signingNonceCommitments,
|
|
30595
|
+
verifyingKey: internalNode.verificationKey
|
|
30596
|
+
});
|
|
30597
|
+
directFromCpfpRefundTxSignature = await this.config.signer.aggregateFrost(
|
|
30598
|
+
{
|
|
30599
|
+
message: directFromCpfpRefundTxSighash,
|
|
30600
|
+
statechainSignatures: creationResponseNode.directFromCpfpRefundTxSigningResult?.signatureShares,
|
|
30601
|
+
statechainPublicKeys: creationResponseNode.directFromCpfpRefundTxSigningResult?.publicKeys,
|
|
30602
|
+
verifyingKey: internalNode.verificationKey,
|
|
30603
|
+
statechainCommitments: creationResponseNode.directFromCpfpRefundTxSigningResult?.signingNonceCommitments,
|
|
30604
|
+
selfCommitment: creationNode.directFromCpfpRefundTxSigningCommitment,
|
|
30605
|
+
selfSignature: directFromCpfpRefundUserSignature,
|
|
30606
|
+
publicKey: internalNode.signingPublicKey
|
|
30607
|
+
}
|
|
30608
|
+
);
|
|
29396
30609
|
}
|
|
29397
30610
|
return {
|
|
29398
|
-
tx,
|
|
30611
|
+
tx: cpfpNodeTx,
|
|
30612
|
+
// Return CPFP version for children
|
|
29399
30613
|
signature: {
|
|
29400
30614
|
nodeId: creationResponseNode.nodeId,
|
|
29401
|
-
nodeTxSignature,
|
|
29402
|
-
|
|
29403
|
-
|
|
29404
|
-
|
|
29405
|
-
|
|
29406
|
-
directFromCpfpRefundTxSignature: new Uint8Array()
|
|
30615
|
+
nodeTxSignature: cpfpNodeTxSignature,
|
|
30616
|
+
directNodeTxSignature,
|
|
30617
|
+
refundTxSignature: cpfpRefundTxSignature,
|
|
30618
|
+
directRefundTxSignature,
|
|
30619
|
+
directFromCpfpRefundTxSignature
|
|
29407
30620
|
}
|
|
29408
30621
|
};
|
|
29409
30622
|
}
|
|
@@ -29466,8 +30679,45 @@ var SigningService = class {
|
|
|
29466
30679
|
constructor(config) {
|
|
29467
30680
|
this.config = config;
|
|
29468
30681
|
}
|
|
29469
|
-
async
|
|
30682
|
+
async signRefundsInternal(refundTx, sighash, leaf, signingCommitments) {
|
|
29470
30683
|
const leafSigningJobs = [];
|
|
30684
|
+
const signingCommitment = await this.config.signer.getRandomSigningCommitment();
|
|
30685
|
+
if (!signingCommitments) {
|
|
30686
|
+
throw new ValidationError("Invalid signing commitments", {
|
|
30687
|
+
field: "signingNonceCommitments",
|
|
30688
|
+
value: signingCommitments,
|
|
30689
|
+
expected: "Non-null signing commitments"
|
|
30690
|
+
});
|
|
30691
|
+
}
|
|
30692
|
+
const signingResult = await this.config.signer.signFrost({
|
|
30693
|
+
message: sighash,
|
|
30694
|
+
keyDerivation: leaf.keyDerivation,
|
|
30695
|
+
publicKey: await this.config.signer.getPublicKeyFromDerivation(
|
|
30696
|
+
leaf.keyDerivation
|
|
30697
|
+
),
|
|
30698
|
+
selfCommitment: signingCommitment,
|
|
30699
|
+
statechainCommitments: signingCommitments,
|
|
30700
|
+
adaptorPubKey: new Uint8Array(),
|
|
30701
|
+
verifyingKey: leaf.leaf.verifyingPublicKey
|
|
30702
|
+
});
|
|
30703
|
+
leafSigningJobs.push({
|
|
30704
|
+
leafId: leaf.leaf.id,
|
|
30705
|
+
signingPublicKey: await this.config.signer.getPublicKeyFromDerivation(
|
|
30706
|
+
leaf.keyDerivation
|
|
30707
|
+
),
|
|
30708
|
+
rawTx: refundTx.toBytes(),
|
|
30709
|
+
signingNonceCommitment: signingCommitment.commitment,
|
|
30710
|
+
userSignature: signingResult,
|
|
30711
|
+
signingCommitments: {
|
|
30712
|
+
signingCommitments
|
|
30713
|
+
}
|
|
30714
|
+
});
|
|
30715
|
+
return leafSigningJobs;
|
|
30716
|
+
}
|
|
30717
|
+
async signRefunds(leaves, receiverIdentityPubkey, cpfpSigningCommitments, directSigningCommitments, directFromCpfpSigningCommitments) {
|
|
30718
|
+
const cpfpLeafSigningJobs = [];
|
|
30719
|
+
const directLeafSigningJobs = [];
|
|
30720
|
+
const directFromCpfpLeafSigningJobs = [];
|
|
29471
30721
|
for (let i = 0; i < leaves.length; i++) {
|
|
29472
30722
|
const leaf = leaves[i];
|
|
29473
30723
|
if (!leaf?.leaf) {
|
|
@@ -29478,14 +30728,20 @@ var SigningService = class {
|
|
|
29478
30728
|
});
|
|
29479
30729
|
}
|
|
29480
30730
|
const nodeTx = getTxFromRawTxBytes(leaf.leaf.nodeTx);
|
|
29481
|
-
const
|
|
30731
|
+
const cpfpNodeOutPoint = {
|
|
29482
30732
|
txid: (0, import_utils21.hexToBytes)(getTxId(nodeTx)),
|
|
29483
30733
|
index: 0
|
|
29484
30734
|
};
|
|
29485
30735
|
const currRefundTx = getTxFromRawTxBytes(leaf.leaf.refundTx);
|
|
29486
|
-
const
|
|
29487
|
-
|
|
29488
|
-
|
|
30736
|
+
const sequence = currRefundTx.getInput(0).sequence;
|
|
30737
|
+
if (!sequence) {
|
|
30738
|
+
throw new ValidationError("Invalid refund transaction", {
|
|
30739
|
+
field: "sequence",
|
|
30740
|
+
value: currRefundTx.getInput(0),
|
|
30741
|
+
expected: "Non-null sequence"
|
|
30742
|
+
});
|
|
30743
|
+
}
|
|
30744
|
+
const { nextSequence, nextDirectSequence } = getNextTransactionSequence(sequence);
|
|
29489
30745
|
const amountSats = currRefundTx.getOutput(0).amount;
|
|
29490
30746
|
if (amountSats === void 0) {
|
|
29491
30747
|
throw new ValidationError("Invalid refund transaction", {
|
|
@@ -29494,48 +30750,90 @@ var SigningService = class {
|
|
|
29494
30750
|
expected: "Non-null amount"
|
|
29495
30751
|
});
|
|
29496
30752
|
}
|
|
29497
|
-
|
|
29498
|
-
|
|
29499
|
-
|
|
30753
|
+
let directNodeTx;
|
|
30754
|
+
let directNodeOutPoint;
|
|
30755
|
+
if (leaf.leaf.directTx.length > 0) {
|
|
30756
|
+
directNodeTx = getTxFromRawTxBytes(leaf.leaf.directTx);
|
|
30757
|
+
directNodeOutPoint = {
|
|
30758
|
+
txid: (0, import_utils21.hexToBytes)(getTxId(directNodeTx)),
|
|
30759
|
+
index: 0
|
|
30760
|
+
};
|
|
30761
|
+
}
|
|
30762
|
+
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } = createRefundTxs({
|
|
30763
|
+
sequence: nextSequence,
|
|
30764
|
+
directSequence: nextDirectSequence,
|
|
30765
|
+
input: cpfpNodeOutPoint,
|
|
30766
|
+
directInput: directNodeOutPoint,
|
|
29500
30767
|
amountSats,
|
|
29501
|
-
receiverIdentityPubkey,
|
|
29502
|
-
this.config.getNetwork()
|
|
30768
|
+
receivingPubkey: receiverIdentityPubkey,
|
|
30769
|
+
network: this.config.getNetwork()
|
|
30770
|
+
});
|
|
30771
|
+
const refundSighash = getSigHashFromTx(
|
|
30772
|
+
cpfpRefundTx,
|
|
30773
|
+
0,
|
|
30774
|
+
nodeTx.getOutput(0)
|
|
29503
30775
|
);
|
|
29504
|
-
const
|
|
29505
|
-
|
|
29506
|
-
|
|
29507
|
-
|
|
29508
|
-
|
|
29509
|
-
|
|
29510
|
-
|
|
29511
|
-
|
|
29512
|
-
|
|
30776
|
+
const signingJobs = await this.signRefundsInternal(
|
|
30777
|
+
cpfpRefundTx,
|
|
30778
|
+
refundSighash,
|
|
30779
|
+
leaf,
|
|
30780
|
+
cpfpSigningCommitments[i]?.signingNonceCommitments
|
|
30781
|
+
);
|
|
30782
|
+
cpfpLeafSigningJobs.push(...signingJobs);
|
|
30783
|
+
if (directRefundTx) {
|
|
30784
|
+
if (!directNodeTx) {
|
|
30785
|
+
throw new ValidationError(
|
|
30786
|
+
"Direct node transaction undefined while direct refund transaction is defined",
|
|
30787
|
+
{
|
|
30788
|
+
field: "directNodeTx",
|
|
30789
|
+
value: directNodeTx,
|
|
30790
|
+
expected: "Non-null direct node transaction"
|
|
30791
|
+
}
|
|
30792
|
+
);
|
|
30793
|
+
}
|
|
30794
|
+
const refundSighash2 = getSigHashFromTx(
|
|
30795
|
+
directRefundTx,
|
|
30796
|
+
0,
|
|
30797
|
+
directNodeTx.getOutput(0)
|
|
30798
|
+
);
|
|
30799
|
+
const signingJobs2 = await this.signRefundsInternal(
|
|
30800
|
+
directRefundTx,
|
|
30801
|
+
refundSighash2,
|
|
30802
|
+
leaf,
|
|
30803
|
+
directSigningCommitments[i]?.signingNonceCommitments
|
|
30804
|
+
);
|
|
30805
|
+
directLeafSigningJobs.push(...signingJobs2);
|
|
29513
30806
|
}
|
|
29514
|
-
|
|
29515
|
-
|
|
29516
|
-
|
|
29517
|
-
|
|
29518
|
-
|
|
29519
|
-
|
|
29520
|
-
|
|
29521
|
-
|
|
29522
|
-
|
|
29523
|
-
|
|
29524
|
-
});
|
|
29525
|
-
leafSigningJobs.push({
|
|
29526
|
-
leafId: leaf.leaf.id,
|
|
29527
|
-
signingPublicKey: await this.config.signer.getPublicKeyFromDerivation(
|
|
29528
|
-
leaf.keyDerivation
|
|
29529
|
-
),
|
|
29530
|
-
rawTx: refundTx.toBytes(),
|
|
29531
|
-
signingNonceCommitment: signingCommitment.commitment,
|
|
29532
|
-
userSignature: signingResult,
|
|
29533
|
-
signingCommitments: {
|
|
29534
|
-
signingCommitments: signingNonceCommitments
|
|
30807
|
+
if (directFromCpfpRefundTx) {
|
|
30808
|
+
if (!directNodeTx) {
|
|
30809
|
+
throw new ValidationError(
|
|
30810
|
+
"Direct node transaction undefined while direct from CPFP refund transaction is defined",
|
|
30811
|
+
{
|
|
30812
|
+
field: "directNodeTx",
|
|
30813
|
+
value: directNodeTx,
|
|
30814
|
+
expected: "Non-null direct node transaction"
|
|
30815
|
+
}
|
|
30816
|
+
);
|
|
29535
30817
|
}
|
|
29536
|
-
|
|
30818
|
+
const refundSighash2 = getSigHashFromTx(
|
|
30819
|
+
directFromCpfpRefundTx,
|
|
30820
|
+
0,
|
|
30821
|
+
nodeTx.getOutput(0)
|
|
30822
|
+
);
|
|
30823
|
+
const signingJobs2 = await this.signRefundsInternal(
|
|
30824
|
+
directFromCpfpRefundTx,
|
|
30825
|
+
refundSighash2,
|
|
30826
|
+
leaf,
|
|
30827
|
+
directFromCpfpSigningCommitments[i]?.signingNonceCommitments
|
|
30828
|
+
);
|
|
30829
|
+
directFromCpfpLeafSigningJobs.push(...signingJobs2);
|
|
30830
|
+
}
|
|
29537
30831
|
}
|
|
29538
|
-
return
|
|
30832
|
+
return {
|
|
30833
|
+
cpfpLeafSigningJobs,
|
|
30834
|
+
directLeafSigningJobs,
|
|
30835
|
+
directFromCpfpLeafSigningJobs
|
|
30836
|
+
};
|
|
29539
30837
|
}
|
|
29540
30838
|
};
|
|
29541
30839
|
|
|
@@ -29543,7 +30841,7 @@ var SigningService = class {
|
|
|
29543
30841
|
init_buffer();
|
|
29544
30842
|
var import_utils22 = require("@noble/curves/abstract/utils");
|
|
29545
30843
|
var import_secp256k114 = require("@noble/curves/secp256k1");
|
|
29546
|
-
var
|
|
30844
|
+
var btc5 = __toESM(require("@scure/btc-signer"), 1);
|
|
29547
30845
|
var import_btc_signer6 = require("@scure/btc-signer");
|
|
29548
30846
|
var import_utils23 = require("@scure/btc-signer/utils");
|
|
29549
30847
|
var STATIC_FAUCET_KEY = (0, import_utils22.hexToBytes)(
|
|
@@ -29689,7 +30987,7 @@ var BitcoinFaucet = class _BitcoinFaucet {
|
|
|
29689
30987
|
}
|
|
29690
30988
|
async sendFaucetCoinToP2WPKHAddress(pubKey) {
|
|
29691
30989
|
const sendToPubKeyTx = new import_btc_signer6.Transaction();
|
|
29692
|
-
const p2wpkhAddress =
|
|
30990
|
+
const p2wpkhAddress = btc5.p2wpkh(pubKey, getNetwork(4 /* LOCAL */)).address;
|
|
29693
30991
|
if (!p2wpkhAddress) {
|
|
29694
30992
|
throw new Error("Invalid P2WPKH address");
|
|
29695
30993
|
}
|
|
@@ -29745,12 +31043,13 @@ var BitcoinFaucet = class _BitcoinFaucet {
|
|
|
29745
31043
|
}
|
|
29746
31044
|
async call(method, params) {
|
|
29747
31045
|
try {
|
|
29748
|
-
const
|
|
31046
|
+
const { fetch: fetch2, Headers: Headers2 } = getFetch();
|
|
31047
|
+
const response = await fetch2(this.url, {
|
|
29749
31048
|
method: "POST",
|
|
29750
|
-
headers: {
|
|
31049
|
+
headers: new Headers2({
|
|
29751
31050
|
"Content-Type": "application/json",
|
|
29752
31051
|
Authorization: "Basic " + btoa(`${this.username}:${this.password}`)
|
|
29753
|
-
},
|
|
31052
|
+
}),
|
|
29754
31053
|
body: JSON.stringify({
|
|
29755
31054
|
jsonrpc: "1.0",
|
|
29756
31055
|
id: "spark-js",
|
|
@@ -30080,31 +31379,37 @@ var SparkWallet = class _SparkWallet extends import_eventemitter3.EventEmitter {
|
|
|
30080
31379
|
}
|
|
30081
31380
|
}
|
|
30082
31381
|
async getLeaves(isBalanceCheck = false) {
|
|
30083
|
-
const
|
|
30084
|
-
|
|
30085
|
-
|
|
30086
|
-
|
|
30087
|
-
|
|
30088
|
-
|
|
30089
|
-
|
|
30090
|
-
}
|
|
31382
|
+
const operatorToLeaves = /* @__PURE__ */ new Map();
|
|
31383
|
+
const ownerIdentityPubkey = await this.config.signer.getIdentityPublicKey();
|
|
31384
|
+
let signingOperators = Object.entries(this.config.getSigningOperators());
|
|
31385
|
+
if (isBalanceCheck) {
|
|
31386
|
+
signingOperators = signingOperators.filter(
|
|
31387
|
+
([id, _]) => id === this.config.getCoordinatorIdentifier()
|
|
31388
|
+
);
|
|
31389
|
+
}
|
|
31390
|
+
await Promise.all(
|
|
31391
|
+
signingOperators.map(async ([id, operator]) => {
|
|
31392
|
+
const leaves2 = await this.queryNodes(
|
|
31393
|
+
{
|
|
31394
|
+
source: {
|
|
31395
|
+
$case: "ownerIdentityPubkey",
|
|
31396
|
+
ownerIdentityPubkey
|
|
31397
|
+
},
|
|
31398
|
+
includeParents: false,
|
|
31399
|
+
network: NetworkToProto[this.config.getNetwork()]
|
|
31400
|
+
},
|
|
31401
|
+
operator.address
|
|
31402
|
+
);
|
|
31403
|
+
operatorToLeaves.set(id, leaves2);
|
|
31404
|
+
})
|
|
31405
|
+
);
|
|
31406
|
+
const leaves = operatorToLeaves.get(
|
|
31407
|
+
this.config.getCoordinatorIdentifier()
|
|
31408
|
+
);
|
|
30091
31409
|
const leavesToIgnore = /* @__PURE__ */ new Set();
|
|
30092
31410
|
if (!isBalanceCheck) {
|
|
30093
|
-
for (const [id,
|
|
30094
|
-
this.config.getSigningOperators()
|
|
30095
|
-
)) {
|
|
31411
|
+
for (const [id, operatorLeaves] of operatorToLeaves) {
|
|
30096
31412
|
if (id !== this.config.getCoordinatorIdentifier()) {
|
|
30097
|
-
const operatorLeaves = await this.queryNodes(
|
|
30098
|
-
{
|
|
30099
|
-
source: {
|
|
30100
|
-
$case: "ownerIdentityPubkey",
|
|
30101
|
-
ownerIdentityPubkey: await this.config.signer.getIdentityPublicKey()
|
|
30102
|
-
},
|
|
30103
|
-
includeParents: false,
|
|
30104
|
-
network: NetworkToProto[this.config.getNetwork()]
|
|
30105
|
-
},
|
|
30106
|
-
operator.address
|
|
30107
|
-
);
|
|
30108
31413
|
for (const [nodeId, leaf] of Object.entries(leaves.nodes)) {
|
|
30109
31414
|
const operatorLeaf = operatorLeaves.nodes[nodeId];
|
|
30110
31415
|
if (!operatorLeaf) {
|
|
@@ -30545,21 +31850,68 @@ var SparkWallet = class _SparkWallet extends import_eventemitter3.EventEmitter {
|
|
|
30545
31850
|
}
|
|
30546
31851
|
}))
|
|
30547
31852
|
);
|
|
30548
|
-
const {
|
|
31853
|
+
const {
|
|
31854
|
+
transfer,
|
|
31855
|
+
signatureMap,
|
|
31856
|
+
directSignatureMap,
|
|
31857
|
+
directFromCpfpSignatureMap
|
|
31858
|
+
} = await this.transferService.startSwapSignRefund(
|
|
30549
31859
|
leafKeyTweaks,
|
|
30550
31860
|
(0, import_utils24.hexToBytes)(this.config.getSspIdentityPublicKey()),
|
|
30551
31861
|
new Date(Date.now() + 2 * 60 * 1e3)
|
|
30552
31862
|
);
|
|
30553
31863
|
try {
|
|
30554
31864
|
if (!transfer.leaves[0]?.leaf) {
|
|
31865
|
+
console.error("[processSwapBatch] First leaf is missing");
|
|
30555
31866
|
throw new Error("Failed to get leaf");
|
|
30556
31867
|
}
|
|
30557
|
-
const
|
|
30558
|
-
if (!
|
|
30559
|
-
|
|
31868
|
+
const cpfpRefundSignature = signatureMap.get(transfer.leaves[0].leaf.id);
|
|
31869
|
+
if (!cpfpRefundSignature) {
|
|
31870
|
+
console.error(
|
|
31871
|
+
"[processSwapBatch] Missing CPFP refund signature for first leaf"
|
|
31872
|
+
);
|
|
31873
|
+
throw new Error("Failed to get CPFP refund signature");
|
|
31874
|
+
}
|
|
31875
|
+
const directRefundSignature = directSignatureMap.get(
|
|
31876
|
+
transfer.leaves[0].leaf.id
|
|
31877
|
+
);
|
|
31878
|
+
if (!directRefundSignature) {
|
|
31879
|
+
console.error(
|
|
31880
|
+
"[processSwapBatch] Missing direct refund signature for first leaf"
|
|
31881
|
+
);
|
|
31882
|
+
throw new Error("Failed to get direct refund signature");
|
|
31883
|
+
}
|
|
31884
|
+
const directFromCpfpRefundSignature = directFromCpfpSignatureMap.get(
|
|
31885
|
+
transfer.leaves[0].leaf.id
|
|
31886
|
+
);
|
|
31887
|
+
if (!directFromCpfpRefundSignature) {
|
|
31888
|
+
console.error(
|
|
31889
|
+
"[processSwapBatch] Missing direct from CPFP refund signature for first leaf"
|
|
31890
|
+
);
|
|
31891
|
+
throw new Error("Failed to get direct from CPFP refund signature");
|
|
31892
|
+
}
|
|
31893
|
+
const {
|
|
31894
|
+
adaptorPrivateKey: cpfpAdaptorPrivateKey,
|
|
31895
|
+
adaptorSignature: cpfpAdaptorSignature
|
|
31896
|
+
} = generateAdaptorFromSignature(cpfpRefundSignature);
|
|
31897
|
+
let directAdaptorPrivateKey = new Uint8Array();
|
|
31898
|
+
let directAdaptorSignature = new Uint8Array();
|
|
31899
|
+
let directFromCpfpAdaptorPrivateKey = new Uint8Array();
|
|
31900
|
+
let directFromCpfpAdaptorSignature = new Uint8Array();
|
|
31901
|
+
if (directRefundSignature.length > 0) {
|
|
31902
|
+
const { adaptorPrivateKey, adaptorSignature } = generateAdaptorFromSignature(directRefundSignature);
|
|
31903
|
+
directAdaptorPrivateKey = adaptorPrivateKey;
|
|
31904
|
+
directAdaptorSignature = adaptorSignature;
|
|
31905
|
+
}
|
|
31906
|
+
if (directFromCpfpRefundSignature.length > 0) {
|
|
31907
|
+
const { adaptorPrivateKey, adaptorSignature } = generateAdaptorFromSignature(directFromCpfpRefundSignature);
|
|
31908
|
+
directFromCpfpAdaptorPrivateKey = adaptorPrivateKey;
|
|
31909
|
+
directFromCpfpAdaptorSignature = adaptorSignature;
|
|
30560
31910
|
}
|
|
30561
|
-
const { adaptorPrivateKey, adaptorSignature } = generateAdaptorFromSignature(refundSignature);
|
|
30562
31911
|
if (!transfer.leaves[0].leaf) {
|
|
31912
|
+
console.error(
|
|
31913
|
+
"[processSwapBatch] First leaf missing when preparing user leaves"
|
|
31914
|
+
);
|
|
30563
31915
|
throw new Error("Failed to get leaf");
|
|
30564
31916
|
}
|
|
30565
31917
|
const userLeaves = [];
|
|
@@ -30568,37 +31920,113 @@ var SparkWallet = class _SparkWallet extends import_eventemitter3.EventEmitter {
|
|
|
30568
31920
|
raw_unsigned_refund_transaction: (0, import_utils24.bytesToHex)(
|
|
30569
31921
|
transfer.leaves[0].intermediateRefundTx
|
|
30570
31922
|
),
|
|
30571
|
-
|
|
31923
|
+
direct_raw_unsigned_refund_transaction: (0, import_utils24.bytesToHex)(
|
|
31924
|
+
transfer.leaves[0].intermediateDirectRefundTx
|
|
31925
|
+
),
|
|
31926
|
+
direct_from_cpfp_raw_unsigned_refund_transaction: (0, import_utils24.bytesToHex)(
|
|
31927
|
+
transfer.leaves[0].intermediateDirectFromCpfpRefundTx
|
|
31928
|
+
),
|
|
31929
|
+
adaptor_added_signature: (0, import_utils24.bytesToHex)(cpfpAdaptorSignature),
|
|
31930
|
+
direct_adaptor_added_signature: (0, import_utils24.bytesToHex)(directAdaptorSignature),
|
|
31931
|
+
direct_from_cpfp_adaptor_added_signature: (0, import_utils24.bytesToHex)(
|
|
31932
|
+
directFromCpfpAdaptorSignature
|
|
31933
|
+
)
|
|
30572
31934
|
});
|
|
30573
31935
|
for (let i = 1; i < transfer.leaves.length; i++) {
|
|
30574
31936
|
const leaf = transfer.leaves[i];
|
|
30575
31937
|
if (!leaf?.leaf) {
|
|
31938
|
+
console.error(`[processSwapBatch] Leaf ${i + 1} is missing`);
|
|
30576
31939
|
throw new Error("Failed to get leaf");
|
|
30577
31940
|
}
|
|
30578
|
-
const
|
|
30579
|
-
if (!
|
|
30580
|
-
|
|
31941
|
+
const cpfpRefundSignature2 = signatureMap.get(leaf.leaf.id);
|
|
31942
|
+
if (!cpfpRefundSignature2) {
|
|
31943
|
+
console.error(
|
|
31944
|
+
`[processSwapBatch] Missing CPFP refund signature for leaf ${i + 1}`
|
|
31945
|
+
);
|
|
31946
|
+
throw new Error("Failed to get CPFP refund signature");
|
|
31947
|
+
}
|
|
31948
|
+
const directRefundSignature2 = directSignatureMap.get(leaf.leaf.id);
|
|
31949
|
+
if (!directRefundSignature2) {
|
|
31950
|
+
console.error(
|
|
31951
|
+
`[processSwapBatch] Missing direct refund signature for leaf ${i + 1}`
|
|
31952
|
+
);
|
|
31953
|
+
throw new Error("Failed to get direct refund signature");
|
|
31954
|
+
}
|
|
31955
|
+
const directFromCpfpRefundSignature2 = directFromCpfpSignatureMap.get(
|
|
31956
|
+
leaf.leaf.id
|
|
31957
|
+
);
|
|
31958
|
+
if (!directFromCpfpRefundSignature2) {
|
|
31959
|
+
console.error(
|
|
31960
|
+
`[processSwapBatch] Missing direct from CPFP refund signature for leaf ${i + 1}`
|
|
31961
|
+
);
|
|
31962
|
+
throw new Error("Failed to get direct from CPFP refund signature");
|
|
30581
31963
|
}
|
|
30582
|
-
const
|
|
30583
|
-
|
|
30584
|
-
|
|
31964
|
+
const cpfpSignature = generateSignatureFromExistingAdaptor(
|
|
31965
|
+
cpfpRefundSignature2,
|
|
31966
|
+
cpfpAdaptorPrivateKey
|
|
30585
31967
|
);
|
|
31968
|
+
let directSignature = new Uint8Array();
|
|
31969
|
+
if (directRefundSignature2.length > 0) {
|
|
31970
|
+
directSignature = generateSignatureFromExistingAdaptor(
|
|
31971
|
+
directRefundSignature2,
|
|
31972
|
+
directAdaptorPrivateKey
|
|
31973
|
+
);
|
|
31974
|
+
}
|
|
31975
|
+
let directFromCpfpSignature = new Uint8Array();
|
|
31976
|
+
if (directFromCpfpRefundSignature2.length > 0) {
|
|
31977
|
+
directFromCpfpSignature = generateSignatureFromExistingAdaptor(
|
|
31978
|
+
directFromCpfpRefundSignature2,
|
|
31979
|
+
directFromCpfpAdaptorPrivateKey
|
|
31980
|
+
);
|
|
31981
|
+
}
|
|
30586
31982
|
userLeaves.push({
|
|
30587
31983
|
leaf_id: leaf.leaf.id,
|
|
30588
31984
|
raw_unsigned_refund_transaction: (0, import_utils24.bytesToHex)(
|
|
30589
31985
|
leaf.intermediateRefundTx
|
|
30590
31986
|
),
|
|
30591
|
-
|
|
31987
|
+
direct_raw_unsigned_refund_transaction: (0, import_utils24.bytesToHex)(
|
|
31988
|
+
leaf.intermediateDirectRefundTx
|
|
31989
|
+
),
|
|
31990
|
+
direct_from_cpfp_raw_unsigned_refund_transaction: (0, import_utils24.bytesToHex)(
|
|
31991
|
+
leaf.intermediateDirectFromCpfpRefundTx
|
|
31992
|
+
),
|
|
31993
|
+
adaptor_added_signature: (0, import_utils24.bytesToHex)(cpfpSignature),
|
|
31994
|
+
direct_adaptor_added_signature: (0, import_utils24.bytesToHex)(directSignature),
|
|
31995
|
+
direct_from_cpfp_adaptor_added_signature: (0, import_utils24.bytesToHex)(
|
|
31996
|
+
directFromCpfpSignature
|
|
31997
|
+
)
|
|
30592
31998
|
});
|
|
30593
31999
|
}
|
|
30594
32000
|
const sspClient = this.getSspClient();
|
|
30595
|
-
const
|
|
30596
|
-
import_secp256k115.secp256k1.getPublicKey(
|
|
32001
|
+
const cpfpAdaptorPubkey = (0, import_utils24.bytesToHex)(
|
|
32002
|
+
import_secp256k115.secp256k1.getPublicKey(cpfpAdaptorPrivateKey)
|
|
30597
32003
|
);
|
|
32004
|
+
if (!cpfpAdaptorPubkey) {
|
|
32005
|
+
throw new Error("Failed to generate CPFP adaptor pubkey");
|
|
32006
|
+
}
|
|
32007
|
+
let directAdaptorPubkey;
|
|
32008
|
+
if (directAdaptorPrivateKey.length > 0) {
|
|
32009
|
+
directAdaptorPubkey = (0, import_utils24.bytesToHex)(
|
|
32010
|
+
import_secp256k115.secp256k1.getPublicKey(directAdaptorPrivateKey)
|
|
32011
|
+
);
|
|
32012
|
+
}
|
|
32013
|
+
let directFromCpfpAdaptorPubkey;
|
|
32014
|
+
if (directFromCpfpAdaptorPrivateKey.length > 0) {
|
|
32015
|
+
directFromCpfpAdaptorPubkey = (0, import_utils24.bytesToHex)(
|
|
32016
|
+
import_secp256k115.secp256k1.getPublicKey(directFromCpfpAdaptorPrivateKey)
|
|
32017
|
+
);
|
|
32018
|
+
}
|
|
30598
32019
|
let request = null;
|
|
32020
|
+
const targetAmountSats = targetAmounts?.reduce((acc, amount) => acc + amount, 0) || leavesBatch.reduce((acc, leaf) => acc + leaf.value, 0);
|
|
32021
|
+
const totalAmountSats = leavesBatch.reduce(
|
|
32022
|
+
(acc, leaf) => acc + leaf.value,
|
|
32023
|
+
0
|
|
32024
|
+
);
|
|
30599
32025
|
request = await sspClient.requestLeaveSwap({
|
|
30600
32026
|
userLeaves,
|
|
30601
|
-
adaptorPubkey,
|
|
32027
|
+
adaptorPubkey: cpfpAdaptorPubkey,
|
|
32028
|
+
directAdaptorPubkey,
|
|
32029
|
+
directFromCpfpAdaptorPubkey,
|
|
30602
32030
|
targetAmountSats: targetAmounts?.reduce((acc, amount) => acc + amount, 0) || leavesBatch.reduce((acc, leaf) => acc + leaf.value, 0),
|
|
30603
32031
|
totalAmountSats: leavesBatch.reduce((acc, leaf) => acc + leaf.value, 0),
|
|
30604
32032
|
targetAmountSatsList: targetAmounts,
|
|
@@ -30607,6 +32035,7 @@ var SparkWallet = class _SparkWallet extends import_eventemitter3.EventEmitter {
|
|
|
30607
32035
|
idempotencyKey: (0, import_uuidv75.uuidv7)()
|
|
30608
32036
|
});
|
|
30609
32037
|
if (!request) {
|
|
32038
|
+
console.error("[processSwapBatch] Leave swap request returned null");
|
|
30610
32039
|
throw new Error("Failed to request leaves swap. No response returned.");
|
|
30611
32040
|
}
|
|
30612
32041
|
const nodes = await this.queryNodes({
|
|
@@ -30620,50 +32049,140 @@ var SparkWallet = class _SparkWallet extends import_eventemitter3.EventEmitter {
|
|
|
30620
32049
|
network: NetworkToProto[this.config.getNetwork()]
|
|
30621
32050
|
});
|
|
30622
32051
|
if (Object.values(nodes.nodes).length !== request.swapLeaves.length) {
|
|
32052
|
+
console.error("[processSwapBatch] Node count mismatch:", {
|
|
32053
|
+
actual: Object.values(nodes.nodes).length,
|
|
32054
|
+
expected: request.swapLeaves.length
|
|
32055
|
+
});
|
|
30623
32056
|
throw new Error("Expected same number of nodes as swapLeaves");
|
|
30624
32057
|
}
|
|
30625
32058
|
for (const [nodeId, node] of Object.entries(nodes.nodes)) {
|
|
30626
32059
|
if (!node.nodeTx) {
|
|
32060
|
+
console.error(`[processSwapBatch] Node tx missing for ${nodeId}`);
|
|
30627
32061
|
throw new Error(`Node tx not found for leaf ${nodeId}`);
|
|
30628
32062
|
}
|
|
30629
32063
|
if (!node.verifyingPublicKey) {
|
|
32064
|
+
console.error(
|
|
32065
|
+
`[processSwapBatch] Verifying public key missing for ${nodeId}`
|
|
32066
|
+
);
|
|
30630
32067
|
throw new Error(`Node public key not found for leaf ${nodeId}`);
|
|
30631
32068
|
}
|
|
30632
32069
|
const leaf = request.swapLeaves.find((leaf2) => leaf2.leafId === nodeId);
|
|
30633
32070
|
if (!leaf) {
|
|
32071
|
+
console.error(`[processSwapBatch] Leaf not found for node ${nodeId}`);
|
|
30634
32072
|
throw new Error(`Leaf not found for node ${nodeId}`);
|
|
30635
32073
|
}
|
|
30636
|
-
const
|
|
30637
|
-
const
|
|
30638
|
-
const
|
|
30639
|
-
const
|
|
32074
|
+
const cpfpNodeTx = getTxFromRawTxBytes(node.nodeTx);
|
|
32075
|
+
const cpfpRefundTxBytes = (0, import_utils24.hexToBytes)(leaf.rawUnsignedRefundTransaction);
|
|
32076
|
+
const cpfpRefundTx = getTxFromRawTxBytes(cpfpRefundTxBytes);
|
|
32077
|
+
const cpfpSighash = getSigHashFromTx(
|
|
32078
|
+
cpfpRefundTx,
|
|
32079
|
+
0,
|
|
32080
|
+
cpfpNodeTx.getOutput(0)
|
|
32081
|
+
);
|
|
30640
32082
|
const nodePublicKey = node.verifyingPublicKey;
|
|
30641
32083
|
const taprootKey = computeTaprootKeyNoScript(nodePublicKey.slice(1));
|
|
30642
|
-
const
|
|
32084
|
+
const cpfpAdaptorSignatureBytes = (0, import_utils24.hexToBytes)(
|
|
32085
|
+
leaf.adaptorSignedSignature
|
|
32086
|
+
);
|
|
32087
|
+
applyAdaptorToSignature(
|
|
32088
|
+
taprootKey.slice(1),
|
|
32089
|
+
cpfpSighash,
|
|
32090
|
+
cpfpAdaptorSignatureBytes,
|
|
32091
|
+
cpfpAdaptorPrivateKey
|
|
32092
|
+
);
|
|
32093
|
+
if (!leaf.directRawUnsignedRefundTransaction) {
|
|
32094
|
+
throw new Error(
|
|
32095
|
+
`Direct raw unsigned refund transaction missing for node ${nodeId}`
|
|
32096
|
+
);
|
|
32097
|
+
}
|
|
32098
|
+
if (!leaf.directAdaptorSignedSignature) {
|
|
32099
|
+
throw new Error(
|
|
32100
|
+
`Direct adaptor signed signature missing for node ${nodeId}`
|
|
32101
|
+
);
|
|
32102
|
+
}
|
|
32103
|
+
const directNodeTx = getTxFromRawTxBytes(node.directTx);
|
|
32104
|
+
const directRefundTxBytes = (0, import_utils24.hexToBytes)(
|
|
32105
|
+
leaf.directRawUnsignedRefundTransaction
|
|
32106
|
+
);
|
|
32107
|
+
const directRefundTx = getTxFromRawTxBytes(directRefundTxBytes);
|
|
32108
|
+
const directSighash = getSigHashFromTx(
|
|
32109
|
+
directRefundTx,
|
|
32110
|
+
0,
|
|
32111
|
+
directNodeTx.getOutput(0)
|
|
32112
|
+
);
|
|
32113
|
+
if (!leaf.directFromCpfpAdaptorSignedSignature) {
|
|
32114
|
+
throw new Error(
|
|
32115
|
+
`Direct adaptor signed signature missing for node ${nodeId}`
|
|
32116
|
+
);
|
|
32117
|
+
}
|
|
32118
|
+
const directAdaptorSignatureBytes = (0, import_utils24.hexToBytes)(
|
|
32119
|
+
leaf.directAdaptorSignedSignature
|
|
32120
|
+
);
|
|
32121
|
+
applyAdaptorToSignature(
|
|
32122
|
+
taprootKey.slice(1),
|
|
32123
|
+
directSighash,
|
|
32124
|
+
directAdaptorSignatureBytes,
|
|
32125
|
+
directAdaptorPrivateKey
|
|
32126
|
+
);
|
|
32127
|
+
if (!leaf.directRawUnsignedRefundTransaction) {
|
|
32128
|
+
throw new Error(
|
|
32129
|
+
`Direct raw unsigned refund transaction missing for node ${nodeId}`
|
|
32130
|
+
);
|
|
32131
|
+
}
|
|
32132
|
+
if (!leaf.directFromCpfpRawUnsignedRefundTransaction) {
|
|
32133
|
+
throw new Error(
|
|
32134
|
+
`Direct raw unsigned refund transaction missing for node ${nodeId}`
|
|
32135
|
+
);
|
|
32136
|
+
}
|
|
32137
|
+
const directFromCpfpRefundTxBytes = (0, import_utils24.hexToBytes)(
|
|
32138
|
+
leaf.directFromCpfpRawUnsignedRefundTransaction
|
|
32139
|
+
);
|
|
32140
|
+
const directFromCpfpRefundTx = getTxFromRawTxBytes(
|
|
32141
|
+
directFromCpfpRefundTxBytes
|
|
32142
|
+
);
|
|
32143
|
+
const directFromCpfpSighash = getSigHashFromTx(
|
|
32144
|
+
directFromCpfpRefundTx,
|
|
32145
|
+
0,
|
|
32146
|
+
cpfpNodeTx.getOutput(0)
|
|
32147
|
+
);
|
|
32148
|
+
const directFromCpfpAdaptorSignatureBytes = (0, import_utils24.hexToBytes)(
|
|
32149
|
+
leaf.directFromCpfpAdaptorSignedSignature
|
|
32150
|
+
);
|
|
30643
32151
|
applyAdaptorToSignature(
|
|
30644
32152
|
taprootKey.slice(1),
|
|
30645
|
-
|
|
30646
|
-
|
|
30647
|
-
|
|
32153
|
+
directFromCpfpSighash,
|
|
32154
|
+
directFromCpfpAdaptorSignatureBytes,
|
|
32155
|
+
directFromCpfpAdaptorPrivateKey
|
|
30648
32156
|
);
|
|
30649
32157
|
}
|
|
30650
32158
|
await this.transferService.deliverTransferPackage(
|
|
30651
32159
|
transfer,
|
|
30652
32160
|
leafKeyTweaks,
|
|
30653
|
-
signatureMap
|
|
32161
|
+
signatureMap,
|
|
32162
|
+
directSignatureMap,
|
|
32163
|
+
directFromCpfpSignatureMap
|
|
30654
32164
|
);
|
|
30655
32165
|
const completeResponse = await sspClient.completeLeaveSwap({
|
|
30656
|
-
adaptorSecretKey: (0, import_utils24.bytesToHex)(
|
|
32166
|
+
adaptorSecretKey: (0, import_utils24.bytesToHex)(cpfpAdaptorPrivateKey),
|
|
32167
|
+
directAdaptorSecretKey: (0, import_utils24.bytesToHex)(directAdaptorPrivateKey),
|
|
32168
|
+
directFromCpfpAdaptorSecretKey: (0, import_utils24.bytesToHex)(
|
|
32169
|
+
directFromCpfpAdaptorPrivateKey
|
|
32170
|
+
),
|
|
30657
32171
|
userOutboundTransferExternalId: transfer.id,
|
|
30658
32172
|
leavesSwapRequestId: request.id
|
|
30659
32173
|
});
|
|
30660
32174
|
if (!completeResponse || !completeResponse.inboundTransfer?.sparkId) {
|
|
32175
|
+
console.error(
|
|
32176
|
+
"[processSwapBatch] Invalid complete response:",
|
|
32177
|
+
completeResponse
|
|
32178
|
+
);
|
|
30661
32179
|
throw new Error("Failed to complete leaves swap");
|
|
30662
32180
|
}
|
|
30663
32181
|
const incomingTransfer = await this.transferService.queryTransfer(
|
|
30664
32182
|
completeResponse.inboundTransfer.sparkId
|
|
30665
32183
|
);
|
|
30666
32184
|
if (!incomingTransfer) {
|
|
32185
|
+
console.error("[processSwapBatch] No incoming transfer found");
|
|
30667
32186
|
throw new Error("Failed to get incoming transfer");
|
|
30668
32187
|
}
|
|
30669
32188
|
return await this.claimTransfer({
|
|
@@ -30673,6 +32192,11 @@ var SparkWallet = class _SparkWallet extends import_eventemitter3.EventEmitter {
|
|
|
30673
32192
|
optimize: false
|
|
30674
32193
|
});
|
|
30675
32194
|
} catch (e) {
|
|
32195
|
+
console.error("[processSwapBatch] Error details:", {
|
|
32196
|
+
error: e,
|
|
32197
|
+
message: e.message,
|
|
32198
|
+
stack: e.stack
|
|
32199
|
+
});
|
|
30676
32200
|
await this.cancelAllSenderInitiatedTransfers();
|
|
30677
32201
|
throw new Error(`Failed to request leaves swap: ${e}`);
|
|
30678
32202
|
}
|
|
@@ -31143,8 +32667,9 @@ var SparkWallet = class _SparkWallet extends import_eventemitter3.EventEmitter {
|
|
|
31143
32667
|
field: "txid"
|
|
31144
32668
|
});
|
|
31145
32669
|
}
|
|
32670
|
+
const { fetch: fetch2, Headers: Headers2 } = getFetch();
|
|
31146
32671
|
const baseUrl = this.config.getElectrsUrl();
|
|
31147
|
-
const headers =
|
|
32672
|
+
const headers = new Headers2();
|
|
31148
32673
|
let txHex;
|
|
31149
32674
|
if (this.config.getNetwork() === 4 /* LOCAL */) {
|
|
31150
32675
|
const localFaucet = BitcoinFaucet.getInstance();
|
|
@@ -31155,9 +32680,9 @@ var SparkWallet = class _SparkWallet extends import_eventemitter3.EventEmitter {
|
|
|
31155
32680
|
const auth = btoa(
|
|
31156
32681
|
`${ELECTRS_CREDENTIALS.username}:${ELECTRS_CREDENTIALS.password}`
|
|
31157
32682
|
);
|
|
31158
|
-
headers
|
|
32683
|
+
headers.set("Authorization", `Basic ${auth}`);
|
|
31159
32684
|
}
|
|
31160
|
-
const response = await
|
|
32685
|
+
const response = await fetch2(`${baseUrl}/tx/${txid}/hex`, {
|
|
31161
32686
|
headers
|
|
31162
32687
|
});
|
|
31163
32688
|
txHex = await response.text();
|
|
@@ -31285,8 +32810,9 @@ var SparkWallet = class _SparkWallet extends import_eventemitter3.EventEmitter {
|
|
|
31285
32810
|
this.mutexes.set(txid, mutex);
|
|
31286
32811
|
}
|
|
31287
32812
|
const nodes = await mutex.runExclusive(async () => {
|
|
32813
|
+
const { fetch: fetch2, Headers: Headers2 } = getFetch();
|
|
31288
32814
|
const baseUrl = this.config.getElectrsUrl();
|
|
31289
|
-
const headers =
|
|
32815
|
+
const headers = new Headers2();
|
|
31290
32816
|
let txHex;
|
|
31291
32817
|
if (this.config.getNetwork() === 4 /* LOCAL */) {
|
|
31292
32818
|
const localFaucet = BitcoinFaucet.getInstance();
|
|
@@ -31297,9 +32823,9 @@ var SparkWallet = class _SparkWallet extends import_eventemitter3.EventEmitter {
|
|
|
31297
32823
|
const auth = btoa(
|
|
31298
32824
|
`${ELECTRS_CREDENTIALS.username}:${ELECTRS_CREDENTIALS.password}`
|
|
31299
32825
|
);
|
|
31300
|
-
headers
|
|
32826
|
+
headers.set("Authorization", `Basic ${auth}`);
|
|
31301
32827
|
}
|
|
31302
|
-
const response = await
|
|
32828
|
+
const response = await fetch2(`${baseUrl}/tx/${txid}/hex`, {
|
|
31303
32829
|
headers
|
|
31304
32830
|
});
|
|
31305
32831
|
txHex = await response.text();
|
|
@@ -31541,10 +33067,16 @@ var SparkWallet = class _SparkWallet extends import_eventemitter3.EventEmitter {
|
|
|
31541
33067
|
const validNodes = [];
|
|
31542
33068
|
for (const node of nodes) {
|
|
31543
33069
|
const nodeTx = getTxFromRawTxBytes(node.nodeTx);
|
|
31544
|
-
const
|
|
31545
|
-
|
|
31546
|
-
|
|
31547
|
-
|
|
33070
|
+
const sequence = nodeTx.getInput(0).sequence;
|
|
33071
|
+
if (!sequence) {
|
|
33072
|
+
throw new ValidationError("Invalid node transaction", {
|
|
33073
|
+
field: "sequence",
|
|
33074
|
+
value: nodeTx.getInput(0),
|
|
33075
|
+
expected: "Non-null sequence"
|
|
33076
|
+
});
|
|
33077
|
+
}
|
|
33078
|
+
const needsRefresh = doesLeafNeedRefresh(sequence, true);
|
|
33079
|
+
if (needsRefresh) {
|
|
31548
33080
|
nodesToExtend.push(node);
|
|
31549
33081
|
nodeIds.push(node.id);
|
|
31550
33082
|
} else {
|
|
@@ -31581,11 +33113,16 @@ var SparkWallet = class _SparkWallet extends import_eventemitter3.EventEmitter {
|
|
|
31581
33113
|
const validNodes = [];
|
|
31582
33114
|
for (const node of nodes) {
|
|
31583
33115
|
const refundTx = getTxFromRawTxBytes(node.refundTx);
|
|
31584
|
-
const
|
|
31585
|
-
|
|
31586
|
-
|
|
31587
|
-
|
|
31588
|
-
|
|
33116
|
+
const sequence = refundTx.getInput(0).sequence;
|
|
33117
|
+
if (!sequence) {
|
|
33118
|
+
throw new ValidationError("Invalid refund transaction", {
|
|
33119
|
+
field: "sequence",
|
|
33120
|
+
value: refundTx.getInput(0),
|
|
33121
|
+
expected: "Non-null sequence"
|
|
33122
|
+
});
|
|
33123
|
+
}
|
|
33124
|
+
const needsRefresh = doesLeafNeedRefresh(sequence);
|
|
33125
|
+
if (needsRefresh) {
|
|
31589
33126
|
nodesToRefresh.push(node);
|
|
31590
33127
|
nodeIds.push(node.id);
|
|
31591
33128
|
} else {
|
|
@@ -31619,7 +33156,7 @@ var SparkWallet = class _SparkWallet extends import_eventemitter3.EventEmitter {
|
|
|
31619
33156
|
throw new Error(`parent node ${node.parentNodeId} not found`);
|
|
31620
33157
|
}
|
|
31621
33158
|
const { nodes: nodes2 } = await this.transferService.refreshTimelockNodes(
|
|
31622
|
-
|
|
33159
|
+
node,
|
|
31623
33160
|
parentNode
|
|
31624
33161
|
);
|
|
31625
33162
|
if (nodes2.length !== 1) {
|
|
@@ -31668,7 +33205,9 @@ var SparkWallet = class _SparkWallet extends import_eventemitter3.EventEmitter {
|
|
|
31668
33205
|
leavesToClaim.push({
|
|
31669
33206
|
leaf: {
|
|
31670
33207
|
...leaf.leaf,
|
|
31671
|
-
refundTx: leaf.intermediateRefundTx
|
|
33208
|
+
refundTx: leaf.intermediateRefundTx,
|
|
33209
|
+
directRefundTx: leaf.intermediateDirectRefundTx,
|
|
33210
|
+
directFromCpfpRefundTx: leaf.intermediateDirectFromCpfpRefundTx
|
|
31672
33211
|
},
|
|
31673
33212
|
keyDerivation: {
|
|
31674
33213
|
type: "ecies" /* ECIES */,
|
|
@@ -31744,7 +33283,7 @@ var SparkWallet = class _SparkWallet extends import_eventemitter3.EventEmitter {
|
|
|
31744
33283
|
if (type && transfer.type !== type) {
|
|
31745
33284
|
continue;
|
|
31746
33285
|
}
|
|
31747
|
-
if (transfer.status !== 2 /* TRANSFER_STATUS_SENDER_KEY_TWEAKED */ && transfer.status !== 3 /* TRANSFER_STATUS_RECEIVER_KEY_TWEAKED */ && transfer.status !== 4 /* TRANSFER_STATUS_RECEIVER_REFUND_SIGNED */ && transfer.status !== 10 /* TRANSFER_STATUS_RECEIVER_KEY_TWEAK_APPLIED */) {
|
|
33286
|
+
if (transfer.status !== 2 /* TRANSFER_STATUS_SENDER_KEY_TWEAKED */ && transfer.status !== 3 /* TRANSFER_STATUS_RECEIVER_KEY_TWEAKED */ && transfer.status !== 4 /* TRANSFER_STATUS_RECEIVER_REFUND_SIGNED */ && transfer.status !== 10 /* TRANSFER_STATUS_RECEIVER_KEY_TWEAK_APPLIED */ && transfer.status !== 9 /* TRANSFER_STATUS_RECEIVER_KEY_TWEAK_LOCKED */) {
|
|
31748
33287
|
continue;
|
|
31749
33288
|
}
|
|
31750
33289
|
promises.push(
|
|
@@ -32032,6 +33571,8 @@ var SparkWallet = class _SparkWallet extends import_eventemitter3.EventEmitter {
|
|
|
32032
33571
|
await this.transferService.deliverTransferPackage(
|
|
32033
33572
|
swapResponse.transfer,
|
|
32034
33573
|
leavesToSend,
|
|
33574
|
+
/* @__PURE__ */ new Map(),
|
|
33575
|
+
/* @__PURE__ */ new Map(),
|
|
32035
33576
|
/* @__PURE__ */ new Map()
|
|
32036
33577
|
);
|
|
32037
33578
|
const sspResponse = await sspClient.requestLightningSend({
|
|
@@ -32794,87 +34335,64 @@ var SparkWallet = class _SparkWallet extends import_eventemitter3.EventEmitter {
|
|
|
32794
34335
|
},
|
|
32795
34336
|
includeParents: true
|
|
32796
34337
|
});
|
|
32797
|
-
|
|
32798
|
-
if (!
|
|
34338
|
+
let leaf = response.nodes[nodeId];
|
|
34339
|
+
if (!leaf) {
|
|
32799
34340
|
throw new ValidationError("Node not found", {
|
|
32800
34341
|
field: "nodeId",
|
|
32801
34342
|
value: nodeId
|
|
32802
34343
|
});
|
|
32803
34344
|
}
|
|
32804
|
-
|
|
32805
|
-
|
|
32806
|
-
|
|
32807
|
-
|
|
32808
|
-
|
|
32809
|
-
|
|
32810
|
-
|
|
32811
|
-
|
|
32812
|
-
|
|
32813
|
-
|
|
32814
|
-
|
|
32815
|
-
});
|
|
32816
|
-
}
|
|
32817
|
-
const result = await this.transferService.refreshTimelockNodes(
|
|
32818
|
-
[node],
|
|
32819
|
-
parentNode
|
|
32820
|
-
);
|
|
32821
|
-
const leafIndex = this.leaves.findIndex((leaf) => leaf.id === node.id);
|
|
32822
|
-
if (leafIndex !== -1 && result.nodes.length > 0) {
|
|
32823
|
-
const newNode = result.nodes[0];
|
|
32824
|
-
if (newNode) {
|
|
32825
|
-
this.leaves[leafIndex] = newNode;
|
|
34345
|
+
let parentNode;
|
|
34346
|
+
let hasParentNode = false;
|
|
34347
|
+
if (!leaf.parentNodeId) {
|
|
34348
|
+
} else {
|
|
34349
|
+
hasParentNode = true;
|
|
34350
|
+
parentNode = response.nodes[leaf.parentNodeId];
|
|
34351
|
+
if (!parentNode) {
|
|
34352
|
+
throw new ValidationError("Parent node not found", {
|
|
34353
|
+
field: "parentNodeId",
|
|
34354
|
+
value: leaf.parentNodeId
|
|
34355
|
+
});
|
|
32826
34356
|
}
|
|
32827
34357
|
}
|
|
32828
|
-
|
|
32829
|
-
|
|
32830
|
-
|
|
32831
|
-
|
|
32832
|
-
|
|
32833
|
-
|
|
32834
|
-
|
|
32835
|
-
|
|
32836
|
-
|
|
32837
|
-
|
|
32838
|
-
|
|
32839
|
-
|
|
32840
|
-
|
|
32841
|
-
|
|
32842
|
-
* @returns {Promise<void>} Promise that resolves when the refund timelock is refreshed
|
|
32843
|
-
*/
|
|
32844
|
-
async testOnly_expireTimelockRefundTx(nodeId) {
|
|
32845
|
-
const sparkClient = await this.connectionManager.createSparkClient(
|
|
32846
|
-
this.config.getCoordinatorAddress()
|
|
32847
|
-
);
|
|
32848
|
-
try {
|
|
32849
|
-
const response = await sparkClient.query_nodes({
|
|
32850
|
-
source: {
|
|
32851
|
-
$case: "nodeIds",
|
|
32852
|
-
nodeIds: {
|
|
32853
|
-
nodeIds: [nodeId]
|
|
34358
|
+
const nodeTx = getTxFromRawTxBytes(leaf.nodeTx);
|
|
34359
|
+
const refundTx = getTxFromRawTxBytes(leaf.refundTx);
|
|
34360
|
+
if (hasParentNode) {
|
|
34361
|
+
const nodeTimelock = getCurrentTimelock(nodeTx.getInput(0).sequence);
|
|
34362
|
+
if (nodeTimelock > 100) {
|
|
34363
|
+
const expiredNodeTxLeaf = await this.transferService.testonly_expireTimeLockNodeTx(
|
|
34364
|
+
leaf,
|
|
34365
|
+
parentNode
|
|
34366
|
+
);
|
|
34367
|
+
if (!expiredNodeTxLeaf.nodes[0]) {
|
|
34368
|
+
throw new ValidationError("No expired node tx leaf", {
|
|
34369
|
+
field: "expiredNodeTxLeaf",
|
|
34370
|
+
value: expiredNodeTxLeaf
|
|
34371
|
+
});
|
|
32854
34372
|
}
|
|
32855
|
-
|
|
32856
|
-
|
|
32857
|
-
});
|
|
32858
|
-
const node = response.nodes[nodeId];
|
|
32859
|
-
if (!node) {
|
|
32860
|
-
throw new ValidationError("Node not found", {
|
|
32861
|
-
field: "nodeId",
|
|
32862
|
-
value: nodeId
|
|
32863
|
-
});
|
|
34373
|
+
leaf = expiredNodeTxLeaf.nodes[0];
|
|
34374
|
+
}
|
|
32864
34375
|
}
|
|
32865
|
-
const
|
|
32866
|
-
|
|
32867
|
-
|
|
32868
|
-
|
|
32869
|
-
|
|
32870
|
-
|
|
34376
|
+
const refundTimelock = getCurrentTimelock(refundTx.getInput(0).sequence);
|
|
34377
|
+
if (refundTimelock > 100) {
|
|
34378
|
+
const expiredTxLeaf = await this.transferService.testonly_expireTimeLockRefundtx(leaf);
|
|
34379
|
+
if (!expiredTxLeaf.nodes[0]) {
|
|
34380
|
+
throw new ValidationError("No expired tx leaf", {
|
|
34381
|
+
field: "expiredTxLeaf",
|
|
34382
|
+
value: expiredTxLeaf
|
|
34383
|
+
});
|
|
32871
34384
|
}
|
|
34385
|
+
leaf = expiredTxLeaf.nodes[0];
|
|
34386
|
+
}
|
|
34387
|
+
const leafIndex = this.leaves.findIndex((leaf2) => leaf2.id === leaf2.id);
|
|
34388
|
+
if (leafIndex !== -1) {
|
|
34389
|
+
this.leaves[leafIndex] = leaf;
|
|
32872
34390
|
}
|
|
32873
34391
|
} catch (error) {
|
|
32874
34392
|
throw new NetworkError(
|
|
32875
|
-
"Failed to refresh
|
|
34393
|
+
"Failed to refresh timelock",
|
|
32876
34394
|
{
|
|
32877
|
-
method: "
|
|
34395
|
+
method: "refresh_timelock"
|
|
32878
34396
|
},
|
|
32879
34397
|
error
|
|
32880
34398
|
);
|
|
@@ -32945,7 +34463,10 @@ setCrypto(cryptoImpl2);
|
|
|
32945
34463
|
AuthenticationError,
|
|
32946
34464
|
ConfigurationError,
|
|
32947
34465
|
DEFAULT_FEE_SATS,
|
|
34466
|
+
DIRECT_TIMELOCK_OFFSET,
|
|
32948
34467
|
DefaultSparkSigner,
|
|
34468
|
+
INITIAL_DIRECT_SEQUENCE,
|
|
34469
|
+
INITIAL_SEQUENCE,
|
|
32949
34470
|
InternalValidationError,
|
|
32950
34471
|
KeyDerivationType,
|
|
32951
34472
|
LRC_WALLET_NETWORK,
|
|
@@ -32958,6 +34479,8 @@ setCrypto(cryptoImpl2);
|
|
|
32958
34479
|
RPCError,
|
|
32959
34480
|
SparkSDKError,
|
|
32960
34481
|
SparkWallet,
|
|
34482
|
+
TEST_UNILATERAL_DIRECT_SEQUENCE,
|
|
34483
|
+
TEST_UNILATERAL_SEQUENCE,
|
|
32961
34484
|
TaprootOutputKeysGenerator,
|
|
32962
34485
|
TaprootSparkSigner,
|
|
32963
34486
|
TokenTransactionService,
|
|
@@ -32977,13 +34500,21 @@ setCrypto(cryptoImpl2);
|
|
|
32977
34500
|
constructFeeBumpTx,
|
|
32978
34501
|
constructUnilateralExitFeeBumpPackages,
|
|
32979
34502
|
constructUnilateralExitTxs,
|
|
34503
|
+
createConnectorRefundTransactions,
|
|
34504
|
+
createLeafNodeTx,
|
|
34505
|
+
createNodeTx,
|
|
34506
|
+
createNodeTxs,
|
|
32980
34507
|
createRefundTx,
|
|
34508
|
+
createRefundTxs,
|
|
34509
|
+
createRootTx,
|
|
32981
34510
|
createSigningCommitment,
|
|
32982
34511
|
createSigningNonce,
|
|
34512
|
+
createSplitTx,
|
|
32983
34513
|
decodeBech32mTokenIdentifier,
|
|
32984
34514
|
decodeBytesToSigningCommitment,
|
|
32985
34515
|
decodeBytesToSigningNonce,
|
|
32986
34516
|
decodeSparkAddress,
|
|
34517
|
+
doesLeafNeedRefresh,
|
|
32987
34518
|
encodeBech32mTokenIdentifier,
|
|
32988
34519
|
encodeSigningCommitmentToBytes,
|
|
32989
34520
|
encodeSigningNonceToBytes,
|