Skip to content

Commit

Permalink
refactor: use mutex instead of locking
Browse files Browse the repository at this point in the history
  • Loading branch information
j4m1ef0rd committed Nov 25, 2024
1 parent c2b1ad4 commit 1714311
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 46 deletions.
67 changes: 49 additions & 18 deletions bouncer/shared/send_btc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,32 +12,63 @@ export const btcClient = new Client({
});

export async function selectInputs(amount: number) {
return btcClientMutex.runExclusive(async () => {
// List unspent UTXOs
const utxos = await btcClient.listUnspent();
// List unspent UTXOs
const utxos = await btcClient.listUnspent();

// Find a UTXO with enough funds
const utxo = utxos.find((u) => u.amount >= amount);
if (!utxo) throw new Error('Insufficient funds');
// TODO: be able to select more than one UTXO

const change = utxo.amount - amount;

// Find a UTXO with enough funds
const utxo = utxos.find((u) => u.amount >= amount);
if (!utxo) throw new Error('Insufficient funds');
// TODO: be able to select more than one UTXO
// Prepare the transaction inputs
const inputs = [
{
txid: utxo.txid,
vout: utxo.vout,
},
];

// Lock the selected UTXO to prevent it from being used in another transaction
await btcClient.lockUnspent(false, [{ txid: utxo.txid, vout: utxo.vout }]);
return {
inputs,
change,
};
}

export async function sendVaultTransaction(
nulldataUtxo: string,
amountBtc: number,
depositAddress: string,
refundAddress: string,
) {
return btcClientMutex.runExclusive(async () => {
const feeBtc = 0.00001;
const { inputs, change } = await selectInputs(Number(amountBtc) + feeBtc);

const change = utxo.amount - amount;
// The `createRawTransaction` function will add the op codes, so we have to remove them here.
const nullDataWithoutOpCodes = nulldataUtxo.replace('0x', '').substring(4);

// Prepare the transaction inputs
const inputs = [
const outputs = [
{
txid: utxo.txid,
vout: utxo.vout,
[depositAddress]: amountBtc,
},
{
data: nullDataWithoutOpCodes,
},
{
[refundAddress]: change,
},
];

return {
inputs,
change,
};
const rawTx = await btcClient.createRawTransaction(inputs, outputs, 0, false);
const signedTx = await btcClient.signRawTransactionWithWallet(rawTx);
const txid = await btcClient.sendRawTransaction(signedTx.hex);

if (!txid) {
throw new Error('Broadcast failed');
}
return txid as string;
});
}

Expand Down
35 changes: 7 additions & 28 deletions bouncer/tests/btc_vault_swap.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import assert from 'assert';
import { ExecutableTest } from '../shared/executable_test';
import { BTC_ENDPOINT, selectInputs, waitForBtcTransaction, btcClient } from '../shared/send_btc';
import { BTC_ENDPOINT, waitForBtcTransaction, sendVaultTransaction } from '../shared/send_btc';
import {
amountToFineAmount,
Asset,
assetDecimals,
btcClientMutex,
createStateChainKeypair,
newAddress,
observeBalanceIncrease,
Expand Down Expand Up @@ -36,9 +35,6 @@ async function buildAndSendBtcVaultSwap(
testBtcVaultSwap.debugLog('Broker:', broker.address);
testBtcVaultSwap.debugLog(`Btc endpoint is set to`, BTC_ENDPOINT);

const feeBtc = 0.00001;
const { inputs, change } = await selectInputs(Number(depositAmountBtc) + feeBtc);

const vaultSwapDetails = (await chainflip.rpc(
`cf_get_vault_swap_details`,
broker.address,
Expand All @@ -54,32 +50,15 @@ async function buildAndSendBtcVaultSwap(
testBtcVaultSwap.debugLog('nulldata_utxo:', vaultSwapDetails.nulldata_utxo);
testBtcVaultSwap.debugLog('deposit_address:', vaultSwapDetails.deposit_address);

// The `createRawTransaction` function will add the op codes, so we have to remove them here.
const nullDataWithoutOpCodes = vaultSwapDetails.nulldata_utxo.replace('0x', '').substring(4);

const outputs = [
{
[vaultSwapDetails.deposit_address]: depositAmountBtc,
},
{
data: nullDataWithoutOpCodes,
},
{
[refundAddress]: change,
},
];

const rawTx = await btcClient.createRawTransaction(inputs, outputs, 0, false);
const signedTx = await btcClient.signRawTransactionWithWallet(rawTx);
const txid = await btcClientMutex.runExclusive(async () =>
btcClient.sendRawTransaction(signedTx.hex),
const txid = await sendVaultTransaction(
vaultSwapDetails.nulldata_utxo,
depositAmountBtc,
vaultSwapDetails.deposit_address,
refundAddress,
);
if (!txid) {
throw new Error('Broadcast failed');
}
testBtcVaultSwap.log('Broadcast successful, txid:', txid);

await waitForBtcTransaction(txid as string);
await waitForBtcTransaction(txid);
testBtcVaultSwap.debugLog('Transaction confirmed');
}

Expand Down

0 comments on commit 1714311

Please sign in to comment.