Skip to content

Commit

Permalink
pr fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
bdemann committed May 16, 2024
1 parent 723b5fe commit 6f8b0f9
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 49 deletions.
2 changes: 1 addition & 1 deletion examples/basic_bitcoin/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"scripts": {
"install": "./scripts/install.sh",
"pretest": "BITCOIN_NETWORK=regtest ts-node --transpile-only --ignore=false test/pretest.ts",
"pretest": "ts-node --transpile-only --ignore=false test/pretest.ts",
"test": "ts-node --transpile-only --ignore=false test/test.ts"
},
"dependencies": {
Expand Down
14 changes: 5 additions & 9 deletions examples/basic_bitcoin/src/bitcoin_wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ async function buildTransaction(
let totalFee = 0n;
// eslint-disable-next-line no-constant-condition
while (true) {
let transaction = buildTransactionWithFee(
const transaction = buildTransactionWithFee(
ownUtxos,
ownAddress,
dstAddress,
Expand Down Expand Up @@ -206,13 +206,13 @@ function buildTransactionWithFee(
);
}

const remainingAmount = totalSpent - amount - fee;

transaction.addOutput(
createScriptPubkey(destAddress, network),
Number(amount)
);

const remainingAmount = totalSpent - amount - fee;

if (remainingAmount >= dustThreshold) {
transaction.addOutput(
createScriptPubkey(ownAddress, network),
Expand Down Expand Up @@ -294,12 +294,8 @@ function mockSigner(
_derivationPath: Uint8Array[],
_messageHash: Uint8Array
): Uint8Array {
let array = new Uint8Array(64);
// bitcoin.script.signature.encode threw away most of the signature when it was all 0's so we need to fill it up with something
for (let i = 0; i < 64; i++) {
array[i] = i + 1;
}
return array;
// bitcoin.script.signature.encode threw away most of the signature when it was all 0's so we need to fill it up with anything besides just 0s
return Uint8Array.from(new Array(64).fill(1));
}

export function determineNetwork(network: BitcoinNetwork): Network {
Expand Down
12 changes: 3 additions & 9 deletions examples/basic_bitcoin/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,6 @@ const app = express();

app.use(express.json());

app.get('/', (req, res) => {
res.send(
`Network: ${NETWORK}, KeyName: ${KEY_NAME}, DerivationPath: ${DERIVATION_PATH}`
);
});

/// Returns the balance of the given bitcoin address.
app.get(
'/get-balance',
Expand Down Expand Up @@ -90,11 +84,11 @@ app.post('/send', async (req, res) => {
app.listen();

function determineKeyName(network: BitcoinNetwork): string {
if (network.mainnet !== undefined) {
if (network.mainnet === null) {
return 'test_key_1';
} else if (network.testnet !== undefined) {
} else if (network.testnet === null) {
return 'test_key_1';
} else if (network.regtest !== undefined) {
} else if (network.regtest === null) {
return 'dfx_test_key';
}
throw new Error('Invalid Bitcoin Network');
Expand Down
6 changes: 0 additions & 6 deletions examples/basic_bitcoin/test/bitcoin.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
import { Transaction } from 'bitcoinjs-lib';
import { execSync } from 'child_process';

export function getTotalOutput(tx: Transaction): number {
return tx.outs.reduce((total, output) => {
return total + output.value;
}, 0);
}

export function generateToAddress(address: string, blocks: number) {
execSync(
`.bitcoin/bin/bitcoin-cli -conf=$(pwd)/.bitcoin.conf generatetoaddress ${blocks} ${address}`
Expand Down
2 changes: 1 addition & 1 deletion examples/basic_bitcoin/test/pretest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ async function pretest() {
stdio: 'inherit'
});

execSync(`dfx deploy`, {
execSync(`BITCOIN_NETWORK=regtest dfx deploy`, {
stdio: 'inherit'
});
}
Expand Down
1 change: 1 addition & 0 deletions examples/basic_bitcoin/test/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ async function startBitcoinDaemon(): Promise<ChildProcessWithoutNullStreams> {
});

console.info(`starting bitcoind...`);
// This await is necessary to ensure the daemon is running
await new Promise((resolve) => setTimeout(resolve, 5000));
return bitcoinDaemon;
}
Expand Down
53 changes: 30 additions & 23 deletions examples/basic_bitcoin/test/tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,23 @@ dns.setDefaultResultOrder('ipv4first');
import { jsonParse, jsonStringify } from 'azle';
import { GetUtxosResult, Utxo } from 'azle/canisters/management';
import { AzleResult, Test } from 'azle/test';
import { Transaction } from 'bitcoinjs-lib';

import {
createWallet,
generate,
generateToAddress,
getMempoolCount,
getTotalOutput,
getTransaction
} from './bitcoin';

const SINGLE_BLOCK_REWARD = 5_000_000_000n;
const FIRST_MINING_SESSION = 101;
const FIRST_AMOUNT_SENT = SINGLE_BLOCK_REWARD / 2n;
const SECOND_AMOUNT_SENT = SINGLE_BLOCK_REWARD * 2n;
const TO_ADDRESS = 'n4HY51WrdxATGEPqYvoNkEsTteRfuRMxpD'; // Regtest address from this WIF L3BybjkmnMdXE6iNEaeZTjVMTHA4TvpYbQozc264Lto9yVDis2nv
const TO_ADDRESS = 'n4HY51WrdxATGEPqYvoNkEsTteRfuRMxpD';

let lastTx = '';
let lastTxid = '';
let toAddressPreviousBalance = 0n;
let canisterPreviousBalance = 0n;

Expand Down Expand Up @@ -58,7 +58,7 @@ export function getTests(canisterId: string): Test[] {
generateToAddress(address, FIRST_MINING_SESSION);
}
},
{ name: 'wait for blocks to settle', wait: 60_000 },
{ name: 'wait for blocks to settle', wait: 30_000 },
{
name: '/get-balance',
test: async () => {
Expand Down Expand Up @@ -102,20 +102,20 @@ export function getTests(canisterId: string): Test[] {

const feePercentiles = jsonParse(await response.text());

// Though blocks are mined no transaction have happened yet so the list should still be empty
// Though blocks are mined no transactions have happened yet so the list should still be empty
return { Ok: feePercentiles.length === 0 };
}
},
{
name: '/get-balance of L3BybjkmnMdXE6iNEaeZTjVMTHA4TvpYbQozc264Lto9yVDis2nv',
name: `/get-balance of ${TO_ADDRESS}`,
test: async () => {
const balance = await getBalance(origin, TO_ADDRESS);

return compareBalances(0n, balance);
}
},
{
name: '/send from canister to L3BybjkmnMdXE6iNEaeZTjVMTHA4TvpYbQozc264Lto9yVDis2nv',
name: `/send from canister to ${TO_ADDRESS}`,
prep: async () => {
const body = jsonStringify({
amountInSatoshi: FIRST_AMOUNT_SENT,
Expand All @@ -126,8 +126,8 @@ export function getTests(canisterId: string): Test[] {
headers: { 'Content-Type': 'application/json' },
body
});
lastTx = await response.text();
console.info(lastTx);
lastTxid = await response.text();
console.info(lastTxid);
}
},
{
Expand All @@ -142,7 +142,7 @@ export function getTests(canisterId: string): Test[] {
},
{ name: 'wait for blocks to settle', wait: 15_000 },
{
name: '/get-balance of L3BybjkmnMdXE6iNEaeZTjVMTHA4TvpYbQozc264Lto9yVDis2nv final',
name: `/get-balance of ${TO_ADDRESS} final`,
test: async () => {
const balance = await getBalance(origin, TO_ADDRESS);
toAddressPreviousBalance = balance;
Expand All @@ -157,12 +157,12 @@ export function getTests(canisterId: string): Test[] {
const balance = await getBalance(origin, address);
canisterPreviousBalance = balance;

// The expected balance of the canister's wallet is:
// all of it's total block mining rewards - the amount sent in the first transaction - the fee

// At the time this transaction was made, the canister only had utxos from block rewards.
// The amount sent and the fee was less than the reward from minting a single block so there will be only one input and it will have the value of that reward.
const fee = getFeeFromTransaction(lastTx, SINGLE_BLOCK_REWARD);
const fee = getFeeFromTransaction(
lastTxid,
SINGLE_BLOCK_REWARD
);

const blockRewards =
SINGLE_BLOCK_REWARD * BigInt(FIRST_MINING_SESSION);
Expand All @@ -188,14 +188,13 @@ export function getTests(canisterId: string): Test[] {
}
},
{
name: 'mine a block for the latest transaction',
name: 'Generate blocks to ensure that enough of the canisters block rewards are available to spend',
prep: async () => {
// Generate blocks to ensure that enough of the canisters block rewards are available to spend
generate(10);
}
},
{
name: '/send big from canister to L3BybjkmnMdXE6iNEaeZTjVMTHA4TvpYbQozc264Lto9yVDis2nv',
name: `/send big from canister to ${TO_ADDRESS}`,
prep: async () => {
const body = jsonStringify({
amountInSatoshi: SECOND_AMOUNT_SENT,
Expand All @@ -206,8 +205,8 @@ export function getTests(canisterId: string): Test[] {
headers: { 'Content-Type': 'application/json' },
body
});
lastTx = await response.text();
console.info(lastTx);
lastTxid = await response.text();
console.info(lastTxid);
}
},
{
Expand All @@ -222,7 +221,7 @@ export function getTests(canisterId: string): Test[] {
},
{ name: 'wait for blocks to settle', wait: 15_000 },
{
name: '/get-balance of L3BybjkmnMdXE6iNEaeZTjVMTHA4TvpYbQozc264Lto9yVDis2nv big',
name: `/get-balance of ${TO_ADDRESS} big`,
test: async () => {
const balance = await getBalance(origin, TO_ADDRESS);
const expectedBalance =
Expand All @@ -237,8 +236,10 @@ export function getTests(canisterId: string): Test[] {
const address = await getP2pkhAddress(origin);
const balance = await getBalance(origin, address);

// At the time this transaction was made, the next utxos to use will be from block rewards.
// The amount sent and the fee were more than the reward from minting two blocks so there will be three inputs and it will have the value of those rewards.
const fee = getFeeFromTransaction(
lastTx,
lastTxid,
SINGLE_BLOCK_REWARD * 3n
);

Expand All @@ -264,7 +265,7 @@ export function getTests(canisterId: string): Test[] {
}
},
{
name: 'mine a block to see if resets the fee percentiles',
name: 'mine a block to see if it resets the fee percentiles',
prep: async () => {
generate(1);
}
Expand Down Expand Up @@ -301,7 +302,7 @@ function compareBalances(

/**
* The fee is determined by finding the difference between the total value of the inputs minus the total value of the outputs
* The value of the outputs is easily found by looking the transaction with the provided txid
* The value of the outputs is easily found by looking at the transaction with the provided txid
* The value of the inputs is not easily calculated automatically and must be provided
* @param txid
* @param totalInputValue
Expand All @@ -313,6 +314,12 @@ function getFeeFromTransaction(txid: string, totalInputValue: bigint): bigint {
return totalInputValue - outputValue;
}

function getTotalOutput(tx: Transaction): number {
return tx.outs.reduce((total, output) => {
return total + output.value;
}, 0);
}

async function getP2pkhAddress(origin: string): Promise<string> {
const response = await fetch(`${origin}/get-p2pkh-address`, {
headers: [['X-Ic-Force-Update', 'true']]
Expand Down

0 comments on commit 6f8b0f9

Please sign in to comment.