#!/usr/bin/env python3 # Copyright (c) 2024 The Bitcoin Unlimited developers import asyncio from test_framework.connectrum.exc import ElectrumErrorResponse from test_framework.constants import COIN from test_framework.environment import on_bch, on_nex from test_framework.util import assert_equal from test_framework.electrumutil import ( ERROR_CODE_INVALID_PARAMS, ElectrumTestFramework, ) from test_framework.electrumconnection import ElectrumConnection class BlockchainHeadersVerbose(ElectrumTestFramework): async def run_test(self): n = self.nodes[0] cli = ElectrumConnection() try: await self.bootstrap_p2p() await cli.connect() await self.test_invalid_params(cli) n.generate(110) # Add some txs to one of the blocks addr = n.getnewaddress() for _ in range(50): n.sendtoaddress(addr, 100_000_000 / COIN) n.generate(1) tip_height = n.getblockcount() assert_equal(tip_height, 111) await self.sync_height(cli) await self.test_basic(n, cli, tip_height) await self.test_by_blockhash(n, cli) finally: cli.disconnect() async def test_basic(self, n, cli, tip_height): for i in range(0, tip_height + 1): expected_header = n.getblockheader(i) expected_header_hex = n.getblockheader(i, False) header = await cli.call("blockchain.block.header_verbose", i) assert_equal(header["hex"], expected_header_hex) assert_equal(header["hash"], expected_header["hash"]) assert_equal(header["height"], expected_header["height"]) assert_equal(header["merkleroot"], expected_header["merkleroot"]) assert_equal(header["nonce"], expected_header["nonce"]) if i > 0: assert_equal( header["previousblockhash"], expected_header["previousblockhash"], ) assert_equal(header["mediantime"], expected_header["mediantime"]) assert_equal(header["time"], expected_header["time"]) if on_bch(): assert_equal(header["version"], expected_header["version"]) elif on_nex(): assert_equal(header["ancestorhash"], expected_header["ancestorhash"]) # nexad doesn't provide txfilter assert "txfilter" in header assert_equal(header["chainwork"], expected_header["chainwork"]) assert_equal(header["size"], expected_header["size"]) assert_equal(header["txcount"], expected_header["txcount"]) assert_equal(header["feepoolamt"], expected_header["feePoolAmt"]) assert_equal(header["utxocommitment"], expected_header["utxoCommitment"]) else: raise NotImplementedError() async def test_by_blockhash(self, n, cli): tip_hash = n.getbestblockhash() header = await cli.call("blockchain.block.header_verbose", tip_hash) assert_equal(tip_hash, header["hash"]) async def test_invalid_params(self, cli): # invalid height try: await cli.call("blockchain.block.header_verbose", 100_000) except ElectrumErrorResponse as e: assert_equal(ERROR_CODE_INVALID_PARAMS, e.response["code"]) # invalid hash try: await cli.call( "blockchain.block.header_verbose", "0f00d0013cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206", ) except ElectrumErrorResponse as e: assert_equal(ERROR_CODE_INVALID_PARAMS, e.response["code"]) if __name__ == "__main__": asyncio.run(BlockchainHeadersVerbose().main())