Beispiel #1
0
def test_parse_merkleblock():
    hex_merkle_block = '00000020df3b053dc46f162a9b00c7f0d5124e2676d47bbe7c5d0793a500000000000000ef445fef2ed495c275892206ca533e7411907971013ab83e3b47bd0d692d14d4dc7c835b67d8001ac157e670bf0d00000aba412a0d1480e370173072c9562becffe87aa661c1e4a6dbc305d38ec5dc088a7cf92e6458aca7b32edae818f9c2c98c37e06bf72ae0ce80649a38655ee1e27d34d9421d940b16732f24b94023e9d572a7f9ab8023434a4feb532d2adfc8c2c2158785d1bd04eb99df2e86c54bc13e139862897217400def5d72c280222c4cbaee7261831e1550dbb8fa82853e9fe506fc5fda3f7b919d8fe74b6282f92763cef8e625f977af7c8619c32a369b832bc2d051ecd9c73c51e76370ceabd4f25097c256597fa898d404ed53425de608ac6bfe426f6e2bb457f1c554866eb69dcb8d6bf6f880e9a59b3cd053e6c7060eeacaacf4dac6697dac20e4bd3f38a2ea2543d1ab7953e3430790a9f81e1c67f5b58c825acf46bd02848384eebe9af917274cdfbb1a28a5d58a23a17977def0de10d644258d9c54f886d47d293a411cb6226103b55635'
    mb = network.parse_merkleblock(BytesIO(bytes.fromhex(hex_merkle_block)))
    assert mb['version'] == 0x20000000
    merkle_root_hex = 'ef445fef2ed495c275892206ca533e7411907971013ab83e3b47bd0d692d14d4'
    merkle_root = bytes.fromhex(merkle_root_hex)[::-1]
    assert mb['merkle_root'] == merkle_root
    prev_block_hash_hex = 'df3b053dc46f162a9b00c7f0d5124e2676d47bbe7c5d0793a500000000000000'
    prev_block_hash = bytes.fromhex(prev_block_hash_hex)[::-1]
    assert mb['prev_block_hash'] == prev_block_hash
    timestamp = util.little_endian_to_int(bytes.fromhex('dc7c835b'))
    assert mb['timestamp'] == timestamp
    bits = bytes.fromhex('67d8001a')
    assert mb['bits'] == bits
    nonce = bytes.fromhex('c157e670')
    assert mb['nonce'] == nonce
    total = util.little_endian_to_int(bytes.fromhex('bf0d0000'))
    assert mb['total'] == total
    hex_hashes = [
        'ba412a0d1480e370173072c9562becffe87aa661c1e4a6dbc305d38ec5dc088a',
        '7cf92e6458aca7b32edae818f9c2c98c37e06bf72ae0ce80649a38655ee1e27d',
        '34d9421d940b16732f24b94023e9d572a7f9ab8023434a4feb532d2adfc8c2c2',
        '158785d1bd04eb99df2e86c54bc13e139862897217400def5d72c280222c4cba',
        'ee7261831e1550dbb8fa82853e9fe506fc5fda3f7b919d8fe74b6282f92763ce',
        'f8e625f977af7c8619c32a369b832bc2d051ecd9c73c51e76370ceabd4f25097',
        'c256597fa898d404ed53425de608ac6bfe426f6e2bb457f1c554866eb69dcb8d',
        '6bf6f880e9a59b3cd053e6c7060eeacaacf4dac6697dac20e4bd3f38a2ea2543',
        'd1ab7953e3430790a9f81e1c67f5b58c825acf46bd02848384eebe9af917274c',
        'dfbb1a28a5d58a23a17977def0de10d644258d9c54f886d47d293a411cb62261',
    ]
    hashes = [bytes.fromhex(h)[::-1] for h in hex_hashes]
    mb['hashes'] == hashes
    flags = bytes.fromhex('b55635')
    assert mb['flags'] == flags
Beispiel #2
0
def parse_segwit(s):
    tx = {
        "version": 1,
        "mark": None,
        "flag": None,
        "txi.count": 0,
        "txis": [],
        "txo.count": 0,
        "txos": [],
        # "wits": append to each txi
        "locktime": 0,
        "hash_all": None
    }
    tx["version"] = util.little_endian_to_int(s.read(4))
    tx["mark"] = s.read(1)
    tx["flag"] = s.read(1)
    if tx["mark"] != b"\x00" and tx["flag"] != b"\x01":
        raise RuntimeError('not a segwit transaction {}'.format(tx["flag"]))
    tx["txi.count"] = util.read_varint(s)
    for _ in range(tx["txi.count"]):
        tx["txis"].append(parse_txi(s))
    tx["txo.count"] = util.read_varint(s)
    for _ in range(tx["txo.count"]):
        tx["txos"].append(parse_txo(s))
    # parse witness script
    for txi in tx["txis"]:
        count = util.read_varint(s)
        for _ in range(count):
            length = util.read_varint(s)
            if length == 0:  # ?
                txi["wits"].append(0)
            else:
                txi["wits"].append(s.read(length))
    tx["locktime"] = util.little_endian_to_int(s.read(4))  # locktime is an integer in 4 bytes, little-endian
    return tx
Beispiel #3
0
def test_little_endian_to_int():
    h = bytes.fromhex('99c3980000000000')
    want = 10011545
    assert util.little_endian_to_int(h) == want
    h = bytes.fromhex('a135ef0100000000')
    want = 32454049
    assert util.little_endian_to_int(h) == want
Beispiel #4
0
def parse(s):
    result = {}
    result['version'] = util.little_endian_to_int(s.read(4))
    result['prev_block_hash'] = s.read(32)[::-1]
    result['merkle_root'] = s.read(32)[::-1]
    result['timestamp'] = util.little_endian_to_int(s.read(4))
    result['bits'] = s.read(4)
    result['nonce'] = s.read(4)

    return result
Beispiel #5
0
def parse_txi(s):
    txi = {
        "txid": 0,  # 32bytes, not hex value.
        "idx": 0,
        "script.len": 0,
        "script": [],
        "seq.no": 0,
        "wits": []
    }
    txi["txid"] = s.read(32)[::-1]  # prev_tx is 32 bytes, little endian // le to be
    txi["idx"] = util.little_endian_to_int(s.read(4))  # prev_index is an integer in 4 bytes, little endian
    txi["script.len"], txi["script"] = script.parse(s)  # parse script
    txi["seq.no"] = util.little_endian_to_int(s.read(4))  # sequence is an integer in 4 bytes, little-endian
    # wits: witness script
    return txi
Beispiel #6
0
def parse_msg(s, testnet=False):
    """Takes a stream and creates a NetworkEnvelope"""
    # check the network magic
    magic = s.read(4)
    if magic == b'':
        raise RuntimeError('Connection reset!')
    if testnet:
        expected_magic = TESTNET_MAGIC
    else:
        expected_magic = MAINNET_MAGIC
    if magic != expected_magic:
        raise RuntimeError('magic is not right {} vs {}'.format(
            magic.hex(), expected_magic.hex()))
    # command 12 bytes
    command = s.read(12)
    # strip the trailing 0's
    command = command.strip(b'\x00')
    # payload length 4 bytes, little endian
    payload_length = util.little_endian_to_int(s.read(4))
    # checksum 4 bytes, first four of hash256 of payload
    checksum = s.read(4)
    # payload is of length payload_length
    payload_bytes = s.read(payload_length)
    # verify checksum
    calculated_checksum = util.hash256(payload_bytes)[:4]
    if calculated_checksum != checksum:
        raise RuntimeError('checksum does not match')

    # return msg
    return {"magic": magic, "command": command, "payload_bytes": payload_bytes}
Beispiel #7
0
def check_pow(obj):
    """Returns whether this block satisfies proof of work"""
    # get the hash256 of the serialization of this block
    h256 = util.hash256(serialize(obj))
    # interpret this hash as a little-endian number
    proof = util.little_endian_to_int(h256)
    # return whether this integer is less than the target
    return proof < target(obj)
Beispiel #8
0
def bits_to_target(bits):
    """Turns bits into a target (large 256-bit integer)"""
    # last byte is exponent
    exponent = bits[-1]
    # the first three bytes are the coefficient in little endian
    coefficient = util.little_endian_to_int(bits[:-1])
    # the formula is:
    # coefficient * 256**(exponent-3)
    return coefficient * 256**(exponent - 3)
Beispiel #9
0
def parse_txo(s):
    txo = {
        "amount": 0,
        "script.len": 0,
        "script": ""
    }
    # amount is an integer in 8 bytes, little endian (amount = satoshi * 10**8, 1 satoshi = 0.00000001btc)
    txo["amount"] = util.little_endian_to_int(s.read(8))
    txo["script.len"], txo["script"] = script.parse(s)  # lock script
    return txo
Beispiel #10
0
def parse_legacy(s):
    tx = {
        "version": 1,
        # "mark": None,
        # "flag": None,
        "txi.count": 0,
        "txis": [],
        "txo.count": 0,
        "txos": [],
        # "wits": None,
        "locktime": 0
    }
    tx["version"] = util.little_endian_to_int(s.read(4))
    tx["txi.count"] = util.read_varint(s)
    for _ in range(tx["txi.count"]):
        tx["txis"].append(parse_txi(s))
    tx["txo.count"] = util.read_varint(s)
    for _ in range(tx["txo.count"]):
        tx["txos"].append(parse_txo(s))
    tx["locktime"] = util.little_endian_to_int(s.read(4))  # locktime is an integer in 4 bytes, little-endian
    return tx
Beispiel #11
0
def parse_merkleblock(s):
    """Takes a byte stream and parses a merkle block. Returns a Merkle Block object"""
    # version - 4 bytes, Little-Endian integer
    version = util.little_endian_to_int(s.read(4))
    # prev_block - 32 bytes, Little-Endian (use [::-1])
    prev_block_hash = s.read(32)[::-1]
    # merkle_root - 32 bytes, Little-Endian (use [::-1])
    merkle_root = s.read(32)[::-1]
    # timestamp - 4 bytes, Little-Endian integer
    timestamp = util.little_endian_to_int(s.read(4))
    # bits - 4 bytes
    bits = s.read(4)
    # nonce - 4 bytes
    nonce = s.read(4)
    # total transactions in block - 4 bytes, Little-Endian integer
    total = util.little_endian_to_int(s.read(4))
    # number of transaction hashes - varint
    num_hashes = util.read_varint(s)
    # each transaction is 32 bytes, Little-Endian
    hashes = []
    for _ in range(num_hashes):
        hashes.append(s.read(32)[::-1])
    # length of flags field - varint
    flags_length = util.read_varint(s)
    # read the flags field
    flags = s.read(flags_length)

    return {
        'version': version,
        'prev_block_hash': prev_block_hash,
        'merkle_root': merkle_root,
        'timestamp': timestamp,
        'bits': bits,
        'nonce': nonce,
        'total': total,
        'hashes': hashes,
        'flags': flags
    }
Beispiel #12
0
def parse(s):
    length = util.read_varint(s)
    commands = []  # initialize the commands array
    count = 0  # initialize the number of bytes we've read to 0
    while count < length:  # loop until we've read length bytes
        temp = s.read(1)[0]  # get code
        count += 1  # increment the bytes we've read
        if 1 <= temp <= 75:  # if the current byte is between 1 and 75 inclusive
            commands.append(s.read(temp))  # add the next n bytes as an cmd
            count += temp  # increase the count by n
        elif temp == 76:  # op_pushdata1
            data_length = util.little_endian_to_int(s.read(1))
            commands.append(s.read(data_length))
            count += data_length + 1
        elif temp == 77:  # op_pushdata2
            data_length = util.little_endian_to_int(s.read(2))
            commands.append(s.read(data_length))
            count += data_length + 2
        else:  # we have an op_code. set the current byte to op_code
            commands.append(temp)  # add the op_code to the list of commands
    if count != length:
        raise SyntaxError('parsing script failed')

    return length, commands