From bc4f545cdefbd0d00a7b1eff1bf2fcf01011aa88 Mon Sep 17 00:00:00 2001 From: Tomasz Slabon Date: Wed, 25 Oct 2023 11:52:36 +0200 Subject: [PATCH] Replaced string with Hex --- typescript/scripts/refund.ts | 11 +- typescript/src/index.ts | 3 - typescript/src/lib/bitcoin/address.ts | 25 +- typescript/src/lib/bitcoin/client.ts | 3 +- typescript/src/lib/bitcoin/ecdsa-key.ts | 27 +- typescript/src/lib/bitcoin/hash.ts | 14 +- typescript/src/lib/bitcoin/header.ts | 11 +- typescript/src/lib/bitcoin/script.ts | 17 +- typescript/src/lib/bitcoin/spv.ts | 33 +- typescript/src/lib/bitcoin/tx.ts | 34 +- typescript/src/lib/contracts/bridge.ts | 80 ++-- typescript/src/lib/contracts/tbtc-token.ts | 7 +- typescript/src/lib/electrum/client.ts | 21 +- typescript/src/lib/ethereum/bridge.ts | 105 ++--- typescript/src/lib/ethereum/tbtc-token.ts | 19 +- typescript/src/services/deposits/deposit.ts | 20 +- .../src/services/deposits/deposits-service.ts | 3 +- typescript/src/services/deposits/funding.ts | 2 +- typescript/src/services/deposits/refund.ts | 19 +- typescript/src/services/maintenance/spv.ts | 3 +- .../src/services/maintenance/wallet-tx.ts | 58 +-- .../redemptions/redemptions-service.ts | 25 +- typescript/test/data/deposit-refund.ts | 31 +- typescript/test/data/deposit-sweep.ts | 197 ++++---- typescript/test/data/electrum.ts | 69 +-- typescript/test/data/proof.ts | 421 +++++++++++------- typescript/test/data/redemption.ts | 186 ++++---- typescript/test/lib/bitcoin.test.ts | 131 +++--- typescript/test/lib/electrum.test.ts | 5 +- typescript/test/lib/ethereum.test.ts | 101 +++-- typescript/test/services/deposits.test.ts | 23 +- typescript/test/services/maintenance.test.ts | 2 +- typescript/test/services/redemptions.test.ts | 39 +- typescript/test/utils/mock-bitcoin-client.ts | 9 +- typescript/test/utils/mock-bridge.ts | 84 ++-- typescript/test/utils/mock-tbtc-token.ts | 8 +- 36 files changed, 1047 insertions(+), 799 deletions(-) diff --git a/typescript/scripts/refund.ts b/typescript/scripts/refund.ts index 11931b978..27a941b04 100644 --- a/typescript/scripts/refund.ts +++ b/typescript/scripts/refund.ts @@ -9,6 +9,7 @@ import { DepositScript, ElectrumClient, ElectrumCredentials, + Hex, } from "../src" program @@ -60,15 +61,15 @@ const depositJson = JSON.parse(fs.readFileSync(depositJsonPath, "utf-8")) const deposit: DepositReceipt = { depositor: depositJson.depositor, - walletPublicKeyHash: depositJson.walletPublicKeyHash, - refundPublicKeyHash: depositJson.refundPublicKeyHash, - blindingFactor: depositJson.blindingFactor, - refundLocktime: depositJson.refundLocktime, + walletPublicKeyHash: Hex.from(depositJson.walletPublicKeyHash), + refundPublicKeyHash: Hex.from(depositJson.refundPublicKeyHash), + blindingFactor: Hex.from(depositJson.blindingFactor), + refundLocktime: Hex.from(depositJson.refundLocktime), } const recoveryAddress = depositJson.btcRecoveryAddress console.log("======= refund provided data ========") -console.log("deposit JSON: ", deposit) +console.log("deposit JSON: ", depositJson) console.log("deposit recovery amount: ", refundAmount) console.log("deposit transaction ID: ", transactionId) console.log("deposit transaction index: ", transactionIndex) diff --git a/typescript/src/index.ts b/typescript/src/index.ts index 628275200..2ee4bcafd 100644 --- a/typescript/src/index.ts +++ b/typescript/src/index.ts @@ -12,6 +12,3 @@ export * from "./services/redemptions" // Export the entrypoint module. export * from "./services/tbtc" - -// TODO: Replace all properties that are expected to be un-prefixed hexadecimal -// strings with a Hex type to increase API consistency. diff --git a/typescript/src/lib/bitcoin/address.ts b/typescript/src/lib/bitcoin/address.ts index 36f660ba2..e8dd25c5a 100644 --- a/typescript/src/lib/bitcoin/address.ts +++ b/typescript/src/lib/bitcoin/address.ts @@ -29,20 +29,19 @@ function publicKeyToAddress( /** * Converts a public key hash into a P2PKH/P2WPKH address. - * @param publicKeyHash Public key hash that will be encoded. Must be an - * unprefixed hex string (without 0x prefix). + * @param publicKeyHash Public key hash that will be encoded. * @param witness If true, a witness public key hash will be encoded and * P2WPKH address will be returned. Returns P2PKH address otherwise * @param bitcoinNetwork Network the address should be encoded for. - * @returns P2PKH or P2WPKH address encoded from the given public key hash + * @returns P2PKH or P2WPKH address encoded from the given public key hash. * @throws Throws an error if network is not supported. */ function publicKeyHashToAddress( - publicKeyHash: string, + publicKeyHash: Hex, witness: boolean, bitcoinNetwork: BitcoinNetwork ): string { - const hash = Buffer.from(publicKeyHash, "hex") + const hash = publicKeyHash.toBuffer() const network = toBitcoinJsLibNetwork(bitcoinNetwork) return witness ? payments.p2wpkh({ hash, network }).address! @@ -54,27 +53,25 @@ function publicKeyHashToAddress( * provided address is not PKH-based. * @param address P2PKH or P2WPKH address that will be decoded. * @param bitcoinNetwork Network the address should be decoded for. - * @returns Public key hash decoded from the address. This will be an unprefixed - * hex string (without 0x prefix). + * @returns Public key hash decoded from the address. */ function addressToPublicKeyHash( address: string, bitcoinNetwork: BitcoinNetwork -): string { +): Hex { const network = toBitcoinJsLibNetwork(bitcoinNetwork) try { // Try extracting hash from P2PKH address. - const hash = payments.p2pkh({ address: address, network }).hash! - return hash.toString("hex") + return Hex.from(payments.p2pkh({ address: address, network }).hash!) } catch (err) {} try { // Try extracting hash from P2WPKH address. - const hash = payments.p2wpkh({ address: address, network }).hash! - return hash.toString("hex") + return Hex.from(payments.p2wpkh({ address: address, network }).hash!) } catch (err) {} + // If neither of them succeeded, throw an error. throw new Error("Address must be P2PKH or P2WPKH valid for given network") } @@ -82,7 +79,7 @@ function addressToPublicKeyHash( * Converts an address to the respective output script. * @param address BTC address. * @param bitcoinNetwork Bitcoin network corresponding to the address. - * @returns The un-prefixed and not prepended with length output script. + * @returns The output script not prepended with length. */ function addressToOutputScript( address: string, @@ -95,7 +92,7 @@ function addressToOutputScript( /** * Converts an output script to the respective network-specific address. - * @param script The unprefixed and not prepended with length output script. + * @param script The output script not prepended with length. * @param bitcoinNetwork Bitcoin network the address should be produced for. * @returns The Bitcoin address. */ diff --git a/typescript/src/lib/bitcoin/client.ts b/typescript/src/lib/bitcoin/client.ts index 6e3d512fe..2df7e1147 100644 --- a/typescript/src/lib/bitcoin/client.ts +++ b/typescript/src/lib/bitcoin/client.ts @@ -1,6 +1,7 @@ import { BitcoinNetwork } from "./network" import { BitcoinRawTx, BitcoinTx, BitcoinTxHash, BitcoinUtxo } from "./tx" import { BitcoinTxMerkleBranch } from "./spv" +import { Hex } from "../../lib/utils" /** * Represents a Bitcoin client. @@ -66,7 +67,7 @@ export interface BitcoinClient { * block. * @return Concatenation of block headers in a hexadecimal format. */ - getHeadersChain(blockHeight: number, chainLength: number): Promise + getHeadersChain(blockHeight: number, chainLength: number): Promise /** * Get Merkle branch for a given transaction. diff --git a/typescript/src/lib/bitcoin/ecdsa-key.ts b/typescript/src/lib/bitcoin/ecdsa-key.ts index f622490be..ffde61f65 100644 --- a/typescript/src/lib/bitcoin/ecdsa-key.ts +++ b/typescript/src/lib/bitcoin/ecdsa-key.ts @@ -9,37 +9,36 @@ import { BitcoinNetwork, toBitcoinJsLibNetwork } from "./network" * @param publicKey - Public key that should be checked. * @returns True if the key is a compressed Bitcoin public key, false otherwise. */ -function isCompressedPublicKey(publicKey: string): boolean { +function isCompressedPublicKey(publicKey: Hex): boolean { + const publicKeyStr = publicKey.toString() + // Must have 33 bytes and 02 or 03 prefix. return ( - publicKey.length == 66 && - (publicKey.substring(0, 2) == "02" || publicKey.substring(0, 2) == "03") + publicKeyStr.length == 66 && + (publicKeyStr.substring(0, 2) == "02" || + publicKeyStr.substring(0, 2) == "03") ) } /** * Compresses the given uncompressed Bitcoin public key. - * @param publicKey Uncompressed 64-byte public key as an unprefixed hex string. + * @param publicKey Uncompressed 64-byte public key. * @returns Compressed 33-byte public key prefixed with 02 or 03. */ -function compressPublicKey(publicKey: string | Hex): string { - if (typeof publicKey === "string") { - publicKey = Hex.from(publicKey) - } - - publicKey = publicKey.toString() +function compressPublicKey(publicKey: Hex): string { + const publicKeyStr = publicKey.toString() // Must have 64 bytes and no prefix. - if (publicKey.length != 128) { + if (publicKeyStr.length != 128) { throw new Error( "The public key parameter must be 64-byte. Neither 0x nor 04 prefix is allowed" ) } // The X coordinate is the first 32 bytes. - const publicKeyX = publicKey.substring(0, 64) + const publicKeyX = publicKeyStr.substring(0, 64) // The Y coordinate is the next 32 bytes. - const publicKeyY = publicKey.substring(64) + const publicKeyY = publicKeyStr.substring(64) const prefix = BigNumber.from(`0x${publicKeyY}`).mod(2).eq(0) ? "02" : "03" @@ -59,7 +58,7 @@ export const BitcoinPublicKeyUtils = { * @param privateKey Private key that should be used to create the key pair. * Should be passed in the WIF format. * @param bitcoinNetwork Bitcoin network the given key pair is relevant for. - * @returns Bitcoin key ring. + * @returns Bitcoin key pair. */ function createKeyPair( privateKey: string, diff --git a/typescript/src/lib/bitcoin/hash.ts b/typescript/src/lib/bitcoin/hash.ts index 876e69888..12bfa698f 100644 --- a/typescript/src/lib/bitcoin/hash.ts +++ b/typescript/src/lib/bitcoin/hash.ts @@ -4,21 +4,19 @@ import { Hex } from "../utils" /** * Computes the HASH160 (i.e. RIPEMD160(SHA256(text))) for the given text. * @param text Text the HASH160 is computed for. - * @returns Hash as a 20-byte un-prefixed hex string. + * @returns 20-byte-long hash. */ -function computeHash160(text: string): string { - const sha256Hash = utils.sha256( - Hex.from(Buffer.from(text, "hex")).toPrefixedString() - ) +function computeHash160(text: Hex): Hex { + const sha256Hash = utils.sha256(text.toPrefixedString()) const hash160 = utils.ripemd160(sha256Hash) - return Hex.from(hash160).toString() + return Hex.from(hash160) } /** * Computes the double SHA256 for the given text. * @param text Text the double SHA256 is computed for. - * @returns Hash as a 32-byte un-prefixed hex string. + * @returns 32-byte-long hash. * @dev Do not confuse it with computeSha256 which computes single SHA256. */ function computeHash256(text: Hex): Hex { @@ -40,7 +38,7 @@ function hashLEToBigNumber(hash: Hex): BigNumber { /** * Computes the single SHA256 for the given text. * @param text Text the single SHA256 is computed for. - * @returns Hash as a 32-byte un-prefixed hex string. + * @returns 32-byte-long hash. * @dev Do not confuse it with computeHash256 which computes double SHA256. */ function computeSha256(text: Hex): Hex { diff --git a/typescript/src/lib/bitcoin/header.ts b/typescript/src/lib/bitcoin/header.ts index 99faa237a..99f8f10cf 100644 --- a/typescript/src/lib/bitcoin/header.ts +++ b/typescript/src/lib/bitcoin/header.ts @@ -89,16 +89,15 @@ function deserializeHeader(rawHeader: Hex): BitcoinHeader { * @param rawHeadersChain - Raw Bitcoin block headers chain. * @returns Deserialized Bitcoin block headers. */ -function deserializeHeadersChain(rawHeadersChain: string): BitcoinHeader[] { - if (rawHeadersChain.length % 160 !== 0) { +function deserializeHeadersChain(rawHeadersChain: Hex): BitcoinHeader[] { + const headersChain = rawHeadersChain.toString() + if (headersChain.length % 160 !== 0) { throw new Error("Incorrect length of Bitcoin headers") } const result: BitcoinHeader[] = [] - for (let i = 0; i < rawHeadersChain.length; i += 160) { - result.push( - deserializeHeader(Hex.from(rawHeadersChain.substring(i, i + 160))) - ) + for (let i = 0; i < headersChain.length; i += 160) { + result.push(deserializeHeader(Hex.from(headersChain.substring(i, i + 160)))) } return result diff --git a/typescript/src/lib/bitcoin/script.ts b/typescript/src/lib/bitcoin/script.ts index a66c39305..a514bddbe 100644 --- a/typescript/src/lib/bitcoin/script.ts +++ b/typescript/src/lib/bitcoin/script.ts @@ -1,3 +1,4 @@ +import { Hex } from "../utils" import { payments } from "bitcoinjs-lib" /** @@ -5,9 +6,9 @@ import { payments } from "bitcoinjs-lib" * @param script The script to be checked. * @returns True if the script is P2PKH, false otherwise. */ -function isP2PKHScript(script: Buffer): boolean { +function isP2PKHScript(script: Hex): boolean { try { - payments.p2pkh({ output: script }) + payments.p2pkh({ output: script.toBuffer() }) return true } catch (err) { return false @@ -19,9 +20,9 @@ function isP2PKHScript(script: Buffer): boolean { * @param script The script to be checked. * @returns True if the script is P2WPKH, false otherwise. */ -function isP2WPKHScript(script: Buffer): boolean { +function isP2WPKHScript(script: Hex): boolean { try { - payments.p2wpkh({ output: script }) + payments.p2wpkh({ output: script.toBuffer() }) return true } catch (err) { return false @@ -33,9 +34,9 @@ function isP2WPKHScript(script: Buffer): boolean { * @param script The script to be checked. * @returns True if the script is P2SH, false otherwise. */ -function isP2SHScript(script: Buffer): boolean { +function isP2SHScript(script: Hex): boolean { try { - payments.p2sh({ output: script }) + payments.p2sh({ output: script.toBuffer() }) return true } catch (err) { return false @@ -47,9 +48,9 @@ function isP2SHScript(script: Buffer): boolean { * @param script The script to be checked. * @returns True if the script is P2WSH, false otherwise. */ -function isP2WSHScript(script: Buffer): boolean { +function isP2WSHScript(script: Hex): boolean { try { - payments.p2wsh({ output: script }) + payments.p2wsh({ output: script.toBuffer() }) return true } catch (err) { return false diff --git a/typescript/src/lib/bitcoin/spv.ts b/typescript/src/lib/bitcoin/spv.ts index 4deb1cec4..596fd4056 100644 --- a/typescript/src/lib/bitcoin/spv.ts +++ b/typescript/src/lib/bitcoin/spv.ts @@ -15,10 +15,9 @@ import { BitcoinHashUtils } from "./hash" */ export interface BitcoinSpvProof { /** - * The merkle proof of transaction inclusion in a block, as an un-prefixed - * hex string. + * The merkle proof of transaction inclusion in a block. */ - merkleProof: string + merkleProof: Hex /** * Transaction index in the block (0-indexed). @@ -26,10 +25,10 @@ export interface BitcoinSpvProof { txIndexInBlock: number /** - * Single byte-string of 80-byte block headers, lowest height first, as an - * un-prefixed hex string. + * Concatenated block headers in hexadecimal format. Each block header is + * 80-byte-long. The block header with the lowest height is first. */ - bitcoinHeaders: string + bitcoinHeaders: Hex } /** @@ -46,7 +45,7 @@ export interface BitcoinTxMerkleBranch { * in order to trace up to obtain the merkle root of the including block, * the deepest pairing first. Each hash is an unprefixed hex string. */ - merkle: string[] + merkle: Hex[] /** * The 0-based index of the transaction's position in the block. @@ -117,12 +116,12 @@ export async function assembleBitcoinSpvProof( * @param txMerkleBranch - Branch of a Merkle tree leading to a transaction. * @returns Transaction inclusion proof in hexadecimal form. */ -function createMerkleProof(txMerkleBranch: BitcoinTxMerkleBranch): string { +function createMerkleProof(txMerkleBranch: BitcoinTxMerkleBranch): Hex { let proof = Buffer.from("") txMerkleBranch.merkle.forEach(function (item) { - proof = Buffer.concat([proof, Buffer.from(item, "hex").reverse()]) + proof = Buffer.concat([proof, item.toBuffer().reverse()]) }) - return proof.toString("hex") + return Hex.from(proof) } /** @@ -315,19 +314,21 @@ function validateMerkleTreeHashes( } /** - * Splits a given Merkle proof string into an array of intermediate node hashes. - * @param merkleProof A string representation of the Merkle proof. + * Splits a given concatenated Merkle proof into an array of intermediate node + * hashes. + * @param merkleProof A concatenated representation of the Merkle proof. * @returns An array of intermediate node hashes. * @throws {Error} If the length of the Merkle proof is not a multiple of 64. */ -function splitMerkleProof(merkleProof: string): Hex[] { - if (merkleProof.length % 64 != 0) { +function splitMerkleProof(merkleProof: Hex): Hex[] { + const merkleProofStr = merkleProof.toString() + if (merkleProofStr.length % 64 != 0) { throw new Error("Incorrect length of Merkle proof") } const intermediateNodeHashes: Hex[] = [] - for (let i = 0; i < merkleProof.length; i += 64) { - intermediateNodeHashes.push(Hex.from(merkleProof.slice(i, i + 64))) + for (let i = 0; i < merkleProofStr.length; i += 64) { + intermediateNodeHashes.push(Hex.from(merkleProofStr.slice(i, i + 64))) } return intermediateNodeHashes diff --git a/typescript/src/lib/bitcoin/tx.ts b/typescript/src/lib/bitcoin/tx.ts index 3593ddfe6..da76eae56 100644 --- a/typescript/src/lib/bitcoin/tx.ts +++ b/typescript/src/lib/bitcoin/tx.ts @@ -102,26 +102,26 @@ export type BitcoinUtxo = BitcoinTxOutpoint & { */ export interface BitcoinRawTxVectors { /** - * Transaction version as an un-prefixed hex string. + * Transaction version as a hex string. */ - version: string + version: Hex /** * All transaction's inputs prepended by the number of transaction inputs, - * as an un-prefixed hex string. + * as a hex string. */ - inputs: string + inputs: Hex /** * All transaction's outputs prepended by the number of transaction outputs, - * as an un-prefixed hex string. + * as a hex string. */ - outputs: string + outputs: Hex /** - * Transaction locktime as an un-prefixed hex string. + * Transaction locktime as a hex string. */ - locktime: string + locktime: Hex } /** @@ -133,11 +133,11 @@ export interface BitcoinRawTxVectors { export function extractBitcoinRawTxVectors( rawTransaction: BitcoinRawTx ): BitcoinRawTxVectors { - const toHex = (bufferWriter: any): string => { - return bufferWriter.render().toString("hex") + const toHex = (bufferWriter: any): Hex => { + return Hex.from(bufferWriter.render()) } - const getTxInputVector = (tx: Tx): string => { + const getTxInputVector = (tx: Tx): Hex => { const buffer = bufio.write() buffer.writeVarint(tx.ins.length) tx.ins.forEach((input) => { @@ -149,7 +149,7 @@ export function extractBitcoinRawTxVectors( return toHex(buffer) } - const getTxOutputVector = (tx: Tx): string => { + const getTxOutputVector = (tx: Tx): Hex => { const buffer = bufio.write() buffer.writeVarint(tx.outs.length) tx.outs.forEach((output) => { @@ -159,13 +159,13 @@ export function extractBitcoinRawTxVectors( return toHex(buffer) } - const getTxVersion = (tx: Tx): string => { + const getTxVersion = (tx: Tx): Hex => { const buffer = bufio.write() buffer.writeU32(tx.version) return toHex(buffer) } - const getTxLocktime = (tx: Tx): string => { + const getTxLocktime = (tx: Tx): Hex => { const buffer = bufio.write() buffer.writeU32(tx.locktime) return toHex(buffer) @@ -207,12 +207,12 @@ function locktimeToNumber(locktimeLE: Buffer | string): number { * @param locktimeStartedAt - Unix timestamp in seconds determining the moment * of the locktime start. * @param locktimeDuration Locktime duration in seconds. - * @returns A 4-byte little-endian locktime as an un-prefixed hex string. + * @returns A 4-byte little-endian locktime. */ function calculateLocktime( locktimeStartedAt: number, locktimeDuration: number -): string { +): Hex { // Locktime is a Unix timestamp in seconds, computed as locktime start // timestamp plus locktime duration. const locktime = BigNumber.from(locktimeStartedAt + locktimeDuration) @@ -225,7 +225,7 @@ function calculateLocktime( // Bitcoin locktime is interpreted as little-endian integer, so we must // adhere to that convention by converting the locktime accordingly. - return locktimeHex.reverse().toString() + return locktimeHex.reverse() } /** diff --git a/typescript/src/lib/contracts/bridge.ts b/typescript/src/lib/contracts/bridge.ts index 0e26c1587..ebf9f1bec 100644 --- a/typescript/src/lib/contracts/bridge.ts +++ b/typescript/src/lib/contracts/bridge.ts @@ -32,13 +32,14 @@ export interface Bridge { * @param mainUtxo - Data of the wallet's main UTXO. * @param vault - Optional identifier of the vault the swept deposits should * be routed in. + * @returns Transaction hash of the submit deposit sweep proof transaction. */ submitDepositSweepProof( sweepTx: BitcoinRawTxVectors, sweepProof: BitcoinSpvProof, mainUtxo: BitcoinUtxo, vault?: ChainIdentifier - ): Promise + ): Promise /** * Reveals a given deposit to the on-chain contract. @@ -48,14 +49,14 @@ export interface Bridge { * @param deposit - Data of the revealed deposit * @param vault - Optional parameter denoting the vault the given deposit * should be routed to - * @returns Transaction hash of the reveal deposit transaction as string + * @returns Transaction hash of the reveal deposit transaction. */ revealDeposit( depositTx: BitcoinRawTxVectors, depositOutputIndex: number, deposit: DepositReceipt, vault?: ChainIdentifier - ): Promise + ): Promise /** * Gets a revealed deposit from the on-chain contract. @@ -76,16 +77,16 @@ export interface Bridge { * @param mainUtxo - The main UTXO of the wallet. Must match the main UTXO * held by the on-chain contract. * @param redeemerOutputScript - The output script that the redeemed funds will - * be locked to. Must be un-prefixed and not prepended with length. + * be locked to. Must not be prepended with length. * @param amount - The amount to be redeemed in satoshis. - * @returns Empty promise. + * @returns Transaction hash of the request redemption transaction. */ requestRedemption( - walletPublicKey: string, + walletPublicKey: Hex, mainUtxo: BitcoinUtxo, - redeemerOutputScript: string, + redeemerOutputScript: Hex, amount: BigNumber - ): Promise + ): Promise /** * Submits a redemption transaction proof to the on-chain contract. @@ -94,13 +95,14 @@ export interface Bridge { * @param mainUtxo - Data of the wallet's main UTXO * @param walletPublicKey - Bitcoin public key of the wallet. Must be in the * compressed form (33 bytes long with 02 or 03 prefix). + * @returns Transaction hash of the submit redemption proof transaction. */ submitRedemptionProof( redemptionTx: BitcoinRawTxVectors, redemptionProof: BitcoinSpvProof, mainUtxo: BitcoinUtxo, - walletPublicKey: string - ): Promise + walletPublicKey: Hex + ): Promise /** * Gets transaction proof difficulty factor from the on-chain contract. @@ -116,13 +118,12 @@ export interface Bridge { * targeted to. Must be in the compressed form (33 bytes long with 02 * or 03 prefix). * @param redeemerOutputScript The redeemer output script the redeemed funds - * are supposed to be locked on. Must be un-prefixed and not prepended - * with length. + * are supposed to be locked on. Must not be prepended with length. * @returns Promise with the pending redemption. */ pendingRedemptions( - walletPublicKey: string, - redeemerOutputScript: string + walletPublicKey: Hex, + redeemerOutputScript: Hex ): Promise /** @@ -131,13 +132,12 @@ export interface Bridge { * targeted to. Must be in the compressed form (33 bytes long with 02 * or 03 prefix). * @param redeemerOutputScript The redeemer output script the redeemed funds - * are supposed to be locked on. Must be un-prefixed and not prepended - * with length. + * are supposed to be locked on. Must not be prepended with length. * @returns Promise with the pending redemption. */ timedOutRedemptions( - walletPublicKey: string, - redeemerOutputScript: string + walletPublicKey: Hex, + redeemerOutputScript: Hex ): Promise /** @@ -146,7 +146,7 @@ export interface Bridge { * public key. If there is no active wallet at the moment, undefined * is returned. */ - activeWalletPublicKey(): Promise + activeWalletPublicKey(): Promise /** * Get emitted NewWalletRegisteredEvent events. @@ -192,31 +192,30 @@ export interface DepositReceipt { depositor: ChainIdentifier /** - * An 8-byte blinding factor as an un-prefixed hex string. Must be unique - * for the given depositor, wallet public key and refund public key. + * An 8-byte blinding factor. Must be unique for the given depositor, wallet + * public key and refund public key. */ - blindingFactor: string + blindingFactor: Hex /** - * Public key hash of the wallet that is meant to receive the deposit. Must - * be an unprefixed hex string (without 0x prefix). + * Public key hash of the wallet that is meant to receive the deposit. * - * You can use `computeHash160` function to get the hash from a plain text public key. + * You can use `computeHash160` function to get the hash from a public key. */ - walletPublicKeyHash: string + walletPublicKeyHash: Hex /** * Public key hash that is meant to be used during deposit refund after the - * locktime passes. Must be an unprefixed hex string (without 0x prefix). + * locktime passes. * - * You can use `computeHash160` function to get the hash from a plain text public key. + * You can use `computeHash160` function to get the hash from a public key. */ - refundPublicKeyHash: string + refundPublicKeyHash: Hex /** - * A 4-byte little-endian refund locktime as an un-prefixed hex string. + * A 4-byte little-endian refund locktime. */ - refundLocktime: string + refundLocktime: Hex } // eslint-disable-next-line valid-jsdoc @@ -227,18 +226,18 @@ export interface DepositReceipt { * validity is chain-specific. This parameter must be validated outside. */ export function validateDepositReceipt(receipt: DepositReceipt) { - if (receipt.blindingFactor.length != 16) { + if (receipt.blindingFactor.toString().length != 16) { throw new Error("Blinding factor must be an 8-byte number") } - if (receipt.walletPublicKeyHash.length != 40) { + if (receipt.walletPublicKeyHash.toString().length != 40) { throw new Error("Invalid wallet public key hash") } - if (receipt.refundPublicKeyHash.length != 40) { + if (receipt.refundPublicKeyHash.toString().length != 40) { throw new Error("Invalid refund public key hash") } - if (receipt.refundLocktime.length != 8) { + if (receipt.refundLocktime.toString().length != 8) { throw new Error("Refund locktime must be a 4-byte number") } } @@ -297,10 +296,10 @@ export interface RedemptionRequest { redeemer: ChainIdentifier /** - * The output script the redeemed Bitcoin funds are locked to. It is un-prefixed - * and is not prepended with length. + * The output script the redeemed Bitcoin funds are locked to. It is not + * prepended with length. */ - redeemerOutputScript: string + redeemerOutputScript: Hex /** * The amount of Bitcoins in satoshis that is requested to be redeemed. @@ -337,10 +336,9 @@ export type RedemptionRequestedEvent = Omit< "requestedAt" > & { /** - * Public key hash of the wallet that is meant to handle the redemption. Must - * be an unprefixed hex string (without 0x prefix). + * Public key hash of the wallet that is meant to handle the redemption. */ - walletPublicKeyHash: string + walletPublicKeyHash: Hex } & ChainEvent /* eslint-disable no-unused-vars */ diff --git a/typescript/src/lib/contracts/tbtc-token.ts b/typescript/src/lib/contracts/tbtc-token.ts index 596c88ddb..01ea195fe 100644 --- a/typescript/src/lib/contracts/tbtc-token.ts +++ b/typescript/src/lib/contracts/tbtc-token.ts @@ -32,16 +32,15 @@ export interface TBTCToken { * @param mainUtxo - The main UTXO of the wallet. Must match the main UTXO * held by the on-chain Bridge contract. * @param redeemerOutputScript - The output script that the redeemed funds - * will be locked to. Must be un-prefixed and not prepended with - * length. + * will be locked to. Must not be prepended with length. * @param amount - The amount to be redeemed with the precision of the tBTC * on-chain token contract. * @returns Transaction hash of the approve and call transaction. */ requestRedemption( - walletPublicKey: string, + walletPublicKey: Hex, mainUtxo: BitcoinUtxo, - redeemerOutputScript: string, + redeemerOutputScript: Hex, amount: BigNumber ): Promise } diff --git a/typescript/src/lib/electrum/client.ts b/typescript/src/lib/electrum/client.ts index d4dbb57c8..881f28564 100644 --- a/typescript/src/lib/electrum/client.ts +++ b/typescript/src/lib/electrum/client.ts @@ -14,7 +14,7 @@ import { BitcoinHashUtils, } from "../bitcoin" import Electrum from "electrum-client-js" -import { BigNumber, utils } from "ethers" +import { BigNumber } from "ethers" import { URL } from "url" import { backoffRetrier, Hex, RetrierFn } from "../utils" @@ -261,7 +261,7 @@ export class ElectrumClient implements BitcoinClient { const script = BitcoinAddressConverter.addressToOutputScript( address, bitcoinNetwork - ).toString() + ) // eslint-disable-next-line camelcase type UnspentOutput = { tx_pos: number; value: number; tx_hash: string } @@ -292,7 +292,7 @@ export class ElectrumClient implements BitcoinClient { const script = BitcoinAddressConverter.addressToOutputScript( address, bitcoinNetwork - ).toString() + ) // eslint-disable-next-line camelcase type HistoryItem = { height: number; tx_hash: string } @@ -518,8 +518,8 @@ export class ElectrumClient implements BitcoinClient { /** * @see {BitcoinClient#getHeadersChain} */ - getHeadersChain(blockHeight: number, chainLength: number): Promise { - return this.withElectrum(async (electrum: Electrum) => { + getHeadersChain(blockHeight: number, chainLength: number): Promise { + return this.withElectrum(async (electrum: Electrum) => { const { hex } = await this.withBackoffRetrier<{ hex: string }>()(async () => { @@ -529,7 +529,7 @@ export class ElectrumClient implements BitcoinClient { ) }) - return hex + return Hex.from(hex) }) } @@ -557,7 +557,7 @@ export class ElectrumClient implements BitcoinClient { return { blockHeight: merkle.block_height, - merkle: merkle.merkle, + merkle: merkle.merkle.map((m) => Hex.from(m)), position: merkle.pos, } } @@ -585,9 +585,6 @@ export class ElectrumClient implements BitcoinClient { * @param script - Bitcoin script as hex string * @returns Electrum script hash as a hex string. */ -export function computeElectrumScriptHash(script: string): string { - const _script = Hex.from(Buffer.from(script, "hex")).toPrefixedString() - const hash256 = utils.sha256(_script) - - return Hex.from(hash256).reverse().toString() +export function computeElectrumScriptHash(script: Hex): string { + return BitcoinHashUtils.computeSha256(script).reverse().toString() } diff --git a/typescript/src/lib/ethereum/bridge.ts b/typescript/src/lib/ethereum/bridge.ts index fecf0fe25..91c266265 100644 --- a/typescript/src/lib/ethereum/bridge.ts +++ b/typescript/src/lib/ethereum/bridge.ts @@ -112,10 +112,10 @@ export class EthereumBridge ).toNumber(), depositor: EthereumAddress.from(event.args!.depositor), amount: BigNumber.from(event.args!.amount), - blindingFactor: Hex.from(event.args!.blindingFactor).toString(), - walletPublicKeyHash: Hex.from(event.args!.walletPubKeyHash).toString(), - refundPublicKeyHash: Hex.from(event.args!.refundPubKeyHash).toString(), - refundLocktime: Hex.from(event.args!.refundLocktime).toString(), + blindingFactor: Hex.from(event.args!.blindingFactor), + walletPublicKeyHash: Hex.from(event.args!.walletPubKeyHash), + refundPublicKeyHash: Hex.from(event.args!.refundPubKeyHash), + refundLocktime: Hex.from(event.args!.refundLocktime), vault: event.args!.vault === constants.AddressZero ? undefined @@ -129,8 +129,8 @@ export class EthereumBridge * @see {Bridge#pendingRedemptions} */ async pendingRedemptions( - walletPublicKey: string, - redeemerOutputScript: string + walletPublicKey: Hex, + redeemerOutputScript: Hex ): Promise { const redemptionKey = EthereumBridge.buildRedemptionKey( BitcoinHashUtils.computeHash160(walletPublicKey), @@ -152,8 +152,8 @@ export class EthereumBridge * @see {Bridge#timedOutRedemptions} */ async timedOutRedemptions( - walletPublicKey: string, - redeemerOutputScript: string + walletPublicKey: Hex, + redeemerOutputScript: Hex ): Promise { const redemptionKey = EthereumBridge.buildRedemptionKey( BitcoinHashUtils.computeHash160(walletPublicKey), @@ -173,19 +173,18 @@ export class EthereumBridge /** * Builds a redemption key required to refer a redemption request. * @param walletPublicKeyHash The wallet public key hash that identifies the - * pending redemption (along with the redeemer output script). Must be - * unprefixed. + * pending redemption (along with the redeemer output script). * @param redeemerOutputScript The redeemer output script that identifies the - * pending redemption (along with the wallet public key hash). Must be - * un-prefixed and not prepended with length. + * pending redemption (along with the wallet public key hash). Must not + * be prepended with length. * @returns The redemption key. */ static buildRedemptionKey( - walletPublicKeyHash: string, - redeemerOutputScript: string + walletPublicKeyHash: Hex, + redeemerOutputScript: Hex ): string { // Convert the output script to raw bytes buffer. - const rawRedeemerOutputScript = Buffer.from(redeemerOutputScript, "hex") + const rawRedeemerOutputScript = redeemerOutputScript.toBuffer() // Prefix the output script bytes buffer with 0x and its own length. const prefixedRawRedeemerOutputScript = `0x${Buffer.concat([ Buffer.from([rawRedeemerOutputScript.length]), @@ -197,7 +196,7 @@ export class EthereumBridge ["bytes32", "bytes20"], [ utils.solidityKeccak256(["bytes"], [prefixedRawRedeemerOutputScript]), - `0x${walletPublicKeyHash}`, + `0x${walletPublicKeyHash.toString()}`, ] ) } @@ -206,13 +205,13 @@ export class EthereumBridge * Parses a redemption request using data fetched from the on-chain contract. * @param request Data of the request. * @param redeemerOutputScript The redeemer output script that identifies the - * pending redemption (along with the wallet public key hash). Must be - * un-prefixed and not prepended with length. + * pending redemption (along with the wallet public key hash). Must not + * be prepended with length. * @returns Parsed redemption request. */ private parseRedemptionRequest( request: RedemptionRequestTypechain, - redeemerOutputScript: string + redeemerOutputScript: Hex ): RedemptionRequest { return { redeemer: EthereumAddress.from(request.redeemer), @@ -233,20 +232,20 @@ export class EthereumBridge depositOutputIndex: number, deposit: DepositReceipt, vault?: ChainIdentifier - ): Promise { + ): Promise { const depositTxParam = { - version: `0x${depositTx.version}`, - inputVector: `0x${depositTx.inputs}`, - outputVector: `0x${depositTx.outputs}`, - locktime: `0x${depositTx.locktime}`, + version: depositTx.version.toPrefixedString(), + inputVector: depositTx.inputs.toPrefixedString(), + outputVector: depositTx.outputs.toPrefixedString(), + locktime: depositTx.locktime.toPrefixedString(), } const revealParam = { fundingOutputIndex: depositOutputIndex, - blindingFactor: `0x${deposit.blindingFactor}`, - walletPubKeyHash: `0x${deposit.walletPublicKeyHash}`, - refundPubKeyHash: `0x${deposit.refundPublicKeyHash}`, - refundLocktime: `0x${deposit.refundLocktime}`, + blindingFactor: deposit.blindingFactor.toPrefixedString(), + walletPubKeyHash: deposit.walletPublicKeyHash.toPrefixedString(), + refundPubKeyHash: deposit.refundPublicKeyHash.toPrefixedString(), + refundLocktime: deposit.refundLocktime.toPrefixedString(), vault: vault ? `0x${vault.identifierHex}` : constants.AddressZero, } @@ -259,7 +258,7 @@ export class EthereumBridge ["Deposit already revealed"] ) - return tx.hash + return Hex.from(tx.hash) } // eslint-disable-next-line valid-jsdoc @@ -271,7 +270,7 @@ export class EthereumBridge sweepProof: BitcoinSpvProof, mainUtxo: BitcoinUtxo, vault?: ChainIdentifier - ): Promise { + ): Promise { const sweepTxParam = { version: `0x${sweepTx.version}`, inputVector: `0x${sweepTx.inputs}`, @@ -280,9 +279,9 @@ export class EthereumBridge } const sweepProofParam = { - merkleProof: `0x${sweepProof.merkleProof}`, + merkleProof: sweepProof.merkleProof.toPrefixedString(), txIndexInBlock: sweepProof.txIndexInBlock, - bitcoinHeaders: `0x${sweepProof.bitcoinHeaders}`, + bitcoinHeaders: sweepProof.bitcoinHeaders.toPrefixedString(), } const mainUtxoParam = { @@ -297,7 +296,7 @@ export class EthereumBridge ? `0x${vault.identifierHex}` : constants.AddressZero - await EthersTransactionUtils.sendWithRetry( + const tx = await EthersTransactionUtils.sendWithRetry( async () => { return await this._instance.submitDepositSweepProof( sweepTxParam, @@ -308,6 +307,8 @@ export class EthereumBridge }, this._totalRetryAttempts ) + + return Hex.from(tx.hash) } // eslint-disable-next-line valid-jsdoc @@ -329,14 +330,13 @@ export class EthereumBridge * @see {Bridge#requestRedemption} */ async requestRedemption( - walletPublicKey: string, + walletPublicKey: Hex, mainUtxo: BitcoinUtxo, - redeemerOutputScript: string, + redeemerOutputScript: Hex, amount: BigNumber - ): Promise { - const walletPublicKeyHash = `0x${BitcoinHashUtils.computeHash160( - walletPublicKey - )}` + ): Promise { + const walletPublicKeyHash = + BitcoinHashUtils.computeHash160(walletPublicKey).toPrefixedString() const mainUtxoParam = { // The Ethereum Bridge expects this hash to be in the Bitcoin internal @@ -347,14 +347,14 @@ export class EthereumBridge } // Convert the output script to raw bytes buffer. - const rawRedeemerOutputScript = Buffer.from(redeemerOutputScript, "hex") + const rawRedeemerOutputScript = redeemerOutputScript.toBuffer() // Prefix the output script bytes buffer with 0x and its own length. const prefixedRawRedeemerOutputScript = `0x${Buffer.concat([ Buffer.from([rawRedeemerOutputScript.length]), rawRedeemerOutputScript, ]).toString("hex")}` - await EthersTransactionUtils.sendWithRetry( + const tx = await EthersTransactionUtils.sendWithRetry( async () => { return await this._instance.requestRedemption( walletPublicKeyHash, @@ -365,6 +365,8 @@ export class EthereumBridge }, this._totalRetryAttempts ) + + return Hex.from(tx.hash) } // eslint-disable-next-line valid-jsdoc @@ -375,8 +377,8 @@ export class EthereumBridge redemptionTx: BitcoinRawTxVectors, redemptionProof: BitcoinSpvProof, mainUtxo: BitcoinUtxo, - walletPublicKey: string - ): Promise { + walletPublicKey: Hex + ): Promise { const redemptionTxParam = { version: `0x${redemptionTx.version}`, inputVector: `0x${redemptionTx.inputs}`, @@ -398,11 +400,10 @@ export class EthereumBridge txOutputValue: mainUtxo.value, } - const walletPublicKeyHash = `0x${BitcoinHashUtils.computeHash160( - walletPublicKey - )}` + const walletPublicKeyHash = + BitcoinHashUtils.computeHash160(walletPublicKey).toPrefixedString() - await EthersTransactionUtils.sendWithRetry( + const tx = await EthersTransactionUtils.sendWithRetry( async () => { return await this._instance.submitRedemptionProof( redemptionTxParam, @@ -413,6 +414,8 @@ export class EthereumBridge }, this._totalRetryAttempts ) + + return Hex.from(tx.hash) } // eslint-disable-next-line valid-jsdoc @@ -484,7 +487,7 @@ export class EthereumBridge /** * @see {Bridge#activeWalletPublicKey} */ - async activeWalletPublicKey(): Promise { + async activeWalletPublicKey(): Promise { const activeWalletPublicKeyHash: string = await backoffRetrier( this._totalRetryAttempts )(async () => { @@ -502,7 +505,7 @@ export class EthereumBridge Hex.from(activeWalletPublicKeyHash) ) - return walletPublicKey.toString() + return walletPublicKey } private async getWalletCompressedPublicKey(ecdsaWalletID: Hex): Promise { @@ -656,9 +659,9 @@ export class EthereumBridge blockNumber: BigNumber.from(event.blockNumber).toNumber(), blockHash: Hex.from(event.blockHash), transactionHash: Hex.from(event.transactionHash), - walletPublicKeyHash: Hex.from(event.args!.walletPubKeyHash).toString(), + walletPublicKeyHash: Hex.from(event.args!.walletPubKeyHash), redeemer: EthereumAddress.from(event.args!.redeemer), - redeemerOutputScript: redeemerOutputScript, + redeemerOutputScript: Hex.from(redeemerOutputScript), requestedAmount: BigNumber.from(event.args!.requestedAmount), treasuryFee: BigNumber.from(event.args!.treasuryFee), txMaxFee: BigNumber.from(event.args!.txMaxFee), diff --git a/typescript/src/lib/ethereum/tbtc-token.ts b/typescript/src/lib/ethereum/tbtc-token.ts index c100473cb..719cb3aca 100644 --- a/typescript/src/lib/ethereum/tbtc-token.ts +++ b/typescript/src/lib/ethereum/tbtc-token.ts @@ -69,9 +69,9 @@ export class EthereumTBTCToken * @see {TBTCToken#requestRedemption} */ async requestRedemption( - walletPublicKey: string, + walletPublicKey: Hex, mainUtxo: BitcoinUtxo, - redeemerOutputScript: string, + redeemerOutputScript: Hex, amount: BigNumber ): Promise { const redeemer = await this._instance?.signer?.getAddress() @@ -103,9 +103,9 @@ export class EthereumTBTCToken private buildRequestRedemptionData( redeemer: EthereumAddress, - walletPublicKey: string, + walletPublicKey: Hex, mainUtxo: BitcoinUtxo, - redeemerOutputScript: string + redeemerOutputScript: Hex ): Hex { const { walletPublicKeyHash, @@ -133,13 +133,12 @@ export class EthereumTBTCToken } private buildBridgeRequestRedemptionData( - walletPublicKey: string, + walletPublicKey: Hex, mainUtxo: BitcoinUtxo, - redeemerOutputScript: string + redeemerOutputScript: Hex ) { - const walletPublicKeyHash = `0x${BitcoinHashUtils.computeHash160( - walletPublicKey - )}` + const walletPublicKeyHash = + BitcoinHashUtils.computeHash160(walletPublicKey).toPrefixedString() const mainUtxoParam = { // The Ethereum Bridge expects this hash to be in the Bitcoin internal @@ -150,7 +149,7 @@ export class EthereumTBTCToken } // Convert the output script to raw bytes buffer. - const rawRedeemerOutputScript = Buffer.from(redeemerOutputScript, "hex") + const rawRedeemerOutputScript = redeemerOutputScript.toBuffer() // Prefix the output script bytes buffer with 0x and its own length. const prefixedRawRedeemerOutputScript = `0x${Buffer.concat([ Buffer.from([rawRedeemerOutputScript.length]), diff --git a/typescript/src/services/deposits/deposit.ts b/typescript/src/services/deposits/deposit.ts index ed93eff73..71ed02467 100644 --- a/typescript/src/services/deposits/deposit.ts +++ b/typescript/src/services/deposits/deposit.ts @@ -111,7 +111,7 @@ export class Deposit { * initiate minting (both modes). */ // TODO: Cover auto funding outpoint detection with unit tests. - async initiateMinting(fundingOutpoint?: BitcoinTxOutpoint): Promise { + async initiateMinting(fundingOutpoint?: BitcoinTxOutpoint): Promise { let resolvedFundingOutpoint: BitcoinTxOutpoint if (typeof fundingOutpoint !== "undefined") { @@ -185,39 +185,39 @@ export class DepositScript { // If witness script hash should be produced, SHA256 should be used. // Legacy script hash needs HASH160. return this.witness - ? BitcoinHashUtils.computeSha256(Hex.from(script)).toBuffer() - : Buffer.from(BitcoinHashUtils.computeHash160(script), "hex") + ? BitcoinHashUtils.computeSha256(script).toBuffer() + : BitcoinHashUtils.computeHash160(script).toBuffer() } /** - * @returns Plain-text deposit script as an un-prefixed hex string. + * @returns Plain-text deposit script as a hex string. */ - async getPlainText(): Promise { + async getPlainText(): Promise { const chunks: Stack = [] // All HEXes pushed to the script must be un-prefixed chunks.push(Buffer.from(this.receipt.depositor.identifierHex, "hex")) chunks.push(opcodes.OP_DROP) - chunks.push(Buffer.from(this.receipt.blindingFactor, "hex")) + chunks.push(this.receipt.blindingFactor.toBuffer()) chunks.push(opcodes.OP_DROP) chunks.push(opcodes.OP_DUP) chunks.push(opcodes.OP_HASH160) - chunks.push(Buffer.from(this.receipt.walletPublicKeyHash, "hex")) + chunks.push(this.receipt.walletPublicKeyHash.toBuffer()) chunks.push(opcodes.OP_EQUAL) chunks.push(opcodes.OP_IF) chunks.push(opcodes.OP_CHECKSIG) chunks.push(opcodes.OP_ELSE) chunks.push(opcodes.OP_DUP) chunks.push(opcodes.OP_HASH160) - chunks.push(Buffer.from(this.receipt.refundPublicKeyHash, "hex")) + chunks.push(this.receipt.refundPublicKeyHash.toBuffer()) chunks.push(opcodes.OP_EQUALVERIFY) - chunks.push(Buffer.from(this.receipt.refundLocktime, "hex")) + chunks.push(this.receipt.refundLocktime.toBuffer()) chunks.push(opcodes.OP_CHECKLOCKTIMEVERIFY) chunks.push(opcodes.OP_DROP) chunks.push(opcodes.OP_CHECKSIG) chunks.push(opcodes.OP_ENDIF) - return script.compile(chunks).toString("hex") + return Hex.from(script.compile(chunks)) } /** diff --git a/typescript/src/services/deposits/deposits-service.ts b/typescript/src/services/deposits/deposits-service.ts index e04048d29..f123b6876 100644 --- a/typescript/src/services/deposits/deposits-service.ts +++ b/typescript/src/services/deposits/deposits-service.ts @@ -9,6 +9,7 @@ import { BitcoinHashUtils, BitcoinLocktimeUtils, } from "../../lib/bitcoin" +import { Hex } from "../../lib/utils" import { Deposit } from "./deposit" import * as crypto from "crypto" @@ -66,7 +67,7 @@ export class DepositsService { ) } - const blindingFactor = crypto.randomBytes(8).toString("hex") + const blindingFactor = Hex.from(crypto.randomBytes(8)) const walletPublicKey = await this.tbtcContracts.bridge.activeWalletPublicKey() diff --git a/typescript/src/services/deposits/funding.ts b/typescript/src/services/deposits/funding.ts index c520f5e83..a3f9d8f7e 100644 --- a/typescript/src/services/deposits/funding.ts +++ b/typescript/src/services/deposits/funding.ts @@ -92,7 +92,7 @@ export class DepositFunding { // TODO: Add support for other utxo types along with unit tests for the // given type. - if (BitcoinScriptUtils.isP2WPKHScript(previousOutputScript)) { + if (BitcoinScriptUtils.isP2WPKHScript(Hex.from(previousOutputScript))) { psbt.addInput({ hash: utxo.transactionHash.reverse().toBuffer(), index: utxo.outputIndex, diff --git a/typescript/src/services/deposits/refund.ts b/typescript/src/services/deposits/refund.ts index d4ad401fb..ef9a4227b 100644 --- a/typescript/src/services/deposits/refund.ts +++ b/typescript/src/services/deposits/refund.ts @@ -12,6 +12,7 @@ import { BitcoinUtxo, } from "../../lib/bitcoin" import { validateDepositReceipt } from "../../lib/contracts" +import { Hex } from "../../lib/utils" import { DepositScript } from "./" import { Signer, @@ -153,7 +154,7 @@ export class DepositRefund { utxo.outputIndex ] const previousOutputValue = previousOutput.value - const previousOutputScript = previousOutput.script + const previousOutputScript = Hex.from(previousOutput.script) if (BitcoinScriptUtils.isP2SHScript(previousOutputScript)) { // P2SH deposit UTXO @@ -188,11 +189,12 @@ export class DepositRefund { * @throws Error if there are discrepancies in values or key formats. */ private async prepareDepositScript(refunderKeyPair: Signer): Promise { - const refunderPublicKey = refunderKeyPair.publicKey.toString("hex") + const refunderPublicKey = Hex.from(refunderKeyPair.publicKey) if ( - BitcoinHashUtils.computeHash160(refunderPublicKey) != - this.script.receipt.refundPublicKeyHash + !BitcoinHashUtils.computeHash160(refunderPublicKey).equals( + this.script.receipt.refundPublicKeyHash + ) ) { throw new Error( "Refund public key does not correspond to wallet private key" @@ -203,7 +205,7 @@ export class DepositRefund { throw new Error("Refunder public key must be compressed") } - return Buffer.from(await this.script.getPlainText(), "hex") + return (await this.script.getPlainText()).toBuffer() } /** @@ -288,10 +290,7 @@ export class DepositRefund { * @param locktime - Locktime as a little endian hexstring. * @returns Locktime as a Unix timestamp. */ -function locktimeToUnixTimestamp(locktime: string): number { - const bigEndianLocktime = Buffer.from(locktime, "hex") - .reverse() - .toString("hex") - +function locktimeToUnixTimestamp(locktime: Hex): number { + const bigEndianLocktime = locktime.reverse().toString() return parseInt(bigEndianLocktime, 16) } diff --git a/typescript/src/services/maintenance/spv.ts b/typescript/src/services/maintenance/spv.ts index c00d690db..3dbd8341e 100644 --- a/typescript/src/services/maintenance/spv.ts +++ b/typescript/src/services/maintenance/spv.ts @@ -5,6 +5,7 @@ import { BitcoinUtxo, extractBitcoinRawTxVectors, } from "../../lib/bitcoin" +import { Hex } from "../../lib/utils" import { ChainIdentifier, TBTCContracts } from "../../lib/contracts" export class Spv { @@ -66,7 +67,7 @@ export class Spv { async submitRedemptionProof( transactionHash: BitcoinTxHash, mainUtxo: BitcoinUtxo, - walletPublicKey: string + walletPublicKey: Hex ): Promise { const confirmations = await this.tbtcContracts.bridge.txProofDifficultyFactor() diff --git a/typescript/src/services/maintenance/wallet-tx.ts b/typescript/src/services/maintenance/wallet-tx.ts index dda223671..595a19171 100644 --- a/typescript/src/services/maintenance/wallet-tx.ts +++ b/typescript/src/services/maintenance/wallet-tx.ts @@ -249,7 +249,7 @@ class DepositSweep { utxo.outputIndex ] const previousOutputValue = previousOutput.value - const previousOutputScript = previousOutput.script + const previousOutputScript = Hex.from(previousOutput.script) const deposit = deposits[depositIndex] @@ -309,10 +309,13 @@ class DepositSweep { previousOutput: TxOutput, walletKeyPair: Signer ) { + const previousOutputScript = Hex.from(previousOutput.script) + const previousOutputValue = previousOutput.value + if ( !this.canSpendOutput( Hex.from(walletKeyPair.publicKey), - previousOutput.script + previousOutputScript ) ) { throw new Error("UTXO does not belong to the wallet") @@ -320,11 +323,11 @@ class DepositSweep { const sigHashType = Transaction.SIGHASH_ALL - if (BitcoinScriptUtils.isP2PKHScript(previousOutput.script)) { + if (BitcoinScriptUtils.isP2PKHScript(previousOutputScript)) { // P2PKH const sigHash = transaction.hashForSignature( inputIndex, - previousOutput.script, + previousOutputScript.toBuffer(), sigHashType ) @@ -339,16 +342,17 @@ class DepositSweep { }).input! transaction.ins[inputIndex].script = scriptSig - } else if (BitcoinScriptUtils.isP2WPKHScript(previousOutput.script)) { + } else if (BitcoinScriptUtils.isP2WPKHScript(previousOutputScript)) { // P2WPKH - const publicKeyHash = payments.p2wpkh({ output: previousOutput.script }) - .hash! + const publicKeyHash = payments.p2wpkh({ + output: previousOutputScript.toBuffer(), + }).hash! const p2pkhScript = payments.p2pkh({ hash: publicKeyHash }).output! const sigHash = transaction.hashForWitnessV0( inputIndex, p2pkhScript, - previousOutput.value, + previousOutputValue, sigHashType ) @@ -466,11 +470,12 @@ class DepositSweep { previousOutputValue: number, walletKeyPair: Signer ): Promise { - const walletPublicKey = walletKeyPair.publicKey.toString("hex") + const walletPublicKey = Hex.from(walletKeyPair.publicKey) if ( - BitcoinHashUtils.computeHash160(walletPublicKey) != - deposit.walletPublicKeyHash + !BitcoinHashUtils.computeHash160(walletPublicKey).equals( + deposit.walletPublicKeyHash + ) ) { throw new Error( "Wallet public key does not correspond to wallet private key" @@ -481,10 +486,7 @@ class DepositSweep { throw new Error("Wallet public key must be compressed") } - return Buffer.from( - await DepositScript.fromReceipt(deposit).getPlainText(), - "hex" - ) + return (await DepositScript.fromReceipt(deposit).getPlainText()).toBuffer() } /** @@ -496,10 +498,14 @@ class DepositSweep { * @returns True if the provided output script matches the P2PKH or P2WPKH * output scripts derived from the given public key. False otherwise. */ - private canSpendOutput(publicKey: Hex, outputScript: Buffer): boolean { + private canSpendOutput(publicKey: Hex, outputScript: Hex): boolean { const pubkeyBuffer = publicKey.toBuffer() - const p2pkhOutput = payments.p2pkh({ pubkey: pubkeyBuffer }).output! - const p2wpkhOutput = payments.p2wpkh({ pubkey: pubkeyBuffer }).output! + const p2pkhOutput = Hex.from( + payments.p2pkh({ pubkey: pubkeyBuffer }).output! + ) + const p2wpkhOutput = Hex.from( + payments.p2wpkh({ pubkey: pubkeyBuffer }).output! + ) return outputScript.equals(p2pkhOutput) || outputScript.equals(p2wpkhOutput) } @@ -541,8 +547,8 @@ class Redemption { * @param mainUtxo - The main UTXO of the wallet. Must match the main UTXO * held by the on-chain Bridge contract * @param redeemerOutputScripts - The list of output scripts that the redeemed - * funds will be locked to. The output scripts must be un-prefixed and - * not prepended with length + * funds will be locked to. The output scripts must not be prepended + * with length * @returns The outcome consisting of: * - the redemption transaction hash, * - the optional new wallet's main UTXO produced by this transaction. @@ -550,7 +556,7 @@ class Redemption { async submitTransaction( walletPrivateKey: string, mainUtxo: BitcoinUtxo, - redeemerOutputScripts: string[] + redeemerOutputScripts: Hex[] ): Promise<{ transactionHash: BitcoinTxHash newMainUtxo?: BitcoinUtxo @@ -571,7 +577,7 @@ class Redemption { bitcoinNetwork ) - const walletPublicKey = walletKeyPair.publicKey.toString("hex") + const walletPublicKey = Hex.from(walletKeyPair.publicKey) const redemptionRequests: RedemptionRequest[] = [] @@ -588,7 +594,7 @@ class Redemption { redemptionRequests.push({ ...redemptionRequest, - redeemerOutputScript: redeemerOutputScript, + redeemerOutputScript, }) } @@ -661,7 +667,7 @@ class Redemption { const previousOutput = Transaction.fromHex(mainUtxo.transactionHex).outs[ mainUtxo.outputIndex ] - const previousOutputScript = previousOutput.script + const previousOutputScript = Hex.from(previousOutput.script) const previousOutputValue = previousOutput.value if (BitcoinScriptUtils.isP2PKHScript(previousOutputScript)) { @@ -675,7 +681,7 @@ class Redemption { hash: mainUtxo.transactionHash.reverse().toBuffer(), index: mainUtxo.outputIndex, witnessUtxo: { - script: previousOutputScript, + script: previousOutputScript.toBuffer(), value: previousOutputValue, }, }) @@ -701,7 +707,7 @@ class Redemption { txTotalFee = txTotalFee.add(request.txMaxFee) psbt.addOutput({ - script: Buffer.from(request.redeemerOutputScript, "hex"), + script: request.redeemerOutputScript.toBuffer(), value: outputValue.toNumber(), }) } diff --git a/typescript/src/services/redemptions/redemptions-service.ts b/typescript/src/services/redemptions/redemptions-service.ts index f3fd5f49c..363f0454a 100644 --- a/typescript/src/services/redemptions/redemptions-service.ts +++ b/typescript/src/services/redemptions/redemptions-service.ts @@ -49,14 +49,14 @@ export class RedemptionsService { amount: BigNumber ): Promise<{ targetChainTxHash: Hex - walletPublicKey: string + walletPublicKey: Hex }> { const bitcoinNetwork = await this.bitcoinClient.getNetwork() const redeemerOutputScript = BitcoinAddressConverter.addressToOutputScript( bitcoinRedeemerAddress, bitcoinNetwork - ).toString() + ) // TODO: Validate the given script is supported for redemption. @@ -82,16 +82,15 @@ export class RedemptionsService { * Finds the oldest live wallet that has enough BTC to handle a redemption * request. * @param redeemerOutputScript The redeemer output script the redeemed funds are - * supposed to be locked on. Must be un-prefixed and not prepended with - * length. + * supposed to be locked on. Must not be prepended with length. * @param amount The amount to be redeemed in satoshis. * @returns Promise with the wallet details needed to request a redemption. */ protected async findWalletForRedemption( - redeemerOutputScript: string, + redeemerOutputScript: Hex, amount: BigNumber ): Promise<{ - walletPublicKey: string + walletPublicKey: Hex mainUtxo: BitcoinUtxo }> { const wallets = @@ -99,7 +98,7 @@ export class RedemptionsService { let walletData: | { - walletPublicKey: string + walletPublicKey: Hex mainUtxo: BitcoinUtxo } | undefined = undefined @@ -140,7 +139,7 @@ export class RedemptionsService { const pendingRedemption = await this.tbtcContracts.bridge.pendingRedemptions( - walletPublicKey.toString(), + walletPublicKey, redeemerOutputScript ) @@ -149,7 +148,7 @@ export class RedemptionsService { `There is a pending redemption request from this wallet to the ` + `same Bitcoin address. Given wallet public key hash` + `(${walletPublicKeyHash.toString()}) and redeemer output script ` + - `(${redeemerOutputScript}) pair can be used for only one ` + + `(${redeemerOutputScript.toString()}) pair can be used for only one ` + `pending request at the same time. ` + `Continue the loop execution to the next wallet...` ) @@ -163,7 +162,7 @@ export class RedemptionsService { if (walletBTCBalance.gte(amount)) { walletData = { - walletPublicKey: walletPublicKey.toString(), + walletPublicKey, mainUtxo, } @@ -239,7 +238,7 @@ export class RedemptionsService { ): Promise => { // Build the wallet Bitcoin address based on its public key hash. const walletAddress = BitcoinAddressConverter.publicKeyHashToAddress( - walletPublicKeyHash.toString(), + walletPublicKeyHash, witnessAddress, bitcoinNetwork ) @@ -330,7 +329,7 @@ export class RedemptionsService { */ async getRedemptionRequests( bitcoinRedeemerAddress: string, - walletPublicKey: string, + walletPublicKey: Hex, type: "pending" | "timedOut" = "pending" ): Promise { const bitcoinNetwork = await this.bitcoinClient.getNetwork() @@ -338,7 +337,7 @@ export class RedemptionsService { const redeemerOutputScript = BitcoinAddressConverter.addressToOutputScript( bitcoinRedeemerAddress, bitcoinNetwork - ).toString() + ) let redemptionRequest: RedemptionRequest | undefined = undefined diff --git a/typescript/test/data/deposit-refund.ts b/typescript/test/data/deposit-refund.ts index ff0782a2a..45dfb3699 100644 --- a/typescript/test/data/deposit-refund.ts +++ b/typescript/test/data/deposit-refund.ts @@ -1,4 +1,5 @@ import { BigNumber } from "ethers" +import { Hex } from "../../src/lib/utils" import { BitcoinRawTx, BitcoinUtxo, @@ -59,9 +60,13 @@ export const depositRefundOfWitnessDepositAndWitnessRefunderAddress: DepositRefu depositor: EthereumAddress.from( "934b98637ca318a4d6e7ca6ffd1690b8e77df637" ), - walletPublicKeyHash: "8db50eb52063ea9d98b3eac91489a90f738986f6", - refundPublicKeyHash: "1b67f27537c7b30a23d8ccefb96a4cacfc72d9a1", - blindingFactor: "f9f0c90d00039523", + walletPublicKeyHash: Hex.from( + "8db50eb52063ea9d98b3eac91489a90f738986f6" + ), + refundPublicKeyHash: Hex.from( + "1b67f27537c7b30a23d8ccefb96a4cacfc72d9a1" + ), + blindingFactor: Hex.from("f9f0c90d00039523"), refundLocktime: BitcoinLocktimeUtils.calculateLocktime( 1674820800, 3600 @@ -116,9 +121,13 @@ export const depositRefundOfNonWitnessDepositAndWitnessRefunderAddress: DepositR depositor: EthereumAddress.from( "934b98637ca318a4d6e7ca6ffd1690b8e77df637" ), - walletPublicKeyHash: "8db50eb52063ea9d98b3eac91489a90f738986f6", - refundPublicKeyHash: "1b67f27537c7b30a23d8ccefb96a4cacfc72d9a1", - blindingFactor: "f9f0c90d00039523", + walletPublicKeyHash: Hex.from( + "8db50eb52063ea9d98b3eac91489a90f738986f6" + ), + refundPublicKeyHash: Hex.from( + "1b67f27537c7b30a23d8ccefb96a4cacfc72d9a1" + ), + blindingFactor: Hex.from("f9f0c90d00039523"), refundLocktime: BitcoinLocktimeUtils.calculateLocktime( 1674820800, 3600 @@ -173,9 +182,13 @@ export const depositRefundOfWitnessDepositAndNonWitnessRefunderAddress: DepositR depositor: EthereumAddress.from( "934b98637ca318a4d6e7ca6ffd1690b8e77df637" ), - walletPublicKeyHash: "8db50eb52063ea9d98b3eac91489a90f738986f6", - refundPublicKeyHash: "1b67f27537c7b30a23d8ccefb96a4cacfc72d9a1", - blindingFactor: "f9f0c90d00039523", + walletPublicKeyHash: Hex.from( + "8db50eb52063ea9d98b3eac91489a90f738986f6" + ), + refundPublicKeyHash: Hex.from( + "1b67f27537c7b30a23d8ccefb96a4cacfc72d9a1" + ), + blindingFactor: Hex.from("f9f0c90d00039523"), refundLocktime: BitcoinLocktimeUtils.calculateLocktime( 1674820800, 3600 diff --git a/typescript/test/data/deposit-sweep.ts b/typescript/test/data/deposit-sweep.ts index 0ba6ffee6..35b551e43 100644 --- a/typescript/test/data/deposit-sweep.ts +++ b/typescript/test/data/deposit-sweep.ts @@ -65,10 +65,14 @@ export const depositSweepWithNoMainUtxoAndWitnessOutput: DepositSweepTestData = "934b98637ca318a4d6e7ca6ffd1690b8e77df637" ), // HASH160 of 03989d253b17a6a0f41838b84ff0d20e8898f9d7b1a98f2564da4cc29dcf8581d9. - walletPublicKeyHash: "8db50eb52063ea9d98b3eac91489a90f738986f6", + walletPublicKeyHash: Hex.from( + "8db50eb52063ea9d98b3eac91489a90f738986f6" + ), // HASH160 of 039d61d62dcd048d3f8550d22eb90b4af908db60231d117aeede04e7bc11907bfa. - refundPublicKeyHash: "e257eccafbc07c381642ce6e7e55120fb077fbed", - blindingFactor: "f9f0c90d00039523", + refundPublicKeyHash: Hex.from( + "e257eccafbc07c381642ce6e7e55120fb077fbed" + ), + blindingFactor: Hex.from("f9f0c90d00039523"), refundLocktime: BitcoinLocktimeUtils.calculateLocktime( 1641650400, 2592000 @@ -96,10 +100,14 @@ export const depositSweepWithNoMainUtxoAndWitnessOutput: DepositSweepTestData = "934b98637ca318a4d6e7ca6ffd1690b8e77df637" ), // HASH160 of 03989d253b17a6a0f41838b84ff0d20e8898f9d7b1a98f2564da4cc29dcf8581d9. - walletPublicKeyHash: "8db50eb52063ea9d98b3eac91489a90f738986f6", + walletPublicKeyHash: Hex.from( + "8db50eb52063ea9d98b3eac91489a90f738986f6" + ), // HASH160 of 039d61d62dcd048d3f8550d22eb90b4af908db60231d117aeede04e7bc11907bfa. - refundPublicKeyHash: "e257eccafbc07c381642ce6e7e55120fb077fbed", - blindingFactor: "f9f0c90d00039523", + refundPublicKeyHash: Hex.from( + "e257eccafbc07c381642ce6e7e55120fb077fbed" + ), + blindingFactor: Hex.from("f9f0c90d00039523"), refundLocktime: BitcoinLocktimeUtils.calculateLocktime( 1641650400, 2592000 @@ -158,10 +166,14 @@ export const depositSweepWithNoMainUtxoAndNonWitnessOutput: DepositSweepTestData "934b98637ca318a4d6e7ca6ffd1690b8e77df637" ), // HASH160 of 03989d253b17a6a0f41838b84ff0d20e8898f9d7b1a98f2564da4cc29dcf8581d9. - walletPublicKeyHash: "8db50eb52063ea9d98b3eac91489a90f738986f6", + walletPublicKeyHash: Hex.from( + "8db50eb52063ea9d98b3eac91489a90f738986f6" + ), // HASH160 of 039d61d62dcd048d3f8550d22eb90b4af908db60231d117aeede04e7bc11907bfa. - refundPublicKeyHash: "e257eccafbc07c381642ce6e7e55120fb077fbed", - blindingFactor: "f9f0c90d00039523", + refundPublicKeyHash: Hex.from( + "e257eccafbc07c381642ce6e7e55120fb077fbed" + ), + blindingFactor: Hex.from("f9f0c90d00039523"), refundLocktime: BitcoinLocktimeUtils.calculateLocktime( 1653302600, 2592000 @@ -213,10 +225,14 @@ export const depositSweepWithWitnessMainUtxoAndWitnessOutput: DepositSweepTestDa "934b98637ca318a4d6e7ca6ffd1690b8e77df637" ), // HASH160 of 03989d253b17a6a0f41838b84ff0d20e8898f9d7b1a98f2564da4cc29dcf8581d9. - walletPublicKeyHash: "8db50eb52063ea9d98b3eac91489a90f738986f6", + walletPublicKeyHash: Hex.from( + "8db50eb52063ea9d98b3eac91489a90f738986f6" + ), // HASH160 of 039d61d62dcd048d3f8550d22eb90b4af908db60231d117aeede04e7bc11907bfa. - refundPublicKeyHash: "e257eccafbc07c381642ce6e7e55120fb077fbed", - blindingFactor: "f9f0c90d00039523", + refundPublicKeyHash: Hex.from( + "e257eccafbc07c381642ce6e7e55120fb077fbed" + ), + blindingFactor: Hex.from("f9f0c90d00039523"), refundLocktime: BitcoinLocktimeUtils.calculateLocktime( 1641650400, 2592000 @@ -245,10 +261,14 @@ export const depositSweepWithWitnessMainUtxoAndWitnessOutput: DepositSweepTestDa "934b98637ca318a4d6e7ca6ffd1690b8e77df637" ), // HASH160 of 03989d253b17a6a0f41838b84ff0d20e8898f9d7b1a98f2564da4cc29dcf8581d9. - walletPublicKeyHash: "8db50eb52063ea9d98b3eac91489a90f738986f6", + walletPublicKeyHash: Hex.from( + "8db50eb52063ea9d98b3eac91489a90f738986f6" + ), // HASH160 of 039d61d62dcd048d3f8550d22eb90b4af908db60231d117aeede04e7bc11907bfa. - refundPublicKeyHash: "e257eccafbc07c381642ce6e7e55120fb077fbed", - blindingFactor: "f9f0c90d00039523", + refundPublicKeyHash: Hex.from( + "e257eccafbc07c381642ce6e7e55120fb077fbed" + ), + blindingFactor: Hex.from("f9f0c90d00039523"), refundLocktime: BitcoinLocktimeUtils.calculateLocktime( 1641650400, 2592000 @@ -343,10 +363,14 @@ export const depositSweepWithNonWitnessMainUtxoAndWitnessOutput: DepositSweepTes "934b98637ca318a4d6e7ca6ffd1690b8e77df637" ), // HASH160 of 03989d253b17a6a0f41838b84ff0d20e8898f9d7b1a98f2564da4cc29dcf8581d9. - walletPublicKeyHash: "8db50eb52063ea9d98b3eac91489a90f738986f6", + walletPublicKeyHash: Hex.from( + "8db50eb52063ea9d98b3eac91489a90f738986f6" + ), // HASH160 of 039d61d62dcd048d3f8550d22eb90b4af908db60231d117aeede04e7bc11907bfa. - refundPublicKeyHash: "e257eccafbc07c381642ce6e7e55120fb077fbed", - blindingFactor: "f9f0c90d00039523", + refundPublicKeyHash: Hex.from( + "e257eccafbc07c381642ce6e7e55120fb077fbed" + ), + blindingFactor: Hex.from("f9f0c90d00039523"), refundLocktime: BitcoinLocktimeUtils.calculateLocktime( 1653302600, 2592000 @@ -404,7 +428,7 @@ export interface DepositSweepProofTestData { rawTransaction: BitcoinRawTx accumulatedTxConfirmations: number latestBlockHeight: number - headersChain: string + headersChain: Hex transactionMerkleBranch: BitcoinTxMerkleBranch } expectedSweepProof: { @@ -498,82 +522,97 @@ export const depositSweepProof: DepositSweepProofTestData = { "120fb077fbed8804e0250162b175ac6800000000", }, latestBlockHeight: 2164335, - headersChain: + headersChain: Hex.from( "04000020642125b3910fdaead521b57955e28893d89f8ce7fd3ba1dd6d0100000" + - "0000000f9e17a266a2267ee02d5ab82a75a76805db821a13abd2e80e0950d8833" + - "11e5355dc21c62ed3e031adefc02c4040000205b6de55e069be71b21a62cd140d" + - "c7031225f7258dc758f19ea01000000000000139966d27d9ed0c0c1ed9162c2fe" + - "a2ccf0ba212706f6bc421d0a2b6211de040d1ac41c62ed3e031a4726538f04e00" + - "0208475e15e0314635d32abf04c761fee528d6a3f2db3b3d13798000000000000" + - "002a3fa06fecd9dd4bf2e25e22a95d4f65435d5c5b42bcf498b4e756f9f4ea67c" + - "ea1c51c62ed3e031a9d7bf3ac000000203f16d450c51853a4cd9569d225028aa0" + - "8ab6139eee31f4f67a010000000000004cda79bc48b970de2fb29c3f38626eb9d" + - "70d8bae7b92aad09f2a0ad2d2f334d35bca1c62ffff001d048fc2170000002068" + - "7e487acbf5eb375c631a15127fbf7d80ca084461e7f26f92c509b6000000006fa" + - "d33bd7c8d651bd6dc86c286f0a99340b668f019b9e97a59fd392c36c4f46910cf" + - "1c62ffff001d407facaa0400002040f4c65610f26f06c4365305b956934501713" + - "e01c2fc08b919e0bc1b00000000e401a6a884ba015e83c6fe2cd363e877ef0398" + - "2e81eaff4e2c95af1e23a670f407d41c62ffff001d58c64d180400002038854bd" + - "62f802e1de14653eceeb7a80290f5e99b8e9db517e36f000000000000a494b803" + - "4039e7855b75563ab83c9410dd67e89bb58e6cd93b85290a885dd749f4d61c62e" + - "d3e031ad9a83746", + "0000000f9e17a266a2267ee02d5ab82a75a76805db821a13abd2e80e0950d8833" + + "11e5355dc21c62ed3e031adefc02c4040000205b6de55e069be71b21a62cd140d" + + "c7031225f7258dc758f19ea01000000000000139966d27d9ed0c0c1ed9162c2fe" + + "a2ccf0ba212706f6bc421d0a2b6211de040d1ac41c62ed3e031a4726538f04e00" + + "0208475e15e0314635d32abf04c761fee528d6a3f2db3b3d13798000000000000" + + "002a3fa06fecd9dd4bf2e25e22a95d4f65435d5c5b42bcf498b4e756f9f4ea67c" + + "ea1c51c62ed3e031a9d7bf3ac000000203f16d450c51853a4cd9569d225028aa0" + + "8ab6139eee31f4f67a010000000000004cda79bc48b970de2fb29c3f38626eb9d" + + "70d8bae7b92aad09f2a0ad2d2f334d35bca1c62ffff001d048fc2170000002068" + + "7e487acbf5eb375c631a15127fbf7d80ca084461e7f26f92c509b6000000006fa" + + "d33bd7c8d651bd6dc86c286f0a99340b668f019b9e97a59fd392c36c4f46910cf" + + "1c62ffff001d407facaa0400002040f4c65610f26f06c4365305b956934501713" + + "e01c2fc08b919e0bc1b00000000e401a6a884ba015e83c6fe2cd363e877ef0398" + + "2e81eaff4e2c95af1e23a670f407d41c62ffff001d58c64d180400002038854bd" + + "62f802e1de14653eceeb7a80290f5e99b8e9db517e36f000000000000a494b803" + + "4039e7855b75563ab83c9410dd67e89bb58e6cd93b85290a885dd749f4d61c62e" + + "d3e031ad9a83746" + ), transactionMerkleBranch: { blockHeight: 2164155, merkle: [ - "322cfdf3ca53cf597b6f08e93489b9a1cfa1f5958c3657474b0d8f5efb5ca92e", - "82aedffef6c9670375effee25740fecce143d21f8abf98307235b7ebd31ad4d1", - "837fa041b9a8f5b42353fdf8981e3b7a78c61858852e43058bfe6cacf9eab5a3", - "a51612d3f3f857e95803a4d86aa6dbbe2e756dc2ed6cc0e04630e8baf597e377", - "a00501650e0c4f8a1e07a5d6d5bc5e75e4c75de61a65f0410cce354bbae78686", + Hex.from( + "322cfdf3ca53cf597b6f08e93489b9a1cfa1f5958c3657474b0d8f5efb5ca92e" + ), + Hex.from( + "82aedffef6c9670375effee25740fecce143d21f8abf98307235b7ebd31ad4d1" + ), + Hex.from( + "837fa041b9a8f5b42353fdf8981e3b7a78c61858852e43058bfe6cacf9eab5a3" + ), + Hex.from( + "a51612d3f3f857e95803a4d86aa6dbbe2e756dc2ed6cc0e04630e8baf597e377" + ), + Hex.from( + "a00501650e0c4f8a1e07a5d6d5bc5e75e4c75de61a65f0410cce354bbae78686" + ), ], position: 6, }, }, expectedSweepProof: { sweepTx: { - version: "01000000", - inputs: + version: Hex.from("01000000"), + inputs: Hex.from( "048f99b22593afdc4e3c08c7821151e801b2e9a16bf307c087a1b8c1f8459e4dea0" + - "0000000c9483045022100bb54f2717647b2f2c5370b5f12b55e27f97a6e2009dcd2" + - "1fca08527df949e1fd022058bc3cd1dd739b89b9e4cda43b13bc59cfb15663b80cb" + - "fa3edb4539107bba35d012103989d253b17a6a0f41838b84ff0d20e8898f9d7b1a9" + - "8f2564da4cc29dcf8581d94c5c14934b98637ca318a4d6e7ca6ffd1690b8e77df63" + - "77508f9f0c90d000395237576a9148db50eb52063ea9d98b3eac91489a90f738986" + - "f68763ac6776a914e257eccafbc07c381642ce6e7e55120fb077fbed8804e025016" + - "2b175ac68fffffffffd337f1abd32f17566e17a3606714d981bb8982339805ebb84" + - "c881174cff44c80000000000ffffffff73a486cf5ca706f513b6bf170ed0e7465d5" + - "bbe2968b4c2a9a207ac0ebc68c5440000000000ffffffff78439e510ac6b659b529" + - "a608611a77ca05f00ca050648212e16447460ec048f50000000000ffffffff", - outputs: - "01789b0000000000001600148db50eb52063ea9d98b3eac91489a90f738986f6", - locktime: "00000000", + "0000000c9483045022100bb54f2717647b2f2c5370b5f12b55e27f97a6e2009dcd2" + + "1fca08527df949e1fd022058bc3cd1dd739b89b9e4cda43b13bc59cfb15663b80cb" + + "fa3edb4539107bba35d012103989d253b17a6a0f41838b84ff0d20e8898f9d7b1a9" + + "8f2564da4cc29dcf8581d94c5c14934b98637ca318a4d6e7ca6ffd1690b8e77df63" + + "77508f9f0c90d000395237576a9148db50eb52063ea9d98b3eac91489a90f738986" + + "f68763ac6776a914e257eccafbc07c381642ce6e7e55120fb077fbed8804e025016" + + "2b175ac68fffffffffd337f1abd32f17566e17a3606714d981bb8982339805ebb84" + + "c881174cff44c80000000000ffffffff73a486cf5ca706f513b6bf170ed0e7465d5" + + "bbe2968b4c2a9a207ac0ebc68c5440000000000ffffffff78439e510ac6b659b529" + + "a608611a77ca05f00ca050648212e16447460ec048f50000000000ffffffff" + ), + outputs: Hex.from( + "01789b0000000000001600148db50eb52063ea9d98b3eac91489a90f738986f6" + ), + locktime: Hex.from("00000000"), }, sweepProof: { - merkleProof: + merkleProof: Hex.from( "2ea95cfb5e8f0d4b4757368c95f5a1cfa1b98934e9086f7b59cf53caf3fd2c32d1d" + - "41ad3ebb735723098bf8a1fd243e1ccfe4057e2feef750367c9f6fedfae82a3b5ea" + - "f9ac6cfe8b05432e855818c6787a3b1e98f8fd5323b4f5a8b941a07f8377e397f5b" + - "ae83046e0c06cedc26d752ebedba66ad8a40358e957f8f3d31216a58686e7ba4b35" + - "ce0c41f0651ae65dc7e4755ebcd5d6a5071e8a4f0c0e650105a0", + "41ad3ebb735723098bf8a1fd243e1ccfe4057e2feef750367c9f6fedfae82a3b5ea" + + "f9ac6cfe8b05432e855818c6787a3b1e98f8fd5323b4f5a8b941a07f8377e397f5b" + + "ae83046e0c06cedc26d752ebedba66ad8a40358e957f8f3d31216a58686e7ba4b35" + + "ce0c41f0651ae65dc7e4755ebcd5d6a5071e8a4f0c0e650105a0" + ), txIndexInBlock: 6, - bitcoinHeaders: + bitcoinHeaders: Hex.from( "04000020642125b3910fdaead521b57955e28893d89f8ce7fd3ba1dd6d010000000" + - "00000f9e17a266a2267ee02d5ab82a75a76805db821a13abd2e80e0950d883311e5" + - "355dc21c62ed3e031adefc02c4040000205b6de55e069be71b21a62cd140dc70312" + - "25f7258dc758f19ea01000000000000139966d27d9ed0c0c1ed9162c2fea2ccf0ba" + - "212706f6bc421d0a2b6211de040d1ac41c62ed3e031a4726538f04e000208475e15" + - "e0314635d32abf04c761fee528d6a3f2db3b3d13798000000000000002a3fa06fec" + - "d9dd4bf2e25e22a95d4f65435d5c5b42bcf498b4e756f9f4ea67cea1c51c62ed3e0" + - "31a9d7bf3ac000000203f16d450c51853a4cd9569d225028aa08ab6139eee31f4f6" + - "7a010000000000004cda79bc48b970de2fb29c3f38626eb9d70d8bae7b92aad09f2" + - "a0ad2d2f334d35bca1c62ffff001d048fc21700000020687e487acbf5eb375c631a" + - "15127fbf7d80ca084461e7f26f92c509b6000000006fad33bd7c8d651bd6dc86c28" + - "6f0a99340b668f019b9e97a59fd392c36c4f46910cf1c62ffff001d407facaa0400" + - "002040f4c65610f26f06c4365305b956934501713e01c2fc08b919e0bc1b0000000" + - "0e401a6a884ba015e83c6fe2cd363e877ef03982e81eaff4e2c95af1e23a670f407" + - "d41c62ffff001d58c64d180400002038854bd62f802e1de14653eceeb7a80290f5e" + - "99b8e9db517e36f000000000000a494b8034039e7855b75563ab83c9410dd67e89b" + - "b58e6cd93b85290a885dd749f4d61c62ed3e031ad9a83746", + "00000f9e17a266a2267ee02d5ab82a75a76805db821a13abd2e80e0950d883311e5" + + "355dc21c62ed3e031adefc02c4040000205b6de55e069be71b21a62cd140dc70312" + + "25f7258dc758f19ea01000000000000139966d27d9ed0c0c1ed9162c2fea2ccf0ba" + + "212706f6bc421d0a2b6211de040d1ac41c62ed3e031a4726538f04e000208475e15" + + "e0314635d32abf04c761fee528d6a3f2db3b3d13798000000000000002a3fa06fec" + + "d9dd4bf2e25e22a95d4f65435d5c5b42bcf498b4e756f9f4ea67cea1c51c62ed3e0" + + "31a9d7bf3ac000000203f16d450c51853a4cd9569d225028aa08ab6139eee31f4f6" + + "7a010000000000004cda79bc48b970de2fb29c3f38626eb9d70d8bae7b92aad09f2" + + "a0ad2d2f334d35bca1c62ffff001d048fc21700000020687e487acbf5eb375c631a" + + "15127fbf7d80ca084461e7f26f92c509b6000000006fad33bd7c8d651bd6dc86c28" + + "6f0a99340b668f019b9e97a59fd392c36c4f46910cf1c62ffff001d407facaa0400" + + "002040f4c65610f26f06c4365305b956934501713e01c2fc08b919e0bc1b0000000" + + "0e401a6a884ba015e83c6fe2cd363e877ef03982e81eaff4e2c95af1e23a670f407" + + "d41c62ffff001d58c64d180400002038854bd62f802e1de14653eceeb7a80290f5e" + + "99b8e9db517e36f000000000000a494b8034039e7855b75563ab83c9410dd67e89b" + + "b58e6cd93b85290a885dd749f4d61c62ed3e031ad9a83746" + ), }, mainUtxo: NO_MAIN_UTXO, }, diff --git a/typescript/test/data/electrum.ts b/typescript/test/data/electrum.ts index 22d930672..38c12becb 100644 --- a/typescript/test/data/electrum.ts +++ b/typescript/test/data/electrum.ts @@ -75,23 +75,24 @@ export const testnetUTXO: BitcoinUtxo = { export const testnetHeadersChain = { blockHeight: 1569342, headersChainLength: 6, - headersChain: + headersChain: Hex.from( "00000020a114bf2d1e930390044cc4e00dd2f490a36dcecb4b6bb702b50200000000000" + - "0583b7a45472123fac1003384cc60fce2129c8d7364969dfa35021ab26c0b0449bccc2e" + - "5dffff001d061013a10000ff3f3210404a744c3170cdd6ad7fc901194c913004faa87f2" + - "91cd3faac2b00000000ecc1620341eeee4881423cab631e6e4a0b003c05ffc2dfc132a2" + - "a902a45df2c573d02e5d148c031af7358d5f00e0ff3fd83c1e679a4766043e3dbc62287" + - "0e64ba4c2cacfa2f45563210100000000000071d244c45daecf0abf15c5f4e47f123109" + - "12918ca56b89c3dfb68103371ae6bf98d42e5d148c031aca5d525e00000020d2a6ad530" + - "4a5bbe4948666fd6775dc2cde9c0cef7060a471fe01000000000000597701d1165c140f" + - "471f2684f1f6b3e97765ee5492619582af5e6d192895e7d34cd92e5dffff001dbb34c42" + - "400000020b9b3fcbb515c899b10bf3889d432ca2782cfad01f9c2cf329fb60e00000000" + - "0048d580fbe9ccf1cadaffe0e780eab57ea401f6260f38bd459d32cc3eef6cbd33ffd92" + - "e5d148c031a3c4277f40000002024af4d64067c20a1ed5cb9fbd432a98fe659e3653378" + - "e6b9ed00000000000000fea85a41c80b307f9cdfd22ac52521ba89ea6467769206d8988" + - "9663cb7742e7358db2e5d148c031a7d30031a0000ff3f6418122efc0ddf2416189b01c0" + - "d98ab7e5072fe1e99c3e275401000000000000496c06f87b8d442db7c6bd36ff05e3a7a" + - "0edb3e0124d26c61d44c584ba1f8ff86bdc2e5d148c031a411e00ae", + "0583b7a45472123fac1003384cc60fce2129c8d7364969dfa35021ab26c0b0449bccc2e" + + "5dffff001d061013a10000ff3f3210404a744c3170cdd6ad7fc901194c913004faa87f2" + + "91cd3faac2b00000000ecc1620341eeee4881423cab631e6e4a0b003c05ffc2dfc132a2" + + "a902a45df2c573d02e5d148c031af7358d5f00e0ff3fd83c1e679a4766043e3dbc62287" + + "0e64ba4c2cacfa2f45563210100000000000071d244c45daecf0abf15c5f4e47f123109" + + "12918ca56b89c3dfb68103371ae6bf98d42e5d148c031aca5d525e00000020d2a6ad530" + + "4a5bbe4948666fd6775dc2cde9c0cef7060a471fe01000000000000597701d1165c140f" + + "471f2684f1f6b3e97765ee5492619582af5e6d192895e7d34cd92e5dffff001dbb34c42" + + "400000020b9b3fcbb515c899b10bf3889d432ca2782cfad01f9c2cf329fb60e00000000" + + "0048d580fbe9ccf1cadaffe0e780eab57ea401f6260f38bd459d32cc3eef6cbd33ffd92" + + "e5d148c031a3c4277f40000002024af4d64067c20a1ed5cb9fbd432a98fe659e3653378" + + "e6b9ed00000000000000fea85a41c80b307f9cdfd22ac52521ba89ea6467769206d8988" + + "9663cb7742e7358db2e5d148c031a7d30031a0000ff3f6418122efc0ddf2416189b01c0" + + "d98ab7e5072fe1e99c3e275401000000000000496c06f87b8d442db7c6bd36ff05e3a7a" + + "0edb3e0124d26c61d44c584ba1f8ff86bdc2e5d148c031a411e00ae" + ), } /** @@ -100,15 +101,33 @@ export const testnetHeadersChain = { export const testnetTransactionMerkleBranch: BitcoinTxMerkleBranch = { blockHeight: 1569342, merkle: [ - "8b5bbb5bdf6727bf70fad4f46fe4eaab04c98119ffbd2d95c29adf32d26f8452", - "53637bacb07965e4a8220836861d1b16c6da29f10ea9ab53fc4eca73074f98b9", - "0267e738108d094ceb05217e2942e9c2a4c6389ac47f476f572c9a319ce4dfbc", - "34e00deec50c48d99678ca2b52b82d6d5432326159c69e7233d0dde0924874b4", - "7a53435e6c86a3620cdbae510901f17958f0540314214379197874ed8ed7a913", - "6315dbb7ce350ceaa16cd4c35c5a147005e8b38ca1e9531bd7320629e8d17f5b", - "40380cdadc0206646208871e952af9dcfdff2f104305ce463aed5eeaf7725d2f", - "5d74bae6a71fd1cff2416865460583319a40343650bd4bb89de0a6ae82097037", - "296ddccfc659e0009aad117c8ed15fb6ff81c2bade73fbc89666a22708d233f9", + Hex.from( + "8b5bbb5bdf6727bf70fad4f46fe4eaab04c98119ffbd2d95c29adf32d26f8452" + ), + Hex.from( + "53637bacb07965e4a8220836861d1b16c6da29f10ea9ab53fc4eca73074f98b9" + ), + Hex.from( + "0267e738108d094ceb05217e2942e9c2a4c6389ac47f476f572c9a319ce4dfbc" + ), + Hex.from( + "34e00deec50c48d99678ca2b52b82d6d5432326159c69e7233d0dde0924874b4" + ), + Hex.from( + "7a53435e6c86a3620cdbae510901f17958f0540314214379197874ed8ed7a913" + ), + Hex.from( + "6315dbb7ce350ceaa16cd4c35c5a147005e8b38ca1e9531bd7320629e8d17f5b" + ), + Hex.from( + "40380cdadc0206646208871e952af9dcfdff2f104305ce463aed5eeaf7725d2f" + ), + Hex.from( + "5d74bae6a71fd1cff2416865460583319a40343650bd4bb89de0a6ae82097037" + ), + Hex.from( + "296ddccfc659e0009aad117c8ed15fb6ff81c2bade73fbc89666a22708d233f9" + ), ], position: 176, } diff --git a/typescript/test/data/proof.ts b/typescript/test/data/proof.ts index bbd94a853..6d3e114c0 100644 --- a/typescript/test/data/proof.ts +++ b/typescript/test/data/proof.ts @@ -18,7 +18,7 @@ export interface ProofTestData { rawTransaction: BitcoinRawTx accumulatedTxConfirmations: number latestBlockHeight: number - headersChain: string + headersChain: Hex transactionMerkleBranch: BitcoinTxMerkleBranch } expectedProof: BitcoinSpvProof & BitcoinTx @@ -68,35 +68,50 @@ export const singleInputProofTestData: ProofTestData = { }, accumulatedTxConfirmations: 50, latestBlockHeight: 2164335, - headersChain: + headersChain: Hex.from( "04e00020732d33ea35d62f9488cff5d64c0d702afd5d88092230ddfcc45f00000" + - "0000000196283ba24a3f5bad91ef95338aa6d214c934f2c1392e39a0447377fe5" + - "b0a04be7c01c62ffff001df0be0a27040000206c318b23e5c42e86ef3edd080e5" + - "0c9c233b9f0b6d186bd57e41300000000000021fb8cda200bff4fec1338d85a1e" + - "005bb4d729d908a7c5c232ecd0713231d0445ec11c62ed3e031a7b43466e04e00" + - "020f416898d79d4a46fa6c54f190ad3d502bad8aa3afdec0714aa000000000000" + - "000603a5cc15e5906cb4eac9f747869fdc9be856e76a110b4f87da90db20f9fbe" + - "28fc11c62ed3e031a15dfc3db04000020642125b3910fdaead521b57955e28893" + - "d89f8ce7fd3ba1dd6d01000000000000f9e17a266a2267ee02d5ab82a75a76805" + - "db821a13abd2e80e0950d883311e5355dc21c62ed3e031adefc02c4040000205b" + - "6de55e069be71b21a62cd140dc7031225f7258dc758f19ea01000000000000139" + - "966d27d9ed0c0c1ed9162c2fea2ccf0ba212706f6bc421d0a2b6211de040d1ac4" + - "1c62ed3e031a4726538f04e000208475e15e0314635d32abf04c761fee528d6a3" + - "f2db3b3d13798000000000000002a3fa06fecd9dd4bf2e25e22a95d4f65435d5c" + - "5b42bcf498b4e756f9f4ea67cea1c51c62ed3e031a9d7bf3ac000000203f16d45" + - "0c51853a4cd9569d225028aa08ab6139eee31f4f67a010000000000004cda79bc" + - "48b970de2fb29c3f38626eb9d70d8bae7b92aad09f2a0ad2d2f334d35bca1c62f" + - "fff001d048fc217", + "0000000196283ba24a3f5bad91ef95338aa6d214c934f2c1392e39a0447377fe5" + + "b0a04be7c01c62ffff001df0be0a27040000206c318b23e5c42e86ef3edd080e5" + + "0c9c233b9f0b6d186bd57e41300000000000021fb8cda200bff4fec1338d85a1e" + + "005bb4d729d908a7c5c232ecd0713231d0445ec11c62ed3e031a7b43466e04e00" + + "020f416898d79d4a46fa6c54f190ad3d502bad8aa3afdec0714aa000000000000" + + "000603a5cc15e5906cb4eac9f747869fdc9be856e76a110b4f87da90db20f9fbe" + + "28fc11c62ed3e031a15dfc3db04000020642125b3910fdaead521b57955e28893" + + "d89f8ce7fd3ba1dd6d01000000000000f9e17a266a2267ee02d5ab82a75a76805" + + "db821a13abd2e80e0950d883311e5355dc21c62ed3e031adefc02c4040000205b" + + "6de55e069be71b21a62cd140dc7031225f7258dc758f19ea01000000000000139" + + "966d27d9ed0c0c1ed9162c2fea2ccf0ba212706f6bc421d0a2b6211de040d1ac4" + + "1c62ed3e031a4726538f04e000208475e15e0314635d32abf04c761fee528d6a3" + + "f2db3b3d13798000000000000002a3fa06fecd9dd4bf2e25e22a95d4f65435d5c" + + "5b42bcf498b4e756f9f4ea67cea1c51c62ed3e031a9d7bf3ac000000203f16d45" + + "0c51853a4cd9569d225028aa08ab6139eee31f4f67a010000000000004cda79bc" + + "48b970de2fb29c3f38626eb9d70d8bae7b92aad09f2a0ad2d2f334d35bca1c62f" + + "fff001d048fc217" + ), transactionMerkleBranch: { blockHeight: 2164152, merkle: [ - "7bffaff2c61291861276da41cf6c3842fad555af97dd1ff98ce41c61a0072b12", - "7a5876ddee8e553ff0650c739b2ec66e192d8afe5fc0ce763bf810457aea330c", - "2d17b67d5519bc39fbef8650afd3fe11fdfb3f471434a5b551cfa9a41441901f", - "1376d102b677591ce2fa62553e2a57ab5919022b03036521facfce93a0338026", - "43ad3aadad675e398c59eb846a8e037cf7de8ba3b38f3388175f25d84b777c80", - "6969c227128793b3c9e99c05f20fb9b91fdb73458fd53151b5fe29d30c10cf9a", - "0a76bc4d8c3d532357be4d188ba89e9ae364a7d3c365e690e3cb07359b86129c", + Hex.from( + "7bffaff2c61291861276da41cf6c3842fad555af97dd1ff98ce41c61a0072b12" + ), + Hex.from( + "7a5876ddee8e553ff0650c739b2ec66e192d8afe5fc0ce763bf810457aea330c" + ), + Hex.from( + "2d17b67d5519bc39fbef8650afd3fe11fdfb3f471434a5b551cfa9a41441901f" + ), + Hex.from( + "1376d102b677591ce2fa62553e2a57ab5919022b03036521facfce93a0338026" + ), + Hex.from( + "43ad3aadad675e398c59eb846a8e037cf7de8ba3b38f3388175f25d84b777c80" + ), + Hex.from( + "6969c227128793b3c9e99c05f20fb9b91fdb73458fd53151b5fe29d30c10cf9a" + ), + Hex.from( + "0a76bc4d8c3d532357be4d188ba89e9ae364a7d3c365e690e3cb07359b86129c" + ), ], position: 11, }, @@ -121,33 +136,35 @@ export const singleInputProofTestData: ProofTestData = { scriptPubKey: Hex.from("00148db50eb52063ea9d98b3eac91489a90f738986f6"), }, ], - merkleProof: + merkleProof: Hex.from( "122b07a0611ce48cf91fdd97af55d5fa42386ccf41da7612869112c6f2afff7b0c" + - "33ea7a4510f83b76cec05ffe8a2d196ec62e9b730c65f03f558eeedd76587a1f90" + - "4114a4a9cf51b5a53414473ffbfd11fed3af5086effb39bc19557db6172d268033" + - "a093cecffa216503032b021959ab572a3e5562fae21c5977b602d17613807c774b" + - "d8255f1788338fb3a38bdef77c038e6a84eb598c395e67adad3aad439acf100cd3" + - "29feb55131d58f4573db1fb9b90ff2059ce9c9b393871227c269699c12869b3507" + - "cbe390e665c3d3a764e39a9ea88b184dbe5723533d8c4dbc760a", + "33ea7a4510f83b76cec05ffe8a2d196ec62e9b730c65f03f558eeedd76587a1f90" + + "4114a4a9cf51b5a53414473ffbfd11fed3af5086effb39bc19557db6172d268033" + + "a093cecffa216503032b021959ab572a3e5562fae21c5977b602d17613807c774b" + + "d8255f1788338fb3a38bdef77c038e6a84eb598c395e67adad3aad439acf100cd3" + + "29feb55131d58f4573db1fb9b90ff2059ce9c9b393871227c269699c12869b3507" + + "cbe390e665c3d3a764e39a9ea88b184dbe5723533d8c4dbc760a" + ), txIndexInBlock: 11, - bitcoinHeaders: + bitcoinHeaders: Hex.from( "04e00020732d33ea35d62f9488cff5d64c0d702afd5d88092230ddfcc45f000000" + - "000000196283ba24a3f5bad91ef95338aa6d214c934f2c1392e39a0447377fe5b0" + - "a04be7c01c62ffff001df0be0a27040000206c318b23e5c42e86ef3edd080e50c9" + - "c233b9f0b6d186bd57e41300000000000021fb8cda200bff4fec1338d85a1e005b" + - "b4d729d908a7c5c232ecd0713231d0445ec11c62ed3e031a7b43466e04e00020f4" + - "16898d79d4a46fa6c54f190ad3d502bad8aa3afdec0714aa000000000000000603" + - "a5cc15e5906cb4eac9f747869fdc9be856e76a110b4f87da90db20f9fbe28fc11c" + - "62ed3e031a15dfc3db04000020642125b3910fdaead521b57955e28893d89f8ce7" + - "fd3ba1dd6d01000000000000f9e17a266a2267ee02d5ab82a75a76805db821a13a" + - "bd2e80e0950d883311e5355dc21c62ed3e031adefc02c4040000205b6de55e069b" + - "e71b21a62cd140dc7031225f7258dc758f19ea01000000000000139966d27d9ed0" + - "c0c1ed9162c2fea2ccf0ba212706f6bc421d0a2b6211de040d1ac41c62ed3e031a" + - "4726538f04e000208475e15e0314635d32abf04c761fee528d6a3f2db3b3d13798" + - "000000000000002a3fa06fecd9dd4bf2e25e22a95d4f65435d5c5b42bcf498b4e7" + - "56f9f4ea67cea1c51c62ed3e031a9d7bf3ac000000203f16d450c51853a4cd9569" + - "d225028aa08ab6139eee31f4f67a010000000000004cda79bc48b970de2fb29c3f" + - "38626eb9d70d8bae7b92aad09f2a0ad2d2f334d35bca1c62ffff001d048fc217", + "000000196283ba24a3f5bad91ef95338aa6d214c934f2c1392e39a0447377fe5b0" + + "a04be7c01c62ffff001df0be0a27040000206c318b23e5c42e86ef3edd080e50c9" + + "c233b9f0b6d186bd57e41300000000000021fb8cda200bff4fec1338d85a1e005b" + + "b4d729d908a7c5c232ecd0713231d0445ec11c62ed3e031a7b43466e04e00020f4" + + "16898d79d4a46fa6c54f190ad3d502bad8aa3afdec0714aa000000000000000603" + + "a5cc15e5906cb4eac9f747869fdc9be856e76a110b4f87da90db20f9fbe28fc11c" + + "62ed3e031a15dfc3db04000020642125b3910fdaead521b57955e28893d89f8ce7" + + "fd3ba1dd6d01000000000000f9e17a266a2267ee02d5ab82a75a76805db821a13a" + + "bd2e80e0950d883311e5355dc21c62ed3e031adefc02c4040000205b6de55e069b" + + "e71b21a62cd140dc7031225f7258dc758f19ea01000000000000139966d27d9ed0" + + "c0c1ed9162c2fea2ccf0ba212706f6bc421d0a2b6211de040d1ac41c62ed3e031a" + + "4726538f04e000208475e15e0314635d32abf04c761fee528d6a3f2db3b3d13798" + + "000000000000002a3fa06fecd9dd4bf2e25e22a95d4f65435d5c5b42bcf498b4e7" + + "56f9f4ea67cea1c51c62ed3e031a9d7bf3ac000000203f16d450c51853a4cd9569" + + "d225028aa08ab6139eee31f4f67a010000000000004cda79bc48b970de2fb29c3f" + + "38626eb9d70d8bae7b92aad09f2a0ad2d2f334d35bca1c62ffff001d048fc217" + ), }, } @@ -237,33 +254,44 @@ export const multipleInputsProofTestData: ProofTestData = { "120fb077fbed8804e0250162b175ac6800000000", }, latestBlockHeight: 2164335, - headersChain: + headersChain: Hex.from( "04000020642125b3910fdaead521b57955e28893d89f8ce7fd3ba1dd6d0100000" + - "0000000f9e17a266a2267ee02d5ab82a75a76805db821a13abd2e80e0950d8833" + - "11e5355dc21c62ed3e031adefc02c4040000205b6de55e069be71b21a62cd140d" + - "c7031225f7258dc758f19ea01000000000000139966d27d9ed0c0c1ed9162c2fe" + - "a2ccf0ba212706f6bc421d0a2b6211de040d1ac41c62ed3e031a4726538f04e00" + - "0208475e15e0314635d32abf04c761fee528d6a3f2db3b3d13798000000000000" + - "002a3fa06fecd9dd4bf2e25e22a95d4f65435d5c5b42bcf498b4e756f9f4ea67c" + - "ea1c51c62ed3e031a9d7bf3ac000000203f16d450c51853a4cd9569d225028aa0" + - "8ab6139eee31f4f67a010000000000004cda79bc48b970de2fb29c3f38626eb9d" + - "70d8bae7b92aad09f2a0ad2d2f334d35bca1c62ffff001d048fc2170000002068" + - "7e487acbf5eb375c631a15127fbf7d80ca084461e7f26f92c509b6000000006fa" + - "d33bd7c8d651bd6dc86c286f0a99340b668f019b9e97a59fd392c36c4f46910cf" + - "1c62ffff001d407facaa0400002040f4c65610f26f06c4365305b956934501713" + - "e01c2fc08b919e0bc1b00000000e401a6a884ba015e83c6fe2cd363e877ef0398" + - "2e81eaff4e2c95af1e23a670f407d41c62ffff001d58c64d180400002038854bd" + - "62f802e1de14653eceeb7a80290f5e99b8e9db517e36f000000000000a494b803" + - "4039e7855b75563ab83c9410dd67e89bb58e6cd93b85290a885dd749f4d61c62e" + - "d3e031ad9a83746", + "0000000f9e17a266a2267ee02d5ab82a75a76805db821a13abd2e80e0950d8833" + + "11e5355dc21c62ed3e031adefc02c4040000205b6de55e069be71b21a62cd140d" + + "c7031225f7258dc758f19ea01000000000000139966d27d9ed0c0c1ed9162c2fe" + + "a2ccf0ba212706f6bc421d0a2b6211de040d1ac41c62ed3e031a4726538f04e00" + + "0208475e15e0314635d32abf04c761fee528d6a3f2db3b3d13798000000000000" + + "002a3fa06fecd9dd4bf2e25e22a95d4f65435d5c5b42bcf498b4e756f9f4ea67c" + + "ea1c51c62ed3e031a9d7bf3ac000000203f16d450c51853a4cd9569d225028aa0" + + "8ab6139eee31f4f67a010000000000004cda79bc48b970de2fb29c3f38626eb9d" + + "70d8bae7b92aad09f2a0ad2d2f334d35bca1c62ffff001d048fc2170000002068" + + "7e487acbf5eb375c631a15127fbf7d80ca084461e7f26f92c509b6000000006fa" + + "d33bd7c8d651bd6dc86c286f0a99340b668f019b9e97a59fd392c36c4f46910cf" + + "1c62ffff001d407facaa0400002040f4c65610f26f06c4365305b956934501713" + + "e01c2fc08b919e0bc1b00000000e401a6a884ba015e83c6fe2cd363e877ef0398" + + "2e81eaff4e2c95af1e23a670f407d41c62ffff001d58c64d180400002038854bd" + + "62f802e1de14653eceeb7a80290f5e99b8e9db517e36f000000000000a494b803" + + "4039e7855b75563ab83c9410dd67e89bb58e6cd93b85290a885dd749f4d61c62e" + + "d3e031ad9a83746" + ), transactionMerkleBranch: { blockHeight: 2164155, merkle: [ - "322cfdf3ca53cf597b6f08e93489b9a1cfa1f5958c3657474b0d8f5efb5ca92e", - "82aedffef6c9670375effee25740fecce143d21f8abf98307235b7ebd31ad4d1", - "837fa041b9a8f5b42353fdf8981e3b7a78c61858852e43058bfe6cacf9eab5a3", - "a51612d3f3f857e95803a4d86aa6dbbe2e756dc2ed6cc0e04630e8baf597e377", - "a00501650e0c4f8a1e07a5d6d5bc5e75e4c75de61a65f0410cce354bbae78686", + Hex.from( + "322cfdf3ca53cf597b6f08e93489b9a1cfa1f5958c3657474b0d8f5efb5ca92e" + ), + Hex.from( + "82aedffef6c9670375effee25740fecce143d21f8abf98307235b7ebd31ad4d1" + ), + Hex.from( + "837fa041b9a8f5b42353fdf8981e3b7a78c61858852e43058bfe6cacf9eab5a3" + ), + Hex.from( + "a51612d3f3f857e95803a4d86aa6dbbe2e756dc2ed6cc0e04630e8baf597e377" + ), + Hex.from( + "a00501650e0c4f8a1e07a5d6d5bc5e75e4c75de61a65f0410cce354bbae78686" + ), ], position: 6, }, @@ -309,31 +337,33 @@ export const multipleInputsProofTestData: ProofTestData = { scriptPubKey: Hex.from("00148db50eb52063ea9d98b3eac91489a90f738986f6"), }, ], - merkleProof: + merkleProof: Hex.from( "2ea95cfb5e8f0d4b4757368c95f5a1cfa1b98934e9086f7b59cf53caf3fd2c32d1d" + - "41ad3ebb735723098bf8a1fd243e1ccfe4057e2feef750367c9f6fedfae82a3b5ea" + - "f9ac6cfe8b05432e855818c6787a3b1e98f8fd5323b4f5a8b941a07f8377e397f5b" + - "ae83046e0c06cedc26d752ebedba66ad8a40358e957f8f3d31216a58686e7ba4b35" + - "ce0c41f0651ae65dc7e4755ebcd5d6a5071e8a4f0c0e650105a0", + "41ad3ebb735723098bf8a1fd243e1ccfe4057e2feef750367c9f6fedfae82a3b5ea" + + "f9ac6cfe8b05432e855818c6787a3b1e98f8fd5323b4f5a8b941a07f8377e397f5b" + + "ae83046e0c06cedc26d752ebedba66ad8a40358e957f8f3d31216a58686e7ba4b35" + + "ce0c41f0651ae65dc7e4755ebcd5d6a5071e8a4f0c0e650105a0" + ), txIndexInBlock: 6, - bitcoinHeaders: + bitcoinHeaders: Hex.from( "04000020642125b3910fdaead521b57955e28893d89f8ce7fd3ba1dd6d010000000" + - "00000f9e17a266a2267ee02d5ab82a75a76805db821a13abd2e80e0950d883311e5" + - "355dc21c62ed3e031adefc02c4040000205b6de55e069be71b21a62cd140dc70312" + - "25f7258dc758f19ea01000000000000139966d27d9ed0c0c1ed9162c2fea2ccf0ba" + - "212706f6bc421d0a2b6211de040d1ac41c62ed3e031a4726538f04e000208475e15" + - "e0314635d32abf04c761fee528d6a3f2db3b3d13798000000000000002a3fa06fec" + - "d9dd4bf2e25e22a95d4f65435d5c5b42bcf498b4e756f9f4ea67cea1c51c62ed3e0" + - "31a9d7bf3ac000000203f16d450c51853a4cd9569d225028aa08ab6139eee31f4f6" + - "7a010000000000004cda79bc48b970de2fb29c3f38626eb9d70d8bae7b92aad09f2" + - "a0ad2d2f334d35bca1c62ffff001d048fc21700000020687e487acbf5eb375c631a" + - "15127fbf7d80ca084461e7f26f92c509b6000000006fad33bd7c8d651bd6dc86c28" + - "6f0a99340b668f019b9e97a59fd392c36c4f46910cf1c62ffff001d407facaa0400" + - "002040f4c65610f26f06c4365305b956934501713e01c2fc08b919e0bc1b0000000" + - "0e401a6a884ba015e83c6fe2cd363e877ef03982e81eaff4e2c95af1e23a670f407" + - "d41c62ffff001d58c64d180400002038854bd62f802e1de14653eceeb7a80290f5e" + - "99b8e9db517e36f000000000000a494b8034039e7855b75563ab83c9410dd67e89b" + - "b58e6cd93b85290a885dd749f4d61c62ed3e031ad9a83746", + "00000f9e17a266a2267ee02d5ab82a75a76805db821a13abd2e80e0950d883311e5" + + "355dc21c62ed3e031adefc02c4040000205b6de55e069be71b21a62cd140dc70312" + + "25f7258dc758f19ea01000000000000139966d27d9ed0c0c1ed9162c2fea2ccf0ba" + + "212706f6bc421d0a2b6211de040d1ac41c62ed3e031a4726538f04e000208475e15" + + "e0314635d32abf04c761fee528d6a3f2db3b3d13798000000000000002a3fa06fec" + + "d9dd4bf2e25e22a95d4f65435d5c5b42bcf498b4e756f9f4ea67cea1c51c62ed3e0" + + "31a9d7bf3ac000000203f16d450c51853a4cd9569d225028aa08ab6139eee31f4f6" + + "7a010000000000004cda79bc48b970de2fb29c3f38626eb9d70d8bae7b92aad09f2" + + "a0ad2d2f334d35bca1c62ffff001d048fc21700000020687e487acbf5eb375c631a" + + "15127fbf7d80ca084461e7f26f92c509b6000000006fad33bd7c8d651bd6dc86c28" + + "6f0a99340b668f019b9e97a59fd392c36c4f46910cf1c62ffff001d407facaa0400" + + "002040f4c65610f26f06c4365305b956934501713e01c2fc08b919e0bc1b0000000" + + "0e401a6a884ba015e83c6fe2cd363e877ef03982e81eaff4e2c95af1e23a670f407" + + "d41c62ffff001d58c64d180400002038854bd62f802e1de14653eceeb7a80290f5e" + + "99b8e9db517e36f000000000000a494b8034039e7855b75563ab83c9410dd67e89b" + + "b58e6cd93b85290a885dd749f4d61c62ed3e031ad9a83746" + ), }, } @@ -346,7 +376,7 @@ export interface TransactionProofData { transaction: BitcoinTx accumulatedTxConfirmations: number latestBlockHeight: number - headersChain: string + headersChain: Hex transactionMerkleBranch: BitcoinTxMerkleBranch previousDifficulty: BigNumber currentDifficulty: BigNumber @@ -414,35 +444,58 @@ export const transactionConfirmationsInOneEpochData: TransactionProofData = { }, accumulatedTxConfirmations: 1798, latestBlockHeight: 777963, - headersChain: + headersChain: Hex.from( "00e0ff2f5ad9c09e1d8aae777a58bf29c41621eb629032598f7900000000000000000" + - "0004dea17724c3b7e67d4cf1ac41a4c7527b884f7406575eaf5b8efaf2fb12572ecb1" + - "ace86339300717760098100000ff3fd3ab40174610c286e569edd20fa713bd98bab53" + - "bee83050000000000000000002345f5ef807cf75de7b30ccfe493c46c6e07aca044aa" + - "2aa106141637f1bb8500a6ade863393007177fbbd4b300800120646d493817f0ac988" + - "6a0a194ca3a957f70c3eb642ffd05000000000000000000d95674b737f097f042eebe" + - "b970c09b274df7e72a9c202ff2292ed72b056ee90967aee863393007172e2bb92e006" + - "03b27a391d248c258ef628dfb8c710ce44c8017667a07941402000000000000000000" + - "35214e58eb018dea1efa7eaf1b7f19ff2d6f0310c122be6dc8c0258d9524ae9382aee" + - "863393007173e82b2000000002003c7003ff9a79f16d956fc764b43b35080efe3a820" + - "af050000000000000000007808e96809cd46d5898d86faabc8f28a8b6572eb8399796" + - "70b2851d78fc1f75f17b3e86339300717450f17650400e020fb9b6a28bb2e9cea36d3" + - "40588f19ffa4e944b050e73f03000000000000000000bbd7534f2550ee99f31efcd77" + - "564f1b5b3f3966a76847896a8d9f9ee964d670ba2b4e8633930071777b10cfc", + "0004dea17724c3b7e67d4cf1ac41a4c7527b884f7406575eaf5b8efaf2fb12572ecb1" + + "ace86339300717760098100000ff3fd3ab40174610c286e569edd20fa713bd98bab53" + + "bee83050000000000000000002345f5ef807cf75de7b30ccfe493c46c6e07aca044aa" + + "2aa106141637f1bb8500a6ade863393007177fbbd4b300800120646d493817f0ac988" + + "6a0a194ca3a957f70c3eb642ffd05000000000000000000d95674b737f097f042eebe" + + "b970c09b274df7e72a9c202ff2292ed72b056ee90967aee863393007172e2bb92e006" + + "03b27a391d248c258ef628dfb8c710ce44c8017667a07941402000000000000000000" + + "35214e58eb018dea1efa7eaf1b7f19ff2d6f0310c122be6dc8c0258d9524ae9382aee" + + "863393007173e82b2000000002003c7003ff9a79f16d956fc764b43b35080efe3a820" + + "af050000000000000000007808e96809cd46d5898d86faabc8f28a8b6572eb8399796" + + "70b2851d78fc1f75f17b3e86339300717450f17650400e020fb9b6a28bb2e9cea36d3" + + "40588f19ffa4e944b050e73f03000000000000000000bbd7534f2550ee99f31efcd77" + + "564f1b5b3f3966a76847896a8d9f9ee964d670ba2b4e8633930071777b10cfc" + ), transactionMerkleBranch: { blockHeight: 776166, merkle: [ - "f6ce0e34cc5b2a4b8cd4fd02a65d7cf62013206969e8e5cf1df18f994abcf1ff", - "08899ec43299b324583722f3e7d0938446a1f31a6ab34c8e24cb4ea9ba6cd384", - "9677b6075dfa2da8bcc98aa10ae7d30f81e6506215eadd3f3739a5d987e62b35", - "aa6712d8820c06ec8ce99f9c19d580ab54bb45f69b426935153b81e7d412ddba", - "b38be47e1dd9a7324ad81a395a133f26fc88cb736a4998dbba6cbabca10629a8", - "13bdefbf92421aa7861528e16e7046b569d25ee0f4b7649492e42e9ea2331c39", - "df429494c5eef971a7ab80c8a0f7f9cdfa30148afef706f07923bd93d5a7e22a", - "c8a3f1bc73146bd4a1a0e848f2b0b4a21be86e4930f239d856af8e9646014236", - "1f514df87fe2c400e508e01cd8967657ef76db9681f65dc82b0bc6d4004b575f", - "e463950c8efd9114237189f07ddf1cfdb72658bad23bce667c269652bd0ade3c", - "3d7ae6df787807320fdc397a7055e86c932a7c36ab1d1f942b92c53bf2a1d2f9", + Hex.from( + "f6ce0e34cc5b2a4b8cd4fd02a65d7cf62013206969e8e5cf1df18f994abcf1ff" + ), + Hex.from( + "08899ec43299b324583722f3e7d0938446a1f31a6ab34c8e24cb4ea9ba6cd384" + ), + Hex.from( + "9677b6075dfa2da8bcc98aa10ae7d30f81e6506215eadd3f3739a5d987e62b35" + ), + Hex.from( + "aa6712d8820c06ec8ce99f9c19d580ab54bb45f69b426935153b81e7d412ddba" + ), + Hex.from( + "b38be47e1dd9a7324ad81a395a133f26fc88cb736a4998dbba6cbabca10629a8" + ), + Hex.from( + "13bdefbf92421aa7861528e16e7046b569d25ee0f4b7649492e42e9ea2331c39" + ), + Hex.from( + "df429494c5eef971a7ab80c8a0f7f9cdfa30148afef706f07923bd93d5a7e22a" + ), + Hex.from( + "c8a3f1bc73146bd4a1a0e848f2b0b4a21be86e4930f239d856af8e9646014236" + ), + Hex.from( + "1f514df87fe2c400e508e01cd8967657ef76db9681f65dc82b0bc6d4004b575f" + ), + Hex.from( + "e463950c8efd9114237189f07ddf1cfdb72658bad23bce667c269652bd0ade3c" + ), + Hex.from( + "3d7ae6df787807320fdc397a7055e86c932a7c36ab1d1f942b92c53bf2a1d2f9" + ), ], position: 17, }, @@ -491,34 +544,55 @@ export const transactionConfirmationsInTwoEpochsData: TransactionProofData = { }, accumulatedTxConfirmations: 3838, latestBlockHeight: 777979, - headersChain: + headersChain: Hex.from( "0040f224871a401b605e02c475e05e147bd418e5e2ae9eb599e200000000000000000" + - "000193dc07aea4388a163ed0e3e5234ef54594cfc046bce727d2d6b3445d3ce0e8c44" + - "0dd663e27c07170c0d54de00e0682c9c27df3b2a1b011753c986c290ce22c60d09a05" + - "3707100000000000000000000ddf3b023ed6368bdac8578bd55d0c3fad7f234ae971b" + - "902b155bee7318bf0919b30dd663e27c0717be025f2b00000020514a9bd87c51caedd" + - "45a20c495f0ba1983b6f3f51639050000000000000000001f4c60a97f4127b4f90fbb" + - "7a6a1041881b10d4f7351340b6770301f62b36725ce10dd66320270717c11c5e7b002" + - "0002043e99cc906d52209796ecb37b252e4514f197d727ea701000000000000000000" + - "274ecaf37779be81c23748d33ef4a0cad36a8abd935a11f0e0a71640c6dd1deaf10dd" + - "66320270717846927aa0000c02090a4a88ab1ad55e235932fe0adc7b4c822b4322f58" + - "9305000000000000000000decc945dc9cdf595715ffeee3bffc0ec0c8c5ff77e43b8e" + - "91213e21a9975c99ddc10d663202707179f93251000203229e618c1eb9274a1acbb74" + - "d44bfe9a4ecfae236ea35e8b0300000000000000000029a9f7b4f6671dec5d6ba05ac" + - "b060fcd2ffc6e46a992189c6f60d770d9c5a5cda31cd66320270717542691a2", + "000193dc07aea4388a163ed0e3e5234ef54594cfc046bce727d2d6b3445d3ce0e8c44" + + "0dd663e27c07170c0d54de00e0682c9c27df3b2a1b011753c986c290ce22c60d09a05" + + "3707100000000000000000000ddf3b023ed6368bdac8578bd55d0c3fad7f234ae971b" + + "902b155bee7318bf0919b30dd663e27c0717be025f2b00000020514a9bd87c51caedd" + + "45a20c495f0ba1983b6f3f51639050000000000000000001f4c60a97f4127b4f90fbb" + + "7a6a1041881b10d4f7351340b6770301f62b36725ce10dd66320270717c11c5e7b002" + + "0002043e99cc906d52209796ecb37b252e4514f197d727ea701000000000000000000" + + "274ecaf37779be81c23748d33ef4a0cad36a8abd935a11f0e0a71640c6dd1deaf10dd" + + "66320270717846927aa0000c02090a4a88ab1ad55e235932fe0adc7b4c822b4322f58" + + "9305000000000000000000decc945dc9cdf595715ffeee3bffc0ec0c8c5ff77e43b8e" + + "91213e21a9975c99ddc10d663202707179f93251000203229e618c1eb9274a1acbb74" + + "d44bfe9a4ecfae236ea35e8b0300000000000000000029a9f7b4f6671dec5d6ba05ac" + + "b060fcd2ffc6e46a992189c6f60d770d9c5a5cda31cd66320270717542691a2" + ), transactionMerkleBranch: { blockHeight: 774142, merkle: [ - "e80f706f53d5abd77070ea6c8a60c141748400e09fc9b373d5cdb0129cbce5ec", - "20d22506199cf00caf2e32e240c77a23c226d5a74de4dc9150ccd6f5200b4dd7", - "8b446693fadaae7479725f0e98430c24f8bf8936f5a5cab7c725692cd78e61e3", - "93e61f1ac82cf6a66e321c60410ae4bdfcc0ab45b7efd50353d7b08104758403", - "1dc52561092701978f1e48a10bc4da5464e668f0f4b3a940853c941474ee52de", - "84aca5ec5b339b69a50b93d35c2fd7b146c037842ca76b33cbf835b9e6c86f0c", - "ebcd1bb7039d40ac0d477af58964b4582c6741d1c901ab4a2b0de15e600cba69", - "38d458a70805902a52342cfc552d374bdb217cd389e9550adfc4f86df6fdce82", - "07781ff50552aefea962f0f4972fe882cb38a281ebdd533c2886d5137b80fbeb", - "e7e530e181683d272293f19fe18a33f1dc05eded12ec27945b49311b2e14ee42", + Hex.from( + "e80f706f53d5abd77070ea6c8a60c141748400e09fc9b373d5cdb0129cbce5ec" + ), + Hex.from( + "20d22506199cf00caf2e32e240c77a23c226d5a74de4dc9150ccd6f5200b4dd7" + ), + Hex.from( + "8b446693fadaae7479725f0e98430c24f8bf8936f5a5cab7c725692cd78e61e3" + ), + Hex.from( + "93e61f1ac82cf6a66e321c60410ae4bdfcc0ab45b7efd50353d7b08104758403" + ), + Hex.from( + "1dc52561092701978f1e48a10bc4da5464e668f0f4b3a940853c941474ee52de" + ), + Hex.from( + "84aca5ec5b339b69a50b93d35c2fd7b146c037842ca76b33cbf835b9e6c86f0c" + ), + Hex.from( + "ebcd1bb7039d40ac0d477af58964b4582c6741d1c901ab4a2b0de15e600cba69" + ), + Hex.from( + "38d458a70805902a52342cfc552d374bdb217cd389e9550adfc4f86df6fdce82" + ), + Hex.from( + "07781ff50552aefea962f0f4972fe882cb38a281ebdd533c2886d5137b80fbeb" + ), + Hex.from( + "e7e530e181683d272293f19fe18a33f1dc05eded12ec27945b49311b2e14ee42" + ), ], position: 262, }, @@ -566,31 +640,46 @@ export const testnetTransactionData: TransactionProofData = { }, accumulatedTxConfirmations: 18, latestBlockHeight: 2421198, - headersChain: + headersChain: Hex.from( "000000203528cf6e8112d970a1adeb9743937d2e980afb43cb8ce3600100000000000" + - "0007bacd9aa2249c74fdba75dd651a16755e9b4dc3c1953f2baa01d657f317e3eb936" + - "62f763ffff001d7045e837000040207184a40ae97e64b2bce8fed41f967eac210e036" + - "9a66855bd2b37c86200000000fe261c184d19c15c7b66c284d5f65e79595f65d576cc" + - "40f20cccf0fcbae3c063a866f7639cde2c193ed763b904e000209885f5bb4bc96f8ff" + - "ed3bf31c6f526f1f71fc6dd3f9bb0ed0200000000000000720c67b13ee8805763110f" + - "b345cbfb5369836344e6a990e4ac0c363211362b2c6168f7639cde2c19294a1006000" + - "040200aafa9b9e947a9bd6fe2e9f04dece7753863d59b11e5c63b1500000000000000" + - "7a63f980ffc1f993c0d7dbe0670e71be2eeae8710a7906f758d3b400dd6a1e6b3c69f" + - "7639cde2c1940a3735000008020ba335b0d58de55cf227fdd35ba380a4a288d4f7926" + - "8be6a01800000000000000ffdc211cb41a97249e18a54aa4861a77f43093d6716995a" + - "9f659370ee1cf8aea406af7639cde2c19254197450000002069b318d3a7c7c154651f" + - "23ac4c3a51c7ec5158f40a62783c0400000000000000f452ef784d467c9f541331552" + - "32d005bdd0f2d323933646976ef2b7275206d7ff96ef763ffff001db18d224b", + "0007bacd9aa2249c74fdba75dd651a16755e9b4dc3c1953f2baa01d657f317e3eb936" + + "62f763ffff001d7045e837000040207184a40ae97e64b2bce8fed41f967eac210e036" + + "9a66855bd2b37c86200000000fe261c184d19c15c7b66c284d5f65e79595f65d576cc" + + "40f20cccf0fcbae3c063a866f7639cde2c193ed763b904e000209885f5bb4bc96f8ff" + + "ed3bf31c6f526f1f71fc6dd3f9bb0ed0200000000000000720c67b13ee8805763110f" + + "b345cbfb5369836344e6a990e4ac0c363211362b2c6168f7639cde2c19294a1006000" + + "040200aafa9b9e947a9bd6fe2e9f04dece7753863d59b11e5c63b1500000000000000" + + "7a63f980ffc1f993c0d7dbe0670e71be2eeae8710a7906f758d3b400dd6a1e6b3c69f" + + "7639cde2c1940a3735000008020ba335b0d58de55cf227fdd35ba380a4a288d4f7926" + + "8be6a01800000000000000ffdc211cb41a97249e18a54aa4861a77f43093d6716995a" + + "9f659370ee1cf8aea406af7639cde2c19254197450000002069b318d3a7c7c154651f" + + "23ac4c3a51c7ec5158f40a62783c0400000000000000f452ef784d467c9f541331552" + + "32d005bdd0f2d323933646976ef2b7275206d7ff96ef763ffff001db18d224b" + ), transactionMerkleBranch: { blockHeight: 2421181, merkle: [ - "33610df4f460e1338d9f6a055de18d5c694edf590722211b6feeec77a9479846", - "0fd7e0afdde99bdfbfdc0d0e6f5ccda4cd1873eee315bb989622fd58bd5c4446", - "2d4ab6c53cedc1a447e21ad2f38c6d9d0d9c761426975a65f83fe10f12e3c9e0", - "0eebd6daa03f6db4a27541a91bcf86612c97d100bc37c3eb321d64d943adb2a5", - "b25854f31fc046eb0f53cddbf2b6de3d54d52710acd79a796c78c3be235f031a", - "1fc5ab77039f59ac2494791fc05c75fb53e2dacf57a20f67e7d6727b38778825", - "5b0acfdbb89af64a583a88e92252b8634bd4da06ee102ecd34c2662955e9f1c7", + Hex.from( + "33610df4f460e1338d9f6a055de18d5c694edf590722211b6feeec77a9479846" + ), + Hex.from( + "0fd7e0afdde99bdfbfdc0d0e6f5ccda4cd1873eee315bb989622fd58bd5c4446" + ), + Hex.from( + "2d4ab6c53cedc1a447e21ad2f38c6d9d0d9c761426975a65f83fe10f12e3c9e0" + ), + Hex.from( + "0eebd6daa03f6db4a27541a91bcf86612c97d100bc37c3eb321d64d943adb2a5" + ), + Hex.from( + "b25854f31fc046eb0f53cddbf2b6de3d54d52710acd79a796c78c3be235f031a" + ), + Hex.from( + "1fc5ab77039f59ac2494791fc05c75fb53e2dacf57a20f67e7d6727b38778825" + ), + Hex.from( + "5b0acfdbb89af64a583a88e92252b8634bd4da06ee102ecd34c2662955e9f1c7" + ), ], position: 4, }, diff --git a/typescript/test/data/redemption.ts b/typescript/test/data/redemption.ts index f840e2b6a..deeea11a3 100644 --- a/typescript/test/data/redemption.ts +++ b/typescript/test/data/redemption.ts @@ -25,8 +25,9 @@ export const walletPrivateKey = * Public key of the wallet in the compressed form corresponding to * walletPrivateKey. */ -export const walletPublicKey = +export const walletPublicKey = Hex.from( "03989d253b17a6a0f41838b84ff0d20e8898f9d7b1a98f2564da4cc29dcf8581d9" +) /** * P2PKH address corresponding to walletPrivateKey. @@ -84,8 +85,9 @@ export const singleP2PKHRedemptionWithWitnessChange: RedemptionTestData = { "82883a4c7a8dd73ef165deb402d432613615ced4" ), // script for testnet P2PKH address mmTeMR8RKu6QzMGTG4ipA71uewm3EuJng5 - redeemerOutputScript: - "76a9144130879211c54df460e484ddf9aac009cb38ee7488ac", + redeemerOutputScript: Hex.from( + "76a9144130879211c54df460e484ddf9aac009cb38ee7488ac" + ), requestedAmount: BigNumber.from(10000), treasuryFee: BigNumber.from(1000), txMaxFee: BigNumber.from(1600), @@ -141,7 +143,9 @@ export const singleP2WPKHRedemptionWithWitnessChange: RedemptionTestData = { "82883a4c7a8dd73ef165deb402d432613615ced4" ), // script for testnet P2WPKH address tb1qgycg0ys3c4xlgc8ysnwln2kqp89n3mn5ts7z3l - redeemerOutputScript: "00144130879211c54df460e484ddf9aac009cb38ee74", + redeemerOutputScript: Hex.from( + "00144130879211c54df460e484ddf9aac009cb38ee74" + ), requestedAmount: BigNumber.from(15000), treasuryFee: BigNumber.from(1100), txMaxFee: BigNumber.from(1700), @@ -197,7 +201,9 @@ export const singleP2SHRedemptionWithWitnessChange: RedemptionTestData = { "82883a4c7a8dd73ef165deb402d432613615ced4" ), // script for testnet P2SH address 2Mxy76sc1qAxiJ1fXMXDXqHvVcPLh6Lf12C - redeemerOutputScript: "a9143ec459d0f3c29286ae5df5fcc421e2786024277e87", + redeemerOutputScript: Hex.from( + "a9143ec459d0f3c29286ae5df5fcc421e2786024277e87" + ), requestedAmount: BigNumber.from(13000), treasuryFee: BigNumber.from(800), txMaxFee: BigNumber.from(1700), @@ -253,8 +259,9 @@ export const singleP2WSHRedemptionWithWitnessChange: RedemptionTestData = { "82883a4c7a8dd73ef165deb402d432613615ced4" ), // script for testnet P2WSH address tb1qs63s8nwjut4tr5t8nudgzwp4m3dpkefjzpmumn90pruce0cye2tq2jkq0y - redeemerOutputScript: - "002086a303cdd2e2eab1d1679f1a813835dc5a1b65321077cdccaf08f98cbf04ca96", + redeemerOutputScript: Hex.from( + "002086a303cdd2e2eab1d1679f1a813835dc5a1b65321077cdccaf08f98cbf04ca96" + ), requestedAmount: BigNumber.from(18000), treasuryFee: BigNumber.from(1000), txMaxFee: BigNumber.from(1400), @@ -310,8 +317,9 @@ export const multipleRedemptionsWithWitnessChange: RedemptionTestData = { "82883a4c7a8dd73ef165deb402d432613615ced4" ), // script for testnet P2PKH address mmTeMR8RKu6QzMGTG4ipA71uewm3EuJng5 - redeemerOutputScript: - "76a9144130879211c54df460e484ddf9aac009cb38ee7488ac", + redeemerOutputScript: Hex.from( + "76a9144130879211c54df460e484ddf9aac009cb38ee7488ac" + ), requestedAmount: BigNumber.from(18000), treasuryFee: BigNumber.from(1000), txMaxFee: BigNumber.from(1100), @@ -326,7 +334,9 @@ export const multipleRedemptionsWithWitnessChange: RedemptionTestData = { "82883a4c7a8dd73ef165deb402d432613615ced4" ), // script for testnet P2WPKH address tb1qgycg0ys3c4xlgc8ysnwln2kqp89n3mn5ts7z3l - redeemerOutputScript: "00144130879211c54df460e484ddf9aac009cb38ee74", + redeemerOutputScript: Hex.from( + "00144130879211c54df460e484ddf9aac009cb38ee74" + ), requestedAmount: BigNumber.from(13000), treasuryFee: BigNumber.from(800), txMaxFee: BigNumber.from(900), @@ -341,7 +351,9 @@ export const multipleRedemptionsWithWitnessChange: RedemptionTestData = { "82883a4c7a8dd73ef165deb402d432613615ced4" ), // script for testnet P2SH address 2Mxy76sc1qAxiJ1fXMXDXqHvVcPLh6Lf12C - redeemerOutputScript: "a9143ec459d0f3c29286ae5df5fcc421e2786024277e87", + redeemerOutputScript: Hex.from( + "a9143ec459d0f3c29286ae5df5fcc421e2786024277e87" + ), requestedAmount: BigNumber.from(12000), treasuryFee: BigNumber.from(1100), txMaxFee: BigNumber.from(1000), @@ -356,8 +368,9 @@ export const multipleRedemptionsWithWitnessChange: RedemptionTestData = { "82883a4c7a8dd73ef165deb402d432613615ced4" ), // script for testnet P2WSH address tb1qs63s8nwjut4tr5t8nudgzwp4m3dpkefjzpmumn90pruce0cye2tq2jkq0y - redeemerOutputScript: - "002086a303cdd2e2eab1d1679f1a813835dc5a1b65321077cdccaf08f98cbf04ca96", + redeemerOutputScript: Hex.from( + "002086a303cdd2e2eab1d1679f1a813835dc5a1b65321077cdccaf08f98cbf04ca96" + ), requestedAmount: BigNumber.from(15000), treasuryFee: BigNumber.from(700), txMaxFee: BigNumber.from(1400), @@ -416,8 +429,9 @@ export const multipleRedemptionsWithoutChange: RedemptionTestData = { "82883a4c7a8dd73ef165deb402d432613615ced4" ), // script for testnet P2PKH address mmTeMR8RKu6QzMGTG4ipA71uewm3EuJng5 - redeemerOutputScript: - "76a9144130879211c54df460e484ddf9aac009cb38ee7488ac", + redeemerOutputScript: Hex.from( + "76a9144130879211c54df460e484ddf9aac009cb38ee7488ac" + ), requestedAmount: BigNumber.from(6000), treasuryFee: BigNumber.from(0), txMaxFee: BigNumber.from(800), @@ -432,7 +446,9 @@ export const multipleRedemptionsWithoutChange: RedemptionTestData = { "82883a4c7a8dd73ef165deb402d432613615ced4" ), // script for testnet P2WPKH address tb1qf0ulldawp79s7knz9v254j5zjyn0demfx2d0xx - redeemerOutputScript: "00144bf9ffb7ae0f8b0f5a622b154aca829126f6e769", + redeemerOutputScript: Hex.from( + "00144bf9ffb7ae0f8b0f5a622b154aca829126f6e769" + ), requestedAmount: BigNumber.from(4000), treasuryFee: BigNumber.from(0), txMaxFee: BigNumber.from(900), @@ -491,7 +507,9 @@ export const singleP2SHRedemptionWithNonWitnessChange: RedemptionTestData = { "82883a4c7a8dd73ef165deb402d432613615ced4" ), // script for testnet P2SH address 2Mxy76sc1qAxiJ1fXMXDXqHvVcPLh6Lf12C - redeemerOutputScript: "a9143ec459d0f3c29286ae5df5fcc421e2786024277e87", + redeemerOutputScript: Hex.from( + "a9143ec459d0f3c29286ae5df5fcc421e2786024277e87" + ), requestedAmount: BigNumber.from(12000), treasuryFee: BigNumber.from(1000), txMaxFee: BigNumber.from(1200), @@ -526,14 +544,14 @@ export interface RedemptionProofTestData { rawTransaction: BitcoinRawTx accumulatedTxConfirmations: number latestBlockHeight: number - headersChain: string + headersChain: Hex transactionMerkleBranch: BitcoinTxMerkleBranch } expectedRedemptionProof: { redemptionTx: BitcoinRawTxVectors redemptionProof: BitcoinSpvProof mainUtxo: BitcoinUtxo - walletPublicKey: string + walletPublicKey: Hex } } @@ -609,76 +627,91 @@ export const redemptionProof: RedemptionProofTestData = { "b84ff0d20e8898f9d7b1a98f2564da4cc29dcf8581d900000000", }, latestBlockHeight: 2226015, - headersChain: + headersChain: Hex.from( "04e000203d93e4b82b59ccaae5aff315b9319248c1119f8f848e421516000000000000" + - "00f28145109cd15498a2c4264dcda1c3d40d1ab1117f6365cc345e5bab9eb8e5a2f990" + - "5e62341f5c19adebd9480000c020a33f8505bae0c529af29b00741e2828e4b4ef2cf4d" + - "a2af790d00000000000000f1dad96fa7c65ae0b2582268ebf6e47b1af887ae9b5af064" + - "ff87b361259f9bb212915e62341f5c19913d8a790000002074ac47fe867411f520786b" + - "bb056d33cc5e412799355f22541600000000000000e428a225d38073c8e8584cf162b4" + - "cdc17eaf766f2fc1beae23f0ebac8b29964ec4955e62ffff001d5ec11e770000a020bc" + - "1e329ea2658a4e0dfe27cb80e2f9712d78e02c5428eb86db93c7e3000000006381e8dd" + - "f3245ddd74afb580b6d1e508273673d14b3620c098bde4c50bdbf65de1975e62341f5c" + - "195a29773400006020e7fc1afb505baced47a255d8a14cb7162b6f94d6aea6a89f4300" + - "000000000000ad26d482c0f48d0aeb1e1d9a8189df9f8dae693203c117a777c6c15522" + - "2da759ef975e62341f5c19595dff820000802004bdf8678a1fd09fd50987f884793410" + - "62e7f2ad11098bd00800000000000000add66b467729d264031adec83bc06e30781153" + - "0b98f49b095bd4c1fee2472e841d995e62341f5c19945d657200004020f8228183708c" + - "5f703e673f381ecee895a8642eed9f700b9c2b00000000000000465ec2f30447552a4a" + - "30ee63964aaebcb040649269eab449fb51823d58835a4aed9a5e62341f5c192fd94baa", + "00f28145109cd15498a2c4264dcda1c3d40d1ab1117f6365cc345e5bab9eb8e5a2f990" + + "5e62341f5c19adebd9480000c020a33f8505bae0c529af29b00741e2828e4b4ef2cf4d" + + "a2af790d00000000000000f1dad96fa7c65ae0b2582268ebf6e47b1af887ae9b5af064" + + "ff87b361259f9bb212915e62341f5c19913d8a790000002074ac47fe867411f520786b" + + "bb056d33cc5e412799355f22541600000000000000e428a225d38073c8e8584cf162b4" + + "cdc17eaf766f2fc1beae23f0ebac8b29964ec4955e62ffff001d5ec11e770000a020bc" + + "1e329ea2658a4e0dfe27cb80e2f9712d78e02c5428eb86db93c7e3000000006381e8dd" + + "f3245ddd74afb580b6d1e508273673d14b3620c098bde4c50bdbf65de1975e62341f5c" + + "195a29773400006020e7fc1afb505baced47a255d8a14cb7162b6f94d6aea6a89f4300" + + "000000000000ad26d482c0f48d0aeb1e1d9a8189df9f8dae693203c117a777c6c15522" + + "2da759ef975e62341f5c19595dff820000802004bdf8678a1fd09fd50987f884793410" + + "62e7f2ad11098bd00800000000000000add66b467729d264031adec83bc06e30781153" + + "0b98f49b095bd4c1fee2472e841d995e62341f5c19945d657200004020f8228183708c" + + "5f703e673f381ecee895a8642eed9f700b9c2b00000000000000465ec2f30447552a4a" + + "30ee63964aaebcb040649269eab449fb51823d58835a4aed9a5e62341f5c192fd94baa" + ), transactionMerkleBranch: { blockHeight: 2196313, merkle: [ - "2e89760feb82c022f9b6757c0a758f8fea953ffce9051cbe5a7cc20e0603c940", - "ad1cae6d060b5dac5d7ff1a933680f15dac822f52316c89e95363856b8a742ae", - "acf6ecc3da4654362678ac2bf0abf82aba1f2071e143718df2b079124e88fec7", - "65ea59172f35ee6db6e4194227bea23daedbda8299bea94710f21c97f3e9cc17", - "8c5b4ce089d0c450bf6125e7d342114246802bf4c9638d222aa9fcbe8e06024e", + Hex.from( + "2e89760feb82c022f9b6757c0a758f8fea953ffce9051cbe5a7cc20e0603c940" + ), + Hex.from( + "ad1cae6d060b5dac5d7ff1a933680f15dac822f52316c89e95363856b8a742ae" + ), + Hex.from( + "acf6ecc3da4654362678ac2bf0abf82aba1f2071e143718df2b079124e88fec7" + ), + Hex.from( + "65ea59172f35ee6db6e4194227bea23daedbda8299bea94710f21c97f3e9cc17" + ), + Hex.from( + "8c5b4ce089d0c450bf6125e7d342114246802bf4c9638d222aa9fcbe8e06024e" + ), ], position: 4, }, }, expectedRedemptionProof: { redemptionTx: { - version: "01000000", - inputs: + version: Hex.from("01000000"), + inputs: Hex.from( "01e30b907d077893bd0ed819c66644027b1dd30e4d3f68bc51da7933f75bbb283d0" + - "100000000ffffffff", - outputs: + "100000000ffffffff" + ), + outputs: Hex.from( "051c3e0000000000001976a9144130879211c54df460e484ddf9aac009cb38ee748" + - "8ac242c0000000000001600144130879211c54df460e484ddf9aac009cb38ee74ac" + - "2600000000000017a9143ec459d0f3c29286ae5df5fcc421e2786024277e8764320" + - "0000000000022002086a303cdd2e2eab1d1679f1a813835dc5a1b65321077cdccaf" + - "08f98cbf04ca96ccfb1400000000001600148db50eb52063ea9d98b3eac91489a90" + - "f738986f6", - locktime: "00000000", + "8ac242c0000000000001600144130879211c54df460e484ddf9aac009cb38ee74ac" + + "2600000000000017a9143ec459d0f3c29286ae5df5fcc421e2786024277e8764320" + + "0000000000022002086a303cdd2e2eab1d1679f1a813835dc5a1b65321077cdccaf" + + "08f98cbf04ca96ccfb1400000000001600148db50eb52063ea9d98b3eac91489a90" + + "f738986f6" + ), + locktime: Hex.from("00000000"), }, redemptionProof: { - merkleProof: + merkleProof: Hex.from( "40c903060ec27c5abe1c05e9fc3f95ea8f8f750a7c75b6f922c082eb0f76892eae4" + - "2a7b8563836959ec81623f522c8da150f6833a9f17f5dac5d0b066dae1cadc7fe88" + - "4e1279b0f28d7143e171201fba2af8abf02bac7826365446dac3ecf6ac17cce9f39" + - "71cf21047a9be9982dadbae3da2be274219e4b66dee352f1759ea654e02068ebefc" + - "a92a228d63c9f42b8046421142d3e72561bf50c4d089e04c5b8c", + "2a7b8563836959ec81623f522c8da150f6833a9f17f5dac5d0b066dae1cadc7fe88" + + "4e1279b0f28d7143e171201fba2af8abf02bac7826365446dac3ecf6ac17cce9f39" + + "71cf21047a9be9982dadbae3da2be274219e4b66dee352f1759ea654e02068ebefc" + + "a92a228d63c9f42b8046421142d3e72561bf50c4d089e04c5b8c" + ), txIndexInBlock: 4, - bitcoinHeaders: + bitcoinHeaders: Hex.from( "04e000203d93e4b82b59ccaae5aff315b9319248c1119f8f848e421516000000000" + - "00000f28145109cd15498a2c4264dcda1c3d40d1ab1117f6365cc345e5bab9eb8e5" + - "a2f9905e62341f5c19adebd9480000c020a33f8505bae0c529af29b00741e2828e4" + - "b4ef2cf4da2af790d00000000000000f1dad96fa7c65ae0b2582268ebf6e47b1af8" + - "87ae9b5af064ff87b361259f9bb212915e62341f5c19913d8a790000002074ac47f" + - "e867411f520786bbb056d33cc5e412799355f22541600000000000000e428a225d3" + - "8073c8e8584cf162b4cdc17eaf766f2fc1beae23f0ebac8b29964ec4955e62ffff0" + - "01d5ec11e770000a020bc1e329ea2658a4e0dfe27cb80e2f9712d78e02c5428eb86" + - "db93c7e3000000006381e8ddf3245ddd74afb580b6d1e508273673d14b3620c098b" + - "de4c50bdbf65de1975e62341f5c195a29773400006020e7fc1afb505baced47a255" + - "d8a14cb7162b6f94d6aea6a89f4300000000000000ad26d482c0f48d0aeb1e1d9a8" + - "189df9f8dae693203c117a777c6c155222da759ef975e62341f5c19595dff820000" + - "802004bdf8678a1fd09fd50987f88479341062e7f2ad11098bd0080000000000000" + - "0add66b467729d264031adec83bc06e307811530b98f49b095bd4c1fee2472e841d" + - "995e62341f5c19945d657200004020f8228183708c5f703e673f381ecee895a8642" + - "eed9f700b9c2b00000000000000465ec2f30447552a4a30ee63964aaebcb0406492" + - "69eab449fb51823d58835a4aed9a5e62341f5c192fd94baa", + "00000f28145109cd15498a2c4264dcda1c3d40d1ab1117f6365cc345e5bab9eb8e5" + + "a2f9905e62341f5c19adebd9480000c020a33f8505bae0c529af29b00741e2828e4" + + "b4ef2cf4da2af790d00000000000000f1dad96fa7c65ae0b2582268ebf6e47b1af8" + + "87ae9b5af064ff87b361259f9bb212915e62341f5c19913d8a790000002074ac47f" + + "e867411f520786bbb056d33cc5e412799355f22541600000000000000e428a225d3" + + "8073c8e8584cf162b4cdc17eaf766f2fc1beae23f0ebac8b29964ec4955e62ffff0" + + "01d5ec11e770000a020bc1e329ea2658a4e0dfe27cb80e2f9712d78e02c5428eb86" + + "db93c7e3000000006381e8ddf3245ddd74afb580b6d1e508273673d14b3620c098b" + + "de4c50bdbf65de1975e62341f5c195a29773400006020e7fc1afb505baced47a255" + + "d8a14cb7162b6f94d6aea6a89f4300000000000000ad26d482c0f48d0aeb1e1d9a8" + + "189df9f8dae693203c117a777c6c155222da759ef975e62341f5c19595dff820000" + + "802004bdf8678a1fd09fd50987f88479341062e7f2ad11098bd0080000000000000" + + "0add66b467729d264031adec83bc06e307811530b98f49b095bd4c1fee2472e841d" + + "995e62341f5c19945d657200004020f8228183708c5f703e673f381ecee895a8642" + + "eed9f700b9c2b00000000000000465ec2f30447552a4a30ee63964aaebcb0406492" + + "69eab449fb51823d58835a4aed9a5e62341f5c192fd94baa" + ), }, mainUtxo: { transactionHash: BitcoinTxHash.from( @@ -687,8 +720,9 @@ export const redemptionProof: RedemptionProofTestData = { outputIndex: 1, value: BigNumber.from(1429580), }, - walletPublicKey: - "03989d253b17a6a0f41838b84ff0d20e8898f9d7b1a98f2564da4cc29dcf8581d9", + walletPublicKey: Hex.from( + "03989d253b17a6a0f41838b84ff0d20e8898f9d7b1a98f2564da4cc29dcf8581d9" + ), }, } @@ -902,7 +936,9 @@ export const findWalletForRedemptionData: { "0xeb9af8E66869902476347a4eFe59a527a57240ED" ), // script for testnet P2PKH address mjc2zGWypwpNyDi4ZxGbBNnUA84bfgiwYc - redeemerOutputScript: "76a9142cd680318747b720d67bf4246eb7403b476adb3488ac", + redeemerOutputScript: Hex.from( + "76a9142cd680318747b720d67bf4246eb7403b476adb3488ac" + ), requestedAmount: BigNumber.from(1000000), treasuryFee: BigNumber.from(20000), txMaxFee: BigNumber.from(20000), diff --git a/typescript/test/lib/bitcoin.test.ts b/typescript/test/lib/bitcoin.test.ts index 80e1212c3..11dacfaac 100644 --- a/typescript/test/lib/bitcoin.test.ts +++ b/typescript/test/lib/bitcoin.test.ts @@ -106,9 +106,10 @@ describe("Bitcoin", () => { context("when public key parameter has a correct length", () => { context("when the Y coordinate is divisible by 2", () => { it("should compress the public key correctly", () => { - const uncompressedPublicKey = + const uncompressedPublicKey = Hex.from( "ff6e1857db52d6dba2bd4239fba722655622bc520709d38011f9adac8ea3477b" + - "45ae275b657f7bac7c1e3d146a564051aee1356895f01e4f29f333502416fa4a" + "45ae275b657f7bac7c1e3d146a564051aee1356895f01e4f29f333502416fa4a" + ) const compressedPublicKey = "02ff6e1857db52d6dba2bd4239fba722655622bc520709d38011f9adac8ea3477b" @@ -120,9 +121,10 @@ describe("Bitcoin", () => { context("when the Y coordinate is not divisible by 2", () => { it("should compress the public key correctly", () => { - const uncompressedPublicKey = + const uncompressedPublicKey = Hex.from( "474444cca71c678f5019d16782b6522735717a94602085b4adf707b465c36ca8" + - "7b5dff055ee1cc3a1fff4715dea2858ca4dd5bba0af30abcd881a6bda4fb70af" + "7b5dff055ee1cc3a1fff4715dea2858ca4dd5bba0af30abcd881a6bda4fb70af" + ) const compressedPublicKey = "03474444cca71c678f5019d16782b6522735717a94602085b4adf707b465c36ca8" @@ -135,10 +137,10 @@ describe("Bitcoin", () => { context("when public key parameter has an incorrect length", () => { it("should throw", () => { - const uncompressedPublicKey = + const uncompressedPublicKey = Hex.from( "04474444cca71c678f5019d16782b6522735717a94602085b4adf707b465c36ca8" + - "7b5dff055ee1cc3a1fff4715dea2858ca4dd5bba0af30abcd881a6bda4fb70af" - + "7b5dff055ee1cc3a1fff4715dea2858ca4dd5bba0af30abcd881a6bda4fb70af" + ) expect(() => compressPublicKey(uncompressedPublicKey)).to.throw( "The public key parameter must be 64-byte. Neither 0x nor 04 prefix is allowed" ) @@ -153,11 +155,14 @@ describe("Bitcoin", () => { describe("computeHash160", () => { it("should compute hash160 correctly", () => { - const compressedPublicKey = + const compressedPublicKey = Hex.from( "03474444cca71c678f5019d16782b6522735717a94602085b4adf707b465c36ca8" + ) const expectedHash160 = "3e1dfbd72483fb3964ca828ee71cf3270cafdc65" - expect(computeHash160(compressedPublicKey)).to.be.equal(expectedHash160) + expect(computeHash160(compressedPublicKey).toString()).to.be.equal( + expectedHash160 + ) }) }) @@ -205,7 +210,7 @@ describe("Bitcoin", () => { }) describe("BitcoinAddressConverter", () => { - const publicKeyHash = "3a38d44d6a0c8d0bb84e0232cc632b7e48c72e0e" + const publicKeyHash = Hex.from("3a38d44d6a0c8d0bb84e0232cc632b7e48c72e0e") const P2WPKHAddress = "bc1q8gudgnt2pjxshwzwqgevccet0eyvwtswt03nuy" const P2PKHAddress = "16JrGhLx5bcBSA34kew9V6Mufa4aXhFe9X" const P2WPKHAddressTestnet = "tb1q8gudgnt2pjxshwzwqgevccet0eyvwtswpf2q8h" @@ -260,7 +265,9 @@ describe("Bitcoin", () => { context("when wrong public key hash is provided", () => { it("should throw", () => { - const wrongPublicKeyHash = "02" + publicKeyHash + const wrongPublicKeyHash = Hex.from( + "02" + publicKeyHash.toString() + ) expect(() => publicKeyHashToAddress( @@ -290,7 +297,9 @@ describe("Bitcoin", () => { context("when wrong public key hash is provided", () => { it("should throw", () => { - const wrongPublicKeyHash = "02" + publicKeyHash + const wrongPublicKeyHash = Hex.from( + "02" + publicKeyHash.toString() + ) expect(() => publicKeyHashToAddress( @@ -322,7 +331,9 @@ describe("Bitcoin", () => { context("when wrong public key hash is provided", () => { it("should throw", () => { - const wrongPublicKeyHash = "02" + publicKeyHash + const wrongPublicKeyHash = Hex.from( + "02" + publicKeyHash.toString() + ) expect(() => publicKeyHashToAddress( @@ -352,7 +363,9 @@ describe("Bitcoin", () => { context("when wrong public key hash is provided", () => { it("should throw", () => { - const wrongPublicKeyHash = "02" + publicKeyHash + const wrongPublicKeyHash = Hex.from( + "02" + publicKeyHash.toString() + ) expect(() => publicKeyHashToAddress( @@ -383,7 +396,7 @@ describe("Bitcoin", () => { it("should decode P2WPKH adress correctly", () => { expect( addressToPublicKeyHash(P2WPKHAddress, BitcoinNetwork.Mainnet) - ).to.be.equal(publicKeyHash) + ).to.be.deep.equal(publicKeyHash) }) }) @@ -391,7 +404,7 @@ describe("Bitcoin", () => { it("should decode P2PKH address correctly", () => { expect( addressToPublicKeyHash(P2PKHAddress, BitcoinNetwork.Mainnet) - ).to.be.equal(publicKeyHash) + ).to.be.deep.equal(publicKeyHash) }) }) @@ -455,7 +468,7 @@ describe("Bitcoin", () => { P2WPKHAddressTestnet, BitcoinNetwork.Testnet ) - ).to.be.equal(publicKeyHash) + ).to.be.deep.equal(publicKeyHash) }) }) @@ -466,7 +479,7 @@ describe("Bitcoin", () => { P2PKHAddressTestnet, BitcoinNetwork.Testnet ) - ).to.be.equal(publicKeyHash) + ).to.be.deep.equal(publicKeyHash) }) }) @@ -585,12 +598,12 @@ describe("Bitcoin", () => { const testData = [ { contextName: "when locktime is a block height", - unprefixedHex: "ede80600", + unprefixedHex: Hex.from("ede80600"), expectedLocktime: 452845, }, { contextName: "when locktime is a timestamp", - unprefixedHex: "06241559", + unprefixedHex: Hex.from("06241559"), expectedLocktime: 1494557702, }, { @@ -604,24 +617,24 @@ describe("Bitcoin", () => { context(test.contextName, () => { context("when input is non-prefixed hex string", () => { it("should return the locktime in seconds", async () => { - expect(locktimeToNumber(test.unprefixedHex)).to.be.equal( - test.expectedLocktime - ) + expect( + locktimeToNumber(test.unprefixedHex.toString()) + ).to.be.equal(test.expectedLocktime) }) }) context("when input is 0x prefixed hex string", () => { it("should return the locktime in seconds", async () => { - expect(locktimeToNumber("0x" + test.unprefixedHex)).to.be.equal( - test.expectedLocktime - ) + expect( + locktimeToNumber(test.unprefixedHex.toPrefixedString()) + ).to.be.equal(test.expectedLocktime) }) }) context("when input is Buffer object", () => { it("should return the locktime in seconds", async () => { expect( - locktimeToNumber(Buffer.from(test.unprefixedHex, "hex")) + locktimeToNumber(test.unprefixedHex.toBuffer()) ).to.be.equal(test.expectedLocktime) }) }) @@ -657,7 +670,7 @@ describe("Bitcoin", () => { // The start timestamp is 1652776752 and locktime duration 2592000 (30 days). // So, the locktime timestamp is 1652776752 + 2592000 = 1655368752 which // is represented as 30ecaa62 hex in the little-endian format. - expect(locktime).to.be.equal("30ecaa62") + expect(locktime.toString()).to.be.equal("30ecaa62") }) }) }) @@ -818,33 +831,27 @@ describe("Bitcoin", () => { const testData = [ { testFunction: isP2PKHScript, - validScript: Buffer.from( - "76a9148db50eb52063ea9d98b3eac91489a90f738986f688ac", - "hex" + validScript: Hex.from( + "76a9148db50eb52063ea9d98b3eac91489a90f738986f688ac" ), name: "P2PKH", }, { testFunction: isP2WPKHScript, - validScript: Buffer.from( - "00148db50eb52063ea9d98b3eac91489a90f738986f6", - "hex" - ), + validScript: Hex.from("00148db50eb52063ea9d98b3eac91489a90f738986f6"), name: "P2WPKH", }, { testFunction: isP2SHScript, - validScript: Buffer.from( - "a914a9a5f97d5d3c4687a52e90718168270005b369c487", - "hex" + validScript: Hex.from( + "a914a9a5f97d5d3c4687a52e90718168270005b369c487" ), name: "P2SH", }, { testFunction: isP2WSHScript, - validScript: Buffer.from( - "0020b1f83e226979dc9fe74e87f6d303dbb08a27a1c7ce91664033f34c7f2d214cd7", - "hex" + validScript: Hex.from( + "0020b1f83e226979dc9fe74e87f6d303dbb08a27a1c7ce91664033f34c7f2d214cd7" ), name: "P2WSH", }, @@ -874,8 +881,8 @@ describe("Bitcoin", () => { depositSweepWithNoMainUtxoAndWitnessOutput.expectedSweep.transaction const decomposedTransaction = extractBitcoinRawTxVectors(rawTransaction) - expect(decomposedTransaction.version).to.be.equal("01000000") - expect(decomposedTransaction.inputs).to.be.equal( + expect(decomposedTransaction.version.toString()).to.be.equal("01000000") + expect(decomposedTransaction.inputs.toString()).to.be.equal( "02bc187be612bc3db8cfcdec56b75e9bc0262ab6eacfe27cc1a699bacd53e3d07400" + "000000c948304502210089a89aaf3fec97ac9ffa91cdff59829f0cb3ef852a468153" + "e2c0e2b473466d2e022072902bb923ef016ac52e941ced78f816bf27991c2b73211e" + @@ -886,14 +893,14 @@ describe("Bitcoin", () => { "68ffffffffdc557e737b6688c5712649b86f7757a722dc3d42786f23b2fa826394df" + "ec545c0000000000ffffffff" ) - expect(decomposedTransaction.outputs).to.be.equal( + expect(decomposedTransaction.outputs.toString()).to.be.equal( "01488a0000000000001600148db50eb52063ea9d98b3eac91489a90f738986f6" ) - expect(decomposedTransaction.locktime).to.be.equal("00000000") + expect(decomposedTransaction.locktime.toString()).to.be.equal("00000000") }) }) - describe("assembleTransactionProof", () => { + describe("assembleBitcoinSpvProof", () => { let bitcoinClient: MockBitcoinClient beforeEach(async () => { @@ -914,9 +921,9 @@ describe("Bitcoin", () => { ) expect(proof.inputs).to.deep.equal(expectedProof.inputs) expect(proof.outputs).to.deep.equal(expectedProof.outputs) - expect(proof.merkleProof).to.equal(expectedProof.merkleProof) + expect(proof.merkleProof).to.deep.equal(expectedProof.merkleProof) expect(proof.txIndexInBlock).to.equal(expectedProof.txIndexInBlock) - expect(proof.bitcoinHeaders).to.equal(expectedProof.bitcoinHeaders) + expect(proof.bitcoinHeaders).to.deep.equal(expectedProof.bitcoinHeaders) }) }) @@ -934,9 +941,9 @@ describe("Bitcoin", () => { ) expect(proof.inputs).to.deep.equal(expectedProof.inputs) expect(proof.outputs).to.deep.equal(expectedProof.outputs) - expect(proof.merkleProof).to.equal(expectedProof.merkleProof) + expect(proof.merkleProof).to.deep.equal(expectedProof.merkleProof) expect(proof.txIndexInBlock).to.equal(expectedProof.txIndexInBlock) - expect(proof.bitcoinHeaders).to.equal(expectedProof.bitcoinHeaders) + expect(proof.bitcoinHeaders).to.deep.equal(expectedProof.bitcoinHeaders) }) }) @@ -1037,9 +1044,10 @@ describe("Bitcoin", () => { ...transactionConfirmationsInOneEpochData, bitcoinChainData: { ...transactionConfirmationsInOneEpochData.bitcoinChainData, - headersChain: - transactionConfirmationsInOneEpochData.bitcoinChainData - .headersChain + "ff", + headersChain: Hex.from( + transactionConfirmationsInOneEpochData.bitcoinChainData.headersChain.toString() + + "ff" + ), }, } await expect( @@ -1057,9 +1065,10 @@ describe("Bitcoin", () => { ...transactionConfirmationsInOneEpochData, bitcoinChainData: { ...transactionConfirmationsInOneEpochData.bitcoinChainData, - headersChain: - transactionConfirmationsInOneEpochData.bitcoinChainData - .headersChain + "f".repeat(160), + headersChain: Hex.from( + transactionConfirmationsInOneEpochData.bitcoinChainData.headersChain.toString() + + "f".repeat(160) + ), }, } await expect( @@ -1076,7 +1085,9 @@ describe("Bitcoin", () => { ...transactionConfirmationsInOneEpochData.bitcoinChainData .transactionMerkleBranch.merkle, ] - merkle[merkle.length - 1] += "ff" + merkle[merkle.length - 1] = Hex.from( + merkle[merkle.length - 1].toString() + "ff" + ) const corruptedProofData: TransactionProofData = { ...transactionConfirmationsInOneEpochData, @@ -1126,7 +1137,7 @@ describe("Bitcoin", () => { .transactionMerkleBranch.merkle, ] - merkle[3] = "ff" + merkle[3].slice(2) + merkle[3] = Hex.from("ff" + merkle[3].toString().slice(2)) const corruptedProofData: TransactionProofData = { ...transactionConfirmationsInOneEpochData, @@ -1168,7 +1179,7 @@ describe("Bitcoin", () => { ...transactionConfirmationsInOneEpochData, bitcoinChainData: { ...transactionConfirmationsInOneEpochData.bitcoinChainData, - headersChain: corruptedHeadersChain, + headersChain: Hex.from(corruptedHeadersChain), }, } @@ -1196,7 +1207,7 @@ describe("Bitcoin", () => { ...transactionConfirmationsInOneEpochData, bitcoinChainData: { ...transactionConfirmationsInOneEpochData.bitcoinChainData, - headersChain: corruptedHeadersChain, + headersChain: Hex.from(corruptedHeadersChain), }, } diff --git a/typescript/test/lib/electrum.test.ts b/typescript/test/lib/electrum.test.ts index 76f521fc0..b54e50b1d 100644 --- a/typescript/test/lib/electrum.test.ts +++ b/typescript/test/lib/electrum.test.ts @@ -3,6 +3,7 @@ import { ElectrumCredentials, ElectrumClient, computeElectrumScriptHash, + Hex, } from "../../src" import { testnetAddress, @@ -224,7 +225,9 @@ describe("Electrum", () => { describe("computeElectrumScriptHash", () => { it("should convert Bitcoin script to an Electrum script hash correctly", () => { - const script = "00144b47c798d12edd17dfb4ea98e5447926f664731c" + const script = Hex.from( + "00144b47c798d12edd17dfb4ea98e5447926f664731c" + ) const expectedScriptHash = "cabdea0bfc10fb3521721dde503487dd1f0e41dd6609da228066757563f292ab" diff --git a/typescript/test/lib/ethereum.test.ts b/typescript/test/lib/ethereum.test.ts index 727c273b3..801e77fe8 100644 --- a/typescript/test/lib/ethereum.test.ts +++ b/typescript/test/lib/ethereum.test.ts @@ -74,15 +74,18 @@ describe("Ethereum", () => { it("should return the pending redemption", async () => { expect( await bridgeHandle.pendingRedemptions( - "03989d253b17a6a0f41838b84ff0d20e8898f9d7b1a98f2564da4cc29dcf8581d9", - "a9143ec459d0f3c29286ae5df5fcc421e2786024277e87" + Hex.from( + "03989d253b17a6a0f41838b84ff0d20e8898f9d7b1a98f2564da4cc29dcf8581d9" + ), + Hex.from("a9143ec459d0f3c29286ae5df5fcc421e2786024277e87") ) ).to.be.eql({ redeemer: EthereumAddress.from( "f39fd6e51aad88f6f4ce6ab8827279cfffb92266" ), - redeemerOutputScript: - "a9143ec459d0f3c29286ae5df5fcc421e2786024277e87", + redeemerOutputScript: Hex.from( + "a9143ec459d0f3c29286ae5df5fcc421e2786024277e87" + ), requestedAmount: BigNumber.from(10000), treasuryFee: BigNumber.from(100), txMaxFee: BigNumber.from(50), @@ -113,15 +116,18 @@ describe("Ethereum", () => { it("should return the timed-out redemption", async () => { expect( await bridgeHandle.timedOutRedemptions( - "03989d253b17a6a0f41838b84ff0d20e8898f9d7b1a98f2564da4cc29dcf8581d9", - "a9143ec459d0f3c29286ae5df5fcc421e2786024277e87" + Hex.from( + "03989d253b17a6a0f41838b84ff0d20e8898f9d7b1a98f2564da4cc29dcf8581d9" + ), + Hex.from("a9143ec459d0f3c29286ae5df5fcc421e2786024277e87") ) ).to.be.eql({ redeemer: EthereumAddress.from( "f39fd6e51aad88f6f4ce6ab8827279cfffb92266" ), - redeemerOutputScript: - "a9143ec459d0f3c29286ae5df5fcc421e2786024277e87", + redeemerOutputScript: Hex.from( + "a9143ec459d0f3c29286ae5df5fcc421e2786024277e87" + ), requestedAmount: BigNumber.from(10000), treasuryFee: BigNumber.from(100), txMaxFee: BigNumber.from(50), @@ -137,20 +143,24 @@ describe("Ethereum", () => { await bridgeHandle.revealDeposit( // Just short byte strings for clarity. { - version: "00000000", - inputs: "11111111", - outputs: "22222222", - locktime: "33333333", + version: Hex.from("00000000"), + inputs: Hex.from("11111111"), + outputs: Hex.from("22222222"), + locktime: Hex.from("33333333"), }, 2, { depositor: EthereumAddress.from( "934b98637ca318a4d6e7ca6ffd1690b8e77df637" ), - walletPublicKeyHash: "8db50eb52063ea9d98b3eac91489a90f738986f6", - refundPublicKeyHash: "28e081f285138ccbe389c1eb8985716230129f89", - blindingFactor: "f9f0c90d00039523", - refundLocktime: "60bcea61", + walletPublicKeyHash: Hex.from( + "8db50eb52063ea9d98b3eac91489a90f738986f6" + ), + refundPublicKeyHash: Hex.from( + "28e081f285138ccbe389c1eb8985716230129f89" + ), + blindingFactor: Hex.from("f9f0c90d00039523"), + refundLocktime: Hex.from("60bcea61"), }, EthereumAddress.from("82883a4c7a8dd73ef165deb402d432613615ced4") ) @@ -182,15 +192,15 @@ describe("Ethereum", () => { await bridgeHandle.submitDepositSweepProof( { - version: "00000000", - inputs: "11111111", - outputs: "22222222", - locktime: "33333333", + version: Hex.from("00000000"), + inputs: Hex.from("11111111"), + outputs: Hex.from("22222222"), + locktime: Hex.from("33333333"), }, { - merkleProof: "44444444", + merkleProof: Hex.from("44444444"), txIndexInBlock: 5, - bitcoinHeaders: "66666666", + bitcoinHeaders: Hex.from("66666666"), }, { transactionHash: BitcoinTxHash.from( @@ -244,7 +254,9 @@ describe("Ethereum", () => { await bridgeContract.mock.requestRedemption.returns() await bridgeHandle.requestRedemption( - "03989d253b17a6a0f41838b84ff0d20e8898f9d7b1a98f2564da4cc29dcf8581d9", + Hex.from( + "03989d253b17a6a0f41838b84ff0d20e8898f9d7b1a98f2564da4cc29dcf8581d9" + ), { transactionHash: BitcoinTxHash.from( "f8eaf242a55ea15e602f9f990e33f67f99dfbe25d1802bbde63cc1caabf99668" @@ -252,7 +264,7 @@ describe("Ethereum", () => { outputIndex: 8, value: BigNumber.from(9999), }, - "a9143ec459d0f3c29286ae5df5fcc421e2786024277e87", + Hex.from("a9143ec459d0f3c29286ae5df5fcc421e2786024277e87"), BigNumber.from(10000) ) }) @@ -278,15 +290,15 @@ describe("Ethereum", () => { await bridgeHandle.submitRedemptionProof( { - version: "00000000", - inputs: "11111111", - outputs: "22222222", - locktime: "33333333", + version: Hex.from("00000000"), + inputs: Hex.from("11111111"), + outputs: Hex.from("22222222"), + locktime: Hex.from("33333333"), }, { - merkleProof: "44444444", + merkleProof: Hex.from("44444444"), txIndexInBlock: 5, - bitcoinHeaders: "66666666", + bitcoinHeaders: Hex.from("66666666"), }, { transactionHash: BitcoinTxHash.from( @@ -295,7 +307,9 @@ describe("Ethereum", () => { outputIndex: 8, value: BigNumber.from(9999), }, - "03989d253b17a6a0f41838b84ff0d20e8898f9d7b1a98f2564da4cc29dcf8581d9" + Hex.from( + "03989d253b17a6a0f41838b84ff0d20e8898f9d7b1a98f2564da4cc29dcf8581d9" + ) ) }) @@ -441,7 +455,9 @@ describe("Ethereum", () => { }) it("should return the active wallet's public key", async () => { - expect(await bridgeHandle.activeWalletPublicKey()).to.be.equal( + expect( + (await bridgeHandle.activeWalletPublicKey())?.toString() + ).to.be.equal( "03989d253b17a6a0f41838b84ff0d20e8898f9d7b1a98f2564da4cc29dcf8581d9" ) }) @@ -512,8 +528,9 @@ describe("Ethereum", () => { vault: EthereumAddress.from( "0x24BE35e7C04E2e0a628614Ce0Ed58805e1C894F7" ), - walletPublicKey: - "03989d253b17a6a0f41838b84ff0d20e8898f9d7b1a98f2564da4cc29dcf8581d9", + walletPublicKey: Hex.from( + "03989d253b17a6a0f41838b84ff0d20e8898f9d7b1a98f2564da4cc29dcf8581d9" + ), mainUtxo: { transactionHash: BitcoinTxHash.from( "f8eaf242a55ea15e602f9f990e33f67f99dfbe25d1802bbde63cc1caabf99668" @@ -524,10 +541,12 @@ describe("Ethereum", () => { redeemer: EthereumAddress.from(signer.address), amount: BigNumber.from(10000), redeemerOutputScript: { - unprefixed: - "0020cdbf909e935c855d3e8d1b61aeb9c5e3c03ae8021b286839b1a72f2e48fdba70", - prefixed: - "0x220020cdbf909e935c855d3e8d1b61aeb9c5e3c03ae8021b286839b1a72f2e48fdba70", + unprefixed: Hex.from( + "0020cdbf909e935c855d3e8d1b61aeb9c5e3c03ae8021b286839b1a72f2e48fdba70" + ), + prefixed: Hex.from( + "220020cdbf909e935c855d3e8d1b61aeb9c5e3c03ae8021b286839b1a72f2e48fdba70" + ), }, } @@ -556,13 +575,11 @@ describe("Ethereum", () => { ["address", "bytes20", "bytes32", "uint32", "uint64", "bytes"], [ redeemer.identifierHex, - Hex.from( - BitcoinHashUtils.computeHash160(walletPublicKey) - ).toPrefixedString(), + BitcoinHashUtils.computeHash160(walletPublicKey).toPrefixedString(), mainUtxo.transactionHash.reverse().toPrefixedString(), mainUtxo.outputIndex, mainUtxo.value, - redeemerOutputScript.prefixed, + redeemerOutputScript.prefixed.toPrefixedString(), ] ) diff --git a/typescript/test/services/deposits.test.ts b/typescript/test/services/deposits.test.ts index 821228f8c..43b0e8561 100644 --- a/typescript/test/services/deposits.test.ts +++ b/typescript/test/services/deposits.test.ts @@ -23,6 +23,7 @@ import { } from "../../src" import { MockBitcoinClient } from "../utils/mock-bitcoin-client" import { MockTBTCContracts } from "../utils/mock-tbtc-contracts" +import { Hex } from "../../src/lib/utils" import { txToJSON } from "../utils/helpers" import { depositRefundOfNonWitnessDepositAndWitnessRefunderAddress, @@ -40,10 +41,10 @@ describe("Deposits", () => { const deposit: DepositReceipt = { depositor: EthereumAddress.from("934b98637ca318a4d6e7ca6ffd1690b8e77df637"), // HASH160 of 03989d253b17a6a0f41838b84ff0d20e8898f9d7b1a98f2564da4cc29dcf8581d9. - walletPublicKeyHash: "8db50eb52063ea9d98b3eac91489a90f738986f6", + walletPublicKeyHash: Hex.from("8db50eb52063ea9d98b3eac91489a90f738986f6"), // HASH160 of 0300d6f28a2f6bf9836f57fcda5d284c9a8f849316119779f0d6090830d97763a9. - refundPublicKeyHash: "28e081f285138ccbe389c1eb8985716230129f89", - blindingFactor: "f9f0c90d00039523", + refundPublicKeyHash: Hex.from("28e081f285138ccbe389c1eb8985716230129f89"), + blindingFactor: Hex.from("f9f0c90d00039523"), refundLocktime: BitcoinLocktimeUtils.calculateLocktime( depositCreatedAt, depositRefundLocktimeDuration @@ -139,7 +140,9 @@ describe("Deposits", () => { // The first byte (0x08) before the blinding factor is this byte length. // In this case it's 8 bytes. expect(script.substring(44, 46)).to.be.equal("08") - expect(script.substring(46, 62)).to.be.equal(deposit.blindingFactor) + expect(script.substring(46, 62)).to.be.equal( + deposit.blindingFactor.toString() + ) // OP_DROP opcode is 0x75. expect(script.substring(62, 64)).to.be.equal("75") @@ -154,7 +157,9 @@ describe("Deposits", () => { // The first byte (0x14) before the public key is this byte length. // In this case it's 20 bytes which is a correct length for a HASH160. expect(script.substring(68, 70)).to.be.equal("14") - expect(script.substring(70, 110)).to.be.equal(deposit.walletPublicKeyHash) + expect(script.substring(70, 110)).to.be.equal( + deposit.walletPublicKeyHash.toString() + ) // OP_EQUAL opcode is 0x87. expect(script.substring(110, 112)).to.be.equal("87") @@ -178,7 +183,9 @@ describe("Deposits", () => { // The first byte (0x14) before the public key is this byte length. // In this case it's 20 bytes which is a correct length for a HASH160. expect(script.substring(122, 124)).to.be.equal("14") - expect(script.substring(124, 164)).to.be.equal(deposit.refundPublicKeyHash) + expect(script.substring(124, 164)).to.be.equal( + deposit.refundPublicKeyHash.toString() + ) // OP_EQUALVERIFY opcode is 0x88. expect(script.substring(164, 166)).to.be.equal("88") @@ -530,14 +537,14 @@ describe("Deposits", () => { describe("DepositScript", () => { describe("getPlainText", () => { - let script: string + let script: Hex beforeEach(async () => { script = await DepositScript.fromReceipt(deposit).getPlainText() }) it("should return script with proper structure", async () => { - assertValidDepositScript(script) + assertValidDepositScript(script.toString()) }) }) diff --git a/typescript/test/services/maintenance.test.ts b/typescript/test/services/maintenance.test.ts index cbca52a78..8b0f3d7bd 100644 --- a/typescript/test/services/maintenance.test.ts +++ b/typescript/test/services/maintenance.test.ts @@ -2541,7 +2541,7 @@ describe("Maintenance", () => { const bridgeLog = tbtcContracts.bridge.redemptionProofLog expect(bridgeLog.length).to.equal(1) expect(bridgeLog[0].mainUtxo).to.equal(mainUtxo) - expect(bridgeLog[0].walletPublicKey).to.equal( + expect(bridgeLog[0].walletPublicKey).to.deep.equal( redemptionProof.expectedRedemptionProof.walletPublicKey ) expect(bridgeLog[0].redemptionTx).to.deep.equal( diff --git a/typescript/test/services/redemptions.test.ts b/typescript/test/services/redemptions.test.ts index 1b9a82e24..2d429696f 100644 --- a/typescript/test/services/redemptions.test.ts +++ b/typescript/test/services/redemptions.test.ts @@ -53,27 +53,26 @@ describe("Redemptions", () => { tbtcContracts = new MockTBTCContracts() bitcoinClient = new MockBitcoinClient() - const walletPublicKeyHash = Hex.from( + const walletPublicKeyHash = BitcoinHashUtils.computeHash160(walletPublicKey) - ) // Prepare NewWalletRegisteredEvent history. Set only relevant fields. tbtcContracts.bridge.newWalletRegisteredEvents = [ { - walletPublicKeyHash: walletPublicKeyHash, + walletPublicKeyHash, } as NewWalletRegisteredEvent, ] // Prepare wallet data in the Bridge. Set only relevant fields. tbtcContracts.bridge.setWallet(walletPublicKeyHash.toPrefixedString(), { state: WalletState.Live, - walletPublicKey: Hex.from(walletPublicKey), + walletPublicKey, pendingRedemptionsValue: BigNumber.from(0), mainUtxoHash: tbtcContracts.bridge.buildUtxoHash(mainUtxo), } as Wallet) const walletAddress = BitcoinAddressConverter.publicKeyHashToAddress( - walletPublicKeyHash.toString(), + walletPublicKeyHash, true, BitcoinNetwork.Testnet ) @@ -105,7 +104,7 @@ describe("Redemptions", () => { await redemptionsService.requestRedemption( BitcoinAddressConverter.outputScriptToAddress( - Hex.from(redeemerOutputScript), + redeemerOutputScript, BitcoinNetwork.Testnet ), amount @@ -153,7 +152,7 @@ describe("Redemptions", () => { const actualRedemptionRequest = await redemptionsService.getRedemptionRequests( BitcoinAddressConverter.outputScriptToAddress( - Hex.from(redemptionRequest.redeemerOutputScript), + redemptionRequest.redeemerOutputScript, BitcoinNetwork.Testnet ), walletPublicKey, @@ -191,7 +190,7 @@ describe("Redemptions", () => { const actualRedemptionRequest = await redemptionsService.getRedemptionRequests( BitcoinAddressConverter.outputScriptToAddress( - Hex.from(redemptionRequest.redeemerOutputScript), + redemptionRequest.redeemerOutputScript, BitcoinNetwork.Testnet ), walletPublicKey, @@ -206,10 +205,10 @@ describe("Redemptions", () => { describe("findWalletForRedemption", () => { class TestRedemptionsService extends RedemptionsService { public async findWalletForRedemption( - redeemerOutputScript: string, + redeemerOutputScript: Hex, amount: BigNumber ): Promise<{ - walletPublicKey: string + walletPublicKey: Hex mainUtxo: BitcoinUtxo }> { return super.findWalletForRedemption(redeemerOutputScript, amount) @@ -221,8 +220,9 @@ describe("Redemptions", () => { let redemptionsService: TestRedemptionsService // script for testnet P2WSH address // tb1qau95mxzh2249aa3y8exx76ltc2sq0e7kw8hj04936rdcmnynhswqqz02vv - const redeemerOutputScript = + const redeemerOutputScript = Hex.from( "0x220020ef0b4d985752aa5ef6243e4c6f6bebc2a007e7d671ef27d4b1d0db8dcc93bc1c" + ) context( "when there are no wallets in the network that can handle redemption", @@ -327,7 +327,7 @@ describe("Redemptions", () => { findWalletForRedemptionData.walletWithPendingRedemption.data expect(result).to.deep.eq({ - walletPublicKey: expectedWalletData.walletPublicKey.toString(), + walletPublicKey: expectedWalletData.walletPublicKey, mainUtxo: expectedWalletData.mainUtxo, }) }) @@ -376,7 +376,7 @@ describe("Redemptions", () => { >() const key = MockBridge.buildRedemptionKey( - walletPublicKeyHash.toString(), + walletPublicKeyHash, redeemerOutputScript ) @@ -408,7 +408,7 @@ describe("Redemptions", () => { findWalletForRedemptionData.liveWallet.data expect(result).to.deep.eq({ - walletPublicKey: expectedWalletData.walletPublicKey.toString(), + walletPublicKey: expectedWalletData.walletPublicKey, mainUtxo: expectedWalletData.mainUtxo, }) }) @@ -440,7 +440,7 @@ describe("Redemptions", () => { findWalletForRedemptionData.liveWallet.data expect(result).to.deep.eq({ - walletPublicKey: expectedWalletData.walletPublicKey.toString(), + walletPublicKey: expectedWalletData.walletPublicKey, mainUtxo: expectedWalletData.mainUtxo, }) }) @@ -465,12 +465,13 @@ describe("Redemptions", () => { >() const pendingRedemption1 = MockBridge.buildRedemptionKey( - walletPublicKeyHash.toString(), + walletPublicKeyHash, redeemerOutputScript ) const pendingRedemption2 = MockBridge.buildRedemptionKey( - findWalletForRedemptionData.liveWallet.event.walletPublicKeyHash.toString(), + findWalletForRedemptionData.liveWallet.event + .walletPublicKeyHash, redeemerOutputScript ) @@ -751,13 +752,13 @@ describe("Redemptions", () => { const walletWitnessAddress = BitcoinAddressConverter.publicKeyHashToAddress( - walletPublicKeyHash.toString(), + walletPublicKeyHash, true, bitcoinNetwork ) const walletLegacyAddress = BitcoinAddressConverter.publicKeyHashToAddress( - walletPublicKeyHash.toString(), + walletPublicKeyHash, false, bitcoinNetwork ) diff --git a/typescript/test/utils/mock-bitcoin-client.ts b/typescript/test/utils/mock-bitcoin-client.ts index 96b01b249..69b55e212 100644 --- a/typescript/test/utils/mock-bitcoin-client.ts +++ b/typescript/test/utils/mock-bitcoin-client.ts @@ -7,6 +7,7 @@ import { BitcoinTx, BitcoinTxHash, } from "../../src/lib/bitcoin" +import { Hex } from "../../src/lib/utils" /** * Mock Bitcoin client used for test purposes. @@ -17,7 +18,7 @@ export class MockBitcoinClient implements BitcoinClient { private _transactions = new Map() private _confirmations = new Map() private _latestHeight = 0 - private _headersChain = "" + private _headersChain = Hex.from("") private _transactionMerkle: BitcoinTxMerkleBranch = { blockHeight: 0, merkle: [], @@ -46,7 +47,7 @@ export class MockBitcoinClient implements BitcoinClient { this._latestHeight = value } - set headersChain(value: string) { + set headersChain(value: Hex) { this._headersChain = value } @@ -116,8 +117,8 @@ export class MockBitcoinClient implements BitcoinClient { }) } - getHeadersChain(blockHeight: number, chainLength: number): Promise { - return new Promise((resolve, _) => { + getHeadersChain(blockHeight: number, chainLength: number): Promise { + return new Promise((resolve, _) => { resolve(this._headersChain) }) } diff --git a/typescript/test/utils/mock-bridge.ts b/typescript/test/utils/mock-bridge.ts index f6fbd0757..a1340a892 100644 --- a/typescript/test/utils/mock-bridge.ts +++ b/typescript/test/utils/mock-bridge.ts @@ -36,9 +36,9 @@ interface RevealDepositLogEntry { } interface RequestRedemptionLogEntry { - walletPublicKey: string + walletPublicKey: Hex mainUtxo: BitcoinUtxo - redeemerOutputScript: string + redeemerOutputScript: Hex amount: BigNumber } @@ -46,7 +46,7 @@ interface RedemptionProofLogEntry { redemptionTx: BitcoinRawTxVectors redemptionProof: BitcoinSpvProof mainUtxo: BitcoinUtxo - walletPublicKey: string + walletPublicKey: Hex } interface NewWalletRegisteredEventsLog { @@ -55,7 +55,7 @@ interface NewWalletRegisteredEventsLog { } interface WalletLog { - walletPublicKeyHash: string + walletPublicKeyHash: Hex } /** @@ -70,7 +70,7 @@ export class MockBridge implements Bridge { private _requestRedemptionLog: RequestRedemptionLogEntry[] = [] private _redemptionProofLog: RedemptionProofLogEntry[] = [] private _deposits = new Map() - private _activeWalletPublicKey: string | undefined + private _activeWalletPublicKey: Hex | undefined private _newWalletRegisteredEvents: NewWalletRegisteredEvent[] = [] private _newWalletRegisteredEventsLog: NewWalletRegisteredEventsLog[] = [] private _wallets = new Map() @@ -120,7 +120,7 @@ export class MockBridge implements Bridge { this._deposits = value } - setActiveWalletPublicKey(activeWalletPublicKey: string) { + setActiveWalletPublicKey(activeWalletPublicKey: Hex) { this._activeWalletPublicKey = activeWalletPublicKey } @@ -159,10 +159,14 @@ export class MockBridge implements Bridge { sweepProof: BitcoinSpvProof, mainUtxo: BitcoinUtxo, vault?: ChainIdentifier - ): Promise { + ): Promise { this._depositSweepProofLog.push({ sweepTx, sweepProof, mainUtxo }) - return new Promise((resolve, _) => { - resolve() + return new Promise((resolve, _) => { + resolve( + Hex.from( + "01ee2a0061b6bd68b6f478c48b9625fac89a4401e73b49d3ee258f9a60c5e65f" + ) + ) }) } @@ -170,12 +174,14 @@ export class MockBridge implements Bridge { depositTx: BitcoinRawTxVectors, depositOutputIndex: number, deposit: DepositReceipt - ): Promise { + ): Promise { this._revealDepositLog.push({ depositTx, depositOutputIndex, deposit }) - return new Promise((resolve, _) => { + return new Promise((resolve, _) => { // random transaction hash resolve( - "2f952bdc206bf51bb745b967cb7166149becada878d3191ffe341155ebcd4883" + Hex.from( + "2f952bdc206bf51bb745b967cb7166149becada878d3191ffe341155ebcd4883" + ) ) }) } @@ -223,33 +229,43 @@ export class MockBridge implements Bridge { redemptionTx: BitcoinRawTxVectors, redemptionProof: BitcoinSpvProof, mainUtxo: BitcoinUtxo, - walletPublicKey: string - ): Promise { + walletPublicKey: Hex + ): Promise { this._redemptionProofLog.push({ redemptionTx, redemptionProof, mainUtxo, walletPublicKey, }) - return new Promise((resolve, _) => { - resolve() + return new Promise((resolve, _) => { + // random transaction hash + resolve( + Hex.from( + "4f6ce6af47d547bb9821d28c21261026f21b72e52d506d17ab81502b8021537d" + ) + ) }) } requestRedemption( - walletPublicKey: string, + walletPublicKey: Hex, mainUtxo: BitcoinUtxo, - redeemerOutputScript: string, + redeemerOutputScript: Hex, amount: BigNumber - ) { + ): Promise { this._requestRedemptionLog.push({ walletPublicKey, mainUtxo, redeemerOutputScript, amount, }) - return new Promise((resolve, _) => { - resolve() + return new Promise((resolve, _) => { + // random transaction hash + resolve( + Hex.from( + "bcbef136592feabdebcc68eb4222a49369a9cfeb7fc5f5ec84583313249025fd" + ) + ) }) } @@ -260,8 +276,8 @@ export class MockBridge implements Bridge { } pendingRedemptions( - walletPublicKey: string, - redeemerOutputScript: string + walletPublicKey: Hex, + redeemerOutputScript: Hex ): Promise { return new Promise((resolve, _) => { resolve( @@ -275,8 +291,8 @@ export class MockBridge implements Bridge { } timedOutRedemptions( - walletPublicKey: string, - redeemerOutputScript: string + walletPublicKey: Hex, + redeemerOutputScript: Hex ): Promise { return new Promise((resolve, _) => { resolve( @@ -290,8 +306,8 @@ export class MockBridge implements Bridge { } private redemptions( - walletPublicKey: string, - redeemerOutputScript: string, + walletPublicKey: Hex, + redeemerOutputScript: Hex, redemptionsMap: Map ): RedemptionRequest { const redemptionKey = MockBridge.buildRedemptionKey( @@ -305,7 +321,7 @@ export class MockBridge implements Bridge { ? (redemptionsMap.get(redemptionKey) as RedemptionRequest) : { redeemer: EthereumAddress.from(constants.AddressZero), - redeemerOutputScript: "", + redeemerOutputScript: Hex.from(""), requestedAmount: BigNumber.from(0), treasuryFee: BigNumber.from(0), txMaxFee: BigNumber.from(0), @@ -314,12 +330,12 @@ export class MockBridge implements Bridge { } static buildRedemptionKey( - walletPublicKeyHash: string, - redeemerOutputScript: string + walletPublicKeyHash: Hex, + redeemerOutputScript: Hex ): string { - const prefixedWalletPublicKeyHash = `0x${walletPublicKeyHash}` + const prefixedWalletPublicKeyHash = walletPublicKeyHash.toPrefixedString() - const rawOutputScript = Buffer.from(redeemerOutputScript, "hex") + const rawOutputScript = redeemerOutputScript.toBuffer() const prefixedOutputScript = `0x${Buffer.concat([ Buffer.from([rawOutputScript.length]), @@ -335,7 +351,7 @@ export class MockBridge implements Bridge { ) } - async activeWalletPublicKey(): Promise { + async activeWalletPublicKey(): Promise { return this._activeWalletPublicKey } @@ -353,7 +369,7 @@ export class MockBridge implements Bridge { async wallets(walletPublicKeyHash: Hex): Promise { this._walletsLog.push({ - walletPublicKeyHash: walletPublicKeyHash.toPrefixedString(), + walletPublicKeyHash, }) const wallet = this._wallets.get(walletPublicKeyHash.toPrefixedString()) return wallet! diff --git a/typescript/test/utils/mock-tbtc-token.ts b/typescript/test/utils/mock-tbtc-token.ts index b2238f550..ba7fdc08d 100644 --- a/typescript/test/utils/mock-tbtc-token.ts +++ b/typescript/test/utils/mock-tbtc-token.ts @@ -5,9 +5,9 @@ import { BitcoinUtxo } from "../../src/lib/bitcoin" import { EthereumAddress } from "../../src" interface RequestRedemptionLog { - walletPublicKey: string + walletPublicKey: Hex mainUtxo: BitcoinUtxo - redeemerOutputScript: string + redeemerOutputScript: Hex amount: BigNumber } @@ -23,9 +23,9 @@ export class MockTBTCToken implements TBTCToken { } async requestRedemption( - walletPublicKey: string, + walletPublicKey: Hex, mainUtxo: BitcoinUtxo, - redeemerOutputScript: string, + redeemerOutputScript: Hex, amount: BigNumber ): Promise { this._requestRedemptionLog.push({