From 6e6f1065fc2a5c290b0cc33f70721d860bd7a982 Mon Sep 17 00:00:00 2001 From: Mete Karasakal <32202283+karasakalmt@users.noreply.github.com> Date: Wed, 6 Dec 2023 15:51:32 +0200 Subject: [PATCH] feat: merkle proof spec test (#496) --- .../state_transition/predicates.ex | 13 +++-- lib/spec/runners/light_client.ex | 52 +++++++++++++++++++ 2 files changed, 60 insertions(+), 5 deletions(-) create mode 100644 lib/spec/runners/light_client.ex diff --git a/lib/lambda_ethereum_consensus/state_transition/predicates.ex b/lib/lambda_ethereum_consensus/state_transition/predicates.ex index 189f01277..cf3885d31 100644 --- a/lib/lambda_ethereum_consensus/state_transition/predicates.ex +++ b/lib/lambda_ethereum_consensus/state_transition/predicates.ex @@ -123,11 +123,14 @@ defmodule LambdaEthereumConsensus.StateTransition.Predicates do SszTypes.root() ) :: boolean def is_valid_merkle_branch?(leaf, branch, depth, index, root) do - root == - branch - |> Enum.take(depth) - |> Enum.with_index() - |> Enum.reduce(leaf, fn {v, i}, value -> hash_merkle_node(v, value, index, i) end) + root == generate_merkle_proof(leaf, branch, depth, index) + end + + def generate_merkle_proof(leaf, branch, depth, index) do + branch + |> Enum.take(depth) + |> Enum.with_index() + |> Enum.reduce(leaf, fn {v, i}, value -> hash_merkle_node(v, value, index, i) end) end defp hash_merkle_node(value_1, value_2, index, i) do diff --git a/lib/spec/runners/light_client.ex b/lib/spec/runners/light_client.ex new file mode 100644 index 000000000..131d50b37 --- /dev/null +++ b/lib/spec/runners/light_client.ex @@ -0,0 +1,52 @@ +defmodule LightClientTestRunner do + alias LambdaEthereumConsensus.StateTransition.Predicates + use ExUnit.CaseTemplate + use TestRunner + + @moduledoc """ + Runner for LightClient test cases. See: https://github.com/ethereum/consensus-specs/tree/dev/tests/formats/light_client + """ + + # Remove handler from here once you implement the corresponding functions + @disabled_handlers [ + # "single_merkle_proof", + "sync", + "update_ranking" + ] + + @impl TestRunner + def skip?(%SpecTestCase{} = testcase) do + Enum.member?(@disabled_handlers, testcase.handler) + end + + @impl TestRunner + def run_test_case(%SpecTestCase{} = testcase) do + handle(testcase.handler, testcase) + end + + defp handle("single_merkle_proof", testcase) do + case_dir = SpecTestCase.dir(testcase) + + object_root = + SpecTestUtils.read_ssz_from_file!( + case_dir <> "/object.ssz_snappy", + String.to_existing_atom("Elixir.SszTypes." <> testcase.suite) + ) + |> Ssz.hash_tree_root!() + + %{leaf: leaf, leaf_index: leaf_index, branch: branch} = + YamlElixir.read_from_file!(case_dir <> "/proof.yaml") + |> SpecTestUtils.sanitize_yaml() + + res = + Predicates.is_valid_merkle_branch?( + leaf, + branch, + Constants.deposit_contract_tree_depth() + 1, + leaf_index, + object_root + ) + + assert true == res + end +end