diff --git a/typescript/src/lib/bitcoin/ecdsa-key.ts b/typescript/src/lib/bitcoin/ecdsa-key.ts index 8ffbd9955..39de4e173 100644 --- a/typescript/src/lib/bitcoin/ecdsa-key.ts +++ b/typescript/src/lib/bitcoin/ecdsa-key.ts @@ -9,7 +9,13 @@ 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: string | Hex): boolean { + if (typeof publicKey === "string") { + publicKey = Hex.from(publicKey) + } + + publicKey = publicKey.toString() + // Must have 33 bytes and 02 or 03 prefix. return ( publicKey.length == 66 && diff --git a/typescript/src/lib/ethereum/bridge.ts b/typescript/src/lib/ethereum/bridge.ts index 25f059a0f..92dcbed73 100644 --- a/typescript/src/lib/ethereum/bridge.ts +++ b/typescript/src/lib/ethereum/bridge.ts @@ -196,7 +196,7 @@ export class EthereumBridge ["bytes32", "bytes20"], [ utils.solidityKeccak256(["bytes"], [prefixedRawRedeemerOutputScript]), - `0x${walletPublicKeyHash}`, + `0x${walletPublicKeyHash.toString()}`, ] ) } diff --git a/typescript/src/services/deposits/refund.ts b/typescript/src/services/deposits/refund.ts index be678b63c..ef9a4227b 100644 --- a/typescript/src/services/deposits/refund.ts +++ b/typescript/src/services/deposits/refund.ts @@ -189,10 +189,10 @@ 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(Hex.from(refunderPublicKey)).equals( + !BitcoinHashUtils.computeHash160(refunderPublicKey).equals( this.script.receipt.refundPublicKeyHash ) ) { diff --git a/typescript/src/services/maintenance/spv.ts b/typescript/src/services/maintenance/spv.ts index 8f546330e..3dbd8341e 100644 --- a/typescript/src/services/maintenance/spv.ts +++ b/typescript/src/services/maintenance/spv.ts @@ -67,7 +67,7 @@ export class Spv { async submitRedemptionProof( transactionHash: BitcoinTxHash, mainUtxo: BitcoinUtxo, - walletPublicKey: string + walletPublicKey: Hex ): Promise { const confirmations = await this.tbtcContracts.bridge.txProofDifficultyFactor() @@ -85,7 +85,7 @@ export class Spv { rawTransactionVectors, proof, mainUtxo, - Hex.from(walletPublicKey) + walletPublicKey ) } } diff --git a/typescript/src/services/maintenance/wallet-tx.ts b/typescript/src/services/maintenance/wallet-tx.ts index dcf838a4d..595a19171 100644 --- a/typescript/src/services/maintenance/wallet-tx.ts +++ b/typescript/src/services/maintenance/wallet-tx.ts @@ -470,10 +470,10 @@ class DepositSweep { previousOutputValue: number, walletKeyPair: Signer ): Promise { - const walletPublicKey = walletKeyPair.publicKey.toString("hex") + const walletPublicKey = Hex.from(walletKeyPair.publicKey) if ( - !BitcoinHashUtils.computeHash160(Hex.from(walletPublicKey)).equals( + !BitcoinHashUtils.computeHash160(walletPublicKey).equals( deposit.walletPublicKeyHash ) ) { @@ -547,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. @@ -556,7 +556,7 @@ class Redemption { async submitTransaction( walletPrivateKey: string, mainUtxo: BitcoinUtxo, - redeemerOutputScripts: string[] + redeemerOutputScripts: Hex[] ): Promise<{ transactionHash: BitcoinTxHash newMainUtxo?: BitcoinUtxo @@ -577,15 +577,15 @@ class Redemption { bitcoinNetwork ) - const walletPublicKey = walletKeyPair.publicKey.toString("hex") + const walletPublicKey = Hex.from(walletKeyPair.publicKey) const redemptionRequests: RedemptionRequest[] = [] for (const redeemerOutputScript of redeemerOutputScripts) { const redemptionRequest = await this.tbtcContracts.bridge.pendingRedemptions( - Hex.from(walletPublicKey), - Hex.from(redeemerOutputScript) + walletPublicKey, + redeemerOutputScript ) if (redemptionRequest.requestedAt == 0) { @@ -594,7 +594,7 @@ class Redemption { redemptionRequests.push({ ...redemptionRequest, - redeemerOutputScript: Hex.from(redeemerOutputScript), + redeemerOutputScript, }) } diff --git a/typescript/src/services/redemptions/redemptions-service.ts b/typescript/src/services/redemptions/redemptions-service.ts index 74b10b680..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. @@ -66,9 +66,9 @@ export class RedemptionsService { ) const txHash = await this.tbtcContracts.tbtcToken.requestRedemption( - Hex.from(walletPublicKey), + walletPublicKey, mainUtxo, - Hex.from(redeemerOutputScript), + redeemerOutputScript, amount ) @@ -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 @@ -141,7 +140,7 @@ export class RedemptionsService { const pendingRedemption = await this.tbtcContracts.bridge.pendingRedemptions( walletPublicKey, - Hex.from(redeemerOutputScript) + redeemerOutputScript ) if (pendingRedemption.requestedAt != 0) { @@ -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, } @@ -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() @@ -345,14 +344,14 @@ export class RedemptionsService { switch (type) { case "pending": { redemptionRequest = await this.tbtcContracts.bridge.pendingRedemptions( - Hex.from(walletPublicKey), + walletPublicKey, redeemerOutputScript ) break } case "timedOut": { redemptionRequest = await this.tbtcContracts.bridge.timedOutRedemptions( - Hex.from(walletPublicKey), + walletPublicKey, redeemerOutputScript ) break diff --git a/typescript/test/services/maintenance.test.ts b/typescript/test/services/maintenance.test.ts index 3fabe2036..cbca52a78 100644 --- a/typescript/test/services/maintenance.test.ts +++ b/typescript/test/services/maintenance.test.ts @@ -1450,7 +1450,7 @@ describe("Maintenance", () => { it("should revert", async () => { const redeemerOutputScripts = data.pendingRedemptions.map( (redemption) => - redemption.pendingRedemption.redeemerOutputScript.toString() + redemption.pendingRedemption.redeemerOutputScript ) const walletTx = new WalletTx( @@ -2533,7 +2533,7 @@ describe("Maintenance", () => { await maintenanceService.spv.submitRedemptionProof( transactionHash, mainUtxo, - walletPublicKey.toString() + walletPublicKey ) }) diff --git a/typescript/test/services/redemptions.test.ts b/typescript/test/services/redemptions.test.ts index 1a974b9e4..c8dbd7344 100644 --- a/typescript/test/services/redemptions.test.ts +++ b/typescript/test/services/redemptions.test.ts @@ -155,7 +155,7 @@ describe("Redemptions", () => { redemptionRequest.redeemerOutputScript, BitcoinNetwork.Testnet ), - walletPublicKey.toString(), + walletPublicKey, "pending" ) @@ -193,7 +193,7 @@ describe("Redemptions", () => { redemptionRequest.redeemerOutputScript, BitcoinNetwork.Testnet ), - walletPublicKey.toString(), + walletPublicKey, "timedOut" ) @@ -205,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) @@ -220,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", @@ -326,7 +327,7 @@ describe("Redemptions", () => { findWalletForRedemptionData.walletWithPendingRedemption.data expect(result).to.deep.eq({ - walletPublicKey: expectedWalletData.walletPublicKey.toString(), + walletPublicKey: expectedWalletData.walletPublicKey, mainUtxo: expectedWalletData.mainUtxo, }) }) @@ -386,7 +387,7 @@ describe("Redemptions", () => { tbtcContracts.bridge.setPendingRedemptions(pendingRedemptions) result = await redemptionsService.findWalletForRedemption( - redeemerOutputScript.toString(), + redeemerOutputScript, amount ) }) @@ -407,7 +408,7 @@ describe("Redemptions", () => { findWalletForRedemptionData.liveWallet.data expect(result).to.deep.eq({ - walletPublicKey: expectedWalletData.walletPublicKey.toString(), + walletPublicKey: expectedWalletData.walletPublicKey, mainUtxo: expectedWalletData.mainUtxo, }) }) @@ -439,7 +440,7 @@ describe("Redemptions", () => { findWalletForRedemptionData.liveWallet.data expect(result).to.deep.eq({ - walletPublicKey: expectedWalletData.walletPublicKey.toString(), + walletPublicKey: expectedWalletData.walletPublicKey, mainUtxo: expectedWalletData.mainUtxo, }) }) @@ -488,7 +489,7 @@ describe("Redemptions", () => { it("should throw an error", async () => { await expect( redemptionsService.findWalletForRedemption( - redeemerOutputScript.toString(), + redeemerOutputScript, amount ) ).to.be.rejectedWith( @@ -824,8 +825,8 @@ export async function runRedemptionScenario( ) ) - const redeemerOutputScripts = data.pendingRedemptions.map((redemption) => - redemption.pendingRedemption.redeemerOutputScript.toString() + const redeemerOutputScripts = data.pendingRedemptions.map( + (redemption) => redemption.pendingRedemption.redeemerOutputScript ) const walletTx = new WalletTx(tbtcContracts, bitcoinClient, data.witness)