コード例 #1
0
def generate_proof_blob(block_dict, tx_index):
    header = block_header(block_dict)

    mpt = HexaryTrie(db={})
    for tx_dict in block_dict["transactions"]:
        key = rlp.encode(utils.parse_as_int(tx_dict['transactionIndex']))
        mpt.set(key, rlp_transaction(tx_dict))

    if mpt.root_hash != normalize_bytes(block_dict['transactionsRoot']):
        raise ValueError(
            "Tx trie root hash does not match. Calculated: {} Sent: {}".format(
                mpt.root_hash.hex(),
                normalize_bytes(block_dict['transactionsRoot']).hex()))

    mpt_key_nibbles = bytes_to_nibbles(rlp.encode(tx_index))
    mpt_path, stack_indexes, stack = generate_proof(mpt, mpt_key_nibbles)

    proof_blob = rlp.encode([
        1,  # proof_type
        header,
        tx_index,
        bytes(mpt_path),
        bytes(stack_indexes),
        stack,
    ])
    return proof_blob
コード例 #2
0
def test_hexary_trie_missing_traversal_node_with_traverse_from():
    db = {}
    trie = HexaryTrie(db, prune=True)

    key1 = to_bytes(0x0123)
    trie.set(
        key1,
        b'use a value long enough that it must be hashed according to trie spec'
    )

    key2 = to_bytes(0x1234)
    trie.set(key2, b'val2')

    # delete first child of the root
    root_node = trie.root_node

    first_child_hash = root_node.raw[0]

    del db[first_child_hash]

    # Get exception with relevant info about lookup nibbles
    with pytest.raises(MissingTraversalNode) as exc_info:
        trie.traverse_from(root_node, (0, 1, 2, 3))

    exception = exc_info.value
    assert exception.nibbles_traversed == (0, )
    assert encode_hex(first_child_hash) in str(exception)

    # Other keys are still traversable
    node = trie.traverse((1, ))
    assert node.value == b'val2'
    assert node.sub_segments == ()
コード例 #3
0
def test_squash_changes_raises_correct_error_on_underlying_missing_data():
    db = {}
    trie = HexaryTrie(db, prune=True)
    trie.set(b'what floats on water?', b'very small rocks')
    old_root_hash = trie.root_hash

    # what if the root node hash is missing from the beginning?
    del db[old_root_hash]

    # the appropriate exception should be raised, when squashing changes
    with trie.squash_changes() as memory_trie:
        with pytest.raises(MissingTrieNode):
            memory_trie[b'what floats on water?']
コード例 #4
0
def test_hexary_trie_batch_save_keeps_last_root_data():
    db = {}
    trie = HexaryTrie(db)
    trie.set(b'what floats on water?', b'very small rocks')
    old_root_hash = trie.root_hash

    with trie.squash_changes() as memory_trie:
        memory_trie.set(b'what floats on water?', b'a duck')

    assert trie[b'what floats on water?'] == b'a duck'

    old_trie = HexaryTrie(db, root_hash=old_root_hash)
    assert old_trie[b'what floats on water?'] == b'very small rocks'
コード例 #5
0
def test_hexary_trie_batch_save_drops_last_root_data_when_pruning():
    db = {}
    trie = HexaryTrie(db, prune=True)
    trie.set(b'what floats on water?', b'very small rocks')
    old_root_hash = trie.root_hash

    with trie.squash_changes() as memory_trie:
        memory_trie.set(b'what floats on water?', b'a duck')

    assert trie[b'what floats on water?'] == b'a duck'

    old_trie = HexaryTrie(db, root_hash=old_root_hash)
    with pytest.raises(KeyError):
        old_trie.root_node
コード例 #6
0
def test_squash_changes_can_still_access_underlying_deleted_data():
    db = {}
    trie = HexaryTrie(db, prune=True)
    trie.set(b'what floats on water?', b'very small rocks')
    old_root_hash = trie.root_hash

    with trie.squash_changes() as memory_trie:
        memory_trie.set(b'what floats on water?', b'a duck')
        verify_ref_count(memory_trie)

        # change to a root hash that the memory trie doesn't have anymore
        memory_trie.root_hash
        memory_trie.root_hash = old_root_hash

        assert memory_trie[b'what floats on water?'] == b'very small rocks'
コード例 #7
0
ファイル: proveth.py プロジェクト: lorenzb/proveth
def generate_proof_blob(block_dict, tx_index):
    header = block_header(block_dict)

    mpt = HexaryTrie(db={})
    for tx_dict in block_dict["transactions"]:
        key = rlp.encode(utils.parse_as_int(tx_dict['transactionIndex']))
        mpt.set(key, rlp_transaction(tx_dict))

    if mpt.root_hash != normalize_bytes(block_dict['transactionsRoot']):
        raise ValueError(
            "Tx trie root hash does not match. Calculated: {} Sent: {}"
            .format(mpt.root_hash.hex(),
                    normalize_bytes(block_dict['transactionsRoot']).hex()))

    return construct_proof_from_mpt(mpt, header, tx_index, 1)
コード例 #8
0
def test_hexary_trie_batch_save_drops_last_root_data_when_pruning():
    db = {}
    trie = HexaryTrie(db, prune=True)
    trie.set(b'what floats on water?', b'very small rocks')
    old_root_hash = trie.root_hash

    with trie.squash_changes() as memory_trie:
        memory_trie.set(b'what floats on water?', b'a duck')
        verify_ref_count(memory_trie)

    assert trie[b'what floats on water?'] == b'a duck'

    old_trie = HexaryTrie(db, root_hash=old_root_hash)
    with pytest.raises(MissingTraversalNode) as excinfo:
        old_trie.root_node

    assert encode_hex(old_root_hash) in str(excinfo.value)
コード例 #9
0
ファイル: proveth.py プロジェクト: lorenzb/proveth
def generate_proof_blob_receipt(block_dict, tx_index, url):
    header = block_header(block_dict)

    mpt = HexaryTrie(db={})
    for tx_dict in block_dict["transactions"]:
        key = rlp.encode(utils.parse_as_int(tx_dict['transactionIndex']))
        receipt = get_receipt(url, tx_dict['hash'])
        mpt.set(key, rlp.encode(receipt))

    if mpt.root_hash != normalize_bytes(block_dict['receiptsRoot']):
        if MODULE_DEBUG:
            print("mpt.root_hash " + str(utils.encode_hex(mpt.root_hash)))
            print("receiptRoot " +
                  str(normalize_bytes(utils.encode_hex(block_dict['receiptsRoot']))))
        raise ValueError("Block receiptRoot hash does not match.")

    return construct_proof_from_mpt(mpt, header, tx_index, 2)
コード例 #10
0
def test_squash_changes_raises_correct_error_on_new_deleted_data():
    db = {}
    trie = HexaryTrie(db, prune=True)
    trie.set(b'what floats on water?', b'very small rocks')

    with trie.squash_changes() as memory_trie:
        memory_trie.set(b'what floats on water?', b'a duck')
        verify_ref_count(memory_trie)
        middle_root_hash = memory_trie.root_hash

        memory_trie.set(b'what floats on water?', b'ooooohh')
        memory_trie.root_hash
        verify_ref_count(memory_trie)

        # change to a root hash that the memory trie doesn't have anymore
        memory_trie.root_hash = middle_root_hash

        with pytest.raises(MissingTrieNode):
            memory_trie[b'what floats on water?']
コード例 #11
0
def test_squash_changes_reverts_trie_root_on_exception():
    db = {}
    trie = HexaryTrie(db, prune=True)
    trie.set(b'\x00', b'B' * 32)
    trie.set(b'\xff', b'C' * 32)
    old_root_hash = trie.root_hash

    # delete the node that will be used during trie fixup
    del db[trie.root_node.raw[0xf]]

    with pytest.raises(MissingTrieNode):
        with trie.squash_changes() as memory_trie:
            try:
                memory_trie[b'\x11'] = b'new val'
            except MissingTrieNode:
                assert False, "Only the squash_changes context exit should raise this exception"

            del memory_trie[b'\xff']

    assert trie.root_hash == old_root_hash
コード例 #12
0
 def verify_transaction_hash(self, block_info, tx_hash):
     txns = block_info.transactions
     tx_index = 0
     # generate the mpt
     mpt = HexaryTrie(db={})
     for tx_dict in txns:
         if tx_dict.hash == tx_hash:
             tx_index = tx_dict.transactionIndex
         key = rlp.encode(utils.parse_as_int(tx_dict['transactionIndex']))
         mpt.set(key, self.rlp_transaction(tx_dict))
     # verify the tx root
     if mpt.root_hash != normalize_bytes(block_info.transactionsRoot):
         return False
     # generate the proof
     mpt_key_nibbles = bytes_to_nibbles(rlp.encode(tx_index))
     proof = tuple(self.generate_proof(mpt, mpt_key_nibbles))
     if HexaryTrie.get_from_proof(mpt.root_hash, rlp.encode(utils.parse_as_int(tx_index)), proof) \
             != self.rlp_transaction(txns[tx_index]):
         return False
     return True
コード例 #13
0
ファイル: merkle_proof.py プロジェクト: multitoken/bridge-cli
def generate_receipt_proof_blob(web3, block_dict, tx_index):
    header = block_header(block_dict)

    mpt = HexaryTrie(db={})
    for tx_dict in block_dict['transactions']:
        key = rlp.encode(tx_dict['transactionIndex'])
        tx_receipt = web3.eth.getTransactionReceipt(tx_dict['hash'])
        mpt.set(key, rlp.encode(receipt(tx_receipt)))

    if mpt.root_hash != normalize_bytes(block_dict['receiptsRoot']):
        raise ValueError('Receipt trie root hash does not match')

    mpt_key_nibbles = bytes_to_nibbles(rlp.encode(tx_index))
    mpt_path, stack_indexes, stack = generate_proof(mpt, mpt_key_nibbles)

    proof_blob = rlp.encode([
        2,  # proof_type
        header,
        tx_index,
        compact_encode(mpt_path),
        bytes(stack_indexes),
        stack,
    ])
    return proof_blob
コード例 #14
0
print(w3.toHex(trie.root_hash))

# Generate Merkle tree
txs = []
B = len(block.transactions)
print("The block has %d transactions" % B)
for key in range(B):
    tx = w3.eth.getTransaction(block.transactions[key])
    raw_tx = _Transaction(tx.nonce, tx.gasPrice, tx.gas,
                          w3.toBytes(hexstr=tx.to), tx.value,
                          w3.toBytes(hexstr=w3.toHex(hexstr=tx.input)), tx.v,
                          w3.toInt(tx.r), w3.toInt(tx.s))
    rlp_tx = rlp.encode(raw_tx)
    assert tx.hash == keccak(rlp_tx)
    txs.append(raw_tx)
    trie.set(rlp.encode(key), rlp_tx)
    # print(rlp_tx)
assert block.transactionsRoot == trie.root_hash
print(w3.toHex(trie.root_hash))

# Generate Merkle tree proof for per each node
proofs = []
for key in range(B):
    proof = trie.get_proof(rlp.encode(key))
    proofs.append(proof)

# Verify Merkle tree proof for per each node
nodes = []
for key in range(B):
    node = HexaryTrie.get_from_proof(trie.root_hash, rlp.encode(key),
                                     proofs[key])
コード例 #15
0
def test_hexary_trie_missing_node():
    db = {}
    trie = HexaryTrie(db, prune=True)

    key1 = to_bytes(0x0123)
    trie.set(
        key1,
        b'use a value long enough that it must be hashed according to trie spec'
    )

    key2 = to_bytes(0x1234)
    trie.set(key2, b'val2')

    trie_root_hash = trie.root_hash

    # delete first child of the root
    root_node = trie.root_node.raw

    first_child_hash = root_node[0]

    del db[first_child_hash]

    # Get exception with relevant info about key
    with pytest.raises(MissingTrieNode) as exc_info:
        trie.get(key1)
    message = str(exc_info.value)

    assert encode_hex(key1) in message
    assert encode_hex(trie_root_hash) in message
    assert encode_hex(first_child_hash) in message

    # Get exception when trying to write into key with shared prefix
    key1_shared_prefix = to_bytes(0x0234)
    with pytest.raises(MissingTrieNode) as set_exc_info:
        trie.set(key1_shared_prefix, b'val2')

    set_exc_message = str(set_exc_info.value)

    assert encode_hex(key1_shared_prefix) in set_exc_message
    assert encode_hex(trie_root_hash) in set_exc_message
    assert encode_hex(first_child_hash) in set_exc_message

    # Get exception when trying to delete key with missing data
    with pytest.raises(MissingTrieNode) as delete_exc_info:
        trie.delete(key1)

    delete_exc_message = str(delete_exc_info.value)

    assert encode_hex(key1) in delete_exc_message
    assert encode_hex(trie_root_hash) in delete_exc_message
    assert encode_hex(first_child_hash) in delete_exc_message

    # Get exception when checking if key exists with missing data
    key1_shared_prefix2 = to_bytes(0x0345)
    with pytest.raises(MissingTrieNode) as existance_exc_info:
        key1_shared_prefix2 in trie

    existance_exc_message = str(existance_exc_info.value)

    assert encode_hex(key1_shared_prefix2) in existance_exc_message
    assert encode_hex(trie_root_hash) in existance_exc_message
    assert encode_hex(first_child_hash) in existance_exc_message

    # Other keys are still accessible
    assert trie.get(key2) == b'val2'
コード例 #16
0
from eth_utils import (
    keccak,
)


trie = HexaryTrie(db={})
print(w3.toHex(trie.root_hash))
print(w3.toHex(keccak(trie.root_node)))
print(w3.toHex(keccak(rlp.encode(trie.root_node))))

print("1", w3.toHex(rlp.encode(1)))
print("ONE", w3.toHex(rlp.encode("ONE")))
print("2", w3.toHex(rlp.encode(2)))
print("TWO", w3.toHex(rlp.encode("TWO")))

trie.set(rlp.encode(1), rlp.encode("ONE"))
print(w3.toHex(trie.root_hash))
print(w3.toHex(keccak(rlp.encode(trie.get_node(trie.root_hash)))))
assert trie.root_hash == keccak(rlp.encode(trie.get_node(trie.root_hash)))
print(trie.get_node(trie.root_hash))


trie.set(rlp.encode(2), rlp.encode("TWO"))
print(w3.toHex(trie.root_hash))
print(w3.toHex(keccak(rlp.encode(trie.get_node(trie.root_hash)))))
assert trie.root_hash == keccak(rlp.encode(trie.get_node(trie.root_hash)))
print(trie.get_node(trie.root_hash))


trie.set(rlp.encode(3), rlp.encode("THREE"))
print(w3.toHex(trie.root_hash))