From 04bdc9dbb53b2b22974cf781a214aedda6a74bca Mon Sep 17 00:00:00 2001 From: Polybius93 <99192647+Polybius93@users.noreply.github.com> Date: Fri, 12 Jul 2024 12:00:29 +0200 Subject: [PATCH] feat: modify uint8array comparing functions (#14) * feat: modify uint8array comparing and functions that use it * feat: add unit tests for utility functions * feat: add tests for specific bitcoin functions --- package.json | 2 +- src/functions/bitcoin/bitcoin-functions.ts | 50 +- .../proof-of-reserve-handler.ts | 4 +- src/utilities/index.ts | 4 + .../bitcoin-transaction.test.constants.ts | 920 ++++++++++++++++++ tests/mocks/constants.ts | 15 + tests/unit/bitcoin-functions.test.ts | 115 +++ tests/unit/utility.test.ts | 145 +++ 8 files changed, 1212 insertions(+), 43 deletions(-) create mode 100644 tests/mocks/bitcoin-transaction.test.constants.ts create mode 100644 tests/unit/bitcoin-functions.test.ts create mode 100644 tests/unit/utility.test.ts diff --git a/package.json b/package.json index cc048c4..b551228 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "type": "module", "name": "dlc-btc-lib", - "version": "1.0.17", + "version": "1.0.18", "description": "This library provides a comprehensive set of interfaces and functions for minting dlcBTC tokens on supported blockchains.", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/src/functions/bitcoin/bitcoin-functions.ts b/src/functions/bitcoin/bitcoin-functions.ts index 82ea715..b9838fe 100644 --- a/src/functions/bitcoin/bitcoin-functions.ts +++ b/src/functions/bitcoin/bitcoin-functions.ts @@ -24,7 +24,12 @@ import { PaymentTypes, UTXO, } from '../../models/bitcoin-models.js'; -import { createRangeFromLength, isDefined, isUndefined } from '../../utilities/index.js'; +import { + compareUint8Arrays, + createRangeFromLength, + isDefined, + isUndefined, +} from '../../utilities/index.js'; const TAPROOT_UNSPENDABLE_KEY_HEX = '0250929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0'; @@ -428,54 +433,19 @@ export function getValueMatchingOutputFromTransaction( return valueMatchingTransactionOutput; } -export function validateScript(script: Uint8Array, outputScript: Uint8Array): boolean { - return ( - outputScript.length === script.length && - outputScript.every((value, index) => value === script[index]) - ); -} - export function getInputIndicesByScript(script: Uint8Array, transaction: Transaction): number[] { - const inputIndices: number[] = []; - - createRangeFromLength(transaction.inputsLength).forEach(index => { + return createRangeFromLength(transaction.inputsLength).flatMap(index => { const inputScript = transaction.getInput(index).witnessUtxo?.script; - - if (!inputScript) { - throw new Error('Could not get Input Script'); - } - - if ( - inputScript.length === script.length && - inputScript.every((value, index) => value === script[index]) - ) { - inputIndices.push(index); - } + return inputScript && compareUint8Arrays(inputScript, script) ? [index] : []; }); - return inputIndices; } -export function finalizeUserInputs( - transaction: Transaction, - userPayment: P2TROut | P2Ret -): Transaction { - const userPaymentScript = userPayment.script; +export function finalizeUserInputs(transaction: Transaction, userPayment: P2TROut | P2Ret): void { createRangeFromLength(transaction.inputsLength).forEach(index => { const inputScript = transaction.getInput(index).witnessUtxo?.script; - - if (!inputScript) { - throw new Error('Could not get Input Script'); - } - - if ( - inputScript.length === userPaymentScript.length && - inputScript.every((value, index) => value === userPaymentScript[index]) - ) { + if (inputScript && compareUint8Arrays(inputScript, userPayment.script)) transaction.finalizeIdx(index); - } }); - - return transaction; } /** diff --git a/src/proof-of-reserve-handlers/proof-of-reserve-handler.ts b/src/proof-of-reserve-handlers/proof-of-reserve-handler.ts index e401a7e..7641404 100644 --- a/src/proof-of-reserve-handlers/proof-of-reserve-handler.ts +++ b/src/proof-of-reserve-handlers/proof-of-reserve-handler.ts @@ -6,7 +6,6 @@ import { deriveUnhardenedPublicKey, getUnspendableKeyCommittedToUUID, getValueMatchingOutputFromTransaction, - validateScript, } from '../functions/bitcoin/bitcoin-functions.js'; import { checkBitcoinTransactionConfirmations, @@ -14,6 +13,7 @@ import { fetchBitcoinTransaction, } from '../functions/bitcoin/bitcoin-request-functions.js'; import { RawVault } from '../models/ethereum-models.js'; +import { compareUint8Arrays } from '../utilities/index.js'; export class ProofOfReserveHandler { private bitcoinBlockchainAPI: string; @@ -65,7 +65,7 @@ export class ProofOfReserveHandler { this.bitcoinNetwork ); - return validateScript( + return compareUint8Arrays( taprootMultisigPayment.script, hex.decode(vaultTransactionOutput.scriptpubkey) ); diff --git a/src/utilities/index.ts b/src/utilities/index.ts index dbb158e..b691e07 100644 --- a/src/utilities/index.ts +++ b/src/utilities/index.ts @@ -45,6 +45,10 @@ export function isDefined(argument: T | undefined): argument is T { return !isUndefined(argument); } +export function compareUint8Arrays(a: Uint8Array, b: Uint8Array): boolean { + return a.length === b.length && a.every((value, index) => value === b[index]); +} + export async function delay(ms: number) { return new Promise(resolve => setTimeout(resolve, ms)); } diff --git a/tests/mocks/bitcoin-transaction.test.constants.ts b/tests/mocks/bitcoin-transaction.test.constants.ts new file mode 100644 index 0000000..dbc6053 --- /dev/null +++ b/tests/mocks/bitcoin-transaction.test.constants.ts @@ -0,0 +1,920 @@ +export const TEST_DEPOSIT_PSBT_PARTIALLY_SIGNED_DEPOSIT_PSBT_1 = + '70736274ff0100c5020000000269680a0f87525a598abaf823342a4cb6d632027252e51d242e51c61770f17c990200000000f0ffffff751757d16e395a1da0457531b8a9eed579bdd87f3d60034b179976be5fb5178a0100000000ffffffff0370170000000000001600145a81f36535980769bccc23c196337a78458abd1e80969800000000002251203789ed985ab9d1c94f5889973376a88d9940835206461151685a7a3fbb84de599ec6202901000000160014add70fb03578d3ac85aab80897395bb046223c92000000000001011f302b6d2901000000160014add70fb03578d3ac85aab80897395bb046223c92220202f4d8696f9b275f4e10af63f03bcb7fbba7b1ed44dd9b12a973c8d20212beb8d1483045022100d7788684a0d1f05f35a861f72457a8d1aa7efbfdf1227d3e6cdf72b7feab9f7e02203d57106adbaf190731c0447e990833835c6de86052161e39b06193ad306e80a1010001012b404b4c00000000002251203789ed985ab9d1c94f5889973376a88d9940835206461151685a7a3fbb84de594114bb7e175e63064479102ee0b69a719a9f54f8f1b29df17cfaa5437697393e7cfce24db130ab82d20d322c295aa18921a7fe87fb13df3d5b3b2ee0469e2a84511440d8fb920db7745d01f2762b6285e10a3d16ef056fd1dc26879eea5dc5410d4da53a458820088e5a22c11ef27527a8db546a0e8997d80b4b3c4f861a6b4410bd482215c1e52a5f154612da28faade658332157966492aa20a523162a8b584682a23dc72645205216652630455eb8546bbab45e6fdef6498eee683ed339f405d326414b05b192ad20bb7e175e63064479102ee0b69a719a9f54f8f1b29df17cfaa5437697393e7cfcacc0011720e52a5f154612da28faade658332157966492aa20a523162a8b584682a23dc726011820e24db130ab82d20d322c295aa18921a7fe87fb13df3d5b3b2ee0469e2a84511400000000'; +// Readable format: +// { +// "global": { +// "unsignedTx": { +// "version": 2, +// "segwitFlag": false, +// "inputs": [ +// { +// "txid": { +// "type": "Uint8Array", +// "value": "997cf17017c6512e241de552720232d6b64c2a3423f8ba8a595a52870f0a6869" +// }, +// "index": 2, +// "finalScriptSig": { +// "type": "Uint8Array", +// "value": "" +// }, +// "sequence": 4294967280 +// }, +// { +// "txid": { +// "type": "Uint8Array", +// "value": "8a17b55fbe7699174b03603d7fd8bd79d5eea9b8317545a01d5a396ed1571775" +// }, +// "index": 1, +// "finalScriptSig": { +// "type": "Uint8Array", +// "value": "" +// }, +// "sequence": 4294967295 +// } +// ], +// "outputs": [ +// { +// "amount": "6000", +// "script": { +// "type": "Uint8Array", +// "value": "00145a81f36535980769bccc23c196337a78458abd1e" +// } +// }, +// { +// "amount": "10000000", +// "script": { +// "type": "Uint8Array", +// "value": "51203789ed985ab9d1c94f5889973376a88d9940835206461151685a7a3fbb84de59" +// } +// }, +// { +// "amount": "4984981150", +// "script": { +// "type": "Uint8Array", +// "value": "0014add70fb03578d3ac85aab80897395bb046223c92" +// } +// } +// ], +// "lockTime": 0 +// }, +// "txVersion": 2 +// }, +// "inputs": [ +// { +// "finalScriptSig": { +// "type": "Uint8Array", +// "value": "" +// }, +// "txid": { +// "type": "Uint8Array", +// "value": "997cf17017c6512e241de552720232d6b64c2a3423f8ba8a595a52870f0a6869" +// }, +// "index": 2, +// "sequence": 4294967280, +// "witnessUtxo": { +// "amount": "4989987632", +// "script": { +// "type": "Uint8Array", +// "value": "0014add70fb03578d3ac85aab80897395bb046223c92" +// } +// }, +// "partialSig": [ +// [ +// { +// "type": "Uint8Array", +// "value": "02f4d8696f9b275f4e10af63f03bcb7fbba7b1ed44dd9b12a973c8d20212beb8d1" +// }, +// { +// "type": "Uint8Array", +// "value": "3045022100d7788684a0d1f05f35a861f72457a8d1aa7efbfdf1227d3e6cdf72b7feab9f7e02203d57106adbaf190731c0447e990833835c6de86052161e39b06193ad306e80a101" +// } +// ] +// ] +// }, +// { +// "finalScriptSig": { +// "type": "Uint8Array", +// "value": "" +// }, +// "txid": { +// "type": "Uint8Array", +// "value": "8a17b55fbe7699174b03603d7fd8bd79d5eea9b8317545a01d5a396ed1571775" +// }, +// "index": 1, +// "sequence": 4294967295, +// "witnessUtxo": { +// "amount": "5000000", +// "script": { +// "type": "Uint8Array", +// "value": "51203789ed985ab9d1c94f5889973376a88d9940835206461151685a7a3fbb84de59" +// } +// }, +// "tapScriptSig": [ +// [ +// { +// "pubKey": { +// "type": "Uint8Array", +// "value": "bb7e175e63064479102ee0b69a719a9f54f8f1b29df17cfaa5437697393e7cfc" +// }, +// "leafHash": { +// "type": "Uint8Array", +// "value": "e24db130ab82d20d322c295aa18921a7fe87fb13df3d5b3b2ee0469e2a845114" +// } +// }, +// { +// "type": "Uint8Array", +// "value": "d8fb920db7745d01f2762b6285e10a3d16ef056fd1dc26879eea5dc5410d4da53a458820088e5a22c11ef27527a8db546a0e8997d80b4b3c4f861a6b4410bd48" +// } +// ] +// ], +// "tapLeafScript": [ +// [ +// { +// "version": 193, +// "internalKey": { +// "type": "Uint8Array", +// "value": "e52a5f154612da28faade658332157966492aa20a523162a8b584682a23dc726" +// }, +// "merklePath": [] +// }, +// { +// "type": "Uint8Array", +// "value": "205216652630455eb8546bbab45e6fdef6498eee683ed339f405d326414b05b192ad20bb7e175e63064479102ee0b69a719a9f54f8f1b29df17cfaa5437697393e7cfcacc0" +// } +// ] +// ], +// "tapInternalKey": { +// "type": "Uint8Array", +// "value": "e52a5f154612da28faade658332157966492aa20a523162a8b584682a23dc726" +// }, +// "tapMerkleRoot": { +// "type": "Uint8Array", +// "value": "e24db130ab82d20d322c295aa18921a7fe87fb13df3d5b3b2ee0469e2a845114" +// } +// } +// ], +// "outputs": [ +// { +// "amount": "6000", +// "script": { +// "type": "Uint8Array", +// "value": "00145a81f36535980769bccc23c196337a78458abd1e" +// } +// }, +// { +// "amount": "10000000", +// "script": { +// "type": "Uint8Array", +// "value": "51203789ed985ab9d1c94f5889973376a88d9940835206461151685a7a3fbb84de59" +// } +// }, +// { +// "amount": "4984981150", +// "script": { +// "type": "Uint8Array", +// "value": "0014add70fb03578d3ac85aab80897395bb046223c92" +// } +// } +// ], +// "opts": { +// "version": 2, +// "lockTime": 0, +// "PSBTVersion": 0 +// } +// } + +export const TEST_DEPOSIT_PSBT_PARTIALLY_SIGNED_DEPOSIT_PSBT_2 = + '70736274ff0100d1020000000266916a1f40ca9c611a60002f81854402ffb424e457c1c23931d06267cf5bc8950000000000f0ffffff8f5413dcad4cbe8876459a1b1fe1817a94206f0d0bbb79765403438c3bb07dbe0100000000ffffffff0370170000000000001600145a81f36535980769bccc23c196337a78458abd1e8096980000000000225120b033a3d9562d22aa4a5476ae9cb6a5858b0959e084b49a3fd92edfba87e8254faa59f42400000000225120676504fcaf89119cc9762c2f867aaa56aa3fffc85158f7dd61da345cdbf4a9be000000000001012b40be402500000000225120676504fcaf89119cc9762c2f867aaa56aa3fffc85158f7dd61da345cdbf4a9be011340fd74c7650cb7edb0eea5fca080ac7dea90ab23ecf616eac1ad4a263d75fcf3940d3c7c09512369cb39a473e4eb1249204df36115095dc2849556686b9087824e011720bb7e175e63064479102ee0b69a719a9f54f8f1b29df17cfaa5437697393e7cfc0001012b404b4c0000000000225120b033a3d9562d22aa4a5476ae9cb6a5858b0959e084b49a3fd92edfba87e8254f4114bb7e175e63064479102ee0b69a719a9f54f8f1b29df17cfaa5437697393e7cfce24db130ab82d20d322c295aa18921a7fe87fb13df3d5b3b2ee0469e2a845114404387a71d8174f9c42ef8ce8cbe0c88c01863fb80ea796955f6678b95a7ae7e07dd1559688bee882feefdda2e98880ea6e6ba886c438bdb2188b41f4f68d09f992215c01fba2e8661f2ed0a747d76578d3a6508a31879569d97da86a0a207c2538ebaa445205216652630455eb8546bbab45e6fdef6498eee683ed339f405d326414b05b192ad20bb7e175e63064479102ee0b69a719a9f54f8f1b29df17cfaa5437697393e7cfcacc00117201fba2e8661f2ed0a747d76578d3a6508a31879569d97da86a0a207c2538ebaa4011820e24db130ab82d20d322c295aa18921a7fe87fb13df3d5b3b2ee0469e2a84511400000000'; +// Readable format: +// { +// "global": { +// "unsignedTx": { +// "version": 2, +// "segwitFlag": false, +// "inputs": [ +// { +// "txid": { +// "type": "Uint8Array", +// "value": "95c85bcf6762d03139c2c157e424b4ff024485812f00601a619cca401f6a9166" +// }, +// "index": 0, +// "finalScriptSig": { +// "type": "Uint8Array", +// "value": "" +// }, +// "sequence": 4294967280 +// }, +// { +// "txid": { +// "type": "Uint8Array", +// "value": "be7db03b8c4303547679bb0b0d6f20947a81e11f1b9a457688be4caddc13548f" +// }, +// "index": 1, +// "finalScriptSig": { +// "type": "Uint8Array", +// "value": "" +// }, +// "sequence": 4294967295 +// } +// ], +// "outputs": [ +// { +// "amount": "6000", +// "script": { +// "type": "Uint8Array", +// "value": "00145a81f36535980769bccc23c196337a78458abd1e" +// } +// }, +// { +// "amount": "10000000", +// "script": { +// "type": "Uint8Array", +// "value": "5120b033a3d9562d22aa4a5476ae9cb6a5858b0959e084b49a3fd92edfba87e8254f" +// } +// }, +// { +// "amount": "619993514", +// "script": { +// "type": "Uint8Array", +// "value": "5120676504fcaf89119cc9762c2f867aaa56aa3fffc85158f7dd61da345cdbf4a9be" +// } +// } +// ], +// "lockTime": 0 +// }, +// "txVersion": 2 +// }, +// "inputs": [ +// { +// "finalScriptSig": { +// "type": "Uint8Array", +// "value": "" +// }, +// "txid": { +// "type": "Uint8Array", +// "value": "95c85bcf6762d03139c2c157e424b4ff024485812f00601a619cca401f6a9166" +// }, +// "index": 0, +// "sequence": 4294967280, +// "witnessUtxo": { +// "amount": "625000000", +// "script": { +// "type": "Uint8Array", +// "value": "5120676504fcaf89119cc9762c2f867aaa56aa3fffc85158f7dd61da345cdbf4a9be" +// } +// }, +// "tapKeySig": { +// "type": "Uint8Array", +// "value": "fd74c7650cb7edb0eea5fca080ac7dea90ab23ecf616eac1ad4a263d75fcf3940d3c7c09512369cb39a473e4eb1249204df36115095dc2849556686b9087824e" +// }, +// "tapInternalKey": { +// "type": "Uint8Array", +// "value": "bb7e175e63064479102ee0b69a719a9f54f8f1b29df17cfaa5437697393e7cfc" +// } +// }, +// { +// "finalScriptSig": { +// "type": "Uint8Array", +// "value": "" +// }, +// "txid": { +// "type": "Uint8Array", +// "value": "be7db03b8c4303547679bb0b0d6f20947a81e11f1b9a457688be4caddc13548f" +// }, +// "index": 1, +// "sequence": 4294967295, +// "witnessUtxo": { +// "amount": "5000000", +// "script": { +// "type": "Uint8Array", +// "value": "5120b033a3d9562d22aa4a5476ae9cb6a5858b0959e084b49a3fd92edfba87e8254f" +// } +// }, +// "tapScriptSig": [ +// [ +// { +// "pubKey": { +// "type": "Uint8Array", +// "value": "bb7e175e63064479102ee0b69a719a9f54f8f1b29df17cfaa5437697393e7cfc" +// }, +// "leafHash": { +// "type": "Uint8Array", +// "value": "e24db130ab82d20d322c295aa18921a7fe87fb13df3d5b3b2ee0469e2a845114" +// } +// }, +// { +// "type": "Uint8Array", +// "value": "4387a71d8174f9c42ef8ce8cbe0c88c01863fb80ea796955f6678b95a7ae7e07dd1559688bee882feefdda2e98880ea6e6ba886c438bdb2188b41f4f68d09f99" +// } +// ] +// ], +// "tapLeafScript": [ +// [ +// { +// "version": 192, +// "internalKey": { +// "type": "Uint8Array", +// "value": "1fba2e8661f2ed0a747d76578d3a6508a31879569d97da86a0a207c2538ebaa4" +// }, +// "merklePath": [] +// }, +// { +// "type": "Uint8Array", +// "value": "205216652630455eb8546bbab45e6fdef6498eee683ed339f405d326414b05b192ad20bb7e175e63064479102ee0b69a719a9f54f8f1b29df17cfaa5437697393e7cfcacc0" +// } +// ] +// ], +// "tapInternalKey": { +// "type": "Uint8Array", +// "value": "1fba2e8661f2ed0a747d76578d3a6508a31879569d97da86a0a207c2538ebaa4" +// }, +// "tapMerkleRoot": { +// "type": "Uint8Array", +// "value": "e24db130ab82d20d322c295aa18921a7fe87fb13df3d5b3b2ee0469e2a845114" +// } +// } +// ], +// "outputs": [ +// { +// "amount": "6000", +// "script": { +// "type": "Uint8Array", +// "value": "00145a81f36535980769bccc23c196337a78458abd1e" +// } +// }, +// { +// "amount": "10000000", +// "script": { +// "type": "Uint8Array", +// "value": "5120b033a3d9562d22aa4a5476ae9cb6a5858b0959e084b49a3fd92edfba87e8254f" +// } +// }, +// { +// "amount": "619993514", +// "script": { +// "type": "Uint8Array", +// "value": "5120676504fcaf89119cc9762c2f867aaa56aa3fffc85158f7dd61da345cdbf4a9be" +// } +// } +// ], +// "opts": { +// "version": 2, +// "lockTime": 0, +// "PSBTVersion": 0 +// } +// } + +export const TEST_DEPOSIT_PSBT_PARTIALLY_SIGNED_DEPOSIT_PSBT_3 = + '70736274ff0100fd17010200000004591440ba8921026ba9c35a08fe1be0b192fa59c328919070216ecc396529adaf0200000000f0ffffffaea70896bc92b479b8dd98d2e706b9c6492cd6f567caf34713c71b10cafd746a0200000000ffffffffbb6f00e7148900daf36a20f08152aebce2ed41085e8bbfc28c8aff796dec4f4f0200000000ffffffffcb6450850a4596027f12d43ce19b624185196fd1831abfda0afffced3e9c0d700100000000ffffffff03001bb700000000001600145a81f36535980769bccc23c196337a78458abd1e402f585402000000225120bca90746e285c10235453757249fcac29178e418bef5492b5add21475f76232a3e539f2601000000160014add70fb03578d3ac85aab80897395bb046223c92000000000001011f10c7202901000000160014add70fb03578d3ac85aab80897395bb046223c92220202f4d8696f9b275f4e10af63f03bcb7fbba7b1ed44dd9b12a973c8d20212beb8d14830450221009a699d65d75cf43a4b9ef89f3717352cb4af3981848e9a406ada7a1a727fc98502207b063ca138901ce774e005ef543cd225c976fb8d1dbfbe5a63d85b96dfaba356010001011f10c7202901000000160014add70fb03578d3ac85aab80897395bb046223c92220202f4d8696f9b275f4e10af63f03bcb7fbba7b1ed44dd9b12a973c8d20212beb8d1483045022100cfd104f2751a744510cc5e07dbb1c48c597db3c69aa48e52de7be379a00db0d40220360c0e608c016a19a4bd19c9235b01f18c6e7998f439475cc8637fdd04d7cecf010001011f10c7202901000000160014add70fb03578d3ac85aab80897395bb046223c92220202f4d8696f9b275f4e10af63f03bcb7fbba7b1ed44dd9b12a973c8d20212beb8d1483045022100de829b10d533c05b3ff7d65caa3503e7d3c16ef5d1a83224c21de63c5f88531d02207d13d47f640aa4f85511293d363af5e7158c328b312e175f9e3e0290eaa54618010001012b404b4c0000000000225120bca90746e285c10235453757249fcac29178e418bef5492b5add21475f76232a4114bb7e175e63064479102ee0b69a719a9f54f8f1b29df17cfaa5437697393e7cfce24db130ab82d20d322c295aa18921a7fe87fb13df3d5b3b2ee0469e2a845114406d997b5d10bccd43e8c210c1b21685f866e14d3648954767cd8656311e3cff3b30c3581d4eafd4468a376af3ab8f305118fad37083fca5da48d3ab9953bfa3602215c1d6d94d6dd718c7ad15270bc3e3ed3058d4c2253942ff1c1cbea1b1105fd6cc9145205216652630455eb8546bbab45e6fdef6498eee683ed339f405d326414b05b192ad20bb7e175e63064479102ee0b69a719a9f54f8f1b29df17cfaa5437697393e7cfcacc0011720d6d94d6dd718c7ad15270bc3e3ed3058d4c2253942ff1c1cbea1b1105fd6cc91011820e24db130ab82d20d322c295aa18921a7fe87fb13df3d5b3b2ee0469e2a84511400000000'; +// Readable format: +// { +// "global": { +// "unsignedTx": { +// "version": 2, +// "segwitFlag": false, +// "inputs": [ +// { +// "txid": { +// "type": "Uint8Array", +// "value": "afad296539cc6e2170909128c359fa92b1e01bfe085ac3a96b022189ba401459" +// }, +// "index": 2, +// "finalScriptSig": { +// "type": "Uint8Array", +// "value": "" +// }, +// "sequence": 4294967280 +// }, +// { +// "txid": { +// "type": "Uint8Array", +// "value": "6a74fdca101bc71347f3ca67f5d62c49c6b906e7d298ddb879b492bc9608a7ae" +// }, +// "index": 2, +// "finalScriptSig": { +// "type": "Uint8Array", +// "value": "" +// }, +// "sequence": 4294967295 +// }, +// { +// "txid": { +// "type": "Uint8Array", +// "value": "4f4fec6d79ff8a8cc2bf8b5e0841ede2bcae5281f0206af3da008914e7006fbb" +// }, +// "index": 2, +// "finalScriptSig": { +// "type": "Uint8Array", +// "value": "" +// }, +// "sequence": 4294967295 +// }, +// { +// "txid": { +// "type": "Uint8Array", +// "value": "700d9c3eedfcff0adabf1a83d16f198541629be13cd4127f0296450a855064cb" +// }, +// "index": 1, +// "finalScriptSig": { +// "type": "Uint8Array", +// "value": "" +// }, +// "sequence": 4294967295 +// } +// ], +// "outputs": [ +// { +// "amount": "12000000", +// "script": { +// "type": "Uint8Array", +// "value": "00145a81f36535980769bccc23c196337a78458abd1e" +// } +// }, +// { +// "amount": "10005000000", +// "script": { +// "type": "Uint8Array", +// "value": "5120bca90746e285c10235453757249fcac29178e418bef5492b5add21475f76232a" +// } +// }, +// { +// "amount": "4942943038", +// "script": { +// "type": "Uint8Array", +// "value": "0014add70fb03578d3ac85aab80897395bb046223c92" +// } +// } +// ], +// "lockTime": 0 +// }, +// "txVersion": 2 +// }, +// "inputs": [ +// { +// "finalScriptSig": { +// "type": "Uint8Array", +// "value": "" +// }, +// "txid": { +// "type": "Uint8Array", +// "value": "afad296539cc6e2170909128c359fa92b1e01bfe085ac3a96b022189ba401459" +// }, +// "index": 2, +// "sequence": 4294967280, +// "witnessUtxo": { +// "amount": "4984981264", +// "script": { +// "type": "Uint8Array", +// "value": "0014add70fb03578d3ac85aab80897395bb046223c92" +// } +// }, +// "partialSig": [ +// [ +// { +// "type": "Uint8Array", +// "value": "02f4d8696f9b275f4e10af63f03bcb7fbba7b1ed44dd9b12a973c8d20212beb8d1" +// }, +// { +// "type": "Uint8Array", +// "value": "30450221009a699d65d75cf43a4b9ef89f3717352cb4af3981848e9a406ada7a1a727fc98502207b063ca138901ce774e005ef543cd225c976fb8d1dbfbe5a63d85b96dfaba35601" +// } +// ] +// ] +// }, +// { +// "finalScriptSig": { +// "type": "Uint8Array", +// "value": "" +// }, +// "txid": { +// "type": "Uint8Array", +// "value": "6a74fdca101bc71347f3ca67f5d62c49c6b906e7d298ddb879b492bc9608a7ae" +// }, +// "index": 2, +// "sequence": 4294967295, +// "witnessUtxo": { +// "amount": "4984981264", +// "script": { +// "type": "Uint8Array", +// "value": "0014add70fb03578d3ac85aab80897395bb046223c92" +// } +// }, +// "partialSig": [ +// [ +// { +// "type": "Uint8Array", +// "value": "02f4d8696f9b275f4e10af63f03bcb7fbba7b1ed44dd9b12a973c8d20212beb8d1" +// }, +// { +// "type": "Uint8Array", +// "value": "3045022100cfd104f2751a744510cc5e07dbb1c48c597db3c69aa48e52de7be379a00db0d40220360c0e608c016a19a4bd19c9235b01f18c6e7998f439475cc8637fdd04d7cecf01" +// } +// ] +// ] +// }, +// { +// "finalScriptSig": { +// "type": "Uint8Array", +// "value": "" +// }, +// "txid": { +// "type": "Uint8Array", +// "value": "4f4fec6d79ff8a8cc2bf8b5e0841ede2bcae5281f0206af3da008914e7006fbb" +// }, +// "index": 2, +// "sequence": 4294967295, +// "witnessUtxo": { +// "amount": "4984981264", +// "script": { +// "type": "Uint8Array", +// "value": "0014add70fb03578d3ac85aab80897395bb046223c92" +// } +// }, +// "partialSig": [ +// [ +// { +// "type": "Uint8Array", +// "value": "02f4d8696f9b275f4e10af63f03bcb7fbba7b1ed44dd9b12a973c8d20212beb8d1" +// }, +// { +// "type": "Uint8Array", +// "value": "3045022100de829b10d533c05b3ff7d65caa3503e7d3c16ef5d1a83224c21de63c5f88531d02207d13d47f640aa4f85511293d363af5e7158c328b312e175f9e3e0290eaa5461801" +// } +// ] +// ] +// }, +// { +// "finalScriptSig": { +// "type": "Uint8Array", +// "value": "" +// }, +// "txid": { +// "type": "Uint8Array", +// "value": "700d9c3eedfcff0adabf1a83d16f198541629be13cd4127f0296450a855064cb" +// }, +// "index": 1, +// "sequence": 4294967295, +// "witnessUtxo": { +// "amount": "5000000", +// "script": { +// "type": "Uint8Array", +// "value": "5120bca90746e285c10235453757249fcac29178e418bef5492b5add21475f76232a" +// } +// }, +// "tapScriptSig": [ +// [ +// { +// "pubKey": { +// "type": "Uint8Array", +// "value": "bb7e175e63064479102ee0b69a719a9f54f8f1b29df17cfaa5437697393e7cfc" +// }, +// "leafHash": { +// "type": "Uint8Array", +// "value": "e24db130ab82d20d322c295aa18921a7fe87fb13df3d5b3b2ee0469e2a845114" +// } +// }, +// { +// "type": "Uint8Array", +// "value": "6d997b5d10bccd43e8c210c1b21685f866e14d3648954767cd8656311e3cff3b30c3581d4eafd4468a376af3ab8f305118fad37083fca5da48d3ab9953bfa360" +// } +// ] +// ], +// "tapLeafScript": [ +// [ +// { +// "version": 193, +// "internalKey": { +// "type": "Uint8Array", +// "value": "d6d94d6dd718c7ad15270bc3e3ed3058d4c2253942ff1c1cbea1b1105fd6cc91" +// }, +// "merklePath": [] +// }, +// { +// "type": "Uint8Array", +// "value": "205216652630455eb8546bbab45e6fdef6498eee683ed339f405d326414b05b192ad20bb7e175e63064479102ee0b69a719a9f54f8f1b29df17cfaa5437697393e7cfcacc0" +// } +// ] +// ], +// "tapInternalKey": { +// "type": "Uint8Array", +// "value": "d6d94d6dd718c7ad15270bc3e3ed3058d4c2253942ff1c1cbea1b1105fd6cc91" +// }, +// "tapMerkleRoot": { +// "type": "Uint8Array", +// "value": "e24db130ab82d20d322c295aa18921a7fe87fb13df3d5b3b2ee0469e2a845114" +// } +// } +// ], +// "outputs": [ +// { +// "amount": "12000000", +// "script": { +// "type": "Uint8Array", +// "value": "00145a81f36535980769bccc23c196337a78458abd1e" +// } +// }, +// { +// "amount": "10005000000", +// "script": { +// "type": "Uint8Array", +// "value": "5120bca90746e285c10235453757249fcac29178e418bef5492b5add21475f76232a" +// } +// }, +// { +// "amount": "4942943038", +// "script": { +// "type": "Uint8Array", +// "value": "0014add70fb03578d3ac85aab80897395bb046223c92" +// } +// } +// ], +// "opts": { +// "version": 2, +// "lockTime": 0, +// "PSBTVersion": 0 +// } +// } + +export const TEST_WITHDRAW_PSBT_PARTIALLY_SIGNED_WITHDRAW_PSBT_1 = + '70736274ff01009c0200000001acf3a308a937ebcc2464fa33f99f1197145b49a7124a72f5511666649d3236030000000000f0ffffff034c1d0000000000001600145a81f36535980769bccc23c196337a78458abd1e404b4c00000000002251203789ed985ab9d1c94f5889973376a88d9940835206461151685a7a3fbb84de599a2c4c0000000000160014add70fb03578d3ac85aab80897395bb046223c92000000000001012b80969800000000002251203789ed985ab9d1c94f5889973376a88d9940835206461151685a7a3fbb84de594114bb7e175e63064479102ee0b69a719a9f54f8f1b29df17cfaa5437697393e7cfce24db130ab82d20d322c295aa18921a7fe87fb13df3d5b3b2ee0469e2a84511440525267fb9b7ea3797aad490251906662f24599c086733a95f33aa1c25c6e47d408d58c8be7a56edb491d56741744e85b746366f9175754f053a7703e69f6ab392215c1e52a5f154612da28faade658332157966492aa20a523162a8b584682a23dc72645205216652630455eb8546bbab45e6fdef6498eee683ed339f405d326414b05b192ad20bb7e175e63064479102ee0b69a719a9f54f8f1b29df17cfaa5437697393e7cfcacc0011720e52a5f154612da28faade658332157966492aa20a523162a8b584682a23dc726011820e24db130ab82d20d322c295aa18921a7fe87fb13df3d5b3b2ee0469e2a84511400000000'; +// Readable format: +// { +// "global": { +// "unsignedTx": { +// "version": 2, +// "segwitFlag": false, +// "inputs": [ +// { +// "txid": { +// "type": "Uint8Array", +// "value": "0336329d64661651f5724a12a7495b1497119ff933fa6424cceb37a908a3f3ac" +// }, +// "index": 0, +// "finalScriptSig": { +// "type": "Uint8Array", +// "value": "" +// }, +// "sequence": 4294967280 +// } +// ], +// "outputs": [ +// { +// "amount": "7500", +// "script": { +// "type": "Uint8Array", +// "value": "00145a81f36535980769bccc23c196337a78458abd1e" +// } +// }, +// { +// "amount": "5000000", +// "script": { +// "type": "Uint8Array", +// "value": "51203789ed985ab9d1c94f5889973376a88d9940835206461151685a7a3fbb84de59" +// } +// }, +// { +// "amount": "4992154", +// "script": { +// "type": "Uint8Array", +// "value": "0014add70fb03578d3ac85aab80897395bb046223c92" +// } +// } +// ], +// "lockTime": 0 +// }, +// "txVersion": 2 +// }, +// "inputs": [ +// { +// "finalScriptSig": { +// "type": "Uint8Array", +// "value": "" +// }, +// "txid": { +// "type": "Uint8Array", +// "value": "0336329d64661651f5724a12a7495b1497119ff933fa6424cceb37a908a3f3ac" +// }, +// "index": 0, +// "sequence": 4294967280, +// "witnessUtxo": { +// "amount": "10000000", +// "script": { +// "type": "Uint8Array", +// "value": "51203789ed985ab9d1c94f5889973376a88d9940835206461151685a7a3fbb84de59" +// } +// }, +// "tapScriptSig": [ +// [ +// { +// "pubKey": { +// "type": "Uint8Array", +// "value": "bb7e175e63064479102ee0b69a719a9f54f8f1b29df17cfaa5437697393e7cfc" +// }, +// "leafHash": { +// "type": "Uint8Array", +// "value": "e24db130ab82d20d322c295aa18921a7fe87fb13df3d5b3b2ee0469e2a845114" +// } +// }, +// { +// "type": "Uint8Array", +// "value": "525267fb9b7ea3797aad490251906662f24599c086733a95f33aa1c25c6e47d408d58c8be7a56edb491d56741744e85b746366f9175754f053a7703e69f6ab39" +// } +// ] +// ], +// "tapLeafScript": [ +// [ +// { +// "version": 193, +// "internalKey": { +// "type": "Uint8Array", +// "value": "e52a5f154612da28faade658332157966492aa20a523162a8b584682a23dc726" +// }, +// "merklePath": [] +// }, +// { +// "type": "Uint8Array", +// "value": "205216652630455eb8546bbab45e6fdef6498eee683ed339f405d326414b05b192ad20bb7e175e63064479102ee0b69a719a9f54f8f1b29df17cfaa5437697393e7cfcacc0" +// } +// ] +// ], +// "tapInternalKey": { +// "type": "Uint8Array", +// "value": "e52a5f154612da28faade658332157966492aa20a523162a8b584682a23dc726" +// }, +// "tapMerkleRoot": { +// "type": "Uint8Array", +// "value": "e24db130ab82d20d322c295aa18921a7fe87fb13df3d5b3b2ee0469e2a845114" +// } +// } +// ], +// "outputs": [ +// { +// "amount": "7500", +// "script": { +// "type": "Uint8Array", +// "value": "00145a81f36535980769bccc23c196337a78458abd1e" +// } +// }, +// { +// "amount": "5000000", +// "script": { +// "type": "Uint8Array", +// "value": "51203789ed985ab9d1c94f5889973376a88d9940835206461151685a7a3fbb84de59" +// } +// }, +// { +// "amount": "4992154", +// "script": { +// "type": "Uint8Array", +// "value": "0014add70fb03578d3ac85aab80897395bb046223c92" +// } +// } +// ], +// "opts": { +// "version": 2, +// "lockTime": 0, +// "PSBTVersion": 0 +// } +// } + +export const TEST_WITHDRAW_PSBT_PARTIALLY_SIGNED_WITHDRAW_PSBT_2 = + '70736274ff0100a80200000001b2097c129d74fc6e80d673ba3a83e4858c046444993991cad52f66d28ff65b970000000000f0ffffff034c1d0000000000001600145a81f36535980769bccc23c196337a78458abd1e404b4c0000000000225120b033a3d9562d22aa4a5476ae9cb6a5858b0959e084b49a3fd92edfba87e8254f822c4c0000000000225120676504fcaf89119cc9762c2f867aaa56aa3fffc85158f7dd61da345cdbf4a9be000000000001012b8096980000000000225120b033a3d9562d22aa4a5476ae9cb6a5858b0959e084b49a3fd92edfba87e8254f4114bb7e175e63064479102ee0b69a719a9f54f8f1b29df17cfaa5437697393e7cfce24db130ab82d20d322c295aa18921a7fe87fb13df3d5b3b2ee0469e2a84511440c06edfdd88bc66ffec4c8ff30fd3f6b38e25ebd85c09635a7b1594f66af614ba320c4d98e1c6017f38c8d752227ca24a5cd178cb462a4444c465fc773738e4b52215c01fba2e8661f2ed0a747d76578d3a6508a31879569d97da86a0a207c2538ebaa445205216652630455eb8546bbab45e6fdef6498eee683ed339f405d326414b05b192ad20bb7e175e63064479102ee0b69a719a9f54f8f1b29df17cfaa5437697393e7cfcacc00117201fba2e8661f2ed0a747d76578d3a6508a31879569d97da86a0a207c2538ebaa4011820e24db130ab82d20d322c295aa18921a7fe87fb13df3d5b3b2ee0469e2a84511400000000'; +// Readable format: +// { +// "global": { +// "unsignedTx": { +// "version": 2, +// "segwitFlag": false, +// "inputs": [ +// { +// "txid": { +// "type": "Uint8Array", +// "value": "975bf68fd2662fd5ca9139994464048c85e4833aba73d6806efc749d127c09b2" +// }, +// "index": 0, +// "finalScriptSig": { +// "type": "Uint8Array", +// "value": "" +// }, +// "sequence": 4294967280 +// } +// ], +// "outputs": [ +// { +// "amount": "7500", +// "script": { +// "type": "Uint8Array", +// "value": "00145a81f36535980769bccc23c196337a78458abd1e" +// } +// }, +// { +// "amount": "5000000", +// "script": { +// "type": "Uint8Array", +// "value": "5120b033a3d9562d22aa4a5476ae9cb6a5858b0959e084b49a3fd92edfba87e8254f" +// } +// }, +// { +// "amount": "4992130", +// "script": { +// "type": "Uint8Array", +// "value": "5120676504fcaf89119cc9762c2f867aaa56aa3fffc85158f7dd61da345cdbf4a9be" +// } +// } +// ], +// "lockTime": 0 +// }, +// "txVersion": 2 +// }, +// "inputs": [ +// { +// "finalScriptSig": { +// "type": "Uint8Array", +// "value": "" +// }, +// "txid": { +// "type": "Uint8Array", +// "value": "975bf68fd2662fd5ca9139994464048c85e4833aba73d6806efc749d127c09b2" +// }, +// "index": 0, +// "sequence": 4294967280, +// "witnessUtxo": { +// "amount": "10000000", +// "script": { +// "type": "Uint8Array", +// "value": "5120b033a3d9562d22aa4a5476ae9cb6a5858b0959e084b49a3fd92edfba87e8254f" +// } +// }, +// "tapScriptSig": [ +// [ +// { +// "pubKey": { +// "type": "Uint8Array", +// "value": "bb7e175e63064479102ee0b69a719a9f54f8f1b29df17cfaa5437697393e7cfc" +// }, +// "leafHash": { +// "type": "Uint8Array", +// "value": "e24db130ab82d20d322c295aa18921a7fe87fb13df3d5b3b2ee0469e2a845114" +// } +// }, +// { +// "type": "Uint8Array", +// "value": "c06edfdd88bc66ffec4c8ff30fd3f6b38e25ebd85c09635a7b1594f66af614ba320c4d98e1c6017f38c8d752227ca24a5cd178cb462a4444c465fc773738e4b5" +// } +// ] +// ], +// "tapLeafScript": [ +// [ +// { +// "version": 192, +// "internalKey": { +// "type": "Uint8Array", +// "value": "1fba2e8661f2ed0a747d76578d3a6508a31879569d97da86a0a207c2538ebaa4" +// }, +// "merklePath": [] +// }, +// { +// "type": "Uint8Array", +// "value": "205216652630455eb8546bbab45e6fdef6498eee683ed339f405d326414b05b192ad20bb7e175e63064479102ee0b69a719a9f54f8f1b29df17cfaa5437697393e7cfcacc0" +// } +// ] +// ], +// "tapInternalKey": { +// "type": "Uint8Array", +// "value": "1fba2e8661f2ed0a747d76578d3a6508a31879569d97da86a0a207c2538ebaa4" +// }, +// "tapMerkleRoot": { +// "type": "Uint8Array", +// "value": "e24db130ab82d20d322c295aa18921a7fe87fb13df3d5b3b2ee0469e2a845114" +// } +// } +// ], +// "outputs": [ +// { +// "amount": "7500", +// "script": { +// "type": "Uint8Array", +// "value": "00145a81f36535980769bccc23c196337a78458abd1e" +// } +// }, +// { +// "amount": "5000000", +// "script": { +// "type": "Uint8Array", +// "value": "5120b033a3d9562d22aa4a5476ae9cb6a5858b0959e084b49a3fd92edfba87e8254f" +// } +// }, +// { +// "amount": "4992130", +// "script": { +// "type": "Uint8Array", +// "value": "5120676504fcaf89119cc9762c2f867aaa56aa3fffc85158f7dd61da345cdbf4a9be" +// } +// } +// ], +// "opts": { +// "version": 2, +// "lockTime": 0, +// "PSBTVersion": 0 +// } +// } diff --git a/tests/mocks/constants.ts b/tests/mocks/constants.ts index 9c3da76..44ac1a5 100644 --- a/tests/mocks/constants.ts +++ b/tests/mocks/constants.ts @@ -48,3 +48,18 @@ export const TEST_REGTEST_ATTESTOR_APIS = [ ]; export const TEST_REGTEST_ATTESTOR_EXTENDED_GROUP_PUBLIC_KEY = 'tpubDDqN2CmTDKaGeqXMayfCZEvjZqntifi4r1ztmRWsGuE1VE4bosR3mBKQwVaCxZcmg8R1nHDMDzDmzjoccBMgwZV1hhz51tAXVnhjABCQcwA'; + +export const TEST_ALICE_NATIVE_SEGWIT_PAYMENT_SCRIPT_1 = + '0014add70fb03578d3ac85aab80897395bb046223c92'; + +export const TEST_ALICE_NATIVE_SEGWIT_PUBLIC_KEY_1 = + '02f4d8696f9b275f4e10af63f03bcb7fbba7b1ed44dd9b12a973c8d20212beb8d1'; + +export const TEST_ALICE_NATIVE_SEGWIT_PUBLIC_KEY_2 = + '0385c8f8844b7c197b96d933b01b2b82b97b9f9d55c81947e1db5cfb3de375508b'; + +export const TEST_ALICE_TAPROOT_PUBLIC_KEY_1 = + '03bb7e175e63064479102ee0b69a719a9f54f8f1b29df17cfaa5437697393e7cfc'; + +export const TEST_ALICE_TAPROOT_PUBLIC_KEY_2 = + '03940f5559dc92a3253e8699e9c632badfe5c2b1a13a113b85022d30cdab9c0ed8'; diff --git a/tests/unit/bitcoin-functions.test.ts b/tests/unit/bitcoin-functions.test.ts new file mode 100644 index 0000000..113520d --- /dev/null +++ b/tests/unit/bitcoin-functions.test.ts @@ -0,0 +1,115 @@ +import { hexToBytes } from '@noble/hashes/utils'; +import { Transaction, p2tr, p2wpkh } from '@scure/btc-signer'; +import { regtest } from 'bitcoinjs-lib/src/networks'; + +import { + ecdsaPublicKeyToSchnorr, + finalizeUserInputs, + getInputIndicesByScript, +} from '../../src/functions/bitcoin/bitcoin-functions'; +import { + TEST_DEPOSIT_PSBT_PARTIALLY_SIGNED_DEPOSIT_PSBT_1, + TEST_DEPOSIT_PSBT_PARTIALLY_SIGNED_DEPOSIT_PSBT_2, + TEST_DEPOSIT_PSBT_PARTIALLY_SIGNED_DEPOSIT_PSBT_3, + TEST_WITHDRAW_PSBT_PARTIALLY_SIGNED_WITHDRAW_PSBT_1, +} from '../mocks/bitcoin-transaction.test.constants'; +import { + TEST_ALICE_NATIVE_SEGWIT_PAYMENT_SCRIPT_1, + TEST_ALICE_NATIVE_SEGWIT_PUBLIC_KEY_1, + TEST_ALICE_NATIVE_SEGWIT_PUBLIC_KEY_2, + TEST_ALICE_TAPROOT_PUBLIC_KEY_1, + TEST_ALICE_TAPROOT_PUBLIC_KEY_2, +} from '../mocks/constants'; + +describe('Bitcoin Functions', () => { + describe('getInputIndicesByScript', () => { + it('correctly retrieves one input index by script', () => { + const transaction = Transaction.fromPSBT( + hexToBytes(TEST_DEPOSIT_PSBT_PARTIALLY_SIGNED_DEPOSIT_PSBT_1) + ); + const aliceScript = hexToBytes(TEST_ALICE_NATIVE_SEGWIT_PAYMENT_SCRIPT_1); + const inputIndices = getInputIndicesByScript(aliceScript, transaction); + expect(inputIndices).toEqual([0]); + }); + + it('correctly retrieves multiple input indices by script', () => { + const transaction = Transaction.fromPSBT( + hexToBytes(TEST_DEPOSIT_PSBT_PARTIALLY_SIGNED_DEPOSIT_PSBT_3) + ); + const aliceScript = hexToBytes(TEST_ALICE_NATIVE_SEGWIT_PAYMENT_SCRIPT_1); + const inputIndices = getInputIndicesByScript(aliceScript, transaction); + expect(inputIndices).toEqual([0, 1, 2]); + }); + + it('correctly retrieve an empty array when no inputs found with given script', () => { + const transaction = Transaction.fromPSBT( + hexToBytes(TEST_WITHDRAW_PSBT_PARTIALLY_SIGNED_WITHDRAW_PSBT_1) + ); + const aliceScript = hexToBytes(TEST_ALICE_NATIVE_SEGWIT_PAYMENT_SCRIPT_1); + const inputIndices = getInputIndicesByScript(aliceScript, transaction); + expect(inputIndices).toEqual([]); + }); + }); + + describe('finalizeUserInputs', () => { + it('correctly finalizes inputs given a transaction and a native segwit payment script', () => { + const transaction = Transaction.fromPSBT( + hexToBytes(TEST_DEPOSIT_PSBT_PARTIALLY_SIGNED_DEPOSIT_PSBT_1) + ); + + const alicePublicKey = Buffer.from(TEST_ALICE_NATIVE_SEGWIT_PUBLIC_KEY_1, 'hex'); + const alicePayment = p2wpkh(alicePublicKey, regtest); + + finalizeUserInputs(transaction, alicePayment); + + expect(transaction.getInput(0).finalScriptWitness).toBeDefined(); + expect(transaction.getInput(1).finalScriptWitness).toBeUndefined(); + }); + + it('does not finalize inputs given a transaction and a native segwit payment script that is not included in this transaction', () => { + const transaction = Transaction.fromPSBT( + hexToBytes(TEST_DEPOSIT_PSBT_PARTIALLY_SIGNED_DEPOSIT_PSBT_1) + ); + + const alicePublicKey = Buffer.from(TEST_ALICE_NATIVE_SEGWIT_PUBLIC_KEY_2, 'hex'); + const alicePayment = p2wpkh(alicePublicKey, regtest); + + finalizeUserInputs(transaction, alicePayment); + + expect(transaction.getInput(0).finalScriptWitness).toBeUndefined(); + expect(transaction.getInput(1).finalScriptWitness).toBeUndefined(); + }); + }); + + it('correctly finalizes inputs given a transaction and a taproot payment script', () => { + const transaction = Transaction.fromPSBT( + hexToBytes(TEST_DEPOSIT_PSBT_PARTIALLY_SIGNED_DEPOSIT_PSBT_2) + ); + + const alicePublicKey = ecdsaPublicKeyToSchnorr( + Buffer.from(TEST_ALICE_TAPROOT_PUBLIC_KEY_1, 'hex') + ); + const alicePayment = p2tr(alicePublicKey, undefined, regtest); + + finalizeUserInputs(transaction, alicePayment); + + expect(transaction.getInput(0).finalScriptWitness).toBeDefined(); + expect(transaction.getInput(1).finalScriptWitness).toBeUndefined(); + }); + + it('does not finalize inputs given a transaction and a taproot payment script that is not included in this transaction', () => { + const transaction = Transaction.fromPSBT( + hexToBytes(TEST_DEPOSIT_PSBT_PARTIALLY_SIGNED_DEPOSIT_PSBT_2) + ); + + const alicePublicKey = ecdsaPublicKeyToSchnorr( + Buffer.from(TEST_ALICE_TAPROOT_PUBLIC_KEY_2, 'hex') + ); + const alicePayment = p2tr(alicePublicKey, undefined, regtest); + + finalizeUserInputs(transaction, alicePayment); + + expect(transaction.getInput(0).finalScriptWitness).toBeUndefined(); + expect(transaction.getInput(1).finalScriptWitness).toBeUndefined(); + }); +}); diff --git a/tests/unit/utility.test.ts b/tests/unit/utility.test.ts new file mode 100644 index 0000000..546246a --- /dev/null +++ b/tests/unit/utility.test.ts @@ -0,0 +1,145 @@ +import { + compareUint8Arrays, + createRangeFromLength, + customShiftValue, + delay, + isDefined, + isUndefined, + reverseBytes, + shiftValue, + truncateAddress, + unshiftValue, +} from '../../src/utilities'; + +describe('Utility Functions', () => { + describe('shiftValue', () => { + it('correctly shifts the value by a power of 10^8', () => { + const value = 1; + const shiftedValue = shiftValue(value); + expect(shiftedValue).toBe(100000000); + }); + }); + + describe('unshiftValue', () => { + it('correctly unshifts the value by a power of 10^8', () => { + const value = 100000000; + const unshiftedValue = unshiftValue(value); + expect(unshiftedValue).toBe(1); + }); + }); + + describe('customShiftValue', () => { + it('correctly shifts the value based on the provided parameters', () => { + const value = 1; + const shift = 12; + const shiftedValue = customShiftValue(value, shift, false); + expect(shiftedValue).toBe(1000000000000); + }); + + it('correctly unshifts the value based on the provided parameters', () => { + const value = 100000000; + const shift = 8; + const unshiftedValue = customShiftValue(value, shift, true); + expect(unshiftedValue).toBe(1); + }); + }); + + describe('truncateAddress', () => { + it('correctly truncates the address to the specified format', () => { + const address = '0x1234567890abcdef'; + const truncatedAddress = truncateAddress(address); + expect(truncatedAddress).toBe('0x12...cdef'); + }); + }); + + describe('createRangeFromLength', () => { + it('creates a range of numbers based on the provided length', () => { + const length = 5; + const range = createRangeFromLength(length); + expect(range).toStrictEqual([0, 1, 2, 3, 4]); + }); + }); + + describe('isUndefined', () => { + it('correctly identifies if a value is undefined', () => { + const value = undefined; + const isValueUndefined = isUndefined(value); + expect(isValueUndefined).toBe(true); + }); + + it('correctly identifies if a value is not undefined', () => { + const value = 1; + const isValueUndefined = isUndefined(value); + expect(isValueUndefined).toBe(false); + }); + }); + + describe('isDefined', () => { + it('correctly identifies if a value is defined', () => { + const value = 1; + const isValueDefined = isDefined(value); + expect(isValueDefined).toBe(true); + }); + + it('correctly identifies if a value is not defined', () => { + const value = undefined; + const isValueDefined = isDefined(value); + expect(isValueDefined).toBe(false); + }); + }); + + describe('compareUint8Arrays', () => { + it('correctly compares two Uint8Arrays for equality', () => { + const uint8ArrayA = new Uint8Array([ + 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x21, 0xff, 0x00, 0x7f, + 0x80, 0xfe, 0x01, 0x76, 0x31, 0x30, + ]); + const uint8ArrayB = new Uint8Array([ + 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x21, 0xff, 0x00, 0x7f, + 0x80, 0xfe, 0x01, 0x76, 0x31, 0x30, + ]); + const areArraysEqual = compareUint8Arrays(uint8ArrayA, uint8ArrayB); + expect(areArraysEqual).toBe(true); + }); + + it('correctly identifies two different Uint8Arrays', () => { + const uint8ArrayA = new Uint8Array([ + 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x21, 0xff, 0x00, 0x7f, + 0x80, 0xfe, 0x01, 0x76, 0x31, 0x30, + ]); + const uint8ArrayB = new Uint8Array([ + 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x21, 0xff, 0x00, 0x7f, + 0x80, 0xfe, 0x01, 0x76, 0x31, 0x31, + ]); + + const areArraysEqual = compareUint8Arrays(uint8ArrayA, uint8ArrayB); + expect(areArraysEqual).toBe(false); + }); + }); + + describe('reverseBytes', () => { + it('correctly reverses the bytes of a Uint8Array', () => { + const uint8Array = new Uint8Array([0x48, 0x65, 0x6c, 0x6c, 0x6f]); + const reversedUint8Array = reverseBytes(uint8Array); + expect(reversedUint8Array).toStrictEqual(new Uint8Array([0x6f, 0x6c, 0x6c, 0x65, 0x48])); + }); + + it('correctly reverses the bytes of a Buffer', () => { + const buffer = Buffer.from([0x48, 0x65, 0x6c, 0x6c, 0x6f]); + const reversedBuffer = reverseBytes(buffer); + expect(reversedBuffer).toStrictEqual(Buffer.from([0x6f, 0x6c, 0x6c, 0x65, 0x48])); + }); + }); + + describe('delay', () => { + it('delays execution for the specified number of milliseconds', () => { + const delayTime = 10; + const startTime = Date.now(); + delay(delayTime).then(() => { + const endTime = Date.now(); + const elapsedTime = endTime - startTime; + expect(elapsedTime).toBeGreaterThanOrEqual(delayTime); + }); + }); + }); +});