From e812955b8f35af0747eff84e09efa4a91246912d Mon Sep 17 00:00:00 2001 From: guha-rahul <52607971+guha-rahul@users.noreply.github.com> Date: Tue, 23 Apr 2024 21:28:37 +0530 Subject: [PATCH] feat: adds Bls.key_validate (#1016) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Tomás Grüner <47506558+MegaRedHand@users.noreply.github.com> --- lib/bls.ex | 3 +- .../execution/rpc.ex | 13 +-- .../state_transition/epoch_processing.ex | 9 +- .../state_transition/shuffling.ex | 3 +- .../store/lru_cache.ex | 3 +- lib/utils/bit_list.ex | 3 +- lib/utils/diff.ex | 6 +- native/bls_nif/src/lib.rs | 10 +- test/fixtures/block.ex | 107 +++++++++--------- test/spec/runners/fork_choice.ex | 6 +- test/spec/runners/helpers/process_blocks.ex | 3 +- test/spec/runners/operations.ex | 3 +- test/spec/runners/ssz_static.ex | 3 +- test/spec/runners/sync.ex | 3 +- test/unit/bls_test.exs | 20 ++++ test/unit/req_resp_test.exs | 42 ++++--- test/unit/snappy_test.exs | 3 +- 17 files changed, 124 insertions(+), 116 deletions(-) create mode 100644 test/unit/bls_test.exs diff --git a/lib/bls.ex b/lib/bls.ex index 837140eb0..bb04c9812 100644 --- a/lib/bls.ex +++ b/lib/bls.ex @@ -46,7 +46,8 @@ defmodule Bls do :erlang.nif_error(:nif_not_loaded) end - # TODO: implement + @spec key_validate(Types.bls_pubkey()) :: + {:ok, boolean} | {:error, binary()} def key_validate(_public_key) do :erlang.nif_error(:nif_not_loaded) end diff --git a/lib/lambda_ethereum_consensus/execution/rpc.ex b/lib/lambda_ethereum_consensus/execution/rpc.ex index 45a8a6a59..679b1fb9d 100644 --- a/lib/lambda_ethereum_consensus/execution/rpc.ex +++ b/lib/lambda_ethereum_consensus/execution/rpc.ex @@ -12,13 +12,12 @@ defmodule LambdaEthereumConsensus.Execution.RPC do {Tesla.Middleware.Headers, [{"authorization", "Bearer #{jwt}"}]} ]) - request_body = - %{ - "jsonrpc" => version, - "method" => method, - "params" => params, - "id" => 1 - } + request_body = %{ + "jsonrpc" => version, + "method" => method, + "params" => params, + "id" => 1 + } with {:ok, result} <- post(client, endpoint, request_body) do result |> validate_rpc_response() diff --git a/lib/lambda_ethereum_consensus/state_transition/epoch_processing.ex b/lib/lambda_ethereum_consensus/state_transition/epoch_processing.ex index 51486cfb8..1685e0b09 100644 --- a/lib/lambda_ethereum_consensus/state_transition/epoch_processing.ex +++ b/lib/lambda_ethereum_consensus/state_transition/epoch_processing.ex @@ -258,8 +258,7 @@ defmodule LambdaEthereumConsensus.StateTransition.EpochProcessing do slots_per_historical_root = ChainSpec.get("SLOTS_PER_HISTORICAL_ROOT") - epochs_per_historical_root = - div(slots_per_historical_root, ChainSpec.get("SLOTS_PER_EPOCH")) + epochs_per_historical_root = div(slots_per_historical_root, ChainSpec.get("SLOTS_PER_EPOCH")) if rem(next_epoch, epochs_per_historical_root) == 0 do with {:ok, block_summary_root} <- @@ -279,8 +278,7 @@ defmodule LambdaEthereumConsensus.StateTransition.EpochProcessing do state_summary_root: state_summary_root } - new_state = - Map.update!(state, :historical_summaries, &(&1 ++ [historical_summary])) + new_state = Map.update!(state, :historical_summaries, &(&1 ++ [historical_summary])) {:ok, new_state} end @@ -303,8 +301,7 @@ defmodule LambdaEthereumConsensus.StateTransition.EpochProcessing do previous_target_balance = get_total_participating_balance(state, target_index, previous_epoch) - current_target_balance = - get_total_participating_balance(state, target_index, current_epoch) + current_target_balance = get_total_participating_balance(state, target_index, current_epoch) total_active_balance = Accessors.get_total_active_balance(state) diff --git a/lib/lambda_ethereum_consensus/state_transition/shuffling.ex b/lib/lambda_ethereum_consensus/state_transition/shuffling.ex index 8389b37b8..67fc091d5 100644 --- a/lib/lambda_ethereum_consensus/state_transition/shuffling.ex +++ b/lib/lambda_ethereum_consensus/state_transition/shuffling.ex @@ -43,8 +43,7 @@ defmodule LambdaEthereumConsensus.StateTransition.Shuffling do defp shuffle_list(input, round, seed) do input_size = Aja.Enum.count(input) - round_bytes = - :binary.encode_unsigned(round, :little) + round_bytes = :binary.encode_unsigned(round, :little) pivot = (seed <> round_bytes) diff --git a/lib/lambda_ethereum_consensus/store/lru_cache.ex b/lib/lambda_ethereum_consensus/store/lru_cache.ex index 4546a80ba..e82011e98 100644 --- a/lib/lambda_ethereum_consensus/store/lru_cache.ex +++ b/lib/lambda_ethereum_consensus/store/lru_cache.ex @@ -134,8 +134,7 @@ defmodule LambdaEthereumConsensus.Store.LRUCache do to_prune = :ets.info(data_table, :size) - max_entries if to_prune > 0 do - {elems, _cont} = - :ets.select(ttl_table, [{:_, [], [:"$_"]}], to_prune + batch_prune_size) + {elems, _cont} = :ets.select(ttl_table, [{:_, [], [:"$_"]}], to_prune + batch_prune_size) elems |> Enum.each(fn {uniq, root} -> diff --git a/lib/utils/bit_list.ex b/lib/utils/bit_list.ex index 076b2eeba..fdb5f0786 100644 --- a/lib/utils/bit_list.ex +++ b/lib/utils/bit_list.ex @@ -29,8 +29,7 @@ defmodule LambdaEthereumConsensus.Utils.BitList do num_bits = bit_size(bitstring) <> = - bitstring + last_byte::integer-little-size(@bits_per_byte)>> = bitstring <>)::bitstring, pre::integer-size(num_bits - @bits_per_byte)>> diff --git a/lib/utils/diff.ex b/lib/utils/diff.ex index e0d45352f..38e6471a4 100644 --- a/lib/utils/diff.ex +++ b/lib/utils/diff.ex @@ -57,11 +57,9 @@ defmodule LambdaEthereumConsensus.Utils.Diff do a_keys = a |> Map.keys() |> MapSet.new() b_keys = b |> Map.keys() |> MapSet.new() - a_extra = - MapSet.difference(a_keys, b_keys) |> Enum.map(fn k -> {k, Map.fetch!(a, k)} end) + a_extra = MapSet.difference(a_keys, b_keys) |> Enum.map(fn k -> {k, Map.fetch!(a, k)} end) - b_extra = - MapSet.difference(b_keys, a_keys) |> Enum.map(fn k -> {k, Map.fetch!(b, k)} end) + b_extra = MapSet.difference(b_keys, a_keys) |> Enum.map(fn k -> {k, Map.fetch!(b, k)} end) d |> add_if_not_empty(:added_left, a_extra) diff --git a/native/bls_nif/src/lib.rs b/native/bls_nif/src/lib.rs index b4c53d444..2b1e1bad1 100644 --- a/native/bls_nif/src/lib.rs +++ b/native/bls_nif/src/lib.rs @@ -142,6 +142,13 @@ fn eth_aggregate_pubkeys<'env>( } } } +#[rustler::nif] +fn key_validate<'env>(public_key: Binary) -> Result { + let _pubkey = + PublicKey::deserialize(public_key.as_slice()).map_err(|err| format!("{:?}", err))?; + + Ok(true) +} rustler::init!( "Elixir.Bls", @@ -152,6 +159,7 @@ rustler::init!( fast_aggregate_verify, eth_fast_aggregate_verify, eth_aggregate_pubkeys, - verify + verify, + key_validate ] ); diff --git a/test/fixtures/block.ex b/test/fixtures/block.ex index 030e8fb7a..d8fbc0c16 100644 --- a/test/fixtures/block.ex +++ b/test/fixtures/block.ex @@ -34,21 +34,20 @@ defmodule Fixtures.Block do @spec beacon_block_body :: BeaconBlockBody.t() def beacon_block_body() do - fields = - [ - randao_reveal: Random.bls_signature(), - eth1_data: eth1_data(), - graffiti: Random.hash32(), - proposer_slashings: [], - attester_slashings: [], - attestations: [], - deposits: [], - voluntary_exits: [], - sync_aggregate: sync_aggregate(), - execution_payload: execution_payload(), - bls_to_execution_changes: [], - blob_kzg_commitments: [] - ] + fields = [ + randao_reveal: Random.bls_signature(), + eth1_data: eth1_data(), + graffiti: Random.hash32(), + proposer_slashings: [], + attester_slashings: [], + attestations: [], + deposits: [], + voluntary_exits: [], + sync_aggregate: sync_aggregate(), + execution_payload: execution_payload(), + bls_to_execution_changes: [], + blob_kzg_commitments: [] + ] struct!(BeaconBlockBody, fields) end @@ -72,26 +71,25 @@ defmodule Fixtures.Block do @spec execution_payload :: ExecutionPayload.t() def execution_payload() do - fields = - [ - parent_hash: Random.hash32(), - fee_recipient: Random.execution_address(), - state_root: Random.root(), - receipts_root: Random.root(), - logs_bloom: Random.binary(256), - prev_randao: Random.hash32(), - block_number: Random.uint64(), - gas_limit: Random.uint64(), - gas_used: Random.uint64(), - timestamp: Random.uint64(), - extra_data: Random.binary(30), - base_fee_per_gas: Random.uint64(), - block_hash: Random.binary(32), - transactions: [], - withdrawals: [], - blob_gas_used: 0, - excess_blob_gas: 0 - ] + fields = [ + parent_hash: Random.hash32(), + fee_recipient: Random.execution_address(), + state_root: Random.root(), + receipts_root: Random.root(), + logs_bloom: Random.binary(256), + prev_randao: Random.hash32(), + block_number: Random.uint64(), + gas_limit: Random.uint64(), + gas_used: Random.uint64(), + timestamp: Random.uint64(), + extra_data: Random.binary(30), + base_fee_per_gas: Random.uint64(), + block_hash: Random.binary(32), + transactions: [], + withdrawals: [], + blob_gas_used: 0, + excess_blob_gas: 0 + ] struct!(ExecutionPayload, fields) end @@ -142,26 +140,25 @@ defmodule Fixtures.Block do @spec execution_payload_header :: ExecutionPayloadHeader.t() def execution_payload_header() do - fields = - [ - parent_hash: Random.binary(32), - fee_recipient: Random.binary(20), - state_root: Random.root(), - receipts_root: Random.root(), - logs_bloom: Random.binary(256), - prev_randao: Random.binary(32), - block_number: Random.uint64(), - gas_limit: Random.uint64(), - gas_used: Random.uint64(), - timestamp: Random.uint64(), - extra_data: Random.binary(30), - base_fee_per_gas: Random.uint256(), - block_hash: Random.binary(32), - transactions_root: Random.root(), - withdrawals_root: Random.root(), - blob_gas_used: 0, - excess_blob_gas: 0 - ] + fields = [ + parent_hash: Random.binary(32), + fee_recipient: Random.binary(20), + state_root: Random.root(), + receipts_root: Random.root(), + logs_bloom: Random.binary(256), + prev_randao: Random.binary(32), + block_number: Random.uint64(), + gas_limit: Random.uint64(), + gas_used: Random.uint64(), + timestamp: Random.uint64(), + extra_data: Random.binary(30), + base_fee_per_gas: Random.uint256(), + block_hash: Random.binary(32), + transactions_root: Random.root(), + withdrawals_root: Random.root(), + blob_gas_used: 0, + excess_blob_gas: 0 + ] struct!(ExecutionPayloadHeader, fields) end diff --git a/test/spec/runners/fork_choice.ex b/test/spec/runners/fork_choice.ex index ba83d9658..8845ea57f 100644 --- a/test/spec/runners/fork_choice.ex +++ b/test/spec/runners/fork_choice.ex @@ -30,8 +30,7 @@ defmodule ForkChoiceTestRunner do anchor_block = SpecTestUtils.read_ssz_from_file!(case_dir <> "/anchor_block.ssz_snappy", BeaconBlock) - steps = - YamlElixir.read_from_file!(case_dir <> "/steps.yaml") |> SpecTestUtils.sanitize_yaml() + steps = YamlElixir.read_from_file!(case_dir <> "/steps.yaml") |> SpecTestUtils.sanitize_yaml() signed_block = %SignedBeaconBlock{message: anchor_block, signature: <<0::768>>} @@ -170,8 +169,7 @@ defmodule ForkChoiceTestRunner do defp load_blob_data(case_dir, block, %{blobs: "blobs_0x" <> _hash = blobs_file, proofs: proofs}) do schema = {:list, TypeAliases.blob(), ChainSpec.get("MAX_BLOBS_PER_BLOCK")} - blobs = - SpecTestUtils.read_ssz_ex_from_file!(case_dir <> "/#{blobs_file}.ssz_snappy", schema) + blobs = SpecTestUtils.read_ssz_ex_from_file!(case_dir <> "/#{blobs_file}.ssz_snappy", schema) block_root = Ssz.hash_tree_root!(block.message) diff --git a/test/spec/runners/helpers/process_blocks.ex b/test/spec/runners/helpers/process_blocks.ex index 6e210ed9d..4919863e1 100644 --- a/test/spec/runners/helpers/process_blocks.ex +++ b/test/spec/runners/helpers/process_blocks.ex @@ -16,8 +16,7 @@ defmodule Helpers.ProcessBlocks do pre = SpecTestUtils.read_ssz_from_file!(case_dir <> "/pre.ssz_snappy", BeaconState) post = SpecTestUtils.read_ssz_from_optional_file!(case_dir <> "/post.ssz_snappy", BeaconState) - meta = - YamlElixir.read_from_file!(case_dir <> "/meta.yaml") |> SpecTestUtils.sanitize_yaml() + meta = YamlElixir.read_from_file!(case_dir <> "/meta.yaml") |> SpecTestUtils.sanitize_yaml() %{blocks_count: blocks_count} = meta diff --git a/test/spec/runners/operations.ex b/test/spec/runners/operations.ex index bcdc86c1f..62fa019e5 100644 --- a/test/spec/runners/operations.ex +++ b/test/spec/runners/operations.ex @@ -121,8 +121,7 @@ defmodule OperationsTestRunner do # We're skipping the tests where execution_valid is false since we make the execution client call # outside of the `process_execution_payload` function for performance reasons. if execution_valid do - result = - Operations.process_execution_payload(pre, body) + result = Operations.process_execution_payload(pre, body) case post do nil -> diff --git a/test/spec/runners/ssz_static.ex b/test/spec/runners/ssz_static.ex index e6193c4a2..f2c5a2dfb 100644 --- a/test/spec/runners/ssz_static.ex +++ b/test/spec/runners/ssz_static.ex @@ -99,8 +99,7 @@ defmodule SszStaticTestRunner do YamlElixir.read_from_file!(case_dir <> "/value.yaml") |> SpecTestUtils.sanitize_yaml() - expected_sanitized = - SpecTestUtils.sanitize_ssz(sanitize_yaml, schema) + expected_sanitized = SpecTestUtils.sanitize_ssz(sanitize_yaml, schema) %{"root" => expected_root} = YamlElixir.read_from_file!(case_dir <> "/roots.yaml") expected_root = expected_root |> SpecTestUtils.sanitize_yaml() diff --git a/test/spec/runners/sync.ex b/test/spec/runners/sync.ex index 7637ace77..d656dee52 100644 --- a/test/spec/runners/sync.ex +++ b/test/spec/runners/sync.ex @@ -25,8 +25,7 @@ defmodule SyncTestRunner do @impl TestRunner def run_test_case(%SpecTestCase{} = testcase) do - original_engine_api_config = - Application.fetch_env!(:lambda_ethereum_consensus, EngineApi) + original_engine_api_config = Application.fetch_env!(:lambda_ethereum_consensus, EngineApi) Application.put_env( :lambda_ethereum_consensus, diff --git a/test/unit/bls_test.exs b/test/unit/bls_test.exs new file mode 100644 index 000000000..3440eb4f0 --- /dev/null +++ b/test/unit/bls_test.exs @@ -0,0 +1,20 @@ +defmodule BlsTest do + use ExUnit.Case + + describe "validate_key" do + test "returns true for valid public key" do + valid_public_key = + Base.decode16!( + "8afc8f134790914b4a15d2fa73b07cafd0d30884fd80ca220c8b9503f5f69c33dd27275b129543d2f7f8f635a81867a0", + case: :mixed + ) + + assert Bls.key_validate(valid_public_key) == {:ok, true} + end + + test "returns false for invalid public key" do + invalid_public_key = <<0::384>> + assert Bls.key_validate(invalid_public_key) == {:error, "BlstError(BLST_BAD_ENCODING)"} + end + end +end diff --git a/test/unit/req_resp_test.exs b/test/unit/req_resp_test.exs index c4981d692..5cb0aff1f 100644 --- a/test/unit/req_resp_test.exs +++ b/test/unit/req_resp_test.exs @@ -124,17 +124,16 @@ defmodule Unit.ReqRespTest do request = %BeaconBlocksByRangeRequest{start_slot: 15_125, count: count} # TODO: generate randomly - response = - [ - %Types.BlobSidecar{ - index: 1, - blob: <<152_521_252::(4096*32)*8>>, - kzg_commitment: <<57_888::48*8>>, - kzg_proof: <<6122::48*8>>, - signed_block_header: Block.signed_beacon_block_header(), - kzg_commitment_inclusion_proof: [<<1551::32*8>>] |> Stream.cycle() |> Enum.take(17) - } - ] + response = [ + %Types.BlobSidecar{ + index: 1, + blob: <<152_521_252::(4096*32)*8>>, + kzg_commitment: <<57_888::48*8>>, + kzg_proof: <<6122::48*8>>, + signed_block_header: Block.signed_beacon_block_header(), + kzg_commitment_inclusion_proof: [<<1551::32*8>>] |> Stream.cycle() |> Enum.take(17) + } + ] assert_complex_request_roundtrip(request, BeaconBlocksByRangeRequest, response) end @@ -145,17 +144,16 @@ defmodule Unit.ReqRespTest do request = Enum.map(1..count, &%BlobIdentifier{block_root: <<&1::256>>, index: &1}) # TODO: generate randomly - response = - [ - %Types.BlobSidecar{ - index: 1, - blob: <<152_521_252::(4096*32)*8>>, - kzg_commitment: <<57_888::48*8>>, - kzg_proof: <<6122::48*8>>, - signed_block_header: Block.signed_beacon_block_header(), - kzg_commitment_inclusion_proof: [<<1551::32*8>>] |> Stream.cycle() |> Enum.take(17) - } - ] + response = [ + %Types.BlobSidecar{ + index: 1, + blob: <<152_521_252::(4096*32)*8>>, + kzg_commitment: <<57_888::48*8>>, + kzg_proof: <<6122::48*8>>, + signed_block_header: Block.signed_beacon_block_header(), + kzg_commitment_inclusion_proof: [<<1551::32*8>>] |> Stream.cycle() |> Enum.take(17) + } + ] assert_complex_request_roundtrip( request, diff --git a/test/unit/snappy_test.exs b/test/unit/snappy_test.exs index d39716444..f45d879f9 100644 --- a/test/unit/snappy_test.exs +++ b/test/unit/snappy_test.exs @@ -61,8 +61,7 @@ defmodule Unit.SnappyTest do test "compress binary" do expected = Base.decode16!("FF060000734E61507059000A0000B3A056EA1100003E0100") - got = - Snappy.compress(Base.decode16!("0000000000000000000000000000000000")) + got = Snappy.compress(Base.decode16!("0000000000000000000000000000000000")) assert got == {:ok, expected} end