Skip to content

Commit

Permalink
feat: ssz support nested containers (#509)
Browse files Browse the repository at this point in the history
  • Loading branch information
f3r10 authored Dec 12, 2023
1 parent e0ddb7e commit 3f6ac3b
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 0 deletions.
14 changes: 14 additions & 0 deletions lib/ssz_ex.ex
Original file line number Diff line number Diff line change
Expand Up @@ -380,8 +380,22 @@ defmodule LambdaEthereumConsensus.SszEx do
defp get_fixed_size({:int, size}), do: div(size, @bits_per_byte)
defp get_fixed_size({:bytes, size}), do: size

defp get_fixed_size(module) when is_atom(module) do
schemas = module.schema()

schemas
|> Enum.map(fn {_, schema} -> get_fixed_size(schema) end)
|> Enum.sum()
end

defp variable_size?({:list, _, _}), do: true
defp variable_size?(:bool), do: false
defp variable_size?({:int, _}), do: false
defp variable_size?({:bytes, _}), do: false

defp variable_size?(module) when is_atom(module) do
module.schema()
|> Enum.map(fn {_, schema} -> variable_size?(schema) end)
|> Enum.any?()
end
end
13 changes: 13 additions & 0 deletions lib/ssz_types/beacon_chain/attestation_data.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ defmodule SszTypes.AttestationData do
Related definitions in `native/ssz_nif/src/types/`.
"""

@behaviour LambdaEthereumConsensus.Container

fields = [
:slot,
:index,
Expand All @@ -22,4 +24,15 @@ defmodule SszTypes.AttestationData do
source: SszTypes.Checkpoint.t(),
target: SszTypes.Checkpoint.t()
}

@impl LambdaEthereumConsensus.Container
def schema do
[
{:slot, {:int, 64}},
{:index, {:int, 64}},
{:beacon_block_root, {:bytes, 32}},
{:source, SszTypes.Checkpoint},
{:target, SszTypes.Checkpoint}
]
end
end
8 changes: 8 additions & 0 deletions lib/ssz_types/beacon_chain/checkpoint.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ defmodule SszTypes.Checkpoint do
Related definitions in `native/ssz_nif/src/types/`.
"""

@behaviour LambdaEthereumConsensus.Container
fields = [
:root,
:epoch
Expand All @@ -16,4 +17,11 @@ defmodule SszTypes.Checkpoint do
epoch: SszTypes.epoch(),
root: SszTypes.root()
}

def schema do
[
{:epoch, {:int, 64}},
{:root, {:bytes, 32}}
]
end
end
10 changes: 10 additions & 0 deletions lib/ssz_types/beacon_chain/indexed_attestation.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ defmodule SszTypes.IndexedAttestation do
Struct definition for `IndexedAttestation`.
Related definitions in `native/ssz_nif/src/types/`.
"""
@behaviour LambdaEthereumConsensus.Container

fields = [
:attesting_indices,
Expand All @@ -19,4 +20,13 @@ defmodule SszTypes.IndexedAttestation do
data: SszTypes.AttestationData.t(),
signature: SszTypes.bls_signature()
}

@impl LambdaEthereumConsensus.Container
def schema do
[
{:attesting_indices, {:list, {:int, 64}, 2048}},
{:data, SszTypes.AttestationData},
{:signature, {:bytes, 96}}
]
end
end
54 changes: 54 additions & 0 deletions test/unit/ssz_ex_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,60 @@ defmodule Unit.SSZExTest do
assert_roundtrip(<<0>>, false, :bool)
end

test "serialize and deserialize nested container" do
checkpoint_source = %SszTypes.Checkpoint{
epoch: 3_776_037_760_046_644_755,
root:
<<29, 22, 191, 147, 188, 238, 162, 89, 147, 162, 202, 111, 169, 162, 84, 95, 194, 85, 54,
172, 44, 74, 37, 128, 248, 21, 86, 246, 151, 54, 24, 54>>
}

checkpoint_target = %SszTypes.Checkpoint{
epoch: 2_840_053_453_521_072_037,
root:
<<15, 174, 23, 120, 4, 9, 2, 116, 67, 73, 254, 53, 197, 3, 191, 166, 104, 34, 121, 2, 57,
69, 75, 69, 254, 237, 132, 68, 254, 49, 127, 175>>
}

attestation_data = %SszTypes.AttestationData{
slot: 5_057_010_135_270_197_978,
index: 6_920_931_864_607_509_210,
beacon_block_root:
<<31, 38, 101, 174, 248, 168, 116, 226, 15, 39, 218, 148, 42, 8, 80, 80, 241, 149, 162,
32, 176, 208, 120, 120, 89, 123, 136, 115, 154, 28, 21, 174>>,
source: checkpoint_source,
target: checkpoint_target
}

indexed_attestation = %SszTypes.IndexedAttestation{
attesting_indices: [15_833_676_831_095_072_535, 7_978_643_446_947_046_229],
data: attestation_data,
signature:
<<46, 244, 83, 164, 182, 222, 218, 247, 8, 186, 138, 100, 5, 96, 34, 117, 134, 123, 219,
188, 181, 11, 209, 57, 207, 24, 249, 42, 74, 27, 228, 97, 73, 46, 219, 202, 122, 149,
135, 30, 91, 126, 180, 69, 129, 170, 147, 142, 242, 27, 233, 63, 242, 7, 144, 8, 192,
165, 194, 220, 77, 247, 128, 107, 41, 199, 166, 59, 34, 160, 222, 114, 250, 250, 3, 130,
145, 8, 45, 65, 13, 82, 44, 80, 30, 181, 239, 54, 152, 237, 244, 72, 231, 179, 239, 22>>
}

serialized =
<<228, 0, 0, 0, 218, 138, 84, 194, 236, 27, 46, 70, 218, 202, 156, 184, 220, 22, 12, 96, 31,
38, 101, 174, 248, 168, 116, 226, 15, 39, 218, 148, 42, 8, 80, 80, 241, 149, 162, 32, 176,
208, 120, 120, 89, 123, 136, 115, 154, 28, 21, 174, 19, 190, 10, 34, 86, 46, 103, 52, 29,
22, 191, 147, 188, 238, 162, 89, 147, 162, 202, 111, 169, 162, 84, 95, 194, 85, 54, 172,
44, 74, 37, 128, 248, 21, 86, 246, 151, 54, 24, 54, 165, 175, 62, 152, 145, 229, 105, 39,
15, 174, 23, 120, 4, 9, 2, 116, 67, 73, 254, 53, 197, 3, 191, 166, 104, 34, 121, 2, 57,
69, 75, 69, 254, 237, 132, 68, 254, 49, 127, 175, 46, 244, 83, 164, 182, 222, 218, 247, 8,
186, 138, 100, 5, 96, 34, 117, 134, 123, 219, 188, 181, 11, 209, 57, 207, 24, 249, 42, 74,
27, 228, 97, 73, 46, 219, 202, 122, 149, 135, 30, 91, 126, 180, 69, 129, 170, 147, 142,
242, 27, 233, 63, 242, 7, 144, 8, 192, 165, 194, 220, 77, 247, 128, 107, 41, 199, 166, 59,
34, 160, 222, 114, 250, 250, 3, 130, 145, 8, 45, 65, 13, 82, 44, 80, 30, 181, 239, 54,
152, 237, 244, 72, 231, 179, 239, 22, 23, 39, 193, 253, 47, 133, 188, 219, 85, 227, 198,
60, 241, 213, 185, 110>>

assert_roundtrip(serialized, indexed_attestation, SszTypes.IndexedAttestation)
end

test "serialize and deserialize list" do
# for test purposes only, do not use in practice
assert_roundtrip(<<1, 1, 0>>, [true, true, false], {:list, :bool, 3})
Expand Down

0 comments on commit 3f6ac3b

Please sign in to comment.