Skip to content

Commit d098d37

Browse files
authored
feat: add default methods for all schemas/ssz types (#947)
1 parent 220cc74 commit d098d37

File tree

4 files changed

+98
-5
lines changed

4 files changed

+98
-5
lines changed

lib/lambda_ethereum_consensus/validator/validator.ex

+1-1
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ defmodule LambdaEthereumConsensus.Validator do
344344
}
345345
}
346346

347-
bits = BitList.default(committee_length) |> BitList.set(index_in_committee)
347+
bits = BitList.zero(committee_length) |> BitList.set(index_in_committee)
348348

349349
signature = Utils.get_attestation_signature(head_state, attestation_data, privkey)
350350

lib/ssz_ex.ex

+19
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,25 @@ defmodule LambdaEthereumConsensus.SszEx do
428428
(size + @bits_per_chunk - 1) |> div(@bits_per_chunk)
429429
end
430430

431+
@doc """
432+
Returns the default value for a schema, which can be a basic or composite type.
433+
"""
434+
def default({:int, _}), do: 0
435+
def default(:bool), do: false
436+
def default({:bytes, size}), do: <<0::size(size * 8)>>
437+
def default({:list, :bytes, _size}), do: <<>>
438+
def default({:list, _, _}), do: []
439+
def default({:vector, :bytes, size}), do: <<0::size(size * 8)>>
440+
def default({:vector, inner_type, size}), do: default(inner_type) |> List.duplicate(size)
441+
def default({:bitlist, _}), do: BitList.default()
442+
def default({:bitvector, size}), do: BitVector.new(size)
443+
444+
def default(module) when is_atom(module) do
445+
module.schema()
446+
|> Enum.map(fn {attr, schema} -> {attr, default(schema)} end)
447+
|> then(&struct!(module, &1))
448+
end
449+
431450
#################
432451
### Private functions
433452
#################

lib/utils/bit_list.ex

+9-3
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,16 @@ defmodule LambdaEthereumConsensus.Utils.BitList do
99
@bits_in_sentinel_bit 1
1010

1111
@doc """
12-
Creates a new bit_list with the given size.
12+
Creates a bit_list full of zeroes, with the given size.
1313
"""
14-
@spec default(non_neg_integer) :: t
15-
def default(size), do: <<0::size(size)>>
14+
@spec zero(non_neg_integer) :: t
15+
def zero(size), do: <<0::size(size)>>
16+
17+
@doc """
18+
Creates a default (empty/size 0) bit list.
19+
"""
20+
@spec default :: t
21+
def default, do: <<>>
1622

1723
@doc """
1824
Creates a new bit_list from bitstring.

test/unit/ssz_ex_test.exs

+69-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
11
defmodule Unit.SSZExTest do
2+
alias LambdaEthereumConsensus.Utils.Diff
3+
4+
alias Types.{
5+
BeaconBlock,
6+
BeaconBlockBody,
7+
Checkpoint,
8+
Eth1Data,
9+
ExecutionPayload,
10+
SyncAggregate
11+
}
12+
213
alias LambdaEthereumConsensus.SszEx
3-
alias Types.Checkpoint
414
use ExUnit.Case
515

616
def assert_roundtrip(serialized, deserialized, schema) do
@@ -463,6 +473,64 @@ defmodule Unit.SSZExTest do
463473
assert_roundtrip(serialized, validator, Types.Validator)
464474
end
465475

476+
@root_size 32
477+
@signature_size 96
478+
@default_signature <<0::size(@signature_size * 8)>>
479+
@default_root <<0::size(@root_size * 8)>>
480+
@default_hash @default_root
481+
482+
test "default block" do
483+
default = SszEx.default(BeaconBlock)
484+
485+
expected = %BeaconBlock{
486+
slot: 0,
487+
proposer_index: 0,
488+
parent_root: @default_root,
489+
state_root: @default_root,
490+
body: %BeaconBlockBody{
491+
randao_reveal: @default_signature,
492+
eth1_data: %Eth1Data{
493+
deposit_root: @default_root,
494+
deposit_count: 0,
495+
block_hash: @default_hash
496+
},
497+
graffiti: <<0::size(32 * 8)>>,
498+
proposer_slashings: [],
499+
attester_slashings: [],
500+
attestations: [],
501+
deposits: [],
502+
voluntary_exits: [],
503+
sync_aggregate: %SyncAggregate{
504+
sync_committee_bits: <<0::size(ChainSpec.get("SYNC_COMMITTEE_SIZE"))>>,
505+
sync_committee_signature: @default_signature
506+
},
507+
execution_payload: %ExecutionPayload{
508+
parent_hash: @default_hash,
509+
fee_recipient: <<0::size(20 * 8)>>,
510+
state_root: @default_root,
511+
receipts_root: @default_root,
512+
logs_bloom: <<0::size(ChainSpec.get("BYTES_PER_LOGS_BLOOM") * 8)>>,
513+
prev_randao: <<0::size(32 * 8)>>,
514+
block_number: 0,
515+
gas_limit: 0,
516+
gas_used: 0,
517+
timestamp: 0,
518+
extra_data: <<>>,
519+
base_fee_per_gas: 0,
520+
block_hash: @default_hash,
521+
transactions: [],
522+
withdrawals: [],
523+
blob_gas_used: 0,
524+
excess_blob_gas: 0
525+
},
526+
bls_to_execution_changes: [],
527+
blob_kzg_commitments: []
528+
}
529+
}
530+
531+
assert Diff.diff(default, expected) == :unchanged
532+
end
533+
466534
test "serialize and deserialize bitlist" do
467535
encoded_bytes = <<160, 92, 1>>
468536
assert {:ok, decoded_bytes} = SszEx.decode(encoded_bytes, {:bitlist, 16})

0 commit comments

Comments
 (0)