From 26d4f0198fc964f49abbcf997777f89576d86b19 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Wed, 25 Jan 2023 22:46:35 +0100 Subject: [PATCH 1/7] Don't get verbose transaction for getTransactionConfirmations As Esplora/Electrs doesn't support verbose transactions details in the response, that would contain the confirmations number we need to workaround it. (See: Blockstream/electrs#36) The workaround: 1. Get the raw transaction 2. Deserialize the raw transaction 3. Find transaction block height by finding it in a history of transactions for the output script included in the transaction. 4. Get the latest block height 5. Calculate number of confirmations by subtracting the transaction block height from the latest block height and adding one. --- typescript/src/electrum.ts | 76 +++++++++++++++++++++++++++++++++++--- 1 file changed, 71 insertions(+), 5 deletions(-) diff --git a/typescript/src/electrum.ts b/typescript/src/electrum.ts index b056b8716..ace6195fe 100644 --- a/typescript/src/electrum.ts +++ b/typescript/src/electrum.ts @@ -203,15 +203,81 @@ export class Client implements BitcoinClient { getTransactionConfirmations( transactionHash: TransactionHash ): Promise { + // We cannot use `blockchain_transaction_get` with `verbose = true` argument + // to get the the transaction details as Esplora/Electrs doesn't support verbose + // transactions. + // See: https://github.com/Blockstream/electrs/pull/36 + return this.withElectrum(async (electrum: any) => { - const transaction = await electrum.blockchain_transaction_get( + const rawTransaction: string = await electrum.blockchain_transaction_get( transactionHash.toString(), - true + false ) - // For unconfirmed transactions `confirmations` property may be undefined, so - // we will return 0 instead. - return transaction.confirmations ?? 0 + // Decode the raw transaction. + const transaction = bcoin.TX.fromRaw(rawTransaction, "hex") + + // As a workaround for the problem described in https://github.com/Blockstream/electrs/pull/36 + // we need to calculate the number of confirmations based on the latest + // block height and block height of the transaction. + // Electrum protocol doesn't expose a function to get the transaction's block + // height (other that the `GetTransaction` that is unsupported by Esplora/Electrs). + // To get the block height of the transaction we query the history of transactions + // for the output script hash, as the history contains the transaction's block + // height. + + // Initialize txBlockHeigh with minimum int32 value to identify a problem when + // a block height was not found in a history of any of the script hashes. + // + // The history is expected to return a block height for confirmed transaction. + // If a transaction is unconfirmed (is still in the mempool) the height will + // have a value of `0` or `-1`. + let txBlockHeight: number = Math.min() + for (const output of transaction.outputs) { + const scriptHash: Buffer = output.script.sha256() + + type HistoryEntry = { + // eslint-disable-next-line camelcase + tx_hash: string + height: number + } + + const scriptHashHistory: HistoryEntry[] = + await electrum.blockchain_scripthash_getHistory( + scriptHash.reverse().toString("hex") + ) + + const tx = scriptHashHistory.find( + (t) => t.tx_hash === transactionHash.toString() + ) + + if (tx) { + txBlockHeight = tx.height + break + } + } + + // History querying didn't come up with the transaction's block height. Return + // an error. + if (txBlockHeight === Math.min()) { + throw new Error( + "failed to find the transaction block height in script hashes' histories" + ) + } + + // If the block height is greater than `0` the transaction is confirmed. + if (txBlockHeight > 0) { + const latestBlockHeight: number = await this.latestBlockHeight() + + if (latestBlockHeight >= txBlockHeight) { + // Add `1` to the calculated difference as if the transaction block + // height equals the latest block height the transaction is already + // confirmed, so it has one confirmation. + return latestBlockHeight - txBlockHeight + 1 + } + } + + return 0 }) } From a7aedd11fbfc7b26cbda5376a33207c7966f48bf Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Wed, 25 Jan 2023 22:49:29 +0100 Subject: [PATCH 2/7] Don't get verbose transaction for getTransaction The simpliest solution is to request verbose format of transaction. Unfortunatelly it's not compatible with Esplora/Electrs implementation of ElectrumX server. (see: Blockstream/electrs#36) As a workaround to cover integration with Esplora/Electrs we get a raw transaction and deserialize it. --- typescript/src/electrum.ts | 44 +++++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/typescript/src/electrum.ts b/typescript/src/electrum.ts index ace6195fe..91da2b135 100644 --- a/typescript/src/electrum.ts +++ b/typescript/src/electrum.ts @@ -149,30 +149,48 @@ export class Client implements BitcoinClient { */ getTransaction(transactionHash: TransactionHash): Promise { return this.withElectrum(async (electrum: any) => { - const transaction = await electrum.blockchain_transaction_get( + // We cannot use `blockchain_transaction_get` with `verbose = true` argument + // to get the the transaction details as Esplora/Electrs doesn't support verbose + // transactions. + // See: https://github.com/Blockstream/electrs/pull/36 + const rawTransaction = await electrum.blockchain_transaction_get( transactionHash.toString(), - true + false ) - const inputs = transaction.vin.map( + if (!rawTransaction) { + throw new Error(`Transaction not found`) + } + + // Decode the raw transaction. + const transaction = bcoin.TX.fromRaw(rawTransaction, "hex") + + const inputs = transaction.inputs.map( (input: any): TransactionInput => ({ - transactionHash: TransactionHash.from(input.txid), - outputIndex: input.vout, - scriptSig: input.scriptSig, + transactionHash: TransactionHash.from(input.prevout.hash).reverse(), + outputIndex: input.prevout.index, + scriptSig: { + asm: input.script.toASM(true), + hex: input.script.toRaw().toString("hex"), + type: input.script.getType(), + }, }) ) - const outputs = transaction.vout.map( - (output: any): TransactionOutput => ({ - outputIndex: output.n, - // The `output.value` is in BTC so it must be converted to satoshis. - value: BigNumber.from((parseFloat(output.value) * 1e8).toFixed(0)), - scriptPubKey: output.scriptPubKey, + const outputs = transaction.outputs.map( + (output: any, i: number): TransactionOutput => ({ + outputIndex: i, + value: BigNumber.from(output.value), + scriptPubKey: { + asm: output.script.toASM(true), + hex: output.script.toRaw().toString("hex"), + type: output.getType().toUpperCase(), + }, }) ) return { - transactionHash: TransactionHash.from(transaction.txid), + transactionHash: TransactionHash.from(transaction.hash()).reverse(), inputs: inputs, outputs: outputs, } From 2097cd822f6bfee74d122d6f97aea130c6d703a2 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Wed, 25 Jan 2023 22:54:46 +0100 Subject: [PATCH 3/7] Update tests for getTransactionConfirmations and latestBlockHeight We can test exact block number, not only it being greater than 6. For that we need to fetch the current block height to compare it with the one we get. We use blockstream as a source of truth. --- typescript/test/electrum.test.ts | 66 ++++++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 4 deletions(-) diff --git a/typescript/test/electrum.test.ts b/typescript/test/electrum.test.ts index 59625486e..0f59d32e9 100644 --- a/typescript/test/electrum.test.ts +++ b/typescript/test/electrum.test.ts @@ -11,6 +11,9 @@ import { testnetUTXO, } from "./data/electrum" import { expect } from "chai" +import https from "https" + +const BLOCKSTREAM_TESTNET_API_URL = "https://blockstream.info/testnet/api" const testnetCredentials: ElectrumCredentials = { host: "electrumx-server.test.tbtc.network", @@ -65,23 +68,52 @@ describe.skip("Electrum", () => { }) describe("getTransactionConfirmations", () => { - it("should return proper confirmations number for the given hash", async () => { - const result = await electrumClient.getTransactionConfirmations( + let result: number + + before(async () => { + result = await electrumClient.getTransactionConfirmations( testnetTransaction.transactionHash ) + }) + + it("should return value greater than 6", async () => { // Strict comparison is not possible as the number of confirmations // constantly grows. We just make sure it's 6+. expect(result).to.be.greaterThan(6) }) + + // This test depends on `latestBlockHeight` function. + it("should return proper confirmations number for the given hash", async () => { + const latestBlockHeight = await electrumClient.latestBlockHeight() + + const expectedResult = + latestBlockHeight - testnetTransactionMerkleBranch.blockHeight + + expect(result).to.be.closeTo(expectedResult, 3) + }) }) describe("latestBlockHeight", () => { - it("should return proper latest block height", async () => { - const result = await electrumClient.latestBlockHeight() + let result: number + + before(async () => { + result = await electrumClient.latestBlockHeight() + }) + + it("should return value greater than 6", async () => { // Strict comparison is not possible as the latest block height // constantly grows. We just make sure it's bigger than 0. expect(result).to.be.greaterThan(0) }) + + // This test depends on fetching the expected latest block height from Blockstream API. + // It can fail if Blockstream API is down or if Blockstream API or if + // Electrum Server used in tests is out-of-sync with the Blockstream API. + it("should return proper latest block height", async () => { + const expectedResult = await getExpectedLatestBlockHeight() + + expect(result).to.be.closeTo(expectedResult, 3) + }) }) describe("getHeadersChain", () => { @@ -104,3 +136,29 @@ describe.skip("Electrum", () => { }) }) }) + +/** + * Gets the height of the last block fetched from the Blockstream API. + * @returns Height of the last block. + */ +function getExpectedLatestBlockHeight(): Promise { + return new Promise((resolve, reject) => { + https + .get(`${BLOCKSTREAM_TESTNET_API_URL}/blocks/tip/height`, (resp) => { + let data = "" + + // A chunk of data has been received. + resp.on("data", (chunk) => { + data += chunk + }) + + // The whole response has been received. Print out the result. + resp.on("end", () => { + resolve(JSON.parse(data)) + }) + }) + .on("error", (err) => { + reject(err) + }) + }) +} From ec91c74e55d55ab92ec009247cdbd5166ae034df Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Wed, 25 Jan 2023 23:03:06 +0100 Subject: [PATCH 4/7] Add more test servers for electrum integration tests We can test electrum integration against different kinds of servers. The most popular implementations are: - ElectrumX - Fulcrum - Electrs/Esplora We can find list of public servers here: https://1209k.com/bitcoin-eye/ele.php?chain=tbtc The electrs-esplora server seems pretty unstable, so we don't want to enable it in tests untill we add retries. --- typescript/test/electrum.test.ts | 196 +++++++++++++++++-------------- 1 file changed, 109 insertions(+), 87 deletions(-) diff --git a/typescript/test/electrum.test.ts b/typescript/test/electrum.test.ts index 0f59d32e9..a54f47dee 100644 --- a/typescript/test/electrum.test.ts +++ b/typescript/test/electrum.test.ts @@ -15,11 +15,28 @@ import https from "https" const BLOCKSTREAM_TESTNET_API_URL = "https://blockstream.info/testnet/api" -const testnetCredentials: ElectrumCredentials = { - host: "electrumx-server.test.tbtc.network", - port: 8443, - protocol: "wss", -} +const testnetCredentials: ElectrumCredentials[] = [ + // electrumx wss + { + host: "electrumx-server.test.tbtc.network", + port: 8443, + protocol: "wss", + }, + // TODO: Enable after retries are implemented + // See: https://github.com/keep-network/tbtc-v2/issues/485 + // // electrs-esplora ssl + // { + // host: "electrum.blockstream.info", + // port: 60002, + // protocol: "ssl", + // }, + // fulcrum tcp + { + host: "testnet.aranguren.org", + port: 51001, + protocol: "tcp", + }, +] /** * This test suite is meant to check the behavior of the Electrum-based @@ -34,105 +51,110 @@ const testnetCredentials: ElectrumCredentials = { * though. */ describe.skip("Electrum", () => { - let electrumClient: ElectrumClient + testnetCredentials.forEach((credentials) => { + describe(`${credentials.protocol}://${credentials.host}:${credentials.port}`, async () => { + let electrumClient: ElectrumClient - before(async () => { - electrumClient = new ElectrumClient(testnetCredentials) - }) + before(async () => { + electrumClient = new ElectrumClient(credentials) + }) - describe("findAllUnspentTransactionOutputs", () => { - it("should return proper UTXOs for the given address", async () => { - const result = await electrumClient.findAllUnspentTransactionOutputs( - testnetAddress - ) - expect(result).to.be.eql([testnetUTXO]) - }) - }) + describe("findAllUnspentTransactionOutputs", () => { + it("should return proper UTXOs for the given address", async () => { + const result = await electrumClient.findAllUnspentTransactionOutputs( + testnetAddress + ) + expect(result).to.be.eql([testnetUTXO]) + }) + }) - describe("getTransaction", () => { - it("should return proper transaction for the given hash", async () => { - const result = await electrumClient.getTransaction( - testnetTransaction.transactionHash - ) - expect(result).to.be.eql(testnetTransaction) - }) - }) + describe("getTransaction", () => { + it("should return proper transaction for the given hash", async () => { + const result = await electrumClient.getTransaction( + testnetTransaction.transactionHash + ) + expect(result).to.be.eql(testnetTransaction) + }) + // TODO: Add case when transaction doesn't exist + }) - describe("getRawTransaction", () => { - it("should return proper raw transaction for the given hash", async () => { - const result = await electrumClient.getRawTransaction( - testnetTransaction.transactionHash - ) - expect(result).to.be.eql(testnetRawTransaction) - }) - }) + describe("getRawTransaction", () => { + it("should return proper raw transaction for the given hash", async () => { + const result = await electrumClient.getRawTransaction( + testnetTransaction.transactionHash + ) + expect(result).to.be.eql(testnetRawTransaction) + }) + }) - describe("getTransactionConfirmations", () => { - let result: number + describe("getTransactionConfirmations", () => { + let result: number - before(async () => { - result = await electrumClient.getTransactionConfirmations( - testnetTransaction.transactionHash - ) - }) + before(async () => { + result = await electrumClient.getTransactionConfirmations( + testnetTransaction.transactionHash + ) + }) - it("should return value greater than 6", async () => { - // Strict comparison is not possible as the number of confirmations - // constantly grows. We just make sure it's 6+. - expect(result).to.be.greaterThan(6) - }) + it("should return value greater than 6", async () => { + // Strict comparison is not possible as the number of confirmations + // constantly grows. We just make sure it's 6+. + expect(result).to.be.greaterThan(6) + }) - // This test depends on `latestBlockHeight` function. - it("should return proper confirmations number for the given hash", async () => { - const latestBlockHeight = await electrumClient.latestBlockHeight() + // This test depends on `latestBlockHeight` function. + it("should return proper confirmations number for the given hash", async () => { + const latestBlockHeight = await electrumClient.latestBlockHeight() - const expectedResult = - latestBlockHeight - testnetTransactionMerkleBranch.blockHeight + const expectedResult = + latestBlockHeight - testnetTransactionMerkleBranch.blockHeight - expect(result).to.be.closeTo(expectedResult, 3) - }) - }) + expect(result).to.be.closeTo(expectedResult, 3) + }) + }) - describe("latestBlockHeight", () => { - let result: number + describe("latestBlockHeight", () => { + let result: number - before(async () => { - result = await electrumClient.latestBlockHeight() - }) + before(async () => { + result = await electrumClient.latestBlockHeight() + }) - it("should return value greater than 6", async () => { - // Strict comparison is not possible as the latest block height - // constantly grows. We just make sure it's bigger than 0. - expect(result).to.be.greaterThan(0) - }) + it("should return value greater than 6", async () => { + // Strict comparison is not possible as the latest block height + // constantly grows. We just make sure it's bigger than 0. + expect(result).to.be.greaterThan(0) + }) - // This test depends on fetching the expected latest block height from Blockstream API. - // It can fail if Blockstream API is down or if Blockstream API or if - // Electrum Server used in tests is out-of-sync with the Blockstream API. - it("should return proper latest block height", async () => { - const expectedResult = await getExpectedLatestBlockHeight() + // This test depends on fetching the expected latest block height from Blockstream API. + // It can fail if Blockstream API is down or if Blockstream API or if + // Electrum Server used in tests is out-of-sync with the Blockstream API. + it("should return proper latest block height", async () => { + const expectedResult = await getExpectedLatestBlockHeight() - expect(result).to.be.closeTo(expectedResult, 3) - }) - }) + expect(result).to.be.closeTo(expectedResult, 3) + }) + }) - describe("getHeadersChain", () => { - it("should return proper headers chain", async () => { - const result = await electrumClient.getHeadersChain( - testnetHeadersChain.blockHeight, - testnetHeadersChain.headersChainLength - ) - expect(result).to.be.eql(testnetHeadersChain.headersChain) - }) - }) + describe("getHeadersChain", () => { + it("should return proper headers chain", async () => { + const result = await electrumClient.getHeadersChain( + testnetHeadersChain.blockHeight, + testnetHeadersChain.headersChainLength + ) + expect(result).to.be.eql(testnetHeadersChain.headersChain) + }) + }) - describe("getTransactionMerkle", () => { - it("should return proper transaction merkle", async () => { - const result = await electrumClient.getTransactionMerkle( - testnetTransaction.transactionHash, - testnetTransactionMerkleBranch.blockHeight - ) - expect(result).to.be.eql(testnetTransactionMerkleBranch) + describe("getTransactionMerkle", () => { + it("should return proper transaction merkle", async () => { + const result = await electrumClient.getTransactionMerkle( + testnetTransaction.transactionHash, + testnetTransactionMerkleBranch.blockHeight + ) + expect(result).to.be.eql(testnetTransactionMerkleBranch) + }) + }) }) }) }) From 093d4ece7d2cd83d3d554a97d0985a67b7f4d154 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Wed, 25 Jan 2023 23:14:28 +0100 Subject: [PATCH 5/7] Define scriptSig and scriptPubKey as Hex Before a7aedd11fbfc7b26cbda5376a33207c7966f48bf under these two properties we returned exactly the valu that was retruned from electrum server. This was causing some unexpected bahaviour as it could happen that different implementation and instances of servers were returning different results. The only thing that we can relay on is a hex value for bytes that were used in the transaction. Here we switch to hexadecimal value to have consistent behaviour and be able to support all major electrum server implementations (ElectrumX, Electrs/Esplora and Fulcrum). The change here is similiar to what we implemented in the Keep Client. --- typescript/src/bitcoin.ts | 4 +- typescript/src/electrum.ts | 13 ++---- typescript/test/data/deposit-sweep.ts | 19 ++++---- typescript/test/data/electrum.ts | 22 ++-------- typescript/test/data/proof.ts | 63 ++++++++------------------- typescript/test/data/redemption.ts | 55 ++++++++--------------- 6 files changed, 53 insertions(+), 123 deletions(-) diff --git a/typescript/src/bitcoin.ts b/typescript/src/bitcoin.ts index 237079ea6..67cf1e0ba 100644 --- a/typescript/src/bitcoin.ts +++ b/typescript/src/bitcoin.ts @@ -66,7 +66,7 @@ export type TransactionInput = TransactionOutpoint & { /** * The scriptSig that unlocks the specified outpoint for spending. */ - scriptSig: any + scriptSig: Hex } /** @@ -86,7 +86,7 @@ export interface TransactionOutput { /** * The receiving scriptPubKey. */ - scriptPubKey: any + scriptPubKey: Hex } /** diff --git a/typescript/src/electrum.ts b/typescript/src/electrum.ts index 91da2b135..7342d1835 100644 --- a/typescript/src/electrum.ts +++ b/typescript/src/electrum.ts @@ -13,6 +13,7 @@ import Electrum from "electrum-client-js" import sha256 from "bcrypto/lib/sha256-browser.js" import { BigNumber } from "ethers" import { URL } from "url" +import { Hex } from "./hex" /** * Represents a set of credentials required to establish an Electrum connection. @@ -169,11 +170,7 @@ export class Client implements BitcoinClient { (input: any): TransactionInput => ({ transactionHash: TransactionHash.from(input.prevout.hash).reverse(), outputIndex: input.prevout.index, - scriptSig: { - asm: input.script.toASM(true), - hex: input.script.toRaw().toString("hex"), - type: input.script.getType(), - }, + scriptSig: Hex.from(input.script.toRaw()), }) ) @@ -181,11 +178,7 @@ export class Client implements BitcoinClient { (output: any, i: number): TransactionOutput => ({ outputIndex: i, value: BigNumber.from(output.value), - scriptPubKey: { - asm: output.script.toASM(true), - hex: output.script.toRaw().toString("hex"), - type: output.getType().toUpperCase(), - }, + scriptPubKey: Hex.from(output.script.toRaw()), }) ) diff --git a/typescript/test/data/deposit-sweep.ts b/typescript/test/data/deposit-sweep.ts index b2ae7ceec..59e3f5770 100644 --- a/typescript/test/data/deposit-sweep.ts +++ b/typescript/test/data/deposit-sweep.ts @@ -10,6 +10,7 @@ import { import { calculateDepositRefundLocktime, Deposit } from "../../src/deposit" import { BigNumber } from "ethers" import { Address } from "../../src/ethereum" +import { Hex } from "../../src" export const NO_MAIN_UTXO = { transactionHash: TransactionHash.from(""), @@ -406,41 +407,37 @@ export const depositSweepProof: DepositSweepProofTestData = { "ea4d9e45f8c1b8a187c007f36ba1e9b201e8511182c7083c4edcaf9325b2998f" ), outputIndex: 0, - scriptSig: { asm: "", hex: "" }, + scriptSig: Hex.from(""), }, { transactionHash: TransactionHash.from( "c844ff4c1781c884bb5e80392398b81b984d7106367ae16675f132bd1a7f33fd" ), outputIndex: 0, - scriptSig: { asm: "", hex: "" }, + scriptSig: Hex.from(""), }, { transactionHash: TransactionHash.from( "44c568bc0eac07a2a9c2b46829be5b5d46e7d00e17bfb613f506a75ccf86a473" ), outputIndex: 0, - scriptSig: { asm: "", hex: "" }, + scriptSig: Hex.from(""), }, { transactionHash: TransactionHash.from( "f548c00e464764e112826450a00cf005ca771a6108a629b559b6c60a519e4378" ), outputIndex: 0, - scriptSig: { asm: "", hex: "" }, + scriptSig: Hex.from(""), }, ], outputs: [ { outputIndex: 0, value: BigNumber.from(39800), - scriptPubKey: { - asm: "OP_0 8db50eb52063ea9d98b3eac91489a90f738986f6", - hex: "00148db50eb52063ea9d98b3eac91489a90f738986f6", - type: "WITNESSPUBKEYHASH", - reqSigs: 1, - addresses: ["tb1q3k6sadfqv04fmx9naty3fzdfpaecnphkfm3cf3"], - }, + scriptPubKey: Hex.from( + "00148db50eb52063ea9d98b3eac91489a90f738986f6" + ), }, ], }, diff --git a/typescript/test/data/electrum.ts b/typescript/test/data/electrum.ts index 7ec46b647..f17708bf4 100644 --- a/typescript/test/data/electrum.ts +++ b/typescript/test/data/electrum.ts @@ -6,6 +6,7 @@ import { TransactionHash, } from "../../src/bitcoin" import { BigNumber } from "ethers" +import { Hex } from "../../src" /** * Bitcoin testnet address used for Electrum client tests. @@ -27,10 +28,7 @@ export const testnetTransaction: Transaction = { "c6ffe9e0f8cca057acad211023ff6b9d46604fbbcb76c6dd669c20b22985f802" ), outputIndex: 1, - scriptSig: { - asm: "", - hex: "", - }, + scriptSig: Hex.from(""), }, ], @@ -38,24 +36,12 @@ export const testnetTransaction: Transaction = { { outputIndex: 0, value: BigNumber.from(101), - scriptPubKey: { - addresses: ["tb1qfdru0xx39mw30ha5a2vw23reymmxgucujfnc7l"], - asm: "OP_0 4b47c798d12edd17dfb4ea98e5447926f664731c", - hex: "00144b47c798d12edd17dfb4ea98e5447926f664731c", - reqSigs: 1, - type: "WITNESSPUBKEYHASH", - }, + scriptPubKey: Hex.from("00144b47c798d12edd17dfb4ea98e5447926f664731c"), }, { outputIndex: 1, value: BigNumber.from(9125), - scriptPubKey: { - addresses: ["tb1q78ezl08lyhuazzfz592sstenmegdns7durc4cl"], - asm: "OP_0 f1f22fbcff25f9d10922a155082f33de50d9c3cd", - hex: "0014f1f22fbcff25f9d10922a155082f33de50d9c3cd", - reqSigs: 1, - type: "WITNESSPUBKEYHASH", - }, + scriptPubKey: Hex.from("0014f1f22fbcff25f9d10922a155082f33de50d9c3cd"), }, ], } diff --git a/typescript/test/data/proof.ts b/typescript/test/data/proof.ts index 8c57afe0e..6540d709d 100644 --- a/typescript/test/data/proof.ts +++ b/typescript/test/data/proof.ts @@ -6,6 +6,7 @@ import { TransactionMerkleBranch, } from "../../src/bitcoin" import { BigNumber } from "ethers" +import { Hex } from "../../src" /** * Represents a set of data used for given proof scenario. @@ -40,23 +41,16 @@ export const singleInputProofTestData: ProofTestData = { "8ee67b585eeb682bf6907ea311282540ee53edf605e0f09757226a4dc3e72a67" ), outputIndex: 0, - scriptSig: { - asm: "", - hex: "", - }, + scriptSig: Hex.from(""), }, ], outputs: [ { outputIndex: 0, value: BigNumber.from(8400), - scriptPubKey: { - asm: "OP_0 8db50eb52063ea9d98b3eac91489a90f738986f6", - hex: "00148db50eb52063ea9d98b3eac91489a90f738986f6", - type: "WITNESSPUBKEYHASH", - reqSigs: 1, - addresses: ["tb1q3k6sadfqv04fmx9naty3fzdfpaecnphkfm3cf3"], - }, + scriptPubKey: Hex.from( + "00148db50eb52063ea9d98b3eac91489a90f738986f6" + ), }, ], }, @@ -117,23 +111,14 @@ export const singleInputProofTestData: ProofTestData = { "8ee67b585eeb682bf6907ea311282540ee53edf605e0f09757226a4dc3e72a67" ), outputIndex: 0, - scriptSig: { - asm: "", - hex: "", - }, + scriptSig: Hex.from(""), }, ], outputs: [ { outputIndex: 0, value: BigNumber.from(8400), - scriptPubKey: { - asm: "OP_0 8db50eb52063ea9d98b3eac91489a90f738986f6", - hex: "00148db50eb52063ea9d98b3eac91489a90f738986f6", - type: "WITNESSPUBKEYHASH", - reqSigs: 1, - addresses: ["tb1q3k6sadfqv04fmx9naty3fzdfpaecnphkfm3cf3"], - }, + scriptPubKey: Hex.from("00148db50eb52063ea9d98b3eac91489a90f738986f6"), }, ], merkleProof: @@ -184,41 +169,37 @@ export const multipleInputsProofTestData: ProofTestData = { "ea4d9e45f8c1b8a187c007f36ba1e9b201e8511182c7083c4edcaf9325b2998f" ), outputIndex: 0, - scriptSig: { asm: "", hex: "" }, + scriptSig: Hex.from(""), }, { transactionHash: TransactionHash.from( "c844ff4c1781c884bb5e80392398b81b984d7106367ae16675f132bd1a7f33fd" ), outputIndex: 0, - scriptSig: { asm: "", hex: "" }, + scriptSig: Hex.from(""), }, { transactionHash: TransactionHash.from( "44c568bc0eac07a2a9c2b46829be5b5d46e7d00e17bfb613f506a75ccf86a473" ), outputIndex: 0, - scriptSig: { asm: "", hex: "" }, + scriptSig: Hex.from(""), }, { transactionHash: TransactionHash.from( "f548c00e464764e112826450a00cf005ca771a6108a629b559b6c60a519e4378" ), outputIndex: 0, - scriptSig: { asm: "", hex: "" }, + scriptSig: Hex.from(""), }, ], outputs: [ { outputIndex: 0, value: BigNumber.from(39800), - scriptPubKey: { - asm: "OP_0 8db50eb52063ea9d98b3eac91489a90f738986f6", - hex: "00148db50eb52063ea9d98b3eac91489a90f738986f6", - type: "WITNESSPUBKEYHASH", - reqSigs: 1, - addresses: ["tb1q3k6sadfqv04fmx9naty3fzdfpaecnphkfm3cf3"], - }, + scriptPubKey: Hex.from( + "00148db50eb52063ea9d98b3eac91489a90f738986f6" + ), }, ], }, @@ -297,41 +278,35 @@ export const multipleInputsProofTestData: ProofTestData = { "ea4d9e45f8c1b8a187c007f36ba1e9b201e8511182c7083c4edcaf9325b2998f" ), outputIndex: 0, - scriptSig: { asm: "", hex: "" }, + scriptSig: Hex.from(""), }, { transactionHash: TransactionHash.from( "c844ff4c1781c884bb5e80392398b81b984d7106367ae16675f132bd1a7f33fd" ), outputIndex: 0, - scriptSig: { asm: "", hex: "" }, + scriptSig: Hex.from(""), }, { transactionHash: TransactionHash.from( "44c568bc0eac07a2a9c2b46829be5b5d46e7d00e17bfb613f506a75ccf86a473" ), outputIndex: 0, - scriptSig: { asm: "", hex: "" }, + scriptSig: Hex.from(""), }, { transactionHash: TransactionHash.from( "f548c00e464764e112826450a00cf005ca771a6108a629b559b6c60a519e4378" ), outputIndex: 0, - scriptSig: { asm: "", hex: "" }, + scriptSig: Hex.from(""), }, ], outputs: [ { outputIndex: 0, value: BigNumber.from(39800), - scriptPubKey: { - asm: "OP_0 8db50eb52063ea9d98b3eac91489a90f738986f6", - hex: "00148db50eb52063ea9d98b3eac91489a90f738986f6", - type: "WITNESSPUBKEYHASH", - reqSigs: 1, - addresses: ["tb1q3k6sadfqv04fmx9naty3fzdfpaecnphkfm3cf3"], - }, + scriptPubKey: Hex.from("00148db50eb52063ea9d98b3eac91489a90f738986f6"), }, ], merkleProof: diff --git a/typescript/test/data/redemption.ts b/typescript/test/data/redemption.ts index 9edb73c6f..8a361c746 100644 --- a/typescript/test/data/redemption.ts +++ b/typescript/test/data/redemption.ts @@ -10,6 +10,7 @@ import { } from "../../src/bitcoin" import { RedemptionRequest } from "../../src/redemption" import { Address } from "../../src/ethereum" +import { Hex } from "../../src" /** * Private key (testnet) of the wallet. @@ -527,66 +528,44 @@ export const redemptionProof: RedemptionProofTestData = { "3d28bb5bf73379da51bc683f4d0ed31d7b024466c619d80ebd9378077d900be3" ), outputIndex: 1, - scriptSig: { asm: "", hex: "" }, + scriptSig: Hex.from(""), }, ], outputs: [ { outputIndex: 0, value: BigNumber.from(15900), - scriptPubKey: { - asm: "OP_DUP OP_HASH160 4130879211c54df460e484ddf9aac009cb38ee74 OP_EQUALVERIFY OP_CHECKSIG", - hex: "76a9144130879211c54df460e484ddf9aac009cb38ee7488ac", - type: "PUBKEYHASH", - reqSigs: 1, - addresses: ["mmTeMR8RKu6QzMGTG4ipA71uewm3EuJng5"], - }, + scriptPubKey: Hex.from( + "76a9144130879211c54df460e484ddf9aac009cb38ee7488ac" + ), }, { outputIndex: 1, value: BigNumber.from(11300), - scriptPubKey: { - asm: "OP_0 4130879211c54df460e484ddf9aac009cb38ee74", - hex: "00144130879211c54df460e484ddf9aac009cb38ee74", - type: "WITNESSPUBKEYHASH", - reqSigs: 1, - addresses: ["tb1qgycg0ys3c4xlgc8ysnwln2kqp89n3mn5ts7z3l"], - }, + scriptPubKey: Hex.from( + "00144130879211c54df460e484ddf9aac009cb38ee74" + ), }, { outputIndex: 2, value: BigNumber.from(9900), - scriptPubKey: { - asm: "OP_HASH160 3ec459d0f3c29286ae5df5fcc421e2786024277e OP_EQUAL", - hex: "a9143ec459d0f3c29286ae5df5fcc421e2786024277e87", - type: "SCRIPTHASH", - reqSigs: 1, - addresses: ["2Mxy76sc1qAxiJ1fXMXDXqHvVcPLh6Lf12C"], - }, + scriptPubKey: Hex.from( + "a9143ec459d0f3c29286ae5df5fcc421e2786024277e87" + ), }, { outputIndex: 3, value: BigNumber.from(12900), - scriptPubKey: { - asm: "OP_0 86a303cdd2e2eab1d1679f1a813835dc5a1b65321077cdccaf08f98cbf04ca96", - hex: "002086a303cdd2e2eab1d1679f1a813835dc5a1b65321077cdccaf08f98cbf04ca96", - type: "WITNESSSCRIPTHASH", - reqSigs: 1, - addresses: [ - "tb1qs63s8nwjut4tr5t8nudgzwp4m3dpkefjzpmumn90pruce0cye2tq2jkq0y", - ], - }, + scriptPubKey: Hex.from( + "002086a303cdd2e2eab1d1679f1a813835dc5a1b65321077cdccaf08f98cbf04ca96" + ), }, { outputIndex: 4, value: BigNumber.from(1375180), - scriptPubKey: { - asm: "OP_0 8db50eb52063ea9d98b3eac91489a90f738986f6", - hex: "00148db50eb52063ea9d98b3eac91489a90f738986f6", - type: "WITNESSPUBKEYHASH", - reqSigs: 1, - addresses: ["tb1q3k6sadfqv04fmx9naty3fzdfpaecnphkfm3cf3"], - }, + scriptPubKey: Hex.from( + "00148db50eb52063ea9d98b3eac91489a90f738986f6" + ), }, ], }, From a56ba9f199da924346134c6da78c3be58ce31d0f Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Wed, 25 Jan 2023 23:18:42 +0100 Subject: [PATCH 6/7] Enable Electrum tests The servers are working now, so we can try enabling the tests. We still need to work on stable results for electrs-esplora server. --- typescript/test/electrum.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typescript/test/electrum.test.ts b/typescript/test/electrum.test.ts index a54f47dee..3c1acefd9 100644 --- a/typescript/test/electrum.test.ts +++ b/typescript/test/electrum.test.ts @@ -50,7 +50,7 @@ const testnetCredentials: ElectrumCredentials[] = [ * out of scope of this suite. The `broadcast` function was tested manually * though. */ -describe.skip("Electrum", () => { +describe("Electrum", () => { testnetCredentials.forEach((credentials) => { describe(`${credentials.protocol}://${credentials.host}:${credentials.port}`, async () => { let electrumClient: ElectrumClient From 4bc9085430a834642fe1682d74d73879c741b8a5 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Thu, 26 Jan 2023 00:04:23 +0100 Subject: [PATCH 7/7] Add electrs-esplora tcp server for tests --- typescript/test/electrum.test.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/typescript/test/electrum.test.ts b/typescript/test/electrum.test.ts index 3c1acefd9..a0aee36c4 100644 --- a/typescript/test/electrum.test.ts +++ b/typescript/test/electrum.test.ts @@ -24,6 +24,12 @@ const testnetCredentials: ElectrumCredentials[] = [ }, // TODO: Enable after retries are implemented // See: https://github.com/keep-network/tbtc-v2/issues/485 + // // electrs-esplora tcp + // { + // host: "electrum.blockstream.info", + // port: 60001, + // protocol: "tcp", + // }, // // electrs-esplora ssl // { // host: "electrum.blockstream.info",