diff --git a/test/erros/test_errors.py b/test/erros/test_errors.py new file mode 100644 index 0000000..b584e3b --- /dev/null +++ b/test/erros/test_errors.py @@ -0,0 +1,27 @@ +from merkly.utils import InvalidHashFunctionError +from merkly.mtree import MerkleTree +from pytest import raises + + +def test_make_proof_value_error(): + leafs = ["a", "b", "c", "d", "e", "f", "g", "h"] + tree = MerkleTree(leafs) + + invalid_leaf = "invalid" + with raises(ValueError) as error: + tree.make_proof(leafs, [], invalid_leaf) + + assert ( + str(error.value) == f"Leaf: {invalid_leaf} does not exist in the tree: {leafs}" + ) + + +def test_invalid_hash_function_error(): + def invalid_hash_function(data): + return 123 + + with raises(InvalidHashFunctionError): + MerkleTree( + ["a", "b", "c", "d"], + invalid_hash_function, + ) diff --git a/test/merkle_proof/test_merkle_proof.py b/test/merkle_proof/test_merkle_proof.py new file mode 100644 index 0000000..b2e6a7a --- /dev/null +++ b/test/merkle_proof/test_merkle_proof.py @@ -0,0 +1,49 @@ +from pytest import mark +from merkly.mtree import MerkleTree +from merkly.node import Node, Side + + +def test_proof_simple_odd_merkle(): + leafs = ["a", "b", "c", "d", "e"] + tree = MerkleTree(leafs, lambda x, y: x + y) + proof = [ + Node(data=b"abcd", side=Side.LEFT), + ] + + result = tree.proof("e") + assert result == proof + + +def test_proof_simple_merkle(): + leafs = ["a", "b", "c", "d"] + tree = MerkleTree(leafs) + proof = [ + Node( + side=Side.RIGHT, + data=bytes.fromhex( + "b5553de315e0edf504d9150af82dafa5c4667fa618ed0a6f19c69b41166c5510" + ), + ), + Node( + side=Side.RIGHT, + data=bytes.fromhex( + "d253a52d4cb00de2895e85f2529e2976e6aaaa5c18106b68ab66813e14415669" + ), + ), + ] + + result = tree.proof("a") + assert result == proof + + +@mark.parametrize( + "leaf", + ["a", "b", "c", "d", "e", "f", "g", "h", "1", "2", "3", "4", "5", "6", "7", "8"], +) +def test_verify_merkle(leaf: str): + tree = MerkleTree( + ["a", "b", "c", "d", "e", "f", "g", "h", "1", "2", "3", "4", "5", "6", "7", "8"] + ) + + result = tree.proof(leaf) + assert tree.verify(result, leaf) diff --git a/test/merkle_root/test_merkle_root.py b/test/merkle_root/test_merkle_root.py new file mode 100644 index 0000000..0cbad50 --- /dev/null +++ b/test/merkle_root/test_merkle_root.py @@ -0,0 +1,182 @@ +from merkly.mtree import MerkleTree +from typing import List +from pytest import mark +import hashlib + + +def test_simple_merkle_tree_constructor(): + leafs = ["a", "b", "c", "d"] + tree = MerkleTree(leafs) + + assert tree.raw_leafs == leafs + for i, j in zip( + tree.short_leafs, + [ + bytes.fromhex("3ac2"), + bytes.fromhex("b555"), + bytes.fromhex("0b42"), + bytes.fromhex("f191"), + ], + ): + assert i == j + assert tree.leafs == [ + bytes.fromhex( + "3ac225168df54212a25c1c01fd35bebfea408fdac2e31ddd6f80a4bbf9a5f1cb" + ), + bytes.fromhex( + "b5553de315e0edf504d9150af82dafa5c4667fa618ed0a6f19c69b41166c5510" + ), + bytes.fromhex( + "0b42b6393c1f53060fe3ddbfcd7aadcca894465a5a438f69c87d790b2299b9b2" + ), + bytes.fromhex( + "f1918e8562236eb17adc8502332f4c9c82bc14e19bfc0aa10ab674ff75b3d2f3" + ), + ] + + assert ( + tree.root.hex() + == "68203f90e9d07dc5859259d7536e87a6ba9d345f2552b5b9de2999ddce9ce1bf" + ) + + +@mark.parametrize( + "leafs, root", + [ + ( + ["a", "b", "c", "d", "e", "f", "g", "h", "1"], + "85d75312120b9d7cc325fef61d5c3b5de921a77f11049b187ddc5b90a3172c6d", + ), + ( + ["a", "b", "c", "d", "e", "f", "g", "h"], + "cd07272f4955ddcfdac38ff36dff9d3e4353498923679ab548ba87e34648e4a3", + ), + ( + ["a", "b", "c", "d", "e"], + "1dd0d2a6ae466d665cb26e1a31f07c57ae5df7d2bc559cd5826d417be9141a5d", + ), + ( + ["a", "b", "c", "d"], + "68203f90e9d07dc5859259d7536e87a6ba9d345f2552b5b9de2999ddce9ce1bf", + ), + ( + ["a", "b"], + "805b21d846b189efaeb0377d6bb0d201b3872a363e607c25088f025b0c6ae1f8", + ), + ], +) +def test_simple_merkle_root_with_keccak256(leafs: List[str], root: str): + tree = MerkleTree(leafs) + result = tree.root.hex() + assert result == root + + +@mark.parametrize( + "leafs, root", + [ + ( + ["a", "b", "c", "d", "e", "f", "g", "h", "1"], + "44611cac12a28960fa9f8d8bf93d9d73944b1425f3ba41d9cffe45c3aa3403d6", + ), + ( + ["a", "b", "c", "d", "e", "f", "g", "h"], + "bd7c8a900be9b67ba7df5c78a652a8474aedd78adb5083e80e49d9479138a23f", + ), + ( + ["a", "b", "c", "d", "e"], + "d71f8983ad4ee170f8129f1ebcdd7440be7798d8e1c80420bf11f1eced610dba", + ), + ( + ["a", "b", "c", "d"], + "14ede5e8e97ad9372327728f5099b95604a39593cac3bd38a343ad76205213e7", + ), + ( + ["a", "b"], + "e5a01fee14e0ed5c48714f22180f25ad8365b53f9779f79dc4a3d7e93963f94a", + ), + ], +) +def test_simple_merkle_root_with_sha_256(leafs: List[str], root: str): + def sha_256(x: bytes, y: bytes) -> bytes: + data = x + y + h = hashlib.sha256() + h.update(data) + return h.digest() + + tree = MerkleTree(leafs, hash_function=sha_256) + result = tree.root.hex() + assert result == root + + +@mark.parametrize( + "leafs, root", + [ + ( + ["a", "b", "c", "d", "e", "f", "g", "h", "1"], + "bf4835202b9091df8d6e44c0e36094fc5dee200ef2aeb385299e0e73d289947a", + ), + ( + ["a", "b", "c", "d", "e", "f", "g", "h"], + "c82d4fe15c85db42ec73121b5c482d86b95b78e05db8f707cde754e2bde30195", + ), + ( + ["a", "b", "c", "d", "e"], + "c79cb7cae8eeca849c11c804ccfde50216bbe143cd557cc0a8bb877c66496e4e", + ), + ( + ["a", "b", "c", "d"], + "565a2fdea5772b9dffdbb0081beeee36b2e9b952a8ef34fc5a58653fe4f9bd3d", + ), + ( + ["a", "b"], + "fb53027dcbe9bb65748239cf200d4512367aafe81c683d0584491bfe7b644279", + ), + ], +) +def test_simple_merkle_root_with_shake256(leafs: List[str], root: str): + def shake_256(x: bytes, y: bytes) -> bytes: + data = x + y + h = hashlib.shake_256() + h.update(data) + return h.digest(32) + + tree = MerkleTree(leafs, hash_function=shake_256) + result = tree.root.hex() + assert result == root + + +@mark.parametrize( + "leafs, root", + [ + ( + ["a", "b", "c", "d", "e", "f", "g", "h", "1"], + "8e106437be21dfca61170ed413a185a73cd081a4a5760a95df4ccc5488874260", + ), + ( + ["a", "b", "c", "d", "e", "f", "g", "h"], + "463baccb1666a42a1156e67f5961be418728a5bd80a97fda6d5054496d7646dc", + ), + ( + ["a", "b", "c", "d", "e"], + "b8efa384f64647583db7ea069c46ec746d4d8c0c1815040431db4134bc0b41fd", + ), + ( + ["a", "b", "c", "d"], + "5267fec4a5327f9d287233f95213afa39d3aad2fee1fa1384b032b79fb3441e8", + ), + ( + ["a", "b"], + "29df505440ebe180c00857e92b0694c56a33762b08944472492b0cbf6ec607e3", + ), + ], +) +def test_simple_merkle_root_with_sha3_256(leafs: List[str], root: str): + def sha3_256(x: bytes, y: bytes) -> bytes: + data = x + y + h = hashlib.sha3_256() + h.update(data) + return h.digest() + + tree = MerkleTree(leafs, hash_function=sha3_256) + result = tree.root.hex() + assert result == root diff --git a/test/test_merkle_tree.py b/test/test_merkle_tree.py deleted file mode 100644 index e8c2b1f..0000000 --- a/test/test_merkle_tree.py +++ /dev/null @@ -1,157 +0,0 @@ -""" -Testing Merkle Tree -""" - -from merkly.node import Side -from merkly.utils import InvalidHashFunctionError -from merkly.mtree import MerkleTree, Node -from pytest import raises, mark -from typing import List - - -def test_simple_merkle_tree_constructor(): - """ - Instantiated a simple Merkle Tree - """ - leafs = ["a", "b", "c", "d"] - tree = MerkleTree(leafs) - - assert tree.raw_leafs == leafs - for i, j in zip(tree.short_leafs, [ - bytes.fromhex("3ac2"), - bytes.fromhex("b555"), - bytes.fromhex("0b42"), - bytes.fromhex("f191"), - ]): - assert i == j - assert tree.leafs == [ - bytes.fromhex("3ac225168df54212a25c1c01fd35bebfea408fdac2e31ddd6f80a4bbf9a5f1cb"), - bytes.fromhex("b5553de315e0edf504d9150af82dafa5c4667fa618ed0a6f19c69b41166c5510"), - bytes.fromhex("0b42b6393c1f53060fe3ddbfcd7aadcca894465a5a438f69c87d790b2299b9b2"), - bytes.fromhex("f1918e8562236eb17adc8502332f4c9c82bc14e19bfc0aa10ab674ff75b3d2f3"), - ] - - assert tree.root.hex() == "68203f90e9d07dc5859259d7536e87a6ba9d345f2552b5b9de2999ddce9ce1bf" - - -@mark.parametrize( - "leafs, root", - [ - ( - ["a", "b", "c", "d", "e", "f", "g", "h", "1"], - "edcaf6c7e68ed0f1e6f9e6cef0b5be147172cdb2d1c10d0285123bb425c2ad4c", - ), - ( - ["a", "b", "c", "d", "e", "f", "g", "h"], - "2dfe93948ecb1a0903dbf034de56d6529e62679519a37ed3b5b3356ab27b7bb8", - ), - ( - ["a", "b", "c", "d", "e"], - "eaccbf1a24f8bfe6b2b4c3be14a4a782080fab07e3ecc81effa7e4d26f8daf80", - ), - ( - ["a", "b", "c", "d"], - "115cbb4775ed495f3d954dfa47164359a97762b40059d9502895def16eed609c", - ), - ( - ["a", "b"], - "414e3a845393ef6d68973ddbf5bd85ff524443cf0e06a361624f3d51b879ec1c", - ), - (["a"], "3ac225168df54212a25c1c01fd35bebfea408fdac2e31ddd6f80a4bbf9a5f1cb"), - ], -) -def test_simple_merkle_root(leafs: List[str], root: str): - """ - Generate a Root of a simple Merkle Tree - """ - tree = MerkleTree(leafs) - assert tree.root == root - - -def test_proof_simple_odd_merkle(): - """ - Instantiated a simple Merkle Tree - """ - leafs = ["a", "b", "c", "d", "e"] - tree = MerkleTree(leafs, lambda x, y: x + y) - proof = [ - Node(data="abcd", side=Side.LEFT), - ] - - assert tree.proof("e") == proof, "Proofs dont's match" - assert tree.verify(proof, "e"), "Proof dont's right" - - -def test_proof_simple_merkle(): - """ - Instantiated a simple Merkle Tree - """ - leafs = ["a", "b", "c", "d"] - tree = MerkleTree(leafs) - proof = [ - Node( - side=Side.RIGHT, - data="b5553de315e0edf504d9150af82dafa5c4667fa618ed0a6f19c69b41166c5510", - ), - Node( - side=Side.RIGHT, - data="64673cf40035df6d3a0d0143cc8426de49b9a93b9ad2d330cb4f0bc390a86d20", - ), - ] - - assert tree.proof("a") == proof - assert tree.verify(proof, "a") - - -@mark.parametrize( - "leaf", - ["a", "b", "c", "d", "e", "f", "g", "h", "1", "2", "3", "4", "5", "6", "7", "8"], -) -def test_verify_simple_merkle(leaf: str): - """ - Instantiated a simple Merkle Tree - """ - tree = MerkleTree( - ["a", "b", "c", "d", "e", "f", "g", "h", "1", "2", "3", "4", "5", "6", "7", "8"] - ) - - assert tree.verify(tree.proof(leaf), leaf), "Proof is False" - - -def test_make_proof_value_error(): - """ - Testa a captura de ValueError na função make_proof - """ - leafs = ["a", "b", "c", "d", "e", "f", "g", "h"] - tree = MerkleTree(leafs) - - invalid_leaf = "invalid" - with raises(ValueError) as error: - tree.make_proof(leafs, [], invalid_leaf) - - assert ( - str(error.value) == f"Leaf: {invalid_leaf} does not exist in the tree: {leafs}" - ) - - -def test_merkle_tree_repr(): - """ - Testa a representação em string (__repr__) da classe MerkleTree - """ - leafs = ["a", "b", "c", "d", "e", "f", "g", "h"] - tree = MerkleTree(leafs, lambda x, y: f"{x}{y}1") - - expected_repr = """MerkleTree(\nraw_leafs: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']\nleafs: ['a1', 'b1', 'c1', 'd1', 'e1', 'f1', 'g1', 'h1']\nshort_leafs: ['a1...', 'b1...', 'c1...', 'd1...', 'e1...', 'f1...', 'g1...', 'h1...'])""" - - assert repr(tree) == expected_repr - - -def test_invalid_hash_function_error(): - def invalid_hash_function_that_returns_an_integer_instead_of_a_string(data): - return 123 - - with raises(InvalidHashFunctionError): - MerkleTree( - ["a", "b", "c", "d"], - invalid_hash_function_that_returns_an_integer_instead_of_a_string, - )