Add sat_to_btc() and conversely btc_to_sat() util functions in functional tests #31345

issue rkrux openend this issue on November 22, 2024
  1. rkrux commented at 12:01 pm on November 22, 2024: none

    Motivation

    In functional tests, there are numerous instances of conversion code with patterns such as / COIN and * COIN that are converting between units satoshis to BTC.

    Following details are as of the latest commit on master 2638fdb4f934be96b7c798dbac38ea5ab8a6374a.

    Patterns stats

    0# satoshis to BTC conversion
    1➜  bitcoin git:(2638fdb4f9) ✗ git grep -n "/ COIN" -- '*.py' | wc -l
    2      22
    3
    4# BTC to satoshis conversion
    5➜  bitcoin git:(2638fdb4f9) ✗ git grep -n "* COIN" -- '*.py' | wc -l
    6     127
    

    Satoshis to BTC conversion instances

     0test/functional/feature_fee_estimation.py:128:        fee_rate=Decimal(feerate * 1000) / COIN,
     1test/functional/feature_fee_estimation.py:301:        high_feerate_kvb = Decimal(high_feerate) / COIN * 10 ** 3
     2test/functional/feature_rbf.py:211:            fee=(Decimal(fee) / COIN) * n,
     3test/functional/feature_rbf.py:220:            fee=(Decimal(fee) / COIN) * n + Decimal("0.1"),
     4test/functional/feature_rbf.py:240:                fee=2 * (Decimal(fee) / COIN) * n,
     5test/functional/feature_rbf.py:356:                fee=Decimal(fee) / COIN,
     6test/functional/interface_usdt_mempool.py:172:        tx = self.wallet.send_self_transfer(from_node=node, fee=fee / COIN)
     7test/functional/interface_usdt_mempool.py:209:        tx = self.wallet.send_self_transfer(from_node=node, fee=fee / COIN)
     8test/functional/interface_usdt_mempool.py:258:            from_node=node, utxo_to_spend=utxo, fee=original_fee / COIN
     9test/functional/interface_usdt_mempool.py:265:            from_node=node, utxo_to_spend=utxo, fee=replacement_fee / COIN
    10test/functional/mempool_ephemeral_dust.py:39:        result["new_utxos"][0]["value"] = Decimal(result["tx"].vout[0].nValue) / COIN
    11test/functional/mempool_ephemeral_dust.py:48:        result["new_utxos"].append({"txid": new_txid, "vout": len(result["tx"].vout) - 1, "value": Decimal(output_value) / COIN, "height": 0, "coinbase": False, "confirmations": 0})
    12test/functional/mempool_package_rbf.py:166:        incremental_sats_required = Decimal(package_3_size) / COIN
    13test/functional/mining_prioritisetransaction.py:97:        fee_delta_b = Decimal(9999) / COIN
    14test/functional/mining_prioritisetransaction.py:98:        fee_delta_c_1 = Decimal(-1234) / COIN
    15test/functional/mining_prioritisetransaction.py:99:        fee_delta_c_2 = Decimal(8888) / COIN
    16test/functional/p2p_ibd_txrelay.py:31:MAX_FEE_FILTER = Decimal(9170997) / COIN
    17test/functional/p2p_ibd_txrelay.py:32:NORMAL_FEE_FILTER = Decimal(100) / COIN
    18test/functional/test_framework/messages.py:492:            % (self.nValue // COIN, self.nValue % COIN,
    19test/functional/test_framework/wallet.py:326:        fee = Decimal(inputs_value_total - outputs_value_total) / COIN
    20test/functional/test_framework/wallet.py:345:                value=Decimal(tx.vout[i].nValue) / COIN,
    21test/functional/wallet_import_rescan.py:280:            variant.initial_amount = get_rand_amount(min_amount=((500 * 20 / COIN) + AMOUNT_DUST))
    

    BTC to Satoshis conversion instances

      0test/functional/feature_bip68_sequence.py:94:        value = int((utxo["value"] - self.relayfee) * COIN)
      1test/functional/feature_bip68_sequence.py:115:        tx2.vout = [CTxOut(int(value - self.relayfee * COIN), SCRIPT_W0_SH_OP_TRUE)]
      2test/functional/feature_bip68_sequence.py:203:            tx.vout.append(CTxOut(int(value - self.relayfee * tx_size * COIN / 1000), SCRIPT_W0_SH_OP_TRUE))
      3test/functional/feature_bip68_sequence.py:233:        tx2.vout = [CTxOut(int(tx1.vout[0].nValue - self.relayfee * COIN), SCRIPT_W0_SH_OP_TRUE)]
      4test/functional/feature_bip68_sequence.py:253:            tx.vout = [CTxOut(int(orig_tx.vout[0].nValue - relayfee * COIN), SCRIPT_W0_SH_OP_TRUE)]
      5test/functional/feature_bip68_sequence.py:365:        tx2.vout = [CTxOut(int(tx1.vout[0].nValue - self.relayfee * COIN), SCRIPT_W0_SH_OP_TRUE)]
      6test/functional/feature_bip68_sequence.py:383:        tx3.vout = [CTxOut(int(tx2.vout[0].nValue - self.relayfee * COIN), SCRIPT_W0_SH_OP_TRUE)]
      7test/functional/feature_block.py:812:        tx = self.create_and_sign_transaction(out[17], 51 * COIN)
      8test/functional/feature_block.py:1162:        tx77 = self.create_and_sign_transaction(out[24], 10 * COIN)
      9test/functional/feature_block.py:1168:        tx78 = self.create_tx(tx77, 0, 9 * COIN)
     10test/functional/feature_block.py:1173:        tx79 = self.create_tx(tx78, 0, 8 * COIN)
     11test/functional/feature_coinstatsindex.py:155:            amount=21 * COIN,
     12test/functional/feature_coinstatsindex.py:164:        tx2.vout = [CTxOut(int(Decimal(tx2_val) * COIN), CScript([OP_RETURN] + [OP_FALSE] * 30))]
     13test/functional/feature_coinstatsindex.py:192:        cb.vout.append(CTxOut(5 * COIN, CScript([OP_FALSE])))
     14test/functional/feature_dbcrash.py:192:            input_amount = int(sum([utxo['value'] for utxo in utxos_to_spend]) * COIN)
     15test/functional/feature_fee_estimation.py:60:    tx.vout[0].nValue = int((total_in - amount - fee) * COIN)
     16test/functional/feature_fee_estimation.py:62:    tx.vout[1].nValue = int(amount * COIN)
     17test/functional/feature_rbf.py:116:        tx.vout[0].nValue -= int(0.1 * COIN)
     18test/functional/feature_rbf.py:131:        initial_nValue = 5 * COIN
     19test/functional/feature_rbf.py:137:        while remaining_value > 1 * COIN:
     20test/functional/feature_rbf.py:138:            remaining_value -= int(0.1 * COIN)
     21test/functional/feature_rbf.py:160:        dbl_tx.vout[0].nValue = int(0.1 * COIN)
     22test/functional/feature_rbf.py:171:        initial_nValue = 5 * COIN
     23test/functional/feature_rbf.py:174:        def branch(prevout, initial_value, max_txs, tree_width=5, fee=0.00001 * COIN, _total_txs=None):
     24test/functional/feature_rbf.py:202:        fee = int(0.00001 * COIN)
     25test/functional/feature_rbf.py:232:            fee = int(0.00001 * COIN)
     26test/functional/feature_rbf.py:250:        tx0_outpoint = self.make_utxo(self.nodes[0], int(1.1 * COIN))
     27test/functional/feature_rbf.py:273:        utxo1 = self.make_utxo(self.nodes[0], int(1.2 * COIN))
     28test/functional/feature_rbf.py:274:        utxo2 = self.make_utxo(self.nodes[0], 3 * COIN)
     29test/functional/feature_rbf.py:312:        confirmed_utxo = self.make_utxo(self.nodes[0], int(1.1 * COIN))
     30test/functional/feature_rbf.py:313:        unconfirmed_utxo = self.make_utxo(self.nodes[0], int(0.1 * COIN), confirmed=False)
     31test/functional/feature_rbf.py:325:            amount_per_output=1 * COIN,
     32test/functional/feature_rbf.py:337:        initial_nValue = 10 * COIN
     33test/functional/feature_rbf.py:339:        fee = int(0.0001 * COIN)
     34test/functional/feature_rbf.py:466:        tx0_outpoint = self.make_utxo(self.nodes[0], int(1.1 * COIN))
     35test/functional/feature_rbf.py:480:            amount_per_output=int(0.00001 * COIN),
     36test/functional/feature_rbf.py:487:        self.nodes[0].prioritisetransaction(txid=tx1a_txid, fee_delta=int(-0.1 * COIN))
     37test/functional/feature_rbf.py:495:        tx1_outpoint = self.make_utxo(self.nodes[0], int(1.1 * COIN))
     38test/functional/feature_rbf.py:516:        self.nodes[0].prioritisetransaction(txid=tx2b["txid"], fee_delta=int(0.1 * COIN))
     39test/functional/feature_rbf.py:557:        confirmed_utxo = self.make_utxo(self.nodes[0], int(2 * COIN))
     40test/functional/feature_segwit.py:279:        tx.vout.append(CTxOut(int(49.99 * COIN), CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE])))
     41test/functional/feature_segwit.py:295:        tx.vout.append(CTxOut(int(49.95 * COIN), CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE])))  # Huge fee
     42test/functional/interface_rest.py:99:        txid = self.wallet.send_to(from_node=self.nodes[0], scriptPubKey=getnewdestination()[1], amount=int(0.1
     43 * COIN))["txid"]
     44test/functional/interface_rest.py:176:        txid = self.wallet.send_to(from_node=self.nodes[0], scriptPubKey=getnewdestination()[1], amount=int(0.
     451 * COIN))["txid"]
     46test/functional/interface_usdt_utxocache.py:195:                assert_equal(50 * COIN, event.value)
     47test/functional/interface_usdt_utxocache.py:301:                        "value": int(prevout_tx["vout"][vin["vout"]]["value"] * COIN),
     48test/functional/interface_usdt_utxocache.py:310:                        "value": int(vout["value"] * COIN),
     49test/functional/mempool_accept.py:91:        tx.vout[0].nValue = int(0.3 * COIN)
     50test/functional/mempool_accept.py:92:        tx.vout[1].nValue = int(49 * COIN)
     51test/functional/mempool_accept.py:120:        tx.vout[0].nValue = int((Decimal('0.3') - fee) * COIN)
     52test/functional/mempool_accept.py:134:        tx.vout[0].nValue = int(output_amount * COIN)
     53test/functional/mempool_accept.py:156:        tx.vout[0].nValue -= int(fee * COIN)  # Double the fee
     54test/functional/mempool_accept.py:184:        tx.vout[0].nValue = int(0.1 * COIN)
     55test/functional/mempool_accept.py:202:        tx.vout[0].nValue = int(0.05 * COIN)
     56test/functional/mempool_accept_wtxid.py:59:        parent.vout.append(CTxOut(int(9.99998 * COIN), script_pubkey))
     57test/functional/mempool_accept_wtxid.py:76:        child_one.vout.append(CTxOut(int(9.99996 * COIN), child_script_pubkey))
     58test/functional/mempool_dust.py:53:            dust_threshold = int(get_fee(tx_size, dust_relay_fee) * COIN)
     59test/functional/mempool_limit.py:254:        cpfp_satoshis = int(cpfp_fee * COIN) + magic_satoshis
     60test/functional/mempool_limit.py:323:        child = self.wallet.create_self_transfer_multi(utxos_to_spend=parent_utxos, fee_per_output=int(cpfp_fee
     61 * COIN))
     62test/functional/mempool_limit.py:372:        node.prioritisetransaction(tx_rich["txid"], 0, int(DEFAULT_FEE * COIN))
     63test/functional/mempool_package_rbf.py:65:            fee_per_output=int(child_fee * COIN // num_child_outputs),
     64test/functional/mempool_package_rbf.py:281:            fee_per_output=int(DEFAULT_CHILD_FEE * COIN),
     65test/functional/mempool_package_rbf.py:314:            fee_per_output=int(DEFAULT_FEE * COIN),
     66test/functional/mempool_package_rbf.py:321:            fee_per_output=int(DEFAULT_FEE * COIN),
     67test/functional/mempool_package_rbf.py:367:            fee_per_output=int(DEFAULT_FEE * COIN),
     68test/functional/mempool_package_rbf.py:374:            fee_per_output=int(DEFAULT_FEE * COIN),
     69test/functional/mempool_package_rbf.py:412:            fee_per_output=int(DEFAULT_FEE * COIN),
     70test/functional/mempool_package_rbf.py:420:            fee_per_output=int(DEFAULT_FEE * COIN),
     71test/functional/mempool_package_rbf.py:427:            fee_per_output=int(DEFAULT_FEE * COIN),
     72test/functional/mempool_package_rbf.py:491:            fee_per_output=int(DEFAULT_CHILD_FEE * COIN),
     73test/functional/mempool_package_rbf.py:579:            fee_per_output=int(DEFAULT_CHILD_FEE * COIN),
     74test/functional/mempool_persist.py:233:        self.nodes[0].prioritisetransaction(tx_node01_secret["txid"], 0, 2 * COIN)
     75test/functional/mempool_persist.py:234:        self.nodes[1].prioritisetransaction(tx_node01_secret["txid"], 0, 3 * COIN)
     76test/functional/mempool_truc.py:551:        fee_to_beat = max(int(tx_v3_child_2["fee"] * COIN), int(tx_unrelated_replacee["fee"]*COIN))
     77test/functional/mining_prioritisetransaction.py:48:        assert_equal(self.nodes[0].getprioritisedtransactions(), { tx_replacee["txid"] : { "fee_d
     78elta" : 100, "in_mempool" : True, "modified_fee": int(tx_replacee["fee"] * COIN + 100)}})
     79test/functional/mining_prioritisetransaction.py:56:        assert_equal(self.nodes[0].getprioritisedtransactions(), { tx_replacee["txid"] : { "fee_d
     80elta" : COIN + 100, "in_mempool" : True, "modified_fee": int(tx_replacee["fee"] * COIN + COIN + 100)}})
     81test/functional/mining_prioritisetransaction.py:100:        self.nodes[0].prioritisetransaction(txid=txid_b, fee_delta=int(fee_delta_b * COIN))
     82test/functional/mining_prioritisetransaction.py:101:        self.nodes[0].prioritisetransaction(txid=txid_c, fee_delta=int(fee_delta_c_1 * COIN))
     83test/functional/mining_prioritisetransaction.py:102:        self.nodes[0].prioritisetransaction(txid=txid_c, fee_delta=int(fee_delta_c_2 * COIN))
     84test/functional/mining_prioritisetransaction.py:114:        assert_equal(self.nodes[0].getprioritisedtransactions(), {txid_b: {"fee_delta" : fee_del
     85ta_b*COIN, "in_mempool" : True, "modified_fee": int(fee_delta_b*COIN + COIN * tx_o_b["fee"])}, txid_c: {"fee_delta" : (fee_delta_c_1 + fee_delta_c_2
     86)*COIN, "in_mempool" : True, "modified_fee": int((fee_delta_c_1 + fee_delta_c_2 ) * COIN + COIN * tx_o_c["fee"])}})
     87test/functional/mining_prioritisetransaction.py:124:        self.nodes[0].prioritisetransaction(txid=txid_b, fee_delta=int(fee_delta_b * COIN))
     88test/functional/mining_prioritisetransaction.py:125:        self.nodes[0].prioritisetransaction(txid=txid_c, fee_delta=int(fee_delta_c_1 * COIN))
     89test/functional/mining_prioritisetransaction.py:126:        self.nodes[0].prioritisetransaction(txid=txid_c, fee_delta=int(fee_delta_c_2 * COIN))
     90test/functional/mining_prioritisetransaction.py:133:        assert_equal(self.nodes[0].getprioritisedtransactions(), {txid_b: {"fee_delta" : fee_del
     91ta_b*COIN, "in_mempool" : True, "modified_fee": int(fee_delta_b*COIN + COIN * tx_o_b["fee"])}, txid_c: {"fee_delta" : (fee_delta_c_1 + fee_delta_c_2
     92)*COIN, "in_mempool" : True, "modified_fee": int((fee_delta_c_1 + fee_delta_c_2 ) * COIN + COIN * tx_o_c["fee"])}})
     93test/functional/p2p_filter.py:141:        rel_txid = self.wallet.send_to(from_node=self.nodes[0], scriptPubKey=filter_peer.watch_script_pubkey, amou
     94nt=1 * COIN)["txid"]
     95test/functional/p2p_filter.py:142:        irr_result = self.wallet.send_to(from_node=self.nodes[0], scriptPubKey=getnewdestination()[1], amount=2 *
     96COIN)
     97test/functional/p2p_filter.py:160:        self.wallet.send_to(from_node=self.nodes[0], scriptPubKey=filter_peer.watch_script_pubkey, amount=9 * COIN
     98)
     99test/functional/p2p_filter.py:189:        self.wallet.send_to(from_node=self.nodes[0], scriptPubKey=getnewdestination()[1], amount=7 * COIN)
    100test/functional/p2p_filter.py:196:        txid = self.wallet.send_to(from_node=self.nodes[0], scriptPubKey=filter_peer.watch_script_pubkey, amount=9
    101 * COIN)["txid"]
    102test/functional/p2p_filter.py:203:            txid = self.wallet.send_to(from_node=self.nodes[0], scriptPubKey=getnewdestination()[1], amount=7 * CO
    103IN)["txid"]
    104test/functional/p2p_invalid_block.py:72:        tx1 = create_tx_with_script(block1.vtx[0], 0, script_sig=bytes([OP_TRUE]), amount=50 * COIN)
    105test/functional/p2p_invalid_block.py:73:        tx2 = create_tx_with_script(tx1, 0, script_sig=bytes([OP_TRUE]), amount=50 * COIN)
    106test/functional/p2p_invalid_block.py:120:        tx3 = create_tx_with_script(tx2, 0, script_sig=bytes([OP_TRUE]), amount=50 * COIN)
    107test/functional/p2p_invalid_tx.py:95:        tx_withhold.vout = [CTxOut(nValue=25 * COIN - 12000, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE)] * 2
    108test/functional/p2p_invalid_tx.py:101:        tx_orphan_1.vout = [CTxOut(nValue=8 * COIN, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE)] * 3
    109test/functional/p2p_invalid_tx.py:107:        tx_orphan_2_no_fee.vout.append(CTxOut(nValue=8 * COIN, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE))
    110test/functional/p2p_invalid_tx.py:112:        tx_orphan_2_valid.vout.append(CTxOut(nValue=8 * COIN - 12000, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE))
    111test/functional/p2p_invalid_tx.py:118:        tx_orphan_2_invalid.vout.append(CTxOut(nValue=11 * COIN, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE))
    112test/functional/p2p_invalid_tx.py:154:            orphan_tx_pool[i].vout.append(CTxOut(nValue=11 * COIN, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE))
    113test/functional/p2p_invalid_tx.py:162:        rejected_parent.vout.append(CTxOut(nValue=11 * COIN, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE))
    114test/functional/p2p_invalid_tx.py:174:        tx_withhold_until_block_A.vout = [CTxOut(nValue=12 * COIN, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE)] * 2
    115test/functional/p2p_invalid_tx.py:179:        tx_orphan_include_by_block_A.vout.append(CTxOut(nValue=12 * COIN - 12000, scriptPubKey=SCRIPT_PUB_KEY_
    116OP_TRUE))
    117test/functional/p2p_invalid_tx.py:199:        tx_withhold_until_block_B.vout.append(CTxOut(nValue=11 * COIN, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE))
    118test/functional/p2p_invalid_tx.py:204:        tx_orphan_include_by_block_B.vout.append(CTxOut(nValue=10 * COIN, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE)
    119)
    120test/functional/p2p_invalid_tx.py:209:        tx_orphan_conflict_by_block_B.vout.append(CTxOut(nValue=9 * COIN, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE)
    121)
    122test/functional/rpc_blockchain.py:679:        tx = create_tx_with_script(block.vtx[0], 0, script_sig=bytes([OP_TRUE]), amount=50 * COIN)
    123test/functional/rpc_createmultisig.py:159:        tx = self.wallet.send_to(from_node=self.nodes[0], scriptPubKey=spk, amount=int(value * COIN))
    124test/functional/rpc_packages.py:248:            fee_per_output=int(DEFAULT_FEE * 5 * COIN),
    125test/functional/rpc_rawtransaction.py:362:        tx.vout = [CTxOut(int(Decimal(tx_val) * COIN), CScript([OP_RETURN] + [OP_FALSE] * 30))]
    126test/functional/rpc_rawtransaction.py:369:        tx.vout = [CTxOut(int(Decimal(tx_val) * COIN), CScript([OP_FALSE] * 10001))]
    127test/functional/rpc_rawtransaction.py:376:        tx.vout = [CTxOut(int(Decimal(tx_val) * COIN), CScript([OP_INVALIDOPCODE]))]
    128test/functional/rpc_rawtransaction.py:383:        tx.vout = [CTxOut(int(Decimal(tx_val) * COIN), CScript([OP_RETURN] + [OP_FALSE] * 30))]
    129test/functional/rpc_rawtransaction.py:390:        tx.vout = [CTxOut(int(Decimal(tx_val) * COIN), CScript([OP_RETURN] + [OP_FALSE] * 30))]
    130test/functional/rpc_rawtransaction.py:397:        tx.vout = [CTxOut(int(Decimal(tx_val) * COIN), CScript([OP_RETURN] + [OP_FALSE] * 30))]
    131test/functional/rpc_scanblocks.py:34:        wallet.send_to(from_node=node, scriptPubKey=spk_1, amount=1 * COIN)
    132test/functional/rpc_scanblocks.py:41:                       amount=1 * COIN)
    133test/functional/rpc_signrawtransactionwithkey.py:53:        tx = self.wallet.send_to(from_node=self.nodes[0], scriptPubKey=script_pub_key, amount=in
    134t(amount * COIN))
    135test/functional/test_framework/blocktools.py:137:    coinbaseoutput.nValue = nValue * COIN
    136test/functional/test_framework/messages.py:40:MAX_MONEY = 21000000 * COIN
    137test/functional/test_framework/messages.py:665:            if tout.nValue < 0 or tout.nValue > 21000000 * COIN:
    138test/functional/wallet_assumeutxo.py:122:                self.mini_wallet.send_to(from_node=n0, scriptPubKey=w_skp, amount=1 * COIN)
    139test/functional/wallet_assumeutxo.py:123:                self.mini_wallet.send_to(from_node=n0, scriptPubKey=w2_skp, amount=10 * COIN)
    140test/functional/wallet_basic.py:817:            assert_equal(this_unspent['ancestorfees'], ancestor_fees * COIN)
    141test/functional/wallet_fundrawtransaction.py:167:        tx.vout = [CTxOut(1 * COIN, bytearray(address_to_scriptpubkey(address)))] * 2
    142test/functional/wallet_fundrawtransaction.py:1304:        assert_equal(fundedtx['fee'] * COIN, tx_size * 10)
    143test/functional/wallet_fundrawtransaction.py:1312:        assert_equal(fundedtx['fee'] * COIN, tx_size * 10)
    144test/functional/wallet_listtransactions.py:198:        tx3_b.vout[0].nValue -= int(Decimal("0.004") * COIN)  # bump the fee
    

    Possible solution

    A possible solution that has garnered some support is to add utility functions in the functional tests such as sat_to_btc() and conversely btc_to_sat() that can get rid of this repetitive inline conversion and make the testing code more readable.

    Prior discussion: #30079 (review)

    Useful Skills

    • Compiling Bitcoin Core from source
    • Running the C++ unit tests and the Python functional tests
    • Basic Python skills

    Guidance for new contributors

    Want to work on this issue?

    For guidance on contributing, please read CONTRIBUTING.md before opening your pull request.

  2. rkrux added the label good first issue on Nov 22, 2024
  3. rkrux renamed this:
    Add `satToBtc()` and conversely `btcToSat()` util functions in functional tests
    Add `sat_to_btc()` and conversely `btc_to_sat()` util functions in functional tests
    on Nov 25, 2024
  4. le0nAg commented at 11:03 am on December 2, 2024: none
    Could I take the issue?
  5. rkrux commented at 5:33 pm on December 2, 2024: none
    @le0nAg Thanks for showing interest in this, there is an open PR for it here: #31356 Maybe coordinate with @andremralves and work on the same PR?

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2024-12-03 21:12 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me