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
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
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
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))
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))
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)))
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
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])