Beispiel #1
0
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)
Beispiel #2
0
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)
Beispiel #3
0
 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)
Beispiel #4
0
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()
Beispiel #5
0
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()
Beispiel #6
0
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()
Beispiel #7
0
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()
Beispiel #8
0
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
Beispiel #9
0
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()
Beispiel #10
0
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 == []
Beispiel #11
0
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
Beispiel #12
0
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
Beispiel #13
0
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
Beispiel #14
0
 def deserialize(cls, data):
     block = BlockData.deserialize(data)
     return cls(block)