0
0
Fork 0
mirror of https://github.com/bitcoin/bitcoin.git synced 2025-02-03 09:56:38 -05:00

Merge bitcoin/bitcoin#27349: test: use address_to_scriptpubkey instead of RPC call

e47ce42f67 refactor: use address_to_scriptpubkey to retrieve addresses scriptpubkey (ismaelsadeeq)
4142d19d74 refactor: move address_to_scriptpubkey to address.py (ismaelsadeeq)

Pull request description:

  PR #27269 enables the function address_to_scriptpubkey() to decode all address types and return their corresponding scriptpubkeys. As a result, there is no longer any need to call getaddressinfo or validateaddress RPCs in order to retrieve an address scriptpubkey, as explained in the comments on this pull request (see https://github.com/bitcoin/bitcoin/pull/27269#pullrequestreview-1353681933 and https://github.com/bitcoin/bitcoin/pull/27269#issuecomment-1481016118).

  Instead of using RPC calls, this update replaces the process of obtaining an address scriptPubkey with the address_to_scriptpubkey method, resulting in improved performance for functional tests.

ACKs for top commit:
  josibake:
    re-ACK e47ce42f67
  theStack:
    ACK e47ce42f67 🌱

Tree-SHA512: 05285349a7d5ce7097b8f2582e573a5135c6deef85ea9936f68f6ce94e9ebb1d84d94f7fc7e5ed833a698e01585addd80deb52e6338f8aee985bf14db45417d2
This commit is contained in:
fanquake 2023-03-29 11:51:03 +01:00
commit c0311b1dda
No known key found for this signature in database
GPG key ID: 2EEB9F5CC09526C1
10 changed files with 38 additions and 29 deletions

View file

@ -14,6 +14,7 @@ Generate COINBASE_MATURITY (CB) more blocks to ensure the coinbases are mature.
""" """
import time import time
from test_framework.address import address_to_scriptpubkey
from test_framework.blocktools import ( from test_framework.blocktools import (
COINBASE_MATURITY, COINBASE_MATURITY,
NORMAL_GBT_REQUEST_PARAMS, NORMAL_GBT_REQUEST_PARAMS,
@ -77,7 +78,7 @@ class NULLDUMMYTest(BitcoinTestFramework):
cms = self.nodes[0].createmultisig(1, [self.pubkey]) cms = self.nodes[0].createmultisig(1, [self.pubkey])
wms = self.nodes[0].createmultisig(1, [self.pubkey], 'p2sh-segwit') wms = self.nodes[0].createmultisig(1, [self.pubkey], 'p2sh-segwit')
self.ms_address = cms["address"] self.ms_address = cms["address"]
ms_unlock_details = {"scriptPubKey": self.nodes[0].validateaddress(self.ms_address)["scriptPubKey"], ms_unlock_details = {"scriptPubKey": address_to_scriptpubkey(self.ms_address).hex(),
"redeemScript": cms["redeemScript"]} "redeemScript": cms["redeemScript"]}
self.wit_ms_address = wms['address'] self.wit_ms_address = wms['address']

View file

@ -8,6 +8,7 @@ import itertools
import json import json
import os import os
from test_framework.address import address_to_scriptpubkey
from test_framework.blocktools import COINBASE_MATURITY from test_framework.blocktools import COINBASE_MATURITY
from test_framework.authproxy import JSONRPCException from test_framework.authproxy import JSONRPCException
from test_framework.descriptors import descsum_create, drop_origins from test_framework.descriptors import descsum_create, drop_origins
@ -193,7 +194,7 @@ class RpcCreateMultiSigTest(BitcoinTestFramework):
assert mredeemw == mredeem assert mredeemw == mredeem
wmulti.unloadwallet() wmulti.unloadwallet()
spk = bytes.fromhex(node0.validateaddress(madd)["scriptPubKey"]) spk = address_to_scriptpubkey(madd)
txid, _ = self.wallet.send_to(from_node=self.nodes[0], scriptPubKey=spk, amount=1300) txid, _ = self.wallet.send_to(from_node=self.nodes[0], scriptPubKey=spk, amount=1300)
tx = node0.getrawtransaction(txid, True) tx = node0.getrawtransaction(txid, True)
vout = [v["n"] for v in tx["vout"] if madd == v["scriptPubKey"]["address"]] vout = [v["n"] for v in tx["vout"] if madd == v["scriptPubKey"]["address"]]

View file

@ -3,6 +3,7 @@
# Distributed under the MIT software license, see the accompanying # Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php. # file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test the scanblocks RPC call.""" """Test the scanblocks RPC call."""
from test_framework.address import address_to_scriptpubkey
from test_framework.blockfilter import ( from test_framework.blockfilter import (
bip158_basic_element_hash, bip158_basic_element_hash,
bip158_relevant_scriptpubkeys, bip158_relevant_scriptpubkeys,
@ -36,7 +37,7 @@ class ScanblocksTest(BitcoinTestFramework):
# send 1.0, mempool only # send 1.0, mempool only
# childkey 5 of `parent_key` # childkey 5 of `parent_key`
wallet.send_to(from_node=node, wallet.send_to(from_node=node,
scriptPubKey=bytes.fromhex(node.validateaddress("mkS4HXoTYWRTescLGaUTGbtTTYX5EjJyEE")['scriptPubKey']), scriptPubKey=address_to_scriptpubkey("mkS4HXoTYWRTescLGaUTGbtTTYX5EjJyEE"),
amount=1 * COIN) amount=1 * COIN)
# mine a block and assure that the mined blockhash is in the filterresult # mine a block and assure that the mined blockhash is in the filterresult

View file

@ -3,12 +3,12 @@
# Distributed under the MIT software license, see the accompanying # Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php. # file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test the scantxoutset rpc call.""" """Test the scantxoutset rpc call."""
from test_framework.address import address_to_scriptpubkey
from test_framework.messages import COIN from test_framework.messages import COIN
from test_framework.test_framework import BitcoinTestFramework from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal, assert_raises_rpc_error from test_framework.util import assert_equal, assert_raises_rpc_error
from test_framework.wallet import ( from test_framework.wallet import (
MiniWallet, MiniWallet,
address_to_scriptpubkey,
getnewdestination, getnewdestination,
) )

View file

@ -8,6 +8,7 @@ from test_framework.blocktools import (
COINBASE_MATURITY, COINBASE_MATURITY,
) )
from test_framework.address import ( from test_framework.address import (
address_to_scriptpubkey,
script_to_p2sh, script_to_p2sh,
) )
from test_framework.key import ECKey from test_framework.key import ECKey
@ -118,7 +119,7 @@ class SignRawTransactionWithKeyTest(BitcoinTestFramework):
}.get(tx_type, "Invalid tx_type") }.get(tx_type, "Invalid tx_type")
redeem_script = script_to_p2wsh_script(witness_script).hex() redeem_script = script_to_p2wsh_script(witness_script).hex()
addr = script_to_p2sh(redeem_script) addr = script_to_p2sh(redeem_script)
script_pub_key = self.nodes[1].validateaddress(addr)['scriptPubKey'] script_pub_key = address_to_scriptpubkey(addr).hex()
# Fund that address # Fund that address
txid = self.send_to_address(addr, 10) txid = self.send_to_address(addr, 10)
vout = find_vout_for_address(self.nodes[0], txid, addr) vout = find_vout_for_address(self.nodes[0], txid, addr)

View file

@ -21,11 +21,17 @@ from .script import (
taproot_construct, taproot_construct,
) )
from .util import assert_equal from .util import assert_equal
from test_framework.script_util import (
keyhash_to_p2pkh_script,
program_to_witness_script,
scripthash_to_p2sh_script,
)
from test_framework.segwit_addr import ( from test_framework.segwit_addr import (
decode_segwit_address, decode_segwit_address,
encode_segwit_address, encode_segwit_address,
) )
ADDRESS_BCRT1_UNSPENDABLE = 'bcrt1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq3xueyj' ADDRESS_BCRT1_UNSPENDABLE = 'bcrt1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq3xueyj'
ADDRESS_BCRT1_UNSPENDABLE_DESCRIPTOR = 'addr(bcrt1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq3xueyj)#juyq9d97' ADDRESS_BCRT1_UNSPENDABLE_DESCRIPTOR = 'addr(bcrt1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq3xueyj)#juyq9d97'
# Coins sent to this address can be spent with a witness stack of just OP_TRUE # Coins sent to this address can be spent with a witness stack of just OP_TRUE
@ -172,6 +178,21 @@ def bech32_to_bytes(address):
return version, bytearray(payload) return version, bytearray(payload)
def address_to_scriptpubkey(address):
"""Converts a given address to the corresponding output script (scriptPubKey)."""
version, payload = bech32_to_bytes(address)
if version is not None:
return program_to_witness_script(version, payload) # testnet segwit scriptpubkey
payload, version = base58_to_byte(address)
if version == 111: # testnet pubkey hash
return keyhash_to_p2pkh_script(payload)
elif version == 196: # testnet script hash
return scripthash_to_p2sh_script(payload)
# TODO: also support other address formats
else:
assert False
class TestFrameworkScript(unittest.TestCase): class TestFrameworkScript(unittest.TestCase):
def test_base58encodedecode(self): def test_base58encodedecode(self):
def check_base58(data, version): def check_base58(data, version):

View file

@ -9,6 +9,7 @@ import time
import unittest import unittest
from .address import ( from .address import (
address_to_scriptpubkey,
key_to_p2sh_p2wpkh, key_to_p2sh_p2wpkh,
key_to_p2wpkh, key_to_p2wpkh,
script_to_p2sh_p2wsh, script_to_p2sh_p2wsh,
@ -205,7 +206,7 @@ def create_witness_tx(node, use_p2wsh, utxo, pubkey, encode_p2sh, amount):
else: else:
addr = key_to_p2sh_p2wpkh(pubkey) if encode_p2sh else key_to_p2wpkh(pubkey) addr = key_to_p2sh_p2wpkh(pubkey) if encode_p2sh else key_to_p2wpkh(pubkey)
if not encode_p2sh: if not encode_p2sh:
assert_equal(node.getaddressinfo(addr)['scriptPubKey'], witness_script(use_p2wsh, pubkey)) assert_equal(address_to_scriptpubkey(addr).hex(), witness_script(use_p2wsh, pubkey))
return node.createrawtransaction([utxo], {addr: amount}) return node.createrawtransaction([utxo], {addr: amount})
def send_to_witness(use_p2wsh, node, utxo, pubkey, encode_p2sh, amount, sign=True, insert_redeem_script=""): def send_to_witness(use_p2wsh, node, utxo, pubkey, encode_p2sh, amount, sign=True, insert_redeem_script=""):

View file

@ -13,8 +13,7 @@ from typing import (
Optional, Optional,
) )
from test_framework.address import ( from test_framework.address import (
base58_to_byte, address_to_scriptpubkey,
bech32_to_bytes,
create_deterministic_address_bcrt1_p2tr_op_true, create_deterministic_address_bcrt1_p2tr_op_true,
key_to_p2pkh, key_to_p2pkh,
key_to_p2sh_p2wpkh, key_to_p2sh_p2wpkh,
@ -49,9 +48,6 @@ from test_framework.script_util import (
key_to_p2pkh_script, key_to_p2pkh_script,
key_to_p2sh_p2wpkh_script, key_to_p2sh_p2wpkh_script,
key_to_p2wpkh_script, key_to_p2wpkh_script,
keyhash_to_p2pkh_script,
program_to_witness_script,
scripthash_to_p2sh_script,
) )
from test_framework.util import ( from test_framework.util import (
assert_equal, assert_equal,
@ -101,7 +97,7 @@ class MiniWallet:
self._scriptPubKey = key_to_p2pk_script(pub_key.get_bytes()) self._scriptPubKey = key_to_p2pk_script(pub_key.get_bytes())
elif mode == MiniWalletMode.ADDRESS_OP_TRUE: elif mode == MiniWalletMode.ADDRESS_OP_TRUE:
self._address, self._internal_key = create_deterministic_address_bcrt1_p2tr_op_true() self._address, self._internal_key = create_deterministic_address_bcrt1_p2tr_op_true()
self._scriptPubKey = bytes.fromhex(self._test_node.validateaddress(self._address)['scriptPubKey']) self._scriptPubKey = address_to_scriptpubkey(self._address)
# When the pre-mined test framework chain is used, it contains coinbase # When the pre-mined test framework chain is used, it contains coinbase
# outputs to the MiniWallet's default address in blocks 76-100 # outputs to the MiniWallet's default address in blocks 76-100
@ -412,18 +408,3 @@ def getnewdestination(address_type='bech32m'):
else: else:
assert False assert False
return pubkey, scriptpubkey, address return pubkey, scriptpubkey, address
def address_to_scriptpubkey(address):
"""Converts a given address to the corresponding output script (scriptPubKey)."""
version, payload = bech32_to_bytes(address)
if version is not None:
return program_to_witness_script(version, payload) # testnet segwit scriptpubkey
payload, version = base58_to_byte(address)
if version == 111: # testnet pubkey hash
return keyhash_to_p2pkh_script(payload)
elif version == 196: # testnet script hash
return scripthash_to_p2sh_script(payload)
# TODO: also support other address formats
else:
assert False

View file

@ -4,6 +4,7 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php. # file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test the avoid_reuse and setwalletflag features.""" """Test the avoid_reuse and setwalletflag features."""
from test_framework.address import address_to_scriptpubkey
from test_framework.test_framework import BitcoinTestFramework from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import ( from test_framework.util import (
assert_approx, assert_approx,
@ -257,7 +258,7 @@ class AvoidReuseTest(BitcoinTestFramework):
if not self.options.descriptors: if not self.options.descriptors:
# For the second send, we transmute it to a related single-key address # For the second send, we transmute it to a related single-key address
# to make sure it's also detected as re-use # to make sure it's also detected as re-use
fund_spk = self.nodes[0].getaddressinfo(fundaddr)["scriptPubKey"] fund_spk = address_to_scriptpubkey(fundaddr).hex()
fund_decoded = self.nodes[0].decodescript(fund_spk) fund_decoded = self.nodes[0].decodescript(fund_spk)
if second_addr_type == "p2sh-segwit": if second_addr_type == "p2sh-segwit":
new_fundaddr = fund_decoded["segwit"]["p2sh-segwit"] new_fundaddr = fund_decoded["segwit"]["p2sh-segwit"]

View file

@ -7,6 +7,7 @@
import os import os
from typing import List from typing import List
from test_framework.address import address_to_scriptpubkey
from test_framework.descriptors import descsum_create from test_framework.descriptors import descsum_create
from test_framework.test_framework import BitcoinTestFramework from test_framework.test_framework import BitcoinTestFramework
from test_framework.test_node import TestNode from test_framework.test_node import TestNode
@ -58,7 +59,7 @@ class WalletFastRescanTest(BitcoinTestFramework):
if 'range' in desc_info: if 'range' in desc_info:
start_range, end_range = desc_info['range'] start_range, end_range = desc_info['range']
addr = w.deriveaddresses(desc_info['desc'], [end_range, end_range])[0] addr = w.deriveaddresses(desc_info['desc'], [end_range, end_range])[0]
spk = bytes.fromhex(w.getaddressinfo(addr)['scriptPubKey']) spk = address_to_scriptpubkey(addr)
self.log.info(f"-> range [{start_range},{end_range}], last address {addr}") self.log.info(f"-> range [{start_range},{end_range}], last address {addr}")
else: else:
spk = bytes.fromhex(fixed_key.p2wpkh_script) spk = bytes.fromhex(fixed_key.p2wpkh_script)