示例#1
0
async def windback(network, shard, header, availability_cache):
    assert WINDBACK_LENGTH > 0

    def add_parent_header(headers):
        parent_header = shard.headers_by_hash[headers[-1].parent_hash]
        return headers + [parent_header]

    header_chain = iterate(add_parent_header, [header])
    n_parents = min(WINDBACK_LENGTH - 1, header.number)
    headers_to_check = reversed(nth(n_parents,
                                    header_chain))  # from root to leaf

    availabilities = {}  # {hash: available, ...} for all headers checked here

    for header in headers_to_check:
        if header.hash in availabilities:
            available = availability_cache[header.hash]
        else:
            available = check_availability(header)
            availabilities[header.hash] = available

        if not available:
            # don't check children of unavailable collations
            break

    # remaining collations are unavailable as one of their ancestors is unavailable
    for header in headers_to_check:
        availabilities[header.hash] = False

    return availabilities
示例#2
0
def calc_merkle_tree_from_leaves(leaves: Sequence[Hash32]) -> MerkleTree:
    if len(leaves) == 0:
        raise ValueError("No leaves given")
    n_layers = math.log2(len(leaves)) + 1
    if not n_layers.is_integer():
        raise ValueError("Number of leaves is not a power of two")
    n_layers = int(n_layers)

    reversed_tree = tuple(take(n_layers, iterate(_hash_layer, leaves)))
    tree = MerkleTree(tuple(reversed(reversed_tree)))

    if len(tree[0]) != 1:
        raise Exception("Invariant: There must only be one root")

    return tree
示例#3
0
def calc_merkle_tree(items: Sequence[Hashable]) -> MerkleTree:
    """Calculate the Merkle tree corresponding to a list of items."""
    if len(items) == 0:
        raise ValidationError("No items given")
    n_layers = math.log2(len(items)) + 1
    if not n_layers.is_integer():
        raise ValidationError("Item number is not a power of two")
    n_layers = int(n_layers)

    leaves = tuple(keccak(item) for item in items)
    tree = cast(MerkleTree, tuple(take(n_layers, iterate(_hash_layer, leaves)))[::-1])
    if len(tree[0]) != 1:
        raise Exception("Invariant: There must only be one root")

    return tree
示例#4
0
    def get_ancestors(self, limit: int, header: BlockHeader) -> Tuple[BaseBlock, ...]:
        """
        Return `limit` number of ancestor blocks from the current canonical head.
        """
        ancestor_count = min(header.block_number, limit)

        # We construct a temporary block object
        vm_class = self.get_vm_class_for_block_number(header.block_number)
        block_class = vm_class.get_block_class()
        block = block_class(header=header, uncles=[])

        ancestor_generator = iterate(compose(
            self.get_block_by_hash,
            operator.attrgetter('parent_hash'),
            operator.attrgetter('header'),
        ), block)
        # we peel off the first element from the iterator which will be the
        # temporary block object we constructed.
        next(ancestor_generator)

        return tuple(take(ancestor_count, ancestor_generator))
示例#5
0
文件: common.py 项目: mhchia/trinity
def get_branch_indices(node_index: int, depth: int) -> Iterable[int]:
    """
    Get the indices of all ancestors up until the root for a node with a given depth.
    """
    yield from take(depth, iterate(lambda index: index // 2, node_index))
示例#6
0
def get_branch_indices(node_index: int, depth: int) -> Sequence[int]:
    """Get the indices of all ancestors up until the root for a node with a given depth."""
    return tuple(take(depth, iterate(lambda index: index // 2, node_index)))
示例#7
0
    try:
        list_data[index] = new_value
    except IndexError:
        raise ValidationError(
            "the length of the given tuple_data is {}, the given index {} is out of index".format(
                len(tuple_data),
                index,
            )
        )
    else:
        return tuple(list_data)


TreeHeight = 32
EmptyNodeHashes = tuple(
    take(TreeHeight, iterate(lambda node_hash: hash_eth2(node_hash + node_hash), b'\x00' * 32))
)


def get_merkle_proof(tree: MerkleTree, item_index: int) -> Iterable[Hash32]:
    """
    Read off the Merkle proof for an item from a Merkle tree.
    """
    if item_index < 0 or item_index >= len(tree[-1]) or tree[-1][item_index] == EmptyNodeHashes[0]:
        raise ValidationError("Item index out of range")

    branch_indices = get_branch_indices(item_index, len(tree))
    proof_indices = [i ^ 1 for i in branch_indices][:-1]  # get sibling by flipping rightmost bit
    return tuple(
        layer[proof_index]
        for layer, proof_index
示例#8
0
from eth_typing import (
    Hash32, )

from .common import (  # noqa: F401
    _calc_parent_hash, _hash_layer, get_branch_indices, get_merkle_proof,
    get_root, MerkleTree, MerkleProof,
)

if TYPE_CHECKING:
    from typing import Tuple  # noqa: F401

TreeDepth = 32
EmptyNodeHashes = tuple(
    take(
        TreeDepth,
        iterate(lambda node_hash: hash_eth2(node_hash + node_hash),
                b'\x00' * 32)))


def verify_merkle_proof(root: Hash32, leaf: Hash32, index: int,
                        proof: MerkleProof) -> bool:
    """
    Verify that the given ``item`` is on the merkle branch ``proof``
    starting with the given ``root``.
    """
    assert len(proof) == TreeDepth
    value = leaf
    for i in range(TreeDepth):
        if index // (2**i) % 2:
            value = hash_eth2(proof[i] + value)
        else:
            value = hash_eth2(value + proof[i])