def test_varint_error() -> None: fname = "block_1.bin" filename = path.join(path.dirname(__file__), "test_data", fname) block_bytes = open(filename, "rb").read() block_bytes = block_bytes[:80] + b"\xff" with pytest.raises(IndexError): Block.deserialize(block_bytes)
def test_dataclasses_json_dict() -> None: fname = "block_481824.bin" filename = path.join(path.dirname(__file__), "test_data", fname) block = open(filename, "rb").read() # dataclass block_data = Block.deserialize(block) assert isinstance(block_data, Block) # str block_json_str = block_data.to_json() assert isinstance(block_json_str, str) assert block_data == Block.from_json(block_json_str) # dict block_dict = block_data.to_dict() assert isinstance(block_dict, dict) assert block_data == Block.from_dict(block_dict) import json datadir = path.join(path.dirname(__file__), "generated_files") filename = path.join(datadir, "block_481824.json") with open(filename, "w") as f: json.dump(block_dict, f, indent=True) block_header = block_data.header.serialize() # dataclass block_header_data = BlockHeader.deserialize(block_header) assert isinstance(block_header_data, BlockHeader) # str block_header_s = block_header_data.to_json() assert isinstance(block_header_s, str) assert block_header_data == BlockHeader.from_json(block_header_s) # dict block_header_d = block_header_data.to_dict() assert isinstance(block_header_d, dict) assert block_header_data == BlockHeader.from_dict(block_header_d) filename = path.join(datadir, "block_header_481824.json") with open(filename, "w") as f: json.dump(block_header_d, f, indent=True)
def get_block(self, hash): if hash not in self.blocks: return None block_location = self.blocks[hash] file = self.__get_block_file(block_location.filename) block_data = self.__get_data_from_file( file, block_location.index, block_location.size ) return Block.deserialize(block_data)
def test_invalid_nonce() -> None: fname = "block_1.bin" filename = path.join(path.dirname(__file__), "test_data", fname) block_bytes = open(filename, "rb").read() block = Block.deserialize(block_bytes) block.header.nonce = 0 err_msg = "Invalid nonce" with pytest.raises(ValueError, match=err_msg): block.assert_valid()
def test_invalid_block_merkleroot_length() -> None: fname = "block_1.bin" filename = path.join(path.dirname(__file__), "test_data", fname) block_bytes = open(filename, "rb").read() block = Block.deserialize(block_bytes) block.header.merkleroot = "00" * 31 err_msg = "Invalid block merkle root length" with pytest.raises(ValueError, match=err_msg): block.header.assert_valid()
def test_invalid_merkleroot() -> None: fname = "block_1.bin" filename = path.join(path.dirname(__file__), "test_data", fname) block_bytes = open(filename, "rb").read() block = Block.deserialize(block_bytes) block.header.merkleroot = "00" * 32 err_msg = "The block merkle root is not the merkle root of the block transactions" with pytest.raises(ValueError, match=err_msg): block.assert_valid()
def test_invalid_block_previoushash_length() -> None: fname = "block_1.bin" filename = path.join(path.dirname(__file__), "test_data", fname) block_bytes = open(filename, "rb").read() block = Block.deserialize(block_bytes) block.header.previousblockhash = "00" * 31 err_msg = "Invalid block previous hash length" with pytest.raises(BTClibValueError, match=err_msg): block.assert_valid()
def generate_random_chain(length, start): # random.seed(42) chain = [] for x in range(length): previous_block_hash = chain[-1].header.hash if chain else start coinbase_in = TxIn( prevout=OutPoint(), scriptSig=script.serialize( [random.randrange(256**32).to_bytes(32, "big").hex()]), sequence=0xFFFFFFFF, txinwitness=[], ) coinbase_out = TxOut( value=50 * 10**8, scriptPubKey=script.serialize( [random.randrange(256**32).to_bytes(32, "big").hex()]), ) coinbase = Tx( version=1, locktime=0, vin=[coinbase_in], vout=[coinbase_out], ) transactions = [coinbase] if chain: tx_in = TxIn( prevout=OutPoint(chain[x - 1].transactions[0].txid, 0), scriptSig=script.serialize( [random.randrange(256**32).to_bytes(32, "big").hex()]), sequence=0xFFFFFFFF, txinwitness=[], ) tx_out = TxOut( value=50 * 10**8, scriptPubKey=script.serialize( [random.randrange(256**32).to_bytes(32, "big").hex()]), ) tx = Tx( version=1, locktime=0, vin=[tx_in], vout=[tx_out], ) transactions.append(tx) header = BlockHeader( version=70015, previousblockhash=previous_block_hash, merkleroot=_generate_merkle_root(transactions), time=1, bits=b"\x23\x00\x00\x01", nonce=1, ) block = Block(header, transactions) chain.append(block) return chain
def test_invalid_block_version() -> None: fname = "block_1.bin" filename = path.join(path.dirname(__file__), "test_data", fname) block_bytes = open(filename, "rb").read() block = Block.deserialize(block_bytes) err_msg = "Invalid block header version" block.header.version = 0 with pytest.raises(ValueError, match=err_msg): block.assert_valid() block.header.version = 0xFFFFFFFF + 1 with pytest.raises(ValueError, match=err_msg): block.assert_valid()
def test_block_481824() -> None: fname = "block_481824.bin" filename = path.join(path.dirname(__file__), "test_data", fname) block_bytes = open(filename, "rb").read() block = Block.deserialize(block_bytes) assert len(block.transactions) == 1866 assert block.serialize() == block_bytes header = block.header assert header.time == 1503539857 # 2017-08-24 03:57:37 GMT+2 assert (header.merkleroot == "6438250cad442b982801ae6994edb8a9ec63c0a0ba117779fbe7ef7f07cad140") assert header.bits == 0x18013CE9.to_bytes(4, "big") assert header.nonce == 0x2254FF22 assert (header.hash == "0000000000000000001c8018d9cb3b742ef25114f27563e3fc4a1902167f9893") assert block.transactions[0].vin[0].txinwitness == []
def test_block_200000() -> None: fname = "block_200000.bin" filename = path.join(path.dirname(__file__), "test_data", fname) block_bytes = open(filename, "rb").read() block = Block.deserialize(block_bytes) assert len(block.transactions) == 388 assert block.serialize() == block_bytes header = block.header assert header.time == 1348310759 # 2012-09-22 12:45:59 GMT+2 assert (header.merkleroot == "a08f8101f50fd9c9b3e5252aff4c1c1bd668f878fffaf3d0dbddeb029c307e88") assert header.bits == 0x1A05DB8B.to_bytes(4, "big") assert header.nonce == 0xF7D8D840 assert (header.hash == "000000000000034a7dedef4a161fa058a2d67a173a90155f3a2fe6fc132e0ebf") assert block.size == 247533 assert block.weight == 989800
def test_block_170() -> None: fname = "block_170.bin" filename = path.join(path.dirname(__file__), "test_data", fname) block_bytes = open(filename, "rb").read() block = Block.deserialize(block_bytes) assert len(block.transactions) == 2 assert block.serialize() == block_bytes header = block.header assert header.time == 1231731025 # 2009-01-12 04:30:25 GMT+1 assert (header.merkleroot == "7dac2c5666815c17a3b36427de37bb9d2e2c5ccec3f8633eb91a4205cb4c10ff") assert header.bits == 0x1D00FFFF.to_bytes(4, "big") assert header.nonce == 0x709E3E28 assert (header.hash == "00000000d1145790a8694403d4063f323d499e655c83426834d4ce2f8dd4a2ee") assert block.size == 490 assert block.weight == 1636
def test_block_1() -> None: fname = "block_1.bin" filename = path.join(path.dirname(__file__), "test_data", fname) block_bytes = open(filename, "rb").read() block = Block.deserialize(block_bytes) assert len(block.transactions) == 1 assert block.serialize() == block_bytes header = block.header assert header.time == 1231469665 # 2009-01-09 03:54:25 GMT+1 assert (header.merkleroot == "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098") assert header.bits == 0x1D00FFFF.to_bytes(4, "big") assert header.nonce == 0x9962E301 assert (header.hash == "00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048") assert block.size == 215 assert block.weight == 536
def deserialize(cls, data): block = BlockData.deserialize(data) return cls(block)