From eac1b66e73da2f72972964baf1d5e358a74b78bc Mon Sep 17 00:00:00 2001 From: Godspower Eze <61994334+Godspower-Eze@users.noreply.github.com> Date: Tue, 12 Dec 2023 13:22:45 +0100 Subject: [PATCH 01/19] Fix spec-test runner command --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 424a827b8..fdea9d514 100644 --- a/README.md +++ b/README.md @@ -127,9 +127,9 @@ Or by a single runner in all configs, with: make spec-test-runner-`runner` # Some examples -make spec-test-config-ssz_static -make spec-test-config-bls -make spec-test-config-operations +make spec-test-runner-ssz_static +make spec-test-runner-bls +make spec-test-runner-operations ``` The complete list of test runners can be found [here](https://github.com/ethereum/consensus-specs/tree/dev/tests/formats). From 3a91893014fabf843baf563bb2c3e5ef24407cf7 Mon Sep 17 00:00:00 2001 From: Godspower Eze Date: Wed, 17 Jan 2024 08:52:22 +0100 Subject: [PATCH 02/19] feat: added boilerplate for merkleization benchmark --- bench/ssz.exs | 20 ++++++++++++++++++++ lib/ssz_ex.ex | 24 ++++++++++++++---------- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/bench/ssz.exs b/bench/ssz.exs index 83454e6cb..6afa6066e 100644 --- a/bench/ssz.exs +++ b/bench/ssz.exs @@ -34,3 +34,23 @@ Benchee.run( warmup: 2, time: 5 ) + + +## Benchmark Merkleization + +list = Stream.cycle([65_535]) |> Enum.take(316) +schema = {:list, {:int, 16}, 1024} +packed_chunks = SszEx.pack(list, schema) +limit = SszEx.chunk_count(schema) + +Benchee.run( + %{ + "SszEx.merkleize_chunks" => fn {chunks, leaf_count} -> SszEx.merkleize_chunks(chunks, leaf_count) end, + "SszEx.merkleize_chunks_with_virtual_padding" => fn {chunks, leaf_count} -> SszEx.merkleize_chunks_with_virtual_padding(chunks, leaf_count) end + }, + inputs: %{ + "args" => {packed_chunks, limit} + }, + warmup: 2, + time: 5 +) \ No newline at end of file diff --git a/lib/ssz_ex.ex b/lib/ssz_ex.ex index cd5bf977b..9d62f5dd4 100644 --- a/lib/ssz_ex.ex +++ b/lib/ssz_ex.ex @@ -142,6 +142,10 @@ defmodule LambdaEthereumConsensus.SszEx do end end + def merkleize_chunks_with_virtual_padding(chunks, leaf_count \\ nil) do + <<>> + end + @spec pack(boolean, :bool) :: binary() def pack(true, :bool), do: <<1::@bits_per_chunk-little>> def pack(false, :bool), do: @zero_chunk @@ -162,6 +166,16 @@ defmodule LambdaEthereumConsensus.SszEx do end end + def chunk_count({:list, {:int, size}, max_size}) do + size = size_of({:int, size}) + (max_size * size + 31) |> div(32) + end + + def chunk_count({:list, :bool, max_size}) do + size = size_of(:bool) + (max_size * size + 31) |> div(32) + end + ################# ### Private functions ################# @@ -600,16 +614,6 @@ defmodule LambdaEthereumConsensus.SszEx do defp size_of({:int, size}), do: size |> div(@bits_per_byte) - defp chunk_count({:list, {:int, size}, max_size}) do - size = size_of({:int, size}) - (max_size * size + 31) |> div(32) - end - - defp chunk_count({:list, :bool, max_size}) do - size = size_of(:bool) - (max_size * size + 31) |> div(32) - end - defp pack_basic_type_list(list, schema) do list |> Enum.reduce(<<>>, fn x, acc -> From 74e73b47327e8612f12c0c048ca738a64a552638 Mon Sep 17 00:00:00 2001 From: Godspower Eze Date: Fri, 19 Jan 2024 12:17:04 +0100 Subject: [PATCH 03/19] update --- bench/ssz.exs | 11 ++- lib/ssz_ex.ex | 191 +++++++++++++++++++++++++++++++++++++- test/unit/ssz_ex_test.exs | 42 +++++++++ 3 files changed, 239 insertions(+), 5 deletions(-) diff --git a/bench/ssz.exs b/bench/ssz.exs index 6afa6066e..ff4770980 100644 --- a/bench/ssz.exs +++ b/bench/ssz.exs @@ -35,7 +35,6 @@ Benchee.run( time: 5 ) - ## Benchmark Merkleization list = Stream.cycle([65_535]) |> Enum.take(316) @@ -45,12 +44,16 @@ limit = SszEx.chunk_count(schema) Benchee.run( %{ - "SszEx.merkleize_chunks" => fn {chunks, leaf_count} -> SszEx.merkleize_chunks(chunks, leaf_count) end, - "SszEx.merkleize_chunks_with_virtual_padding" => fn {chunks, leaf_count} -> SszEx.merkleize_chunks_with_virtual_padding(chunks, leaf_count) end + "SszEx.merkleize_chunks" => fn {chunks, leaf_count} -> + SszEx.merkleize_chunks(chunks, leaf_count) + end, + "SszEx.merkleize_chunks_with_virtual_padding" => fn {chunks, leaf_count} -> + SszEx.merkleize_chunks_with_virtual_padding(chunks, leaf_count) + end }, inputs: %{ "args" => {packed_chunks, limit} }, warmup: 2, time: 5 -) \ No newline at end of file +) diff --git a/lib/ssz_ex.ex b/lib/ssz_ex.ex index a2e522641..b7e566198 100644 --- a/lib/ssz_ex.ex +++ b/lib/ssz_ex.ex @@ -14,6 +14,123 @@ defmodule LambdaEthereumConsensus.SszEx do @bits_per_byte 8 @bits_per_chunk @bytes_per_chunk * @bits_per_byte @zero_chunk <<0::size(@bits_per_chunk)>> + @zero_hashes <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 245, 165, 253, 66, 209, 106, 32, 48, 39, 152, 239, 110, 211, 9, + 151, 155, 67, 0, 61, 35, 32, 217, 240, 232, 234, 152, 49, 169, 39, 89, 251, 75, + 219, 86, 17, 78, 0, 253, 212, 193, 248, 92, 137, 43, 243, 90, 201, 168, 146, 137, + 170, 236, 177, 235, 208, 169, 108, 222, 96, 106, 116, 139, 93, 113, 199, 128, 9, + 253, 240, 127, 197, 106, 17, 241, 34, 55, 6, 88, 163, 83, 170, 165, 66, 237, 99, + 228, 76, 75, 193, 95, 244, 205, 16, 90, 179, 60, 83, 109, 152, 131, 127, 45, 209, + 101, 165, 93, 94, 234, 233, 20, 133, 149, 68, 114, 213, 111, 36, 109, 242, 86, + 191, 60, 174, 25, 53, 42, 18, 60, 158, 253, 224, 82, 170, 21, 66, 159, 174, 5, + 186, 212, 208, 177, 215, 198, 77, 166, 77, 3, 215, 161, 133, 74, 88, 140, 44, + 184, 67, 12, 13, 48, 216, 141, 223, 238, 212, 0, 168, 117, 85, 150, 178, 25, 66, + 193, 73, 126, 17, 76, 48, 46, 97, 24, 41, 15, 145, 230, 119, 41, 118, 4, 31, 161, + 135, 235, 13, 219, 165, 126, 53, 246, 210, 134, 103, 56, 2, 164, 175, 89, 117, + 226, 37, 6, 199, 207, 76, 100, 187, 107, 229, 238, 17, 82, 127, 44, 38, 132, 100, + 118, 253, 95, 197, 74, 93, 67, 56, 81, 103, 201, 81, 68, 242, 100, 63, 83, 60, + 200, 91, 185, 209, 107, 120, 47, 141, 125, 177, 147, 80, 109, 134, 88, 45, 37, + 36, 5, 184, 64, 1, 135, 146, 202, 210, 191, 18, 89, 241, 239, 90, 165, 248, 135, + 225, 60, 178, 240, 9, 79, 81, 225, 255, 255, 10, 215, 230, 89, 119, 47, 149, 52, + 193, 149, 200, 21, 239, 196, 1, 78, 241, 225, 218, 237, 68, 4, 192, 99, 133, 209, + 17, 146, 233, 43, 108, 240, 65, 39, 219, 5, 68, 28, 216, 51, 16, 122, 82, 190, + 133, 40, 104, 137, 14, 67, 23, 230, 160, 42, 180, 118, 131, 170, 117, 150, 66, + 32, 183, 208, 95, 135, 95, 20, 0, 39, 239, 81, 24, 162, 36, 123, 187, 132, 206, + 143, 47, 15, 17, 35, 98, 48, 133, 218, 247, 150, 12, 50, 159, 95, 223, 106, 245, + 245, 187, 219, 107, 233, 239, 138, 166, 24, 228, 191, 128, 115, 150, 8, 103, 23, + 30, 41, 103, 111, 139, 40, 77, 234, 106, 8, 168, 94, 181, 141, 144, 15, 94, 24, + 46, 60, 80, 239, 116, 150, 158, 161, 108, 119, 38, 197, 73, 117, 124, 194, 53, + 35, 195, 105, 88, 125, 167, 41, 55, 132, 212, 154, 117, 2, 255, 207, 176, 52, 11, + 29, 120, 133, 104, 133, 0, 202, 48, 129, 97, 167, 249, 107, 98, 223, 157, 8, 59, + 113, 252, 200, 242, 187, 143, 230, 177, 104, 146, 86, 192, 211, 133, 244, 47, 91, + 190, 32, 39, 162, 44, 25, 150, 225, 16, 186, 151, 193, 113, 211, 229, 148, 141, + 233, 43, 235, 141, 13, 99, 195, 158, 186, 222, 133, 9, 224, 174, 60, 156, 56, + 118, 251, 95, 161, 18, 190, 24, 249, 5, 236, 172, 254, 203, 146, 5, 118, 3, 171, + 149, 238, 200, 178, 229, 65, 202, 212, 233, 29, 227, 131, 133, 242, 224, 70, 97, + 159, 84, 73, 108, 35, 130, 203, 108, 172, 213, 185, 140, 38, 245, 164, 248, 147, + 233, 8, 145, 119, 117, 182, 43, 255, 35, 41, 77, 187, 227, 161, 205, 142, 108, + 193, 195, 91, 72, 1, 136, 123, 100, 106, 111, 129, 241, 127, 205, 219, 167, 181, + 146, 227, 19, 51, 147, 193, 97, 148, 250, 199, 67, 26, 191, 47, 84, 133, 237, + 113, 29, 178, 130, 24, 60, 129, 158, 8, 235, 170, 138, 141, 127, 227, 175, 140, + 170, 8, 90, 118, 57, 168, 50, 0, 20, 87, 223, 185, 18, 138, 128, 97, 20, 42, 208, + 51, 86, 41, 255, 35, 255, 156, 254, 179, 195, 55, 215, 165, 26, 111, 191, 0, 185, + 227, 76, 82, 225, 201, 25, 92, 150, 155, 212, 231, 160, 191, 213, 29, 92, 91, + 237, 156, 17, 103, 231, 31, 10, 168, 60, 195, 46, 223, 190, 250, 159, 77, 62, 1, + 116, 202, 133, 24, 46, 236, 159, 58, 9, 246, 166, 192, 223, 99, 119, 165, 16, + 215, 49, 32, 111, 168, 10, 80, 187, 106, 190, 41, 8, 80, 88, 241, 98, 18, 33, 42, + 96, 238, 200, 240, 73, 254, 203, 146, 216, 200, 224, 168, 75, 192, 33, 53, 43, + 254, 203, 237, 221, 233, 147, 131, 159, 97, 76, 61, 172, 10, 62, 227, 117, 67, + 249, 180, 18, 177, 97, 153, 220, 21, 142, 35, 181, 68, 97, 158, 49, 39, 36, 187, + 109, 124, 49, 83, 237, 157, 231, 145, 215, 100, 163, 102, 179, 137, 175, 19, 197, + 139, 248, 168, 217, 4, 129, 164, 103, 101, 124, 221, 41, 134, 38, 130, 80, 98, + 141, 12, 16, 227, 133, 197, 140, 97, 145, 230, 251, 224, 81, 145, 188, 192, 79, + 19, 63, 44, 234, 114, 193, 196, 132, 137, 48, 189, 123, 168, 202, 197, 70, 97, 7, + 33, 19, 251, 39, 136, 105, 224, 123, 184, 88, 127, 145, 57, 41, 51, 55, 77, 1, + 123, 203, 225, 136, 105, 255, 44, 34, 178, 140, 193, 5, 16, 217, 133, 50, 146, + 128, 51, 40, 190, 79, 176, 232, 4, 149, 232, 187, 141, 39, 31, 91, 136, 150, 54, + 181, 254, 40, 231, 159, 27, 133, 15, 134, 88, 36, 108, 233, 182, 161, 231, 180, + 159, 192, 109, 183, 20, 62, 143, 224, 180, 242, 176, 197, 82, 58, 92, 152, 94, + 146, 159, 112, 175, 40, 208, 189, 209, 169, 10, 128, 143, 151, 127, 89, 124, 124, + 119, 140, 72, 158, 152, 211, 189, 137, 16, 211, 26, 192, 247, 198, 246, 126, 2, + 230, 228, 225, 189, 239, 185, 148, 198, 9, 137, 83, 243, 70, 54, 186, 43, 108, + 162, 10, 71, 33, 210, 178, 106, 136, 103, 34, 255, 28, 154, 126, 95, 241, 207, + 72, 180, 173, 21, 130, 211, 244, 228, 161, 0, 79, 59, 32, 216, 197, 162, 183, 19, + 135, 164, 37, 74, 217, 51, 235, 197, 47, 7, 90, 226, 41, 100, 107, 111, 106, 237, + 25, 165, 227, 114, 207, 41, 80, 129, 64, 30, 184, 147, 255, 89, 155, 63, 154, + 204, 12, 13, 62, 125, 50, 137, 33, 222, 181, 150, 18, 7, 104, 1, 232, 205, 97, + 89, 33, 7, 181, 198, 124, 121, 184, 70, 89, 92, 198, 50, 12, 57, 91, 70, 54, 44, + 191, 185, 9, 253, 178, 54, 173, 36, 17, 180, 228, 136, 56, 16, 160, 116, 184, 64, + 70, 70, 137, 152, 108, 63, 138, 128, 145, 130, 126, 23, 195, 39, 85, 216, 251, + 54, 135, 186, 59, 164, 159, 52, 44, 119, 245, 161, 248, 155, 236, 131, 216, 17, + 68, 110, 26, 70, 113, 57, 33, 61, 100, 11, 106, 116, 247, 33, 13, 79, 142, 126, + 16, 57, 121, 14, 123, 244, 239, 162, 7, 85, 90, 16, 166, 219, 29, 212, 185, 93, + 163, 19, 170, 168, 139, 136, 254, 118, 173, 33, 181, 22, 203, 198, 69, 255, 227, + 74, 181, 222, 28, 138, 239, 140, 212, 231, 248, 210, 181, 30, 142, 20, 86, 173, + 199, 86, 60, 218, 32, 111, 107, 254, 141, 43, 204, 66, 55, 183, 74, 80, 71, 5, + 142, 244, 85, 51, 158, 205, 115, 96, 203, 99, 191, 187, 142, 229, 68, 142, 100, + 48, 186, 4, 167, 242, 60, 233, 24, 23, 64, 220, 34, 12, 129, 71, 130, 101, 79, + 238, 106, 206, 185, 241, 236, 146, 34, 196, 226, 70, 125, 10, 177, 104, 8, 55, + 174, 249, 71, 108, 137, 89, 10, 44, 140, 201, 179, 183, 79, 73, 103, 199, 87, + 196, 157, 152, 102, 164, 75, 172, 242, 31, 162, 237, 103, 93, 223, 162, 154, 66, + 188, 173, 130, 246, 169, 228, 18, 132, 216, 8, 234, 211, 25, 242, 159, 59, 8, 32, + 157, 104, 15, 14, 44, 231, 21, 16, 208, 113, 226, 5, 209, 166, 109, 53, 74, 103, + 185, 207, 23, 149, 113, 216, 229, 249, 119, 146, 113, 110, 141, 212, 236, 68, 25, + 104, 57, 163, 247, 198, 183, 79, 139, 172, 250, 250, 48, 37, 242, 248, 149, 9, + 194, 199, 28, 116, 251, 160, 205, 146, 133, 142, 244, 155, 7, 128, 251, 84, 121, + 116, 108, 138, 155, 252, 179, 70, 51, 52, 167, 193, 231, 246, 112, 90, 166, 1, + 26, 106, 148, 150, 69, 1, 109, 180, 172, 222, 12, 169, 171, 214, 109, 199, 157, + 130, 102, 66, 48, 86, 7, 150, 253, 117, 102, 79, 174, 247, 68, 238, 78, 82, 215, + 39, 30, 43, 187, 118, 159, 145, 237, 111, 155, 116, 216, 182, 148, 245, 102, 6, + 133, 44, 123, 163, 174, 74, 65, 127, 232, 84, 91, 20, 43, 200, 159, 74, 220, 215, + 174, 19, 148, 28, 186, 183, 117, 11, 131, 233, 240, 166, 109, 22, 190, 100, 120, + 143, 175, 204, 74, 165, 32, 57, 154, 219, 174, 209, 149, 248, 177, 44, 78, 179, + 30, 193, 1, 104, 229, 10, 171, 198, 89, 166, 174, 165, 22, 220, 232, 51, 215, + 166, 113, 96, 230, 139, 244, 201, 4, 74, 83, 7, 125, 242, 114, 122, 208, 12, 243, + 111, 73, 73, 199, 182, 129, 169, 18, 20, 12, 187, 48, 158, 171, 240, 149, 220, + 103, 20, 249, 244, 216, 100, 187, 165, 175, 250, 224, 179, 90, 226, 245, 227, 86, + 91, 204, 58, 71, 178, 18, 118, 119, 1, 34, 106, 142, 190, 250, 40, 134, 101, 166, + 68, 165, 2, 115, 51, 94, 251, 182, 16, 81, 15, 36, 27, 91, 114, 12, 138, 54, 141, + 89, 166, 154, 93, 65, 171, 253, 153, 84, 37, 130, 118, 37, 147, 129, 49, 175, 12, + 79, 51, 254, 11, 212, 104, 140, 34, 44, 33, 250, 157, 168, 232, 156, 170, 3, 248, + 68, 44, 100, 46, 245, 15, 161, 166, 103, 166, 230, 209, 5, 199, 124, 92, 195, + 254, 200, 215, 170, 37, 112, 207, 26, 48, 119, 181, 3, 195, 128, 105, 160, 160, + 141, 252, 155, 66, 217, 108, 45, 225, 155, 109, 18, 123, 138, 225, 54, 221, 207, + 62, 90, 208, 220, 228, 34, 196, 90, 86, 246, 31, 106, 116, 125, 52, 131, 130, + 175, 9, 109, 190, 11, 240, 134, 199, 187, 57, 178, 162, 192, 188, 54, 182, 33, + 171, 12, 115, 142, 152, 133, 215, 49, 216, 23, 64, 58, 177, 52, 117, 29, 25, 18, + 105, 2, 108, 134, 153, 78, 170, 139, 67, 168, 59, 74, 209, 246, 208, 231, 115, + 129, 196, 226, 151, 74, 251, 200, 246, 154, 116, 82, 97, 29, 178, 210, 62, 174, + 38, 249, 189, 187, 136, 149, 142, 244, 76, 100, 208, 254, 152, 123, 233, 247, 38, + 173, 249, 56, 245, 15, 108, 114, 92, 127, 129, 96, 55, 191, 228, 82, 205, 30, + 123, 163, 90, 196, 126, 220, 180, 154, 154, 43, 39, 174, 202, 112, 220, 228, 131, + 203, 125, 237, 31, 44, 234, 26, 245, 31, 178, 139, 98, 136, 124, 57, 153, 138, + 201, 254, 244, 223, 222, 218, 31, 7, 224, 113, 186, 85, 138, 23, 58, 253, 6, 203, + 195, 255, 29, 89, 249, 139, 108, 85, 29, 149, 8, 147, 87, 5, 125, 92, 139, 226, + 100, 2, 39, 158, 157, 240, 177, 223, 26, 16, 183, 43, 243, 146, 127, 47, 138, 24, + 31, 124, 153, 221, 33, 90, 117, 41, 191, 226, 150, 169, 96, 58, 20, 70, 115, 113, + 134, 210, 26, 235, 139, 199, 174, 89, 225, 253, 33, 236, 197, 2, 201, 177, 20, + 95, 57, 80, 203, 125, 62, 56, 66, 68, 111, 129, 164, 240, 223, 29, 245, 55, 206, + 225, 57, 239, 100, 234, 152, 75, 217>> @spec hash(iodata()) :: binary() def hash(data), do: :crypto.hash(:sha256, data) @@ -164,7 +281,75 @@ defmodule LambdaEthereumConsensus.SszEx do end def merkleize_chunks_with_virtual_padding(chunks, leaf_count \\ nil) do - <<>> + chunks_count = chunks |> get_chunks_len() + + if chunks_count == 0 and leaf_count == nil do + @zero_chunk + else + power = leaf_count |> compute_pow() + height = power + 1 + layers = chunks + last_index = chunks_count - 1 + + 1..(height - 1) + |> Enum.reverse() + |> Enum.reduce(last_index, fn i, acc_last_index -> + 0..(2 ** i - 1) + |> Enum.filter(fn x -> rem(x, 2) == 0 end) + |> Enum.reduce_while(layers, fn j, acc_layers -> + parent_index = j |> div(2) + + nodes = + cond do + j < acc_last_index -> + start = parent_index * @bytes_per_chunk + stop = (j + 2) * @bytes_per_chunk + focus = acc_layers |> :binary.part(start, stop - start) + focus_len = focus |> byte_size() + children_index = focus_len - 2 * @bytes_per_chunk + <> = focus + + <> = + children + + {parent, left, right} + + j == acc_last_index -> + start = parent_index * @bytes_per_chunk + stop = (j + 1) * @bytes_per_chunk + focus = acc_layers |> :binary.part(start, stop - start) + focus_len = focus |> byte_size() + children_index = focus_len - @bytes_per_chunk + <> = focus + depth = height - i - 1 + + right = @zero_hashes |> :binary.part(depth - 1, @bytes_per_chunk) + {parent, left, right} + + true -> + :error + end + + case nodes do + :error -> + {:halt, acc_layers} + + {parent, left, right} -> + if j == 0 do + hash = hash_nodes(left, right) + acc_layers |> IO.inspect() + {:cont, acc_layers} + else + parent = hash_nodes(left, right) + acc_layers |> IO.inspect() + {:cont, acc_layers} + end + end + end) + + acc_last_index |> div(2) + end) + end end @spec pack(boolean, :bool) :: binary() @@ -687,4 +872,8 @@ defmodule LambdaEthereumConsensus.SszEx do defp get_chunks_len(chunks) do chunks |> byte_size() |> div(@bytes_per_chunk) end + + defp compute_pow(value) do + :math.log2(value) |> trunc() + end end diff --git a/test/unit/ssz_ex_test.exs b/test/unit/ssz_ex_test.exs index 2f9c5fec3..7bb846c0c 100644 --- a/test/unit/ssz_ex_test.exs +++ b/test/unit/ssz_ex_test.exs @@ -145,6 +145,48 @@ defmodule Unit.SSZExTest do # assert root |> Base.encode16(case: :lower) == expected_value end + test "merklelization of chunks with virtual padding" do + chunks = <<0::248>> + root = SszEx.merkleize_chunks_with_virtual_padding(chunks) + expected_value = "0000000000000000000000000000000000000000000000000000000000000000" + # assert root |> Base.encode16(case: :lower) == expected_value + + zero = <<0::256>> + ones = 0..31 |> Enum.reduce(<<>>, fn _, acc -> <<1>> <> acc end) + + # chunks = zero <> zero + # root = chunks |> SszEx.merkleize_chunks_with_virtual_padding(2) + # expected_value = "f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b" + # assert root |> Base.encode16(case: :lower) == expected_value + + # ones = 0..31 |> Enum.reduce(<<>>, fn _, acc -> <<1>> <> acc end) + + # chunks = ones <> ones + # root = chunks |> SszEx.merkleize_chunks(2) + # expected_value = "7c8975e1e60a5c8337f28edf8c33c3b180360b7279644a9bc1af3c51e6220bf5" + # assert root |> Base.encode16(case: :lower) == expected_value + + # chunks = zero <> zero <> zero <> zero + # root = chunks |> SszEx.merkleize_chunks_with_virtual_padding(4) + # expected_value = "db56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71" + # assert root |> Base.encode16(case: :lower) == expected_value + + chunks = ones <> ones <> ones <> ones <> ones <> ones + root = chunks |> SszEx.merkleize_chunks_with_virtual_padding(8) + # expected_value = "0ef7df63c204ef203d76145627b8083c49aa7c55ebdee2967556f55a4f65a238" + # assert root |> Base.encode16(case: :lower) == expected_value + + # chunks = zero <> zero <> zero <> zero <> zero <> zero <> zero <> zero + # root = chunks |> SszEx.merkleize_chunks(8) + # expected_value = "c78009fdf07fc56a11f122370658a353aaa542ed63e44c4bc15ff4cd105ab33c" + # assert root |> Base.encode16(case: :lower) == expected_value + + # chunks = ones + # root = chunks |> SszEx.merkleize_chunks(4) + # expected_value = "29797eded0e83376b70f2bf034cc0811ae7f1414653b1d720dfd18f74cf13309" + # assert root |> Base.encode16(case: :lower) == expected_value + end + test "hash tree root of list" do ## reference: https://github.com/ralexstokes/ssz-rs/blob/1f94d5dfc70c86dab672e91ac46af04a5f96c342/ssz-rs/src/merkleization/mod.rs#L459 From b3244457bf0f4c1ee105acb94d51d2d7e4682a0f Mon Sep 17 00:00:00 2001 From: Godspower Eze Date: Tue, 23 Jan 2024 00:04:59 +0100 Subject: [PATCH 04/19] update --- lib/ssz_ex.ex | 112 +++++++++++++++++++------------------- test/unit/ssz_ex_test.exs | 82 +++++++++++++++++++--------- 2 files changed, 113 insertions(+), 81 deletions(-) diff --git a/lib/ssz_ex.ex b/lib/ssz_ex.ex index b7e566198..325ab826c 100644 --- a/lib/ssz_ex.ex +++ b/lib/ssz_ex.ex @@ -291,64 +291,66 @@ defmodule LambdaEthereumConsensus.SszEx do layers = chunks last_index = chunks_count - 1 - 1..(height - 1) - |> Enum.reverse() - |> Enum.reduce(last_index, fn i, acc_last_index -> - 0..(2 ** i - 1) - |> Enum.filter(fn x -> rem(x, 2) == 0 end) - |> Enum.reduce_while(layers, fn j, acc_layers -> - parent_index = j |> div(2) - - nodes = - cond do - j < acc_last_index -> - start = parent_index * @bytes_per_chunk - stop = (j + 2) * @bytes_per_chunk - focus = acc_layers |> :binary.part(start, stop - start) - focus_len = focus |> byte_size() - children_index = focus_len - 2 * @bytes_per_chunk - <> = focus - - <> = - children - - {parent, left, right} - - j == acc_last_index -> - start = parent_index * @bytes_per_chunk - stop = (j + 1) * @bytes_per_chunk - focus = acc_layers |> :binary.part(start, stop - start) - focus_len = focus |> byte_size() - children_index = focus_len - @bytes_per_chunk - <> = focus - depth = height - i - 1 - - right = @zero_hashes |> :binary.part(depth - 1, @bytes_per_chunk) - {parent, left, right} - - true -> - :error - end - - case nodes do - :error -> - {:halt, acc_layers} - - {parent, left, right} -> - if j == 0 do - hash = hash_nodes(left, right) - acc_layers |> IO.inspect() - {:cont, acc_layers} - else - parent = hash_nodes(left, right) - acc_layers |> IO.inspect() - {:cont, acc_layers} + {_, final_layer} = + 1..(height - 1) + |> Enum.reverse() + |> Enum.reduce({last_index, layers}, fn i, {acc_last_index, acc_layers} -> + updated_layers = + 0..(2 ** i - 1) + |> Enum.filter(fn x -> rem(x, 2) == 0 end) + |> Enum.reduce_while(acc_layers, fn j, acc_layers -> + parent_index = j |> div(2) + + nodes = + cond do + j < acc_last_index -> + start = parent_index * @bytes_per_chunk + stop = (j + 2) * @bytes_per_chunk + focus = acc_layers |> :binary.part(start, stop - start) + focus_len = focus |> byte_size() + children_index = focus_len - 2 * @bytes_per_chunk + <<_::binary-size(children_index), children::binary>> = focus + + <> = + children + + {children_index, left, right} + + j == acc_last_index -> + start = parent_index * @bytes_per_chunk + stop = (j + 1) * @bytes_per_chunk + focus = acc_layers |> :binary.part(start, stop - start) + focus_len = focus |> byte_size() + children_index = focus_len - @bytes_per_chunk + <<_::binary-size(children_index), left::binary>> = focus + depth = height - i - 1 + + offset = (depth + 1) * @bytes_per_chunk - @bytes_per_chunk + + <<_::binary-size(offset), right::binary-size(@bytes_per_chunk), _::binary>> = + @zero_hashes + + {children_index, left, right} + + true -> + :error + end + + case nodes do + :error -> + {:halt, acc_layers} + + {index, left, right} -> + hash = hash_nodes(left, right) + {:cont, replace_chunk(acc_layers, index, hash)} end - end + end) + + {acc_last_index |> div(2), updated_layers} end) - acc_last_index |> div(2) - end) + <> = final_layer + root end end diff --git a/test/unit/ssz_ex_test.exs b/test/unit/ssz_ex_test.exs index 7bb846c0c..b92059d4c 100644 --- a/test/unit/ssz_ex_test.exs +++ b/test/unit/ssz_ex_test.exs @@ -146,44 +146,74 @@ defmodule Unit.SSZExTest do end test "merklelization of chunks with virtual padding" do - chunks = <<0::248>> - root = SszEx.merkleize_chunks_with_virtual_padding(chunks) - expected_value = "0000000000000000000000000000000000000000000000000000000000000000" + zero = <<0::256>> + + # chunks = zero + # root = SszEx.merkleize_chunks_with_virtual_padding(chunks) + # expected_value = "0000000000000000000000000000000000000000000000000000000000000000" # assert root |> Base.encode16(case: :lower) == expected_value - zero = <<0::256>> + chunks = zero <> zero + root = chunks |> SszEx.merkleize_chunks_with_virtual_padding(2) + expected_value = "f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b" + assert root |> Base.encode16(case: :lower) == expected_value + ones = 0..31 |> Enum.reduce(<<>>, fn _, acc -> <<1>> <> acc end) - # chunks = zero <> zero - # root = chunks |> SszEx.merkleize_chunks_with_virtual_padding(2) - # expected_value = "f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b" - # assert root |> Base.encode16(case: :lower) == expected_value + chunks = ones <> ones + root = chunks |> SszEx.merkleize_chunks_with_virtual_padding(2) + expected_value = "7c8975e1e60a5c8337f28edf8c33c3b180360b7279644a9bc1af3c51e6220bf5" + assert root |> Base.encode16(case: :lower) == expected_value - # ones = 0..31 |> Enum.reduce(<<>>, fn _, acc -> <<1>> <> acc end) + chunks = zero <> zero <> zero <> zero + root = chunks |> SszEx.merkleize_chunks_with_virtual_padding(4) + expected_value = "db56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71" + assert root |> Base.encode16(case: :lower) == expected_value - # chunks = ones <> ones - # root = chunks |> SszEx.merkleize_chunks(2) - # expected_value = "7c8975e1e60a5c8337f28edf8c33c3b180360b7279644a9bc1af3c51e6220bf5" - # assert root |> Base.encode16(case: :lower) == expected_value + chunks = zero <> zero <> zero <> zero <> zero <> zero <> zero <> zero + root = chunks |> SszEx.merkleize_chunks_with_virtual_padding(8) + expected_value = "c78009fdf07fc56a11f122370658a353aaa542ed63e44c4bc15ff4cd105ab33c" + assert root |> Base.encode16(case: :lower) == expected_value - # chunks = zero <> zero <> zero <> zero - # root = chunks |> SszEx.merkleize_chunks_with_virtual_padding(4) - # expected_value = "db56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71" - # assert root |> Base.encode16(case: :lower) == expected_value + chunks = ones + root = chunks |> SszEx.merkleize_chunks_with_virtual_padding(4) + expected_value = "29797eded0e83376b70f2bf034cc0811ae7f1414653b1d720dfd18f74cf13309" + assert root |> Base.encode16(case: :lower) == expected_value + + twos = 0..31 |> Enum.reduce(<<>>, fn _, acc -> <<2>> <> acc end) + + chunks = twos + root = chunks |> SszEx.merkleize_chunks_with_virtual_padding(8) + expected_value = "fa4cf775712aa8a2fe5dcb5a517d19b2e9effcf58ff311b9fd8e4a7d308e6d00" + assert root |> Base.encode16(case: :lower) == expected_value + + chunks = ones <> ones <> ones + root = chunks |> SszEx.merkleize_chunks_with_virtual_padding(4) + expected_value = "65aa94f2b59e517abd400cab655f42821374e433e41b8fe599f6bb15484adcec" + assert root |> Base.encode16(case: :lower) == expected_value + + chunks = ones <> ones <> ones <> ones <> ones + root = chunks |> SszEx.merkleize_chunks_with_virtual_padding(8) + expected_value = "0ae67e34cba4ad2bbfea5dc39e6679b444021522d861fab00f05063c54341289" + assert root |> Base.encode16(case: :lower) == expected_value chunks = ones <> ones <> ones <> ones <> ones <> ones root = chunks |> SszEx.merkleize_chunks_with_virtual_padding(8) - # expected_value = "0ef7df63c204ef203d76145627b8083c49aa7c55ebdee2967556f55a4f65a238" - # assert root |> Base.encode16(case: :lower) == expected_value + expected_value = "0ef7df63c204ef203d76145627b8083c49aa7c55ebdee2967556f55a4f65a238" + assert root |> Base.encode16(case: :lower) == expected_value - # chunks = zero <> zero <> zero <> zero <> zero <> zero <> zero <> zero - # root = chunks |> SszEx.merkleize_chunks(8) - # expected_value = "c78009fdf07fc56a11f122370658a353aaa542ed63e44c4bc15ff4cd105ab33c" - # assert root |> Base.encode16(case: :lower) == expected_value + ## Large Leaf Count - # chunks = ones - # root = chunks |> SszEx.merkleize_chunks(4) - # expected_value = "29797eded0e83376b70f2bf034cc0811ae7f1414653b1d720dfd18f74cf13309" + chunks = ones <> ones <> ones <> ones <> ones + root = chunks |> SszEx.merkleize_chunks_with_virtual_padding(2 ** 10) + expected_value = "2647cb9e26bd83eeb0982814b2ac4d6cc4a65d0d98637f1a73a4c06d3db0e6ce" + assert root |> Base.encode16(case: :lower) == expected_value + + ## TOO HEAVY COMPUTATION! + # chunks = 1..70 |> Enum.reduce(<<>>, fn _, acc -> acc <> ones end) + # leaf_count = 9_223_372_036_854_775_808 # 2 ** 63 + # root = chunks |> SszEx.merkleize_chunks_with_virtual_padding(leaf_count) + # expected_value = "9317695d95b5a3b46e976b5a9cbfcfccb600accaddeda9ac867cc9669b862979" # assert root |> Base.encode16(case: :lower) == expected_value end From 3bae02055fcd0cfa1615d07b1602d7fc1730fd31 Mon Sep 17 00:00:00 2001 From: Godspower Eze Date: Tue, 23 Jan 2024 16:53:01 +0100 Subject: [PATCH 05/19] update --- lib/ssz_ex.ex | 174 ++++++++++++++++++++++---------------- test/unit/ssz_ex_test.exs | 12 +-- 2 files changed, 105 insertions(+), 81 deletions(-) diff --git a/lib/ssz_ex.ex b/lib/ssz_ex.ex index 325ab826c..82642bfda 100644 --- a/lib/ssz_ex.ex +++ b/lib/ssz_ex.ex @@ -225,7 +225,7 @@ defmodule LambdaEthereumConsensus.SszEx do if chunks_len > limit do {:error, "chunk size exceeds limit"} else - root = merkleize_chunks(chunks, limit) |> mix_in_length(len) + root = merkleize_chunks_with_virtual_padding(chunks, limit) |> mix_in_length(len) {:ok, root} end end @@ -234,7 +234,7 @@ defmodule LambdaEthereumConsensus.SszEx do {:ok, Types.root()} | {:error, String.t()} def hash_tree_root_vector_basic_type(chunks) do leaf_count = chunks |> get_chunks_len() |> next_pow_of_two() - root = merkleize_chunks(chunks, leaf_count) + root = merkleize_chunks_with_virtual_padding(chunks, leaf_count) {:ok, root} end @@ -280,77 +280,35 @@ defmodule LambdaEthereumConsensus.SszEx do end end - def merkleize_chunks_with_virtual_padding(chunks, leaf_count \\ nil) do - chunks_count = chunks |> get_chunks_len() + def merkleize_chunks_with_virtual_padding(chunks, leaf_count) do + chunks_len = chunks |> get_chunks_len() + power = leaf_count |> compute_pow() + height = power + 1 - if chunks_count == 0 and leaf_count == nil do - @zero_chunk - else - power = leaf_count |> compute_pow() - height = power + 1 - layers = chunks - last_index = chunks_count - 1 + cond do + chunks_len == 0 -> + depth = height - 1 + get_zero_hash(depth) - {_, final_layer} = - 1..(height - 1) - |> Enum.reverse() - |> Enum.reduce({last_index, layers}, fn i, {acc_last_index, acc_layers} -> - updated_layers = - 0..(2 ** i - 1) - |> Enum.filter(fn x -> rem(x, 2) == 0 end) - |> Enum.reduce_while(acc_layers, fn j, acc_layers -> - parent_index = j |> div(2) - - nodes = - cond do - j < acc_last_index -> - start = parent_index * @bytes_per_chunk - stop = (j + 2) * @bytes_per_chunk - focus = acc_layers |> :binary.part(start, stop - start) - focus_len = focus |> byte_size() - children_index = focus_len - 2 * @bytes_per_chunk - <<_::binary-size(children_index), children::binary>> = focus - - <> = - children - - {children_index, left, right} - - j == acc_last_index -> - start = parent_index * @bytes_per_chunk - stop = (j + 1) * @bytes_per_chunk - focus = acc_layers |> :binary.part(start, stop - start) - focus_len = focus |> byte_size() - children_index = focus_len - @bytes_per_chunk - <<_::binary-size(children_index), left::binary>> = focus - depth = height - i - 1 - - offset = (depth + 1) * @bytes_per_chunk - @bytes_per_chunk - - <<_::binary-size(offset), right::binary-size(@bytes_per_chunk), _::binary>> = - @zero_hashes - - {children_index, left, right} - - true -> - :error - end - - case nodes do - :error -> - {:halt, acc_layers} - - {index, left, right} -> - hash = hash_nodes(left, right) - {:cont, replace_chunk(acc_layers, index, hash)} - end - end) - - {acc_last_index |> div(2), updated_layers} - end) + chunks_len == 1 and leaf_count == 1 -> + chunks - <> = final_layer - root + true -> + power = leaf_count |> compute_pow() + height = power + 1 + layers = chunks + last_index = chunks_len - 1 + + {_, final_layer} = + 1..(height - 1) + |> Enum.reverse() + |> Enum.reduce({last_index, layers}, fn i, {acc_last_index, acc_layers} -> + updated_layers = update_layers(i, height, acc_layers, acc_last_index) + {acc_last_index |> div(2), updated_layers} + end) + + <> = final_layer + root end end @@ -856,11 +814,16 @@ defmodule LambdaEthereumConsensus.SszEx do end defp next_pow_of_two(len) when is_integer(len) and len >= 0 do - if len == 0 do - 0 - else - n = ((len <<< 1) - 1) |> :math.log2() |> trunc() - 2 ** n + cond do + len == 0 -> + 0 + + len == 1 -> + 1 + + true -> + n = ((len <<< 1) - 1) |> :math.log2() |> trunc() + 2 ** n end end @@ -878,4 +841,65 @@ defmodule LambdaEthereumConsensus.SszEx do defp compute_pow(value) do :math.log2(value) |> trunc() end + + defp get_zero_hash(depth) do + offset = (depth + 1) * @bytes_per_chunk - @bytes_per_chunk + <<_::binary-size(offset), hash::binary-size(@bytes_per_chunk), _::binary>> = @zero_hashes + hash + end + + defp update_layers(i, height, acc_layers, acc_last_index) do + 0..(2 ** i - 1) + |> Enum.filter(fn x -> rem(x, 2) == 0 end) + |> Enum.reduce_while(acc_layers, fn j, acc_layers -> + parent_index = j |> div(2) + nodes = get_nodes(parent_index, i, j, height, acc_layers, acc_last_index) + hash_nodes_and_replace(nodes, acc_layers) + end) + end + + defp get_nodes(parent_index, i, j, height, acc_layers, acc_last_index) do + nodes = + cond do + j < acc_last_index -> + start = parent_index * @bytes_per_chunk + stop = (j + 2) * @bytes_per_chunk + focus = acc_layers |> :binary.part(start, stop - start) + focus_len = focus |> byte_size() + children_index = focus_len - 2 * @bytes_per_chunk + <<_::binary-size(children_index), children::binary>> = focus + + <> = + children + + {children_index, left, right} + + j == acc_last_index -> + start = parent_index * @bytes_per_chunk + stop = (j + 1) * @bytes_per_chunk + focus = acc_layers |> :binary.part(start, stop - start) + focus_len = focus |> byte_size() + children_index = focus_len - @bytes_per_chunk + <<_::binary-size(children_index), left::binary>> = focus + depth = height - i - 1 + right = get_zero_hash(depth) + {children_index, left, right} + + true -> + :error + end + + nodes + end + + defp hash_nodes_and_replace(nodes, layers) do + case nodes do + :error -> + {:halt, layers} + + {index, left, right} -> + hash = hash_nodes(left, right) + {:cont, replace_chunk(layers, index, hash)} + end + end end diff --git a/test/unit/ssz_ex_test.exs b/test/unit/ssz_ex_test.exs index b92059d4c..da59f0c7e 100644 --- a/test/unit/ssz_ex_test.exs +++ b/test/unit/ssz_ex_test.exs @@ -72,8 +72,8 @@ defmodule Unit.SSZExTest do end test "merklelization of chunks" do - ## Reference: https://github.com/ralexstokes/ssz-rs/blob/1f94d5dfc70c86dab672e91ac46af04a5f96c342/ssz-rs/src/merkleization/mod.rs#L371 - ## https://github.com/ralexstokes/ssz-rs/blob/1f94d5dfc70c86dab672e91ac46af04a5f96c342/ssz-rs/src/merkleization/mod.rs#L416 + # Reference: https://github.com/ralexstokes/ssz-rs/blob/1f94d5dfc70c86dab672e91ac46af04a5f96c342/ssz-rs/src/merkleization/mod.rs#L371 + # https://github.com/ralexstokes/ssz-rs/blob/1f94d5dfc70c86dab672e91ac46af04a5f96c342/ssz-rs/src/merkleization/mod.rs#L416 zero = <<0::256>> chunks = zero @@ -148,10 +148,10 @@ defmodule Unit.SSZExTest do test "merklelization of chunks with virtual padding" do zero = <<0::256>> - # chunks = zero - # root = SszEx.merkleize_chunks_with_virtual_padding(chunks) - # expected_value = "0000000000000000000000000000000000000000000000000000000000000000" - # assert root |> Base.encode16(case: :lower) == expected_value + chunks = zero + root = SszEx.merkleize_chunks_with_virtual_padding(chunks, 1) + expected_value = "0000000000000000000000000000000000000000000000000000000000000000" + assert root |> Base.encode16(case: :lower) == expected_value chunks = zero <> zero root = chunks |> SszEx.merkleize_chunks_with_virtual_padding(2) From 143cca19435fe28fe48e95749f2a1e38b52021bd Mon Sep 17 00:00:00 2001 From: Godspower Eze Date: Wed, 24 Jan 2024 13:51:07 +0100 Subject: [PATCH 06/19] update --- lib/ssz_ex.ex | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/lib/ssz_ex.ex b/lib/ssz_ex.ex index 2212fc46c..0623e53da 100644 --- a/lib/ssz_ex.ex +++ b/lib/ssz_ex.ex @@ -333,13 +333,8 @@ defmodule LambdaEthereumConsensus.SszEx do end end - def chunk_count({:list, {:int, size}, max_size}) do - size = size_of({:int, size}) - (max_size * size + 31) |> div(32) - end - - def chunk_count({:list, :bool, max_size}) do - size = size_of(:bool) + def chunk_count({:list, type, max_size}) do + size = size_of(type) (max_size * size + 31) |> div(32) end From 208e62c242b6b0eb95cdc24836a2ac9d3f0521da Mon Sep 17 00:00:00 2001 From: Godspower Eze Date: Wed, 24 Jan 2024 13:58:47 +0100 Subject: [PATCH 07/19] update --- lib/ssz_ex.ex | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/lib/ssz_ex.ex b/lib/ssz_ex.ex index 45e570cdd..82939cb95 100644 --- a/lib/ssz_ex.ex +++ b/lib/ssz_ex.ex @@ -779,18 +779,11 @@ defmodule LambdaEthereumConsensus.SszEx do end end - defp next_pow_of_two(len) when is_integer(len) and len >= 0 do - cond do - len == 0 -> - 0 - - len == 1 -> - 1 + defp next_pow_of_two(len) when len == 0, do: 0 - true -> - n = ((len <<< 1) - 1) |> :math.log2() |> trunc() - 2 ** n - end + defp next_pow_of_two(len) when is_integer(len) and len > 0 do + n = ((len <<< 1) - 1) |> compute_pow() + 2 ** n end defp replace_chunk(chunks, start, new_chunk) do From 755b740e97d1cb631254fe22bc5725e9488e7f5a Mon Sep 17 00:00:00 2001 From: Godspower Eze Date: Wed, 24 Jan 2024 14:03:30 +0100 Subject: [PATCH 08/19] update --- lib/ssz_ex.ex | 62 ++++++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 33 deletions(-) diff --git a/lib/ssz_ex.ex b/lib/ssz_ex.ex index 82939cb95..1e67aecf7 100644 --- a/lib/ssz_ex.ex +++ b/lib/ssz_ex.ex @@ -817,39 +817,35 @@ defmodule LambdaEthereumConsensus.SszEx do end) end - defp get_nodes(parent_index, i, j, height, acc_layers, acc_last_index) do - nodes = - cond do - j < acc_last_index -> - start = parent_index * @bytes_per_chunk - stop = (j + 2) * @bytes_per_chunk - focus = acc_layers |> :binary.part(start, stop - start) - focus_len = focus |> byte_size() - children_index = focus_len - 2 * @bytes_per_chunk - <<_::binary-size(children_index), children::binary>> = focus - - <> = - children - - {children_index, left, right} - - j == acc_last_index -> - start = parent_index * @bytes_per_chunk - stop = (j + 1) * @bytes_per_chunk - focus = acc_layers |> :binary.part(start, stop - start) - focus_len = focus |> byte_size() - children_index = focus_len - @bytes_per_chunk - <<_::binary-size(children_index), left::binary>> = focus - depth = height - i - 1 - right = get_zero_hash(depth) - {children_index, left, right} - - true -> - :error - end - - nodes - end + defp get_nodes(parent_index, _i, j, _height, acc_layers, acc_last_index) + when j < acc_last_index do + start = parent_index * @bytes_per_chunk + stop = (j + 2) * @bytes_per_chunk + focus = acc_layers |> :binary.part(start, stop - start) + focus_len = focus |> byte_size() + children_index = focus_len - 2 * @bytes_per_chunk + <<_::binary-size(children_index), children::binary>> = focus + + <> = + children + + {children_index, left, right} + end + + defp get_nodes(parent_index, i, j, height, acc_layers, acc_last_index) + when j == acc_last_index do + start = parent_index * @bytes_per_chunk + stop = (j + 1) * @bytes_per_chunk + focus = acc_layers |> :binary.part(start, stop - start) + focus_len = focus |> byte_size() + children_index = focus_len - @bytes_per_chunk + <<_::binary-size(children_index), left::binary>> = focus + depth = height - i - 1 + right = get_zero_hash(depth) + {children_index, left, right} + end + + defp get_nodes(_, _, _, _, _, _), do: :error defp hash_nodes_and_replace(nodes, layers) do case nodes do From fe46df3b10dc11e1f496d52bd2d8b446804834d4 Mon Sep 17 00:00:00 2001 From: Godspower Eze Date: Thu, 25 Jan 2024 12:33:45 +0100 Subject: [PATCH 09/19] update --- lib/ssz_ex.ex | 128 +------------------------------------- lib/utils/zero_hashes.ex | 130 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 133 insertions(+), 125 deletions(-) create mode 100644 lib/utils/zero_hashes.ex diff --git a/lib/ssz_ex.ex b/lib/ssz_ex.ex index 1e67aecf7..091b7cc00 100644 --- a/lib/ssz_ex.ex +++ b/lib/ssz_ex.ex @@ -4,6 +4,7 @@ defmodule LambdaEthereumConsensus.SszEx do """ alias LambdaEthereumConsensus.Utils.BitList alias LambdaEthereumConsensus.Utils.BitVector + alias LambdaEthereumConsensus.Utils.ZeroHashes import alias LambdaEthereumConsensus.Utils.BitVector ################# @@ -15,123 +16,6 @@ defmodule LambdaEthereumConsensus.SszEx do @bits_per_byte 8 @bits_per_chunk @bytes_per_chunk * @bits_per_byte @zero_chunk <<0::size(@bits_per_chunk)>> - @zero_hashes <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 245, 165, 253, 66, 209, 106, 32, 48, 39, 152, 239, 110, 211, 9, - 151, 155, 67, 0, 61, 35, 32, 217, 240, 232, 234, 152, 49, 169, 39, 89, 251, 75, - 219, 86, 17, 78, 0, 253, 212, 193, 248, 92, 137, 43, 243, 90, 201, 168, 146, 137, - 170, 236, 177, 235, 208, 169, 108, 222, 96, 106, 116, 139, 93, 113, 199, 128, 9, - 253, 240, 127, 197, 106, 17, 241, 34, 55, 6, 88, 163, 83, 170, 165, 66, 237, 99, - 228, 76, 75, 193, 95, 244, 205, 16, 90, 179, 60, 83, 109, 152, 131, 127, 45, 209, - 101, 165, 93, 94, 234, 233, 20, 133, 149, 68, 114, 213, 111, 36, 109, 242, 86, - 191, 60, 174, 25, 53, 42, 18, 60, 158, 253, 224, 82, 170, 21, 66, 159, 174, 5, - 186, 212, 208, 177, 215, 198, 77, 166, 77, 3, 215, 161, 133, 74, 88, 140, 44, - 184, 67, 12, 13, 48, 216, 141, 223, 238, 212, 0, 168, 117, 85, 150, 178, 25, 66, - 193, 73, 126, 17, 76, 48, 46, 97, 24, 41, 15, 145, 230, 119, 41, 118, 4, 31, 161, - 135, 235, 13, 219, 165, 126, 53, 246, 210, 134, 103, 56, 2, 164, 175, 89, 117, - 226, 37, 6, 199, 207, 76, 100, 187, 107, 229, 238, 17, 82, 127, 44, 38, 132, 100, - 118, 253, 95, 197, 74, 93, 67, 56, 81, 103, 201, 81, 68, 242, 100, 63, 83, 60, - 200, 91, 185, 209, 107, 120, 47, 141, 125, 177, 147, 80, 109, 134, 88, 45, 37, - 36, 5, 184, 64, 1, 135, 146, 202, 210, 191, 18, 89, 241, 239, 90, 165, 248, 135, - 225, 60, 178, 240, 9, 79, 81, 225, 255, 255, 10, 215, 230, 89, 119, 47, 149, 52, - 193, 149, 200, 21, 239, 196, 1, 78, 241, 225, 218, 237, 68, 4, 192, 99, 133, 209, - 17, 146, 233, 43, 108, 240, 65, 39, 219, 5, 68, 28, 216, 51, 16, 122, 82, 190, - 133, 40, 104, 137, 14, 67, 23, 230, 160, 42, 180, 118, 131, 170, 117, 150, 66, - 32, 183, 208, 95, 135, 95, 20, 0, 39, 239, 81, 24, 162, 36, 123, 187, 132, 206, - 143, 47, 15, 17, 35, 98, 48, 133, 218, 247, 150, 12, 50, 159, 95, 223, 106, 245, - 245, 187, 219, 107, 233, 239, 138, 166, 24, 228, 191, 128, 115, 150, 8, 103, 23, - 30, 41, 103, 111, 139, 40, 77, 234, 106, 8, 168, 94, 181, 141, 144, 15, 94, 24, - 46, 60, 80, 239, 116, 150, 158, 161, 108, 119, 38, 197, 73, 117, 124, 194, 53, - 35, 195, 105, 88, 125, 167, 41, 55, 132, 212, 154, 117, 2, 255, 207, 176, 52, 11, - 29, 120, 133, 104, 133, 0, 202, 48, 129, 97, 167, 249, 107, 98, 223, 157, 8, 59, - 113, 252, 200, 242, 187, 143, 230, 177, 104, 146, 86, 192, 211, 133, 244, 47, 91, - 190, 32, 39, 162, 44, 25, 150, 225, 16, 186, 151, 193, 113, 211, 229, 148, 141, - 233, 43, 235, 141, 13, 99, 195, 158, 186, 222, 133, 9, 224, 174, 60, 156, 56, - 118, 251, 95, 161, 18, 190, 24, 249, 5, 236, 172, 254, 203, 146, 5, 118, 3, 171, - 149, 238, 200, 178, 229, 65, 202, 212, 233, 29, 227, 131, 133, 242, 224, 70, 97, - 159, 84, 73, 108, 35, 130, 203, 108, 172, 213, 185, 140, 38, 245, 164, 248, 147, - 233, 8, 145, 119, 117, 182, 43, 255, 35, 41, 77, 187, 227, 161, 205, 142, 108, - 193, 195, 91, 72, 1, 136, 123, 100, 106, 111, 129, 241, 127, 205, 219, 167, 181, - 146, 227, 19, 51, 147, 193, 97, 148, 250, 199, 67, 26, 191, 47, 84, 133, 237, - 113, 29, 178, 130, 24, 60, 129, 158, 8, 235, 170, 138, 141, 127, 227, 175, 140, - 170, 8, 90, 118, 57, 168, 50, 0, 20, 87, 223, 185, 18, 138, 128, 97, 20, 42, 208, - 51, 86, 41, 255, 35, 255, 156, 254, 179, 195, 55, 215, 165, 26, 111, 191, 0, 185, - 227, 76, 82, 225, 201, 25, 92, 150, 155, 212, 231, 160, 191, 213, 29, 92, 91, - 237, 156, 17, 103, 231, 31, 10, 168, 60, 195, 46, 223, 190, 250, 159, 77, 62, 1, - 116, 202, 133, 24, 46, 236, 159, 58, 9, 246, 166, 192, 223, 99, 119, 165, 16, - 215, 49, 32, 111, 168, 10, 80, 187, 106, 190, 41, 8, 80, 88, 241, 98, 18, 33, 42, - 96, 238, 200, 240, 73, 254, 203, 146, 216, 200, 224, 168, 75, 192, 33, 53, 43, - 254, 203, 237, 221, 233, 147, 131, 159, 97, 76, 61, 172, 10, 62, 227, 117, 67, - 249, 180, 18, 177, 97, 153, 220, 21, 142, 35, 181, 68, 97, 158, 49, 39, 36, 187, - 109, 124, 49, 83, 237, 157, 231, 145, 215, 100, 163, 102, 179, 137, 175, 19, 197, - 139, 248, 168, 217, 4, 129, 164, 103, 101, 124, 221, 41, 134, 38, 130, 80, 98, - 141, 12, 16, 227, 133, 197, 140, 97, 145, 230, 251, 224, 81, 145, 188, 192, 79, - 19, 63, 44, 234, 114, 193, 196, 132, 137, 48, 189, 123, 168, 202, 197, 70, 97, 7, - 33, 19, 251, 39, 136, 105, 224, 123, 184, 88, 127, 145, 57, 41, 51, 55, 77, 1, - 123, 203, 225, 136, 105, 255, 44, 34, 178, 140, 193, 5, 16, 217, 133, 50, 146, - 128, 51, 40, 190, 79, 176, 232, 4, 149, 232, 187, 141, 39, 31, 91, 136, 150, 54, - 181, 254, 40, 231, 159, 27, 133, 15, 134, 88, 36, 108, 233, 182, 161, 231, 180, - 159, 192, 109, 183, 20, 62, 143, 224, 180, 242, 176, 197, 82, 58, 92, 152, 94, - 146, 159, 112, 175, 40, 208, 189, 209, 169, 10, 128, 143, 151, 127, 89, 124, 124, - 119, 140, 72, 158, 152, 211, 189, 137, 16, 211, 26, 192, 247, 198, 246, 126, 2, - 230, 228, 225, 189, 239, 185, 148, 198, 9, 137, 83, 243, 70, 54, 186, 43, 108, - 162, 10, 71, 33, 210, 178, 106, 136, 103, 34, 255, 28, 154, 126, 95, 241, 207, - 72, 180, 173, 21, 130, 211, 244, 228, 161, 0, 79, 59, 32, 216, 197, 162, 183, 19, - 135, 164, 37, 74, 217, 51, 235, 197, 47, 7, 90, 226, 41, 100, 107, 111, 106, 237, - 25, 165, 227, 114, 207, 41, 80, 129, 64, 30, 184, 147, 255, 89, 155, 63, 154, - 204, 12, 13, 62, 125, 50, 137, 33, 222, 181, 150, 18, 7, 104, 1, 232, 205, 97, - 89, 33, 7, 181, 198, 124, 121, 184, 70, 89, 92, 198, 50, 12, 57, 91, 70, 54, 44, - 191, 185, 9, 253, 178, 54, 173, 36, 17, 180, 228, 136, 56, 16, 160, 116, 184, 64, - 70, 70, 137, 152, 108, 63, 138, 128, 145, 130, 126, 23, 195, 39, 85, 216, 251, - 54, 135, 186, 59, 164, 159, 52, 44, 119, 245, 161, 248, 155, 236, 131, 216, 17, - 68, 110, 26, 70, 113, 57, 33, 61, 100, 11, 106, 116, 247, 33, 13, 79, 142, 126, - 16, 57, 121, 14, 123, 244, 239, 162, 7, 85, 90, 16, 166, 219, 29, 212, 185, 93, - 163, 19, 170, 168, 139, 136, 254, 118, 173, 33, 181, 22, 203, 198, 69, 255, 227, - 74, 181, 222, 28, 138, 239, 140, 212, 231, 248, 210, 181, 30, 142, 20, 86, 173, - 199, 86, 60, 218, 32, 111, 107, 254, 141, 43, 204, 66, 55, 183, 74, 80, 71, 5, - 142, 244, 85, 51, 158, 205, 115, 96, 203, 99, 191, 187, 142, 229, 68, 142, 100, - 48, 186, 4, 167, 242, 60, 233, 24, 23, 64, 220, 34, 12, 129, 71, 130, 101, 79, - 238, 106, 206, 185, 241, 236, 146, 34, 196, 226, 70, 125, 10, 177, 104, 8, 55, - 174, 249, 71, 108, 137, 89, 10, 44, 140, 201, 179, 183, 79, 73, 103, 199, 87, - 196, 157, 152, 102, 164, 75, 172, 242, 31, 162, 237, 103, 93, 223, 162, 154, 66, - 188, 173, 130, 246, 169, 228, 18, 132, 216, 8, 234, 211, 25, 242, 159, 59, 8, 32, - 157, 104, 15, 14, 44, 231, 21, 16, 208, 113, 226, 5, 209, 166, 109, 53, 74, 103, - 185, 207, 23, 149, 113, 216, 229, 249, 119, 146, 113, 110, 141, 212, 236, 68, 25, - 104, 57, 163, 247, 198, 183, 79, 139, 172, 250, 250, 48, 37, 242, 248, 149, 9, - 194, 199, 28, 116, 251, 160, 205, 146, 133, 142, 244, 155, 7, 128, 251, 84, 121, - 116, 108, 138, 155, 252, 179, 70, 51, 52, 167, 193, 231, 246, 112, 90, 166, 1, - 26, 106, 148, 150, 69, 1, 109, 180, 172, 222, 12, 169, 171, 214, 109, 199, 157, - 130, 102, 66, 48, 86, 7, 150, 253, 117, 102, 79, 174, 247, 68, 238, 78, 82, 215, - 39, 30, 43, 187, 118, 159, 145, 237, 111, 155, 116, 216, 182, 148, 245, 102, 6, - 133, 44, 123, 163, 174, 74, 65, 127, 232, 84, 91, 20, 43, 200, 159, 74, 220, 215, - 174, 19, 148, 28, 186, 183, 117, 11, 131, 233, 240, 166, 109, 22, 190, 100, 120, - 143, 175, 204, 74, 165, 32, 57, 154, 219, 174, 209, 149, 248, 177, 44, 78, 179, - 30, 193, 1, 104, 229, 10, 171, 198, 89, 166, 174, 165, 22, 220, 232, 51, 215, - 166, 113, 96, 230, 139, 244, 201, 4, 74, 83, 7, 125, 242, 114, 122, 208, 12, 243, - 111, 73, 73, 199, 182, 129, 169, 18, 20, 12, 187, 48, 158, 171, 240, 149, 220, - 103, 20, 249, 244, 216, 100, 187, 165, 175, 250, 224, 179, 90, 226, 245, 227, 86, - 91, 204, 58, 71, 178, 18, 118, 119, 1, 34, 106, 142, 190, 250, 40, 134, 101, 166, - 68, 165, 2, 115, 51, 94, 251, 182, 16, 81, 15, 36, 27, 91, 114, 12, 138, 54, 141, - 89, 166, 154, 93, 65, 171, 253, 153, 84, 37, 130, 118, 37, 147, 129, 49, 175, 12, - 79, 51, 254, 11, 212, 104, 140, 34, 44, 33, 250, 157, 168, 232, 156, 170, 3, 248, - 68, 44, 100, 46, 245, 15, 161, 166, 103, 166, 230, 209, 5, 199, 124, 92, 195, - 254, 200, 215, 170, 37, 112, 207, 26, 48, 119, 181, 3, 195, 128, 105, 160, 160, - 141, 252, 155, 66, 217, 108, 45, 225, 155, 109, 18, 123, 138, 225, 54, 221, 207, - 62, 90, 208, 220, 228, 34, 196, 90, 86, 246, 31, 106, 116, 125, 52, 131, 130, - 175, 9, 109, 190, 11, 240, 134, 199, 187, 57, 178, 162, 192, 188, 54, 182, 33, - 171, 12, 115, 142, 152, 133, 215, 49, 216, 23, 64, 58, 177, 52, 117, 29, 25, 18, - 105, 2, 108, 134, 153, 78, 170, 139, 67, 168, 59, 74, 209, 246, 208, 231, 115, - 129, 196, 226, 151, 74, 251, 200, 246, 154, 116, 82, 97, 29, 178, 210, 62, 174, - 38, 249, 189, 187, 136, 149, 142, 244, 76, 100, 208, 254, 152, 123, 233, 247, 38, - 173, 249, 56, 245, 15, 108, 114, 92, 127, 129, 96, 55, 191, 228, 82, 205, 30, - 123, 163, 90, 196, 126, 220, 180, 154, 154, 43, 39, 174, 202, 112, 220, 228, 131, - 203, 125, 237, 31, 44, 234, 26, 245, 31, 178, 139, 98, 136, 124, 57, 153, 138, - 201, 254, 244, 223, 222, 218, 31, 7, 224, 113, 186, 85, 138, 23, 58, 253, 6, 203, - 195, 255, 29, 89, 249, 139, 108, 85, 29, 149, 8, 147, 87, 5, 125, 92, 139, 226, - 100, 2, 39, 158, 157, 240, 177, 223, 26, 16, 183, 43, 243, 146, 127, 47, 138, 24, - 31, 124, 153, 221, 33, 90, 117, 41, 191, 226, 150, 169, 96, 58, 20, 70, 115, 113, - 134, 210, 26, 235, 139, 199, 174, 89, 225, 253, 33, 236, 197, 2, 201, 177, 20, - 95, 57, 80, 203, 125, 62, 56, 66, 68, 111, 129, 164, 240, 223, 29, 245, 55, 206, - 225, 57, 239, 100, 234, 152, 75, 217>> @spec hash(iodata()) :: binary() def hash(data), do: :crypto.hash(:sha256, data) @@ -289,7 +173,7 @@ defmodule LambdaEthereumConsensus.SszEx do cond do chunks_len == 0 -> depth = height - 1 - get_zero_hash(depth) + ZeroHashes.get_zero_hash(depth) chunks_len == 1 and leaf_count == 1 -> chunks @@ -801,12 +685,6 @@ defmodule LambdaEthereumConsensus.SszEx do :math.log2(value) |> trunc() end - defp get_zero_hash(depth) do - offset = (depth + 1) * @bytes_per_chunk - @bytes_per_chunk - <<_::binary-size(offset), hash::binary-size(@bytes_per_chunk), _::binary>> = @zero_hashes - hash - end - defp update_layers(i, height, acc_layers, acc_last_index) do 0..(2 ** i - 1) |> Enum.filter(fn x -> rem(x, 2) == 0 end) @@ -841,7 +719,7 @@ defmodule LambdaEthereumConsensus.SszEx do children_index = focus_len - @bytes_per_chunk <<_::binary-size(children_index), left::binary>> = focus depth = height - i - 1 - right = get_zero_hash(depth) + right = ZeroHashes.get_zero_hash(depth) {children_index, left, right} end diff --git a/lib/utils/zero_hashes.ex b/lib/utils/zero_hashes.ex new file mode 100644 index 000000000..81db2ac05 --- /dev/null +++ b/lib/utils/zero_hashes.ex @@ -0,0 +1,130 @@ +defmodule LambdaEthereumConsensus.Utils.ZeroHashes do + @moduledoc """ + Precomputed zero hashes + """ + + @bytes_per_chunk 32 + @zero_hashes <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 245, 165, 253, 66, 209, 106, 32, 48, 39, 152, 239, 110, 211, 9, + 151, 155, 67, 0, 61, 35, 32, 217, 240, 232, 234, 152, 49, 169, 39, 89, 251, 75, + 219, 86, 17, 78, 0, 253, 212, 193, 248, 92, 137, 43, 243, 90, 201, 168, 146, 137, + 170, 236, 177, 235, 208, 169, 108, 222, 96, 106, 116, 139, 93, 113, 199, 128, 9, + 253, 240, 127, 197, 106, 17, 241, 34, 55, 6, 88, 163, 83, 170, 165, 66, 237, 99, + 228, 76, 75, 193, 95, 244, 205, 16, 90, 179, 60, 83, 109, 152, 131, 127, 45, 209, + 101, 165, 93, 94, 234, 233, 20, 133, 149, 68, 114, 213, 111, 36, 109, 242, 86, + 191, 60, 174, 25, 53, 42, 18, 60, 158, 253, 224, 82, 170, 21, 66, 159, 174, 5, + 186, 212, 208, 177, 215, 198, 77, 166, 77, 3, 215, 161, 133, 74, 88, 140, 44, + 184, 67, 12, 13, 48, 216, 141, 223, 238, 212, 0, 168, 117, 85, 150, 178, 25, 66, + 193, 73, 126, 17, 76, 48, 46, 97, 24, 41, 15, 145, 230, 119, 41, 118, 4, 31, 161, + 135, 235, 13, 219, 165, 126, 53, 246, 210, 134, 103, 56, 2, 164, 175, 89, 117, + 226, 37, 6, 199, 207, 76, 100, 187, 107, 229, 238, 17, 82, 127, 44, 38, 132, 100, + 118, 253, 95, 197, 74, 93, 67, 56, 81, 103, 201, 81, 68, 242, 100, 63, 83, 60, + 200, 91, 185, 209, 107, 120, 47, 141, 125, 177, 147, 80, 109, 134, 88, 45, 37, + 36, 5, 184, 64, 1, 135, 146, 202, 210, 191, 18, 89, 241, 239, 90, 165, 248, 135, + 225, 60, 178, 240, 9, 79, 81, 225, 255, 255, 10, 215, 230, 89, 119, 47, 149, 52, + 193, 149, 200, 21, 239, 196, 1, 78, 241, 225, 218, 237, 68, 4, 192, 99, 133, 209, + 17, 146, 233, 43, 108, 240, 65, 39, 219, 5, 68, 28, 216, 51, 16, 122, 82, 190, + 133, 40, 104, 137, 14, 67, 23, 230, 160, 42, 180, 118, 131, 170, 117, 150, 66, + 32, 183, 208, 95, 135, 95, 20, 0, 39, 239, 81, 24, 162, 36, 123, 187, 132, 206, + 143, 47, 15, 17, 35, 98, 48, 133, 218, 247, 150, 12, 50, 159, 95, 223, 106, 245, + 245, 187, 219, 107, 233, 239, 138, 166, 24, 228, 191, 128, 115, 150, 8, 103, 23, + 30, 41, 103, 111, 139, 40, 77, 234, 106, 8, 168, 94, 181, 141, 144, 15, 94, 24, + 46, 60, 80, 239, 116, 150, 158, 161, 108, 119, 38, 197, 73, 117, 124, 194, 53, + 35, 195, 105, 88, 125, 167, 41, 55, 132, 212, 154, 117, 2, 255, 207, 176, 52, 11, + 29, 120, 133, 104, 133, 0, 202, 48, 129, 97, 167, 249, 107, 98, 223, 157, 8, 59, + 113, 252, 200, 242, 187, 143, 230, 177, 104, 146, 86, 192, 211, 133, 244, 47, 91, + 190, 32, 39, 162, 44, 25, 150, 225, 16, 186, 151, 193, 113, 211, 229, 148, 141, + 233, 43, 235, 141, 13, 99, 195, 158, 186, 222, 133, 9, 224, 174, 60, 156, 56, + 118, 251, 95, 161, 18, 190, 24, 249, 5, 236, 172, 254, 203, 146, 5, 118, 3, 171, + 149, 238, 200, 178, 229, 65, 202, 212, 233, 29, 227, 131, 133, 242, 224, 70, 97, + 159, 84, 73, 108, 35, 130, 203, 108, 172, 213, 185, 140, 38, 245, 164, 248, 147, + 233, 8, 145, 119, 117, 182, 43, 255, 35, 41, 77, 187, 227, 161, 205, 142, 108, + 193, 195, 91, 72, 1, 136, 123, 100, 106, 111, 129, 241, 127, 205, 219, 167, 181, + 146, 227, 19, 51, 147, 193, 97, 148, 250, 199, 67, 26, 191, 47, 84, 133, 237, + 113, 29, 178, 130, 24, 60, 129, 158, 8, 235, 170, 138, 141, 127, 227, 175, 140, + 170, 8, 90, 118, 57, 168, 50, 0, 20, 87, 223, 185, 18, 138, 128, 97, 20, 42, 208, + 51, 86, 41, 255, 35, 255, 156, 254, 179, 195, 55, 215, 165, 26, 111, 191, 0, 185, + 227, 76, 82, 225, 201, 25, 92, 150, 155, 212, 231, 160, 191, 213, 29, 92, 91, + 237, 156, 17, 103, 231, 31, 10, 168, 60, 195, 46, 223, 190, 250, 159, 77, 62, 1, + 116, 202, 133, 24, 46, 236, 159, 58, 9, 246, 166, 192, 223, 99, 119, 165, 16, + 215, 49, 32, 111, 168, 10, 80, 187, 106, 190, 41, 8, 80, 88, 241, 98, 18, 33, 42, + 96, 238, 200, 240, 73, 254, 203, 146, 216, 200, 224, 168, 75, 192, 33, 53, 43, + 254, 203, 237, 221, 233, 147, 131, 159, 97, 76, 61, 172, 10, 62, 227, 117, 67, + 249, 180, 18, 177, 97, 153, 220, 21, 142, 35, 181, 68, 97, 158, 49, 39, 36, 187, + 109, 124, 49, 83, 237, 157, 231, 145, 215, 100, 163, 102, 179, 137, 175, 19, 197, + 139, 248, 168, 217, 4, 129, 164, 103, 101, 124, 221, 41, 134, 38, 130, 80, 98, + 141, 12, 16, 227, 133, 197, 140, 97, 145, 230, 251, 224, 81, 145, 188, 192, 79, + 19, 63, 44, 234, 114, 193, 196, 132, 137, 48, 189, 123, 168, 202, 197, 70, 97, 7, + 33, 19, 251, 39, 136, 105, 224, 123, 184, 88, 127, 145, 57, 41, 51, 55, 77, 1, + 123, 203, 225, 136, 105, 255, 44, 34, 178, 140, 193, 5, 16, 217, 133, 50, 146, + 128, 51, 40, 190, 79, 176, 232, 4, 149, 232, 187, 141, 39, 31, 91, 136, 150, 54, + 181, 254, 40, 231, 159, 27, 133, 15, 134, 88, 36, 108, 233, 182, 161, 231, 180, + 159, 192, 109, 183, 20, 62, 143, 224, 180, 242, 176, 197, 82, 58, 92, 152, 94, + 146, 159, 112, 175, 40, 208, 189, 209, 169, 10, 128, 143, 151, 127, 89, 124, 124, + 119, 140, 72, 158, 152, 211, 189, 137, 16, 211, 26, 192, 247, 198, 246, 126, 2, + 230, 228, 225, 189, 239, 185, 148, 198, 9, 137, 83, 243, 70, 54, 186, 43, 108, + 162, 10, 71, 33, 210, 178, 106, 136, 103, 34, 255, 28, 154, 126, 95, 241, 207, + 72, 180, 173, 21, 130, 211, 244, 228, 161, 0, 79, 59, 32, 216, 197, 162, 183, 19, + 135, 164, 37, 74, 217, 51, 235, 197, 47, 7, 90, 226, 41, 100, 107, 111, 106, 237, + 25, 165, 227, 114, 207, 41, 80, 129, 64, 30, 184, 147, 255, 89, 155, 63, 154, + 204, 12, 13, 62, 125, 50, 137, 33, 222, 181, 150, 18, 7, 104, 1, 232, 205, 97, + 89, 33, 7, 181, 198, 124, 121, 184, 70, 89, 92, 198, 50, 12, 57, 91, 70, 54, 44, + 191, 185, 9, 253, 178, 54, 173, 36, 17, 180, 228, 136, 56, 16, 160, 116, 184, 64, + 70, 70, 137, 152, 108, 63, 138, 128, 145, 130, 126, 23, 195, 39, 85, 216, 251, + 54, 135, 186, 59, 164, 159, 52, 44, 119, 245, 161, 248, 155, 236, 131, 216, 17, + 68, 110, 26, 70, 113, 57, 33, 61, 100, 11, 106, 116, 247, 33, 13, 79, 142, 126, + 16, 57, 121, 14, 123, 244, 239, 162, 7, 85, 90, 16, 166, 219, 29, 212, 185, 93, + 163, 19, 170, 168, 139, 136, 254, 118, 173, 33, 181, 22, 203, 198, 69, 255, 227, + 74, 181, 222, 28, 138, 239, 140, 212, 231, 248, 210, 181, 30, 142, 20, 86, 173, + 199, 86, 60, 218, 32, 111, 107, 254, 141, 43, 204, 66, 55, 183, 74, 80, 71, 5, + 142, 244, 85, 51, 158, 205, 115, 96, 203, 99, 191, 187, 142, 229, 68, 142, 100, + 48, 186, 4, 167, 242, 60, 233, 24, 23, 64, 220, 34, 12, 129, 71, 130, 101, 79, + 238, 106, 206, 185, 241, 236, 146, 34, 196, 226, 70, 125, 10, 177, 104, 8, 55, + 174, 249, 71, 108, 137, 89, 10, 44, 140, 201, 179, 183, 79, 73, 103, 199, 87, + 196, 157, 152, 102, 164, 75, 172, 242, 31, 162, 237, 103, 93, 223, 162, 154, 66, + 188, 173, 130, 246, 169, 228, 18, 132, 216, 8, 234, 211, 25, 242, 159, 59, 8, 32, + 157, 104, 15, 14, 44, 231, 21, 16, 208, 113, 226, 5, 209, 166, 109, 53, 74, 103, + 185, 207, 23, 149, 113, 216, 229, 249, 119, 146, 113, 110, 141, 212, 236, 68, 25, + 104, 57, 163, 247, 198, 183, 79, 139, 172, 250, 250, 48, 37, 242, 248, 149, 9, + 194, 199, 28, 116, 251, 160, 205, 146, 133, 142, 244, 155, 7, 128, 251, 84, 121, + 116, 108, 138, 155, 252, 179, 70, 51, 52, 167, 193, 231, 246, 112, 90, 166, 1, + 26, 106, 148, 150, 69, 1, 109, 180, 172, 222, 12, 169, 171, 214, 109, 199, 157, + 130, 102, 66, 48, 86, 7, 150, 253, 117, 102, 79, 174, 247, 68, 238, 78, 82, 215, + 39, 30, 43, 187, 118, 159, 145, 237, 111, 155, 116, 216, 182, 148, 245, 102, 6, + 133, 44, 123, 163, 174, 74, 65, 127, 232, 84, 91, 20, 43, 200, 159, 74, 220, 215, + 174, 19, 148, 28, 186, 183, 117, 11, 131, 233, 240, 166, 109, 22, 190, 100, 120, + 143, 175, 204, 74, 165, 32, 57, 154, 219, 174, 209, 149, 248, 177, 44, 78, 179, + 30, 193, 1, 104, 229, 10, 171, 198, 89, 166, 174, 165, 22, 220, 232, 51, 215, + 166, 113, 96, 230, 139, 244, 201, 4, 74, 83, 7, 125, 242, 114, 122, 208, 12, 243, + 111, 73, 73, 199, 182, 129, 169, 18, 20, 12, 187, 48, 158, 171, 240, 149, 220, + 103, 20, 249, 244, 216, 100, 187, 165, 175, 250, 224, 179, 90, 226, 245, 227, 86, + 91, 204, 58, 71, 178, 18, 118, 119, 1, 34, 106, 142, 190, 250, 40, 134, 101, 166, + 68, 165, 2, 115, 51, 94, 251, 182, 16, 81, 15, 36, 27, 91, 114, 12, 138, 54, 141, + 89, 166, 154, 93, 65, 171, 253, 153, 84, 37, 130, 118, 37, 147, 129, 49, 175, 12, + 79, 51, 254, 11, 212, 104, 140, 34, 44, 33, 250, 157, 168, 232, 156, 170, 3, 248, + 68, 44, 100, 46, 245, 15, 161, 166, 103, 166, 230, 209, 5, 199, 124, 92, 195, + 254, 200, 215, 170, 37, 112, 207, 26, 48, 119, 181, 3, 195, 128, 105, 160, 160, + 141, 252, 155, 66, 217, 108, 45, 225, 155, 109, 18, 123, 138, 225, 54, 221, 207, + 62, 90, 208, 220, 228, 34, 196, 90, 86, 246, 31, 106, 116, 125, 52, 131, 130, + 175, 9, 109, 190, 11, 240, 134, 199, 187, 57, 178, 162, 192, 188, 54, 182, 33, + 171, 12, 115, 142, 152, 133, 215, 49, 216, 23, 64, 58, 177, 52, 117, 29, 25, 18, + 105, 2, 108, 134, 153, 78, 170, 139, 67, 168, 59, 74, 209, 246, 208, 231, 115, + 129, 196, 226, 151, 74, 251, 200, 246, 154, 116, 82, 97, 29, 178, 210, 62, 174, + 38, 249, 189, 187, 136, 149, 142, 244, 76, 100, 208, 254, 152, 123, 233, 247, 38, + 173, 249, 56, 245, 15, 108, 114, 92, 127, 129, 96, 55, 191, 228, 82, 205, 30, + 123, 163, 90, 196, 126, 220, 180, 154, 154, 43, 39, 174, 202, 112, 220, 228, 131, + 203, 125, 237, 31, 44, 234, 26, 245, 31, 178, 139, 98, 136, 124, 57, 153, 138, + 201, 254, 244, 223, 222, 218, 31, 7, 224, 113, 186, 85, 138, 23, 58, 253, 6, 203, + 195, 255, 29, 89, 249, 139, 108, 85, 29, 149, 8, 147, 87, 5, 125, 92, 139, 226, + 100, 2, 39, 158, 157, 240, 177, 223, 26, 16, 183, 43, 243, 146, 127, 47, 138, 24, + 31, 124, 153, 221, 33, 90, 117, 41, 191, 226, 150, 169, 96, 58, 20, 70, 115, 113, + 134, 210, 26, 235, 139, 199, 174, 89, 225, 253, 33, 236, 197, 2, 201, 177, 20, + 95, 57, 80, 203, 125, 62, 56, 66, 68, 111, 129, 164, 240, 223, 29, 245, 55, 206, + 225, 57, 239, 100, 234, 152, 75, 217>> + + def get_zero_hash(depth) do + offset = (depth + 1) * @bytes_per_chunk - @bytes_per_chunk + <<_::binary-size(offset), hash::binary-size(@bytes_per_chunk), _::binary>> = @zero_hashes + hash + end +end From 4c91091790db31c891ddd50d5485157d1dc9f6bd Mon Sep 17 00:00:00 2001 From: Godspower Eze Date: Thu, 25 Jan 2024 12:53:14 +0100 Subject: [PATCH 10/19] update --- lib/ssz_ex.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ssz_ex.ex b/lib/ssz_ex.ex index 091b7cc00..9a30c6b58 100644 --- a/lib/ssz_ex.ex +++ b/lib/ssz_ex.ex @@ -4,8 +4,8 @@ defmodule LambdaEthereumConsensus.SszEx do """ alias LambdaEthereumConsensus.Utils.BitList alias LambdaEthereumConsensus.Utils.BitVector - alias LambdaEthereumConsensus.Utils.ZeroHashes import alias LambdaEthereumConsensus.Utils.BitVector + alias LambdaEthereumConsensus.Utils.ZeroHashes ################# ### Public API From 1190247876f80a412e509109963d82c2079b9fec Mon Sep 17 00:00:00 2001 From: Godspower Eze Date: Sun, 28 Jan 2024 18:33:25 +0100 Subject: [PATCH 11/19] feat: added merkleization of containers --- lib/spec/runners/ssz_generic.ex | 6 ++++-- lib/ssz_ex.ex | 36 +++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/lib/spec/runners/ssz_generic.ex b/lib/spec/runners/ssz_generic.ex index be0bc3ea8..96de18061 100644 --- a/lib/spec/runners/ssz_generic.ex +++ b/lib/spec/runners/ssz_generic.ex @@ -69,13 +69,15 @@ defmodule SszGenericTestRunner do {:container, module}, real_serialized, real_deserialized, - _hash_tree_root + expected_hash_tree_root ) do real_struct = struct!(module, real_deserialized) {:ok, deserialized} = SszEx.decode(real_serialized, module) assert deserialized == real_struct {:ok, serialized} = SszEx.encode(real_struct, module) assert serialized == real_serialized + actual_hash_tree_root = SszEx.hash_tree_root!(real_struct, module) + assert actual_hash_tree_root == expected_hash_tree_root end defp assert_ssz( @@ -92,7 +94,7 @@ defmodule SszGenericTestRunner do assert serialized == real_serialized - {:ok, actual_hash_tree_root} = SszEx.hash_tree_root(real_deserialized, schema) + actual_hash_tree_root = SszEx.hash_tree_root!(real_deserialized, schema) assert actual_hash_tree_root == expected_hash_tree_root end diff --git a/lib/ssz_ex.ex b/lib/ssz_ex.ex index 9a30c6b58..732b99d58 100644 --- a/lib/ssz_ex.ex +++ b/lib/ssz_ex.ex @@ -74,6 +74,37 @@ defmodule LambdaEthereumConsensus.SszEx do @spec hash_tree_root!(non_neg_integer, {:int, non_neg_integer}) :: Types.root() def hash_tree_root!(value, {:int, size}), do: pack(value, {:int, size}) + @spec hash_tree_root!(binary, {:bytes, non_neg_integer}) :: Types.root() + def hash_tree_root!(value, {:bytes, size}) do + packed_chunks = pack(value, {:bytes, size}) + leaf_count = packed_chunks |> get_chunks_len() |> next_pow_of_two() + root = merkleize_chunks_with_virtual_padding(packed_chunks, leaf_count) + root + end + + @spec hash_tree_root!(list(), {:list, any, non_neg_integer}) :: Types.root() + def hash_tree_root!(list, {:list, type, size}) do + {:ok, root} = hash_tree_root(list, {:list, type, size}) + root + end + + @spec hash_tree_root!(list(), {:vector, any, non_neg_integer}) :: Types.root() + def hash_tree_root!(vector, {:vector, type, size}) do + {:ok, root} = hash_tree_root(vector, {:vector, type, size}) + root + end + + def hash_tree_root!(container, module) when is_map(container) do + chunks = module.schema() |> Enum.reduce(<<>>, fn {key, schema}, acc_root -> + value = container |> Map.get(key) + root = hash_tree_root!(value, schema) + acc_root <> root + end) + leaf_count = chunks |> get_chunks_len() |> next_pow_of_two() + root = merkleize_chunks_with_virtual_padding(chunks, leaf_count) + root + end + @spec hash_tree_root(list(), {:list, any, non_neg_integer}) :: {:ok, Types.root()} | {:error, String.t()} def hash_tree_root(list, {:list, type, size}) do @@ -206,6 +237,11 @@ defmodule LambdaEthereumConsensus.SszEx do <> |> pack_bytes() end + @spec pack(binary, {:bytes, non_neg_integer}) :: binary() + def pack(value, {:bytes, _size}) do + value |> pack_bytes() + end + @spec pack(list(), {:list | :vector, any, non_neg_integer}) :: binary() | :error def pack(list, {type, schema, _}) when type in [:vector, :list] do if variable_size?(schema) do From 9ed34f6cc13adaf386bac31eb0272f8bb7ebe48f Mon Sep 17 00:00:00 2001 From: Godspower Eze Date: Sun, 28 Jan 2024 18:39:40 +0100 Subject: [PATCH 12/19] update --- lib/ssz_ex.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ssz_ex.ex b/lib/ssz_ex.ex index 9a30c6b58..b78e20909 100644 --- a/lib/ssz_ex.ex +++ b/lib/ssz_ex.ex @@ -663,7 +663,7 @@ defmodule LambdaEthereumConsensus.SszEx do end end - defp next_pow_of_two(len) when len == 0, do: 0 + defp next_pow_of_two(0) do: 0 defp next_pow_of_two(len) when is_integer(len) and len > 0 do n = ((len <<< 1) - 1) |> compute_pow() From 92f061aef77ae2744111a6f887ae50fdf6d0be2d Mon Sep 17 00:00:00 2001 From: Godspower Eze Date: Sun, 28 Jan 2024 18:40:19 +0100 Subject: [PATCH 13/19] update --- lib/ssz_ex.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ssz_ex.ex b/lib/ssz_ex.ex index b78e20909..eee85d9ae 100644 --- a/lib/ssz_ex.ex +++ b/lib/ssz_ex.ex @@ -663,7 +663,7 @@ defmodule LambdaEthereumConsensus.SszEx do end end - defp next_pow_of_two(0) do: 0 + defp next_pow_of_two(0), do: 0 defp next_pow_of_two(len) when is_integer(len) and len > 0 do n = ((len <<< 1) - 1) |> compute_pow() From 8ded18e15f846677fa5b6a9bf063ca985bf9104d Mon Sep 17 00:00:00 2001 From: Godspower Eze Date: Sun, 28 Jan 2024 19:19:25 +0100 Subject: [PATCH 14/19] update --- lib/ssz_ex.ex | 14 +++++++------- lib/utils/zero_hashes.ex | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/lib/ssz_ex.ex b/lib/ssz_ex.ex index eee85d9ae..3be4e0c6f 100644 --- a/lib/ssz_ex.ex +++ b/lib/ssz_ex.ex @@ -222,6 +222,13 @@ defmodule LambdaEthereumConsensus.SszEx do (max_size * size + 31) |> div(32) end + def replace_chunk(chunks, start, new_chunk) do + <> = + chunks + + <> + end + ################# ### Private functions ################# @@ -670,13 +677,6 @@ defmodule LambdaEthereumConsensus.SszEx do 2 ** n end - defp replace_chunk(chunks, start, new_chunk) do - <> = - chunks - - <> - end - defp get_chunks_len(chunks) do chunks |> byte_size() |> div(@bytes_per_chunk) end diff --git a/lib/utils/zero_hashes.ex b/lib/utils/zero_hashes.ex index 81db2ac05..6c0daafc6 100644 --- a/lib/utils/zero_hashes.ex +++ b/lib/utils/zero_hashes.ex @@ -3,7 +3,11 @@ defmodule LambdaEthereumConsensus.Utils.ZeroHashes do Precomputed zero hashes """ + alias LambdaEthereumConsensus.SszEx + + @bits_per_byte 8 @bytes_per_chunk 32 + @max_merkle_tree_depth 64 @zero_hashes <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245, 165, 253, 66, 209, 106, 32, 48, 39, 152, 239, 110, 211, 9, 151, 155, 67, 0, 61, 35, 32, 217, 240, 232, 234, 152, 49, 169, 39, 89, 251, 75, @@ -122,6 +126,21 @@ defmodule LambdaEthereumConsensus.Utils.ZeroHashes do 95, 57, 80, 203, 125, 62, 56, 66, 68, 111, 129, 164, 240, 223, 29, 245, 55, 206, 225, 57, 239, 100, 234, 152, 75, 217>> + def compute_zero_hashes() do + buffer = <<0::size(@bytes_per_chunk * @max_merkle_tree_depth * @bits_per_byte)>> + + 0..(@max_merkle_tree_depth - 2) + |> Enum.reduce(buffer, fn index, acc_buffer -> + start = index * @bytes_per_chunk + stop = (index + 2) * @bytes_per_chunk + focus = acc_buffer |> :binary.part(start, stop - start) + <> = focus + hash = SszEx.hash_nodes(left, left) + change_index = (index + 1) * @bytes_per_chunk + SszEx.replace_chunk(acc_buffer, change_index, hash) + end) + end + def get_zero_hash(depth) do offset = (depth + 1) * @bytes_per_chunk - @bytes_per_chunk <<_::binary-size(offset), hash::binary-size(@bytes_per_chunk), _::binary>> = @zero_hashes From c104a482e1e29155ac0d7acfe5f4f2963b318764 Mon Sep 17 00:00:00 2001 From: Godspower Eze Date: Sun, 28 Jan 2024 19:23:36 +0100 Subject: [PATCH 15/19] update --- lib/ssz_ex.ex | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/ssz_ex.ex b/lib/ssz_ex.ex index 431ef3c44..2a08647d8 100644 --- a/lib/ssz_ex.ex +++ b/lib/ssz_ex.ex @@ -95,11 +95,14 @@ defmodule LambdaEthereumConsensus.SszEx do end def hash_tree_root!(container, module) when is_map(container) do - chunks = module.schema() |> Enum.reduce(<<>>, fn {key, schema}, acc_root -> - value = container |> Map.get(key) - root = hash_tree_root!(value, schema) - acc_root <> root - end) + chunks = + module.schema() + |> Enum.reduce(<<>>, fn {key, schema}, acc_root -> + value = container |> Map.get(key) + root = hash_tree_root!(value, schema) + acc_root <> root + end) + leaf_count = chunks |> get_chunks_len() |> next_pow_of_two() root = merkleize_chunks_with_virtual_padding(chunks, leaf_count) root From 938c4bef3ebf9332cc120222c7c6e9426fdd880f Mon Sep 17 00:00:00 2001 From: Godspower Eze Date: Sun, 28 Jan 2024 19:27:59 +0100 Subject: [PATCH 16/19] update --- lib/utils/zero_hashes.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/utils/zero_hashes.ex b/lib/utils/zero_hashes.ex index 6c0daafc6..87bf067ac 100644 --- a/lib/utils/zero_hashes.ex +++ b/lib/utils/zero_hashes.ex @@ -126,7 +126,7 @@ defmodule LambdaEthereumConsensus.Utils.ZeroHashes do 95, 57, 80, 203, 125, 62, 56, 66, 68, 111, 129, 164, 240, 223, 29, 245, 55, 206, 225, 57, 239, 100, 234, 152, 75, 217>> - def compute_zero_hashes() do + def compute_zero_hashes do buffer = <<0::size(@bytes_per_chunk * @max_merkle_tree_depth * @bits_per_byte)>> 0..(@max_merkle_tree_depth - 2) From 1ee15b71d7de405c00176f753672183ef53432c8 Mon Sep 17 00:00:00 2001 From: Godspower Eze Date: Sun, 28 Jan 2024 19:52:00 +0100 Subject: [PATCH 17/19] update --- lib/ssz_ex.ex | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/ssz_ex.ex b/lib/ssz_ex.ex index 2a08647d8..2af1ad9a5 100644 --- a/lib/ssz_ex.ex +++ b/lib/ssz_ex.ex @@ -94,6 +94,7 @@ defmodule LambdaEthereumConsensus.SszEx do root end + @spec hash_tree_root!(struct(), atom()) :: Types.root() def hash_tree_root!(container, module) when is_map(container) do chunks = module.schema() From 70219b9928d3fa355b80a85e462aabba9a65d7ed Mon Sep 17 00:00:00 2001 From: Godspower Eze Date: Mon, 29 Jan 2024 17:03:07 +0100 Subject: [PATCH 18/19] update --- test/unit/ssz_ex_test.exs | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/test/unit/ssz_ex_test.exs b/test/unit/ssz_ex_test.exs index e6e70954f..6699da098 100644 --- a/test/unit/ssz_ex_test.exs +++ b/test/unit/ssz_ex_test.exs @@ -136,13 +136,6 @@ defmodule Unit.SSZExTest do root = chunks |> SszEx.merkleize_chunks(2 ** 10) expected_value = "2647cb9e26bd83eeb0982814b2ac4d6cc4a65d0d98637f1a73a4c06d3db0e6ce" assert root |> Base.encode16(case: :lower) == expected_value - - ## TOO HEAVY COMPUTATION! - # chunks = 1..70 |> Enum.reduce(<<>>, fn _, acc -> acc <> ones end) - # leaf_count = 9_223_372_036_854_775_808 # 2 ** 63 - # root = chunks |> SszEx.merkleize_chunks(leaf_count) - # expected_value = "9317695d95b5a3b46e976b5a9cbfcfccb600accaddeda9ac867cc9669b862979" - # assert root |> Base.encode16(case: :lower) == expected_value end test "merklelization of chunks with virtual padding" do @@ -208,13 +201,6 @@ defmodule Unit.SSZExTest do root = chunks |> SszEx.merkleize_chunks_with_virtual_padding(2 ** 10) expected_value = "2647cb9e26bd83eeb0982814b2ac4d6cc4a65d0d98637f1a73a4c06d3db0e6ce" assert root |> Base.encode16(case: :lower) == expected_value - - ## TOO HEAVY COMPUTATION! - # chunks = 1..70 |> Enum.reduce(<<>>, fn _, acc -> acc <> ones end) - # leaf_count = 9_223_372_036_854_775_808 # 2 ** 63 - # root = chunks |> SszEx.merkleize_chunks_with_virtual_padding(leaf_count) - # expected_value = "9317695d95b5a3b46e976b5a9cbfcfccb600accaddeda9ac867cc9669b862979" - # assert root |> Base.encode16(case: :lower) == expected_value end test "hash tree root of list" do From eb1a6b2f12d4ef6e75d0fc4166d0af426166c015 Mon Sep 17 00:00:00 2001 From: Godspower Eze Date: Mon, 29 Jan 2024 17:50:42 +0100 Subject: [PATCH 19/19] update --- lib/ssz_ex.ex | 25 +++++--- lib/utils/zero_hashes.ex | 135 +++------------------------------------ 2 files changed, 26 insertions(+), 134 deletions(-) diff --git a/lib/ssz_ex.ex b/lib/ssz_ex.ex index 3be4e0c6f..b7df120fc 100644 --- a/lib/ssz_ex.ex +++ b/lib/ssz_ex.ex @@ -16,6 +16,7 @@ defmodule LambdaEthereumConsensus.SszEx do @bits_per_byte 8 @bits_per_chunk @bytes_per_chunk * @bits_per_byte @zero_chunk <<0::size(@bits_per_chunk)>> + @zero_hashes ZeroHashes.compute_zero_hashes() @spec hash(iodata()) :: binary() def hash(data), do: :crypto.hash(:sha256, data) @@ -173,7 +174,7 @@ defmodule LambdaEthereumConsensus.SszEx do cond do chunks_len == 0 -> depth = height - 1 - ZeroHashes.get_zero_hash(depth) + get_zero_hash(depth) chunks_len == 1 and leaf_count == 1 -> chunks @@ -222,13 +223,6 @@ defmodule LambdaEthereumConsensus.SszEx do (max_size * size + 31) |> div(32) end - def replace_chunk(chunks, start, new_chunk) do - <> = - chunks - - <> - end - ################# ### Private functions ################# @@ -719,7 +713,7 @@ defmodule LambdaEthereumConsensus.SszEx do children_index = focus_len - @bytes_per_chunk <<_::binary-size(children_index), left::binary>> = focus depth = height - i - 1 - right = ZeroHashes.get_zero_hash(depth) + right = get_zero_hash(depth) {children_index, left, right} end @@ -735,4 +729,17 @@ defmodule LambdaEthereumConsensus.SszEx do {:cont, replace_chunk(layers, index, hash)} end end + + defp replace_chunk(chunks, start, new_chunk) do + <> = + chunks + + <> + end + + defp get_zero_hash(depth) do + offset = (depth + 1) * @bytes_per_chunk - @bytes_per_chunk + <<_::binary-size(offset), hash::binary-size(@bytes_per_chunk), _::binary>> = @zero_hashes + hash + end end diff --git a/lib/utils/zero_hashes.ex b/lib/utils/zero_hashes.ex index 87bf067ac..cc268d599 100644 --- a/lib/utils/zero_hashes.ex +++ b/lib/utils/zero_hashes.ex @@ -3,128 +3,10 @@ defmodule LambdaEthereumConsensus.Utils.ZeroHashes do Precomputed zero hashes """ - alias LambdaEthereumConsensus.SszEx - @bits_per_byte 8 @bytes_per_chunk 32 + @bits_per_chunk @bytes_per_chunk * @bits_per_byte @max_merkle_tree_depth 64 - @zero_hashes <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 245, 165, 253, 66, 209, 106, 32, 48, 39, 152, 239, 110, 211, 9, - 151, 155, 67, 0, 61, 35, 32, 217, 240, 232, 234, 152, 49, 169, 39, 89, 251, 75, - 219, 86, 17, 78, 0, 253, 212, 193, 248, 92, 137, 43, 243, 90, 201, 168, 146, 137, - 170, 236, 177, 235, 208, 169, 108, 222, 96, 106, 116, 139, 93, 113, 199, 128, 9, - 253, 240, 127, 197, 106, 17, 241, 34, 55, 6, 88, 163, 83, 170, 165, 66, 237, 99, - 228, 76, 75, 193, 95, 244, 205, 16, 90, 179, 60, 83, 109, 152, 131, 127, 45, 209, - 101, 165, 93, 94, 234, 233, 20, 133, 149, 68, 114, 213, 111, 36, 109, 242, 86, - 191, 60, 174, 25, 53, 42, 18, 60, 158, 253, 224, 82, 170, 21, 66, 159, 174, 5, - 186, 212, 208, 177, 215, 198, 77, 166, 77, 3, 215, 161, 133, 74, 88, 140, 44, - 184, 67, 12, 13, 48, 216, 141, 223, 238, 212, 0, 168, 117, 85, 150, 178, 25, 66, - 193, 73, 126, 17, 76, 48, 46, 97, 24, 41, 15, 145, 230, 119, 41, 118, 4, 31, 161, - 135, 235, 13, 219, 165, 126, 53, 246, 210, 134, 103, 56, 2, 164, 175, 89, 117, - 226, 37, 6, 199, 207, 76, 100, 187, 107, 229, 238, 17, 82, 127, 44, 38, 132, 100, - 118, 253, 95, 197, 74, 93, 67, 56, 81, 103, 201, 81, 68, 242, 100, 63, 83, 60, - 200, 91, 185, 209, 107, 120, 47, 141, 125, 177, 147, 80, 109, 134, 88, 45, 37, - 36, 5, 184, 64, 1, 135, 146, 202, 210, 191, 18, 89, 241, 239, 90, 165, 248, 135, - 225, 60, 178, 240, 9, 79, 81, 225, 255, 255, 10, 215, 230, 89, 119, 47, 149, 52, - 193, 149, 200, 21, 239, 196, 1, 78, 241, 225, 218, 237, 68, 4, 192, 99, 133, 209, - 17, 146, 233, 43, 108, 240, 65, 39, 219, 5, 68, 28, 216, 51, 16, 122, 82, 190, - 133, 40, 104, 137, 14, 67, 23, 230, 160, 42, 180, 118, 131, 170, 117, 150, 66, - 32, 183, 208, 95, 135, 95, 20, 0, 39, 239, 81, 24, 162, 36, 123, 187, 132, 206, - 143, 47, 15, 17, 35, 98, 48, 133, 218, 247, 150, 12, 50, 159, 95, 223, 106, 245, - 245, 187, 219, 107, 233, 239, 138, 166, 24, 228, 191, 128, 115, 150, 8, 103, 23, - 30, 41, 103, 111, 139, 40, 77, 234, 106, 8, 168, 94, 181, 141, 144, 15, 94, 24, - 46, 60, 80, 239, 116, 150, 158, 161, 108, 119, 38, 197, 73, 117, 124, 194, 53, - 35, 195, 105, 88, 125, 167, 41, 55, 132, 212, 154, 117, 2, 255, 207, 176, 52, 11, - 29, 120, 133, 104, 133, 0, 202, 48, 129, 97, 167, 249, 107, 98, 223, 157, 8, 59, - 113, 252, 200, 242, 187, 143, 230, 177, 104, 146, 86, 192, 211, 133, 244, 47, 91, - 190, 32, 39, 162, 44, 25, 150, 225, 16, 186, 151, 193, 113, 211, 229, 148, 141, - 233, 43, 235, 141, 13, 99, 195, 158, 186, 222, 133, 9, 224, 174, 60, 156, 56, - 118, 251, 95, 161, 18, 190, 24, 249, 5, 236, 172, 254, 203, 146, 5, 118, 3, 171, - 149, 238, 200, 178, 229, 65, 202, 212, 233, 29, 227, 131, 133, 242, 224, 70, 97, - 159, 84, 73, 108, 35, 130, 203, 108, 172, 213, 185, 140, 38, 245, 164, 248, 147, - 233, 8, 145, 119, 117, 182, 43, 255, 35, 41, 77, 187, 227, 161, 205, 142, 108, - 193, 195, 91, 72, 1, 136, 123, 100, 106, 111, 129, 241, 127, 205, 219, 167, 181, - 146, 227, 19, 51, 147, 193, 97, 148, 250, 199, 67, 26, 191, 47, 84, 133, 237, - 113, 29, 178, 130, 24, 60, 129, 158, 8, 235, 170, 138, 141, 127, 227, 175, 140, - 170, 8, 90, 118, 57, 168, 50, 0, 20, 87, 223, 185, 18, 138, 128, 97, 20, 42, 208, - 51, 86, 41, 255, 35, 255, 156, 254, 179, 195, 55, 215, 165, 26, 111, 191, 0, 185, - 227, 76, 82, 225, 201, 25, 92, 150, 155, 212, 231, 160, 191, 213, 29, 92, 91, - 237, 156, 17, 103, 231, 31, 10, 168, 60, 195, 46, 223, 190, 250, 159, 77, 62, 1, - 116, 202, 133, 24, 46, 236, 159, 58, 9, 246, 166, 192, 223, 99, 119, 165, 16, - 215, 49, 32, 111, 168, 10, 80, 187, 106, 190, 41, 8, 80, 88, 241, 98, 18, 33, 42, - 96, 238, 200, 240, 73, 254, 203, 146, 216, 200, 224, 168, 75, 192, 33, 53, 43, - 254, 203, 237, 221, 233, 147, 131, 159, 97, 76, 61, 172, 10, 62, 227, 117, 67, - 249, 180, 18, 177, 97, 153, 220, 21, 142, 35, 181, 68, 97, 158, 49, 39, 36, 187, - 109, 124, 49, 83, 237, 157, 231, 145, 215, 100, 163, 102, 179, 137, 175, 19, 197, - 139, 248, 168, 217, 4, 129, 164, 103, 101, 124, 221, 41, 134, 38, 130, 80, 98, - 141, 12, 16, 227, 133, 197, 140, 97, 145, 230, 251, 224, 81, 145, 188, 192, 79, - 19, 63, 44, 234, 114, 193, 196, 132, 137, 48, 189, 123, 168, 202, 197, 70, 97, 7, - 33, 19, 251, 39, 136, 105, 224, 123, 184, 88, 127, 145, 57, 41, 51, 55, 77, 1, - 123, 203, 225, 136, 105, 255, 44, 34, 178, 140, 193, 5, 16, 217, 133, 50, 146, - 128, 51, 40, 190, 79, 176, 232, 4, 149, 232, 187, 141, 39, 31, 91, 136, 150, 54, - 181, 254, 40, 231, 159, 27, 133, 15, 134, 88, 36, 108, 233, 182, 161, 231, 180, - 159, 192, 109, 183, 20, 62, 143, 224, 180, 242, 176, 197, 82, 58, 92, 152, 94, - 146, 159, 112, 175, 40, 208, 189, 209, 169, 10, 128, 143, 151, 127, 89, 124, 124, - 119, 140, 72, 158, 152, 211, 189, 137, 16, 211, 26, 192, 247, 198, 246, 126, 2, - 230, 228, 225, 189, 239, 185, 148, 198, 9, 137, 83, 243, 70, 54, 186, 43, 108, - 162, 10, 71, 33, 210, 178, 106, 136, 103, 34, 255, 28, 154, 126, 95, 241, 207, - 72, 180, 173, 21, 130, 211, 244, 228, 161, 0, 79, 59, 32, 216, 197, 162, 183, 19, - 135, 164, 37, 74, 217, 51, 235, 197, 47, 7, 90, 226, 41, 100, 107, 111, 106, 237, - 25, 165, 227, 114, 207, 41, 80, 129, 64, 30, 184, 147, 255, 89, 155, 63, 154, - 204, 12, 13, 62, 125, 50, 137, 33, 222, 181, 150, 18, 7, 104, 1, 232, 205, 97, - 89, 33, 7, 181, 198, 124, 121, 184, 70, 89, 92, 198, 50, 12, 57, 91, 70, 54, 44, - 191, 185, 9, 253, 178, 54, 173, 36, 17, 180, 228, 136, 56, 16, 160, 116, 184, 64, - 70, 70, 137, 152, 108, 63, 138, 128, 145, 130, 126, 23, 195, 39, 85, 216, 251, - 54, 135, 186, 59, 164, 159, 52, 44, 119, 245, 161, 248, 155, 236, 131, 216, 17, - 68, 110, 26, 70, 113, 57, 33, 61, 100, 11, 106, 116, 247, 33, 13, 79, 142, 126, - 16, 57, 121, 14, 123, 244, 239, 162, 7, 85, 90, 16, 166, 219, 29, 212, 185, 93, - 163, 19, 170, 168, 139, 136, 254, 118, 173, 33, 181, 22, 203, 198, 69, 255, 227, - 74, 181, 222, 28, 138, 239, 140, 212, 231, 248, 210, 181, 30, 142, 20, 86, 173, - 199, 86, 60, 218, 32, 111, 107, 254, 141, 43, 204, 66, 55, 183, 74, 80, 71, 5, - 142, 244, 85, 51, 158, 205, 115, 96, 203, 99, 191, 187, 142, 229, 68, 142, 100, - 48, 186, 4, 167, 242, 60, 233, 24, 23, 64, 220, 34, 12, 129, 71, 130, 101, 79, - 238, 106, 206, 185, 241, 236, 146, 34, 196, 226, 70, 125, 10, 177, 104, 8, 55, - 174, 249, 71, 108, 137, 89, 10, 44, 140, 201, 179, 183, 79, 73, 103, 199, 87, - 196, 157, 152, 102, 164, 75, 172, 242, 31, 162, 237, 103, 93, 223, 162, 154, 66, - 188, 173, 130, 246, 169, 228, 18, 132, 216, 8, 234, 211, 25, 242, 159, 59, 8, 32, - 157, 104, 15, 14, 44, 231, 21, 16, 208, 113, 226, 5, 209, 166, 109, 53, 74, 103, - 185, 207, 23, 149, 113, 216, 229, 249, 119, 146, 113, 110, 141, 212, 236, 68, 25, - 104, 57, 163, 247, 198, 183, 79, 139, 172, 250, 250, 48, 37, 242, 248, 149, 9, - 194, 199, 28, 116, 251, 160, 205, 146, 133, 142, 244, 155, 7, 128, 251, 84, 121, - 116, 108, 138, 155, 252, 179, 70, 51, 52, 167, 193, 231, 246, 112, 90, 166, 1, - 26, 106, 148, 150, 69, 1, 109, 180, 172, 222, 12, 169, 171, 214, 109, 199, 157, - 130, 102, 66, 48, 86, 7, 150, 253, 117, 102, 79, 174, 247, 68, 238, 78, 82, 215, - 39, 30, 43, 187, 118, 159, 145, 237, 111, 155, 116, 216, 182, 148, 245, 102, 6, - 133, 44, 123, 163, 174, 74, 65, 127, 232, 84, 91, 20, 43, 200, 159, 74, 220, 215, - 174, 19, 148, 28, 186, 183, 117, 11, 131, 233, 240, 166, 109, 22, 190, 100, 120, - 143, 175, 204, 74, 165, 32, 57, 154, 219, 174, 209, 149, 248, 177, 44, 78, 179, - 30, 193, 1, 104, 229, 10, 171, 198, 89, 166, 174, 165, 22, 220, 232, 51, 215, - 166, 113, 96, 230, 139, 244, 201, 4, 74, 83, 7, 125, 242, 114, 122, 208, 12, 243, - 111, 73, 73, 199, 182, 129, 169, 18, 20, 12, 187, 48, 158, 171, 240, 149, 220, - 103, 20, 249, 244, 216, 100, 187, 165, 175, 250, 224, 179, 90, 226, 245, 227, 86, - 91, 204, 58, 71, 178, 18, 118, 119, 1, 34, 106, 142, 190, 250, 40, 134, 101, 166, - 68, 165, 2, 115, 51, 94, 251, 182, 16, 81, 15, 36, 27, 91, 114, 12, 138, 54, 141, - 89, 166, 154, 93, 65, 171, 253, 153, 84, 37, 130, 118, 37, 147, 129, 49, 175, 12, - 79, 51, 254, 11, 212, 104, 140, 34, 44, 33, 250, 157, 168, 232, 156, 170, 3, 248, - 68, 44, 100, 46, 245, 15, 161, 166, 103, 166, 230, 209, 5, 199, 124, 92, 195, - 254, 200, 215, 170, 37, 112, 207, 26, 48, 119, 181, 3, 195, 128, 105, 160, 160, - 141, 252, 155, 66, 217, 108, 45, 225, 155, 109, 18, 123, 138, 225, 54, 221, 207, - 62, 90, 208, 220, 228, 34, 196, 90, 86, 246, 31, 106, 116, 125, 52, 131, 130, - 175, 9, 109, 190, 11, 240, 134, 199, 187, 57, 178, 162, 192, 188, 54, 182, 33, - 171, 12, 115, 142, 152, 133, 215, 49, 216, 23, 64, 58, 177, 52, 117, 29, 25, 18, - 105, 2, 108, 134, 153, 78, 170, 139, 67, 168, 59, 74, 209, 246, 208, 231, 115, - 129, 196, 226, 151, 74, 251, 200, 246, 154, 116, 82, 97, 29, 178, 210, 62, 174, - 38, 249, 189, 187, 136, 149, 142, 244, 76, 100, 208, 254, 152, 123, 233, 247, 38, - 173, 249, 56, 245, 15, 108, 114, 92, 127, 129, 96, 55, 191, 228, 82, 205, 30, - 123, 163, 90, 196, 126, 220, 180, 154, 154, 43, 39, 174, 202, 112, 220, 228, 131, - 203, 125, 237, 31, 44, 234, 26, 245, 31, 178, 139, 98, 136, 124, 57, 153, 138, - 201, 254, 244, 223, 222, 218, 31, 7, 224, 113, 186, 85, 138, 23, 58, 253, 6, 203, - 195, 255, 29, 89, 249, 139, 108, 85, 29, 149, 8, 147, 87, 5, 125, 92, 139, 226, - 100, 2, 39, 158, 157, 240, 177, 223, 26, 16, 183, 43, 243, 146, 127, 47, 138, 24, - 31, 124, 153, 221, 33, 90, 117, 41, 191, 226, 150, 169, 96, 58, 20, 70, 115, 113, - 134, 210, 26, 235, 139, 199, 174, 89, 225, 253, 33, 236, 197, 2, 201, 177, 20, - 95, 57, 80, 203, 125, 62, 56, 66, 68, 111, 129, 164, 240, 223, 29, 245, 55, 206, - 225, 57, 239, 100, 234, 152, 75, 217>> def compute_zero_hashes do buffer = <<0::size(@bytes_per_chunk * @max_merkle_tree_depth * @bits_per_byte)>> @@ -135,15 +17,18 @@ defmodule LambdaEthereumConsensus.Utils.ZeroHashes do stop = (index + 2) * @bytes_per_chunk focus = acc_buffer |> :binary.part(start, stop - start) <> = focus - hash = SszEx.hash_nodes(left, left) + hash = hash_nodes(left, left) change_index = (index + 1) * @bytes_per_chunk - SszEx.replace_chunk(acc_buffer, change_index, hash) + replace_chunk(acc_buffer, change_index, hash) end) end - def get_zero_hash(depth) do - offset = (depth + 1) * @bytes_per_chunk - @bytes_per_chunk - <<_::binary-size(offset), hash::binary-size(@bytes_per_chunk), _::binary>> = @zero_hashes - hash + defp hash_nodes(left, right), do: :crypto.hash(:sha256, left <> right) + + defp replace_chunk(chunks, start, new_chunk) do + <> = + chunks + + <> end end