def test_verify_tree(self): raw_leaves = [secrets.token_bytes(16) for _ in range(16)] m = MerkleTree(raw_leaves) tree_nodes = m.nodes[len(m.nodes) // 2:] tree_hash = m.hash_of_nodes() self.assertTrue(MerkleTree.verify_tree(tree_nodes, tree_hash))
def test_verify_tree_invalid(self): raw_leaves = [secrets.token_bytes(16) for _ in range(16)] m = MerkleTree(raw_leaves) # Set the last leaf to a random value obviously different then whatever was used to build the tree # this should cause validation to fail bad_leaves = m.leaves bad_leaves[-1] = secrets.token_bytes(16) self.assertFalse(MerkleTree.verify_tree(bad_leaves, m.root))
def validate_block_contender(self, block: BlockContender) -> bool: """ Helper method to validate a block contender. For a block contender to be valid it must: 1) Have a provable merkle tree, ie. all nodes must be hash of (left child + right child) 2) Be signed by at least 2/3 of the top 32 delegates :param block_contender: The BlockContender to validate :return: True if the BlockContender is valid, false otherwise """ def _validate_sigs(signatures, msg) -> bool: for sig in signatures: self.log.info("mn verifying signature: {}".format(sig)) if not sig.verify(msg, sig.sender): self.log.error( "!!!! Oh no why couldnt we verify sig {}???".format( sig)) return False return True # Development sanity checks (these should be removed in production) assert len( block.nodes ) >= 1, "Masternode got block contender with no nodes! {}".format( block) assert len(block.signatures) >= Constants.Testnet.Majority, \ "Received a block contender with only {} signatures (which is less than a majority of {}"\ .format(len(block.signatures), Constants.Testnet.Majority) # TODO -- ensure that this block contender's previous block is this Masternode's current block... # Prove Merkle Tree hash_of_nodes = MerkleTree.hash_nodes(block.nodes) tx_hashes = block.nodes[len(block.nodes) // 2:] if not MerkleTree.verify_tree(tx_hashes, hash_of_nodes): self.log.error( "\n\n\n\nCOULD NOT VERIFY MERKLE TREE FOR BLOCK CONTENDER {}\n\n\n" .format(block)) return False # Validate signatures if not _validate_sigs(block.signatures, hash_of_nodes): self.log.error( "MN COULD NOT VALIDATE SIGNATURES FOR CONTENDER {}".format( block)) return False return True
def test_verify_tree(self): raw_leaves = [secrets.token_bytes(16) for _ in range(16)] m = MerkleTree(raw_leaves) self.assertTrue(MerkleTree.verify_tree(m.leaves, m.root))