Skip to content

Commit

Permalink
feat:bootstrap test
Browse files Browse the repository at this point in the history
Signed-off-by: Chen Kai <[email protected]>
  • Loading branch information
GrapeBaBa committed Apr 11, 2024
1 parent df8ac57 commit 831453a
Show file tree
Hide file tree
Showing 9 changed files with 187 additions and 21 deletions.
11 changes: 9 additions & 2 deletions portalnetwork/beacon/beacon_network.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ type BeaconNetwork struct {
Spec *common.Spec
}

func (bn *BeaconNetwork) GetUpdates(firstPeriod, count uint64) (LightClientUpdateRange, error) {
func (bn *BeaconNetwork) GetUpdates(firstPeriod, count uint64) ([]*capella.LightClientUpdate, error) {
lightClientUpdateKey := &LightClientUpdateKey{
StartPeriod: firstPeriod,
Count: count,
Expand All @@ -44,7 +44,14 @@ func (bn *BeaconNetwork) GetUpdates(firstPeriod, count uint64) (LightClientUpdat
return nil, err
}

return lightClientUpdateRange, nil
updates := make([]*capella.LightClientUpdate, len(lightClientUpdateRange))
for i, update := range lightClientUpdateRange {
if update.ForkDigest != Capella {
return nil, errors.New("unknown fork digest")
}
updates[i] = update.LightClientUpdate.(*capella.LightClientUpdate)
}
return updates, nil
}

func (bn *BeaconNetwork) GetCheckpointData(checkpointHash tree.Root) (*capella.LightClientBootstrap, error) {
Expand Down
52 changes: 34 additions & 18 deletions portalnetwork/beacon/light_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ var (
)

type ConsensusAPI interface {
GetUpdates(firstPeriod, count uint64) (LightClientUpdateRange, error)
GetUpdates(firstPeriod, count uint64) ([]*capella.LightClientUpdate, error)
GetCheckpointData(checkpointHash common.Root) (*capella.LightClientBootstrap, error)
GetFinalityData() (*capella.LightClientFinalityUpdate, error)
GetOptimisticData() (*capella.LightClientOptimisticUpdate, error)
Expand All @@ -52,7 +52,7 @@ type ConsensusLightClient struct {
API ConsensusAPI
InitialCheckpoint common.Root
LastCheckpoint common.Root
Config Config
Config *Config
Logger log.Logger
}

Expand All @@ -62,7 +62,7 @@ type Config struct {
DefaultCheckpoint common.Root
Checkpoint common.Root
DataDir string
ChainConfig ChainConfig
Chain ChainConfig
Spec *common.Spec
MaxCheckpointAge uint64
Fallback string
Expand All @@ -79,13 +79,29 @@ type ChainConfig struct {
type GenericUpdate struct {
AttestedHeader *common.BeaconBlockHeader
SyncAggregate *altair.SyncAggregate
SingnatureSlot common.Slot
SignatureSlot common.Slot
NextSyncCommittee *common.SyncCommittee
NextSyncCommitteeBranch *altair.SyncCommitteeProofBranch
FinalizedHeader *common.BeaconBlockHeader
FinalityBranch *altair.FinalizedRootProofBranch
}

func NewConsensusLightClient(api ConsensusAPI, config *Config, checkpointBlockRoot common.Root, logger log.Logger) (*ConsensusLightClient, error) {
client := &ConsensusLightClient{
API: api,
Config: config,
Logger: logger,
InitialCheckpoint: checkpointBlockRoot,
}

err := client.bootstrap()
if err != nil {
return nil, err
}

return client, nil
}

//lint:ignore U1000 placeholder function
func (c *ConsensusLightClient) bootstrap() error {
bootstrap, err := c.API.GetCheckpointData(c.InitialCheckpoint)
Expand Down Expand Up @@ -150,25 +166,25 @@ func (c *ConsensusLightClient) VerifyGenericUpdate(update *GenericUpdate) error
return ErrInsufficientParticipation
}
updateFinalizedSlot := update.FinalizedHeader.Slot
validTime := uint64(c.expectedCurrentSlot()) >= uint64(update.SingnatureSlot) && update.SingnatureSlot > update.AttestedHeader.Slot && update.AttestedHeader.Slot >= updateFinalizedSlot
validTime := uint64(c.expectedCurrentSlot()) >= uint64(update.SignatureSlot) && update.SignatureSlot > update.AttestedHeader.Slot && update.AttestedHeader.Slot >= updateFinalizedSlot
if !validTime {
return ErrInvalidTimestamp
}

storePeriod := CalcSyncPeriod(uint64(c.Store.FinalizedHeader.Slot))
updateSigPeriod := CalcSyncPeriod(uint64(update.SingnatureSlot))
updateSigPeriod := CalcSyncPeriod(uint64(update.SignatureSlot))
validPeriod := false
if c.Store.NextSyncCommittee != nil {
validPeriod = (updateSigPeriod == storePeriod || updateSigPeriod == storePeriod+1)
validPeriod = updateSigPeriod == storePeriod || updateSigPeriod == storePeriod+1
} else {
validPeriod = (updateSigPeriod == storePeriod)
validPeriod = updateSigPeriod == storePeriod
}
if !validPeriod {
return ErrInvalidPeriod
}

updateAttestedPeriod := CalcSyncPeriod(uint64(update.AttestedHeader.Slot))
updateHasNextCommittee := (c.Store.NextSyncCommittee == nil && update.NextSyncCommittee != nil && updateAttestedPeriod == storePeriod)
updateHasNextCommittee := c.Store.NextSyncCommittee == nil && update.NextSyncCommittee != nil && updateAttestedPeriod == storePeriod

if update.AttestedHeader.Slot <= c.Store.FinalizedHeader.Slot && !updateHasNextCommittee {
return ErrNotRelevant
Expand All @@ -180,7 +196,7 @@ func (c *ConsensusLightClient) VerifyGenericUpdate(update *GenericUpdate) error
}
}
if update.NextSyncCommittee != nil && update.NextSyncCommitteeBranch != nil {
isValid := IsNextCommitteeProofValid(c.Config.Spec, *update.AttestedHeader, *update.NextSyncCommittee, *update.NextSyncCommitteeBranch)
isValid := IsNextCommitteeProofValid(*update.AttestedHeader, *update.NextSyncCommittee, *update.NextSyncCommitteeBranch)
if !isValid {
return ErrInvalidNextSyncCommitteeProof
}
Expand All @@ -195,7 +211,7 @@ func (c *ConsensusLightClient) VerifyGenericUpdate(update *GenericUpdate) error

pks := GetParticipatingKeys(*syncCommittee, update.SyncAggregate.SyncCommitteeBits)

isValidSig, err := c.VerifySyncCommitteeSignature(pks, *update.AttestedHeader, update.SyncAggregate.SyncCommitteeSignature, update.SingnatureSlot)
isValidSig, err := c.VerifySyncCommitteeSignature(pks, *update.AttestedHeader, update.SyncAggregate.SyncCommitteeSignature, update.SignatureSlot)
if err != nil {
return err
}
Expand Down Expand Up @@ -239,19 +255,19 @@ func (c *ConsensusLightClient) VerifySyncCommitteeSignature(pks []common.BLSPubk
}

func (c *ConsensusLightClient) ComputeCommitteeSignRoot(headerRoot tree.Root, slot common.Slot) common.Root {
genesisRoot := c.Config.ChainConfig.GenesisRoot
genesisRoot := c.Config.Chain.GenesisRoot
domainType := hexutil.MustDecode("0x07000000")
forkVersion := c.Config.Spec.ForkVersion(slot)
domain := common.ComputeDomain(common.BLSDomainType(domainType), forkVersion, genesisRoot)
return ComputeSigningRoot(headerRoot, domain)
}

func (c *ConsensusLightClient) expectedCurrentSlot() common.Slot {
return c.Config.Spec.TimeToSlot(common.Timestamp(time.Now().Unix()), common.Timestamp(c.Config.ChainConfig.GenesisTime))
return c.Config.Spec.TimeToSlot(common.Timestamp(time.Now().Unix()), common.Timestamp(c.Config.Chain.GenesisTime))
}

func (c *ConsensusLightClient) slotTimestamp(slot common.Slot) (common.Timestamp, error) {
atSlot, err := c.Config.Spec.TimeAtSlot(slot, common.Timestamp(c.Config.ChainConfig.GenesisTime))
atSlot, err := c.Config.Spec.TimeAtSlot(slot, common.Timestamp(c.Config.Chain.GenesisTime))
if err != nil {
return 0, err
}
Expand All @@ -267,7 +283,7 @@ func FromLightClientUpdate(update *capella.LightClientUpdate) *GenericUpdate {
return &GenericUpdate{
AttestedHeader: &update.AttestedHeader.Beacon,
SyncAggregate: &update.SyncAggregate,
SingnatureSlot: update.SignatureSlot,
SignatureSlot: update.SignatureSlot,
NextSyncCommittee: &update.NextSyncCommittee,
NextSyncCommitteeBranch: &update.NextSyncCommitteeBranch,
FinalizedHeader: &update.FinalizedHeader.Beacon,
Expand All @@ -279,7 +295,7 @@ func FromLightClientFinalityUpdate(update *capella.LightClientFinalityUpdate) *G
return &GenericUpdate{
AttestedHeader: &update.AttestedHeader.Beacon,
SyncAggregate: &update.SyncAggregate,
SingnatureSlot: update.SignatureSlot,
SignatureSlot: update.SignatureSlot,
FinalizedHeader: &update.FinalizedHeader.Beacon,
FinalityBranch: &update.FinalityBranch,
}
Expand All @@ -289,7 +305,7 @@ func FromLightClientOptimisticUpdate(update *capella.LightClientOptimisticUpdate
return &GenericUpdate{
AttestedHeader: &update.AttestedHeader.Beacon,
SyncAggregate: &update.SyncAggregate,
SingnatureSlot: update.SignatureSlot,
SignatureSlot: update.SignatureSlot,
}
}

Expand All @@ -312,7 +328,7 @@ func IsFinalityProofValid(attestedHeader common.BeaconBlockHeader, finalityHeade
return merkle.VerifyMerkleBranch(leaf, finalityBranch[:], 6, 41, root)
}

func IsNextCommitteeProofValid(spec *common.Spec, attestedHeader common.BeaconBlockHeader, nextCommittee common.SyncCommittee, nextCommitteeBranch altair.SyncCommitteeProofBranch) bool {
func IsNextCommitteeProofValid(attestedHeader common.BeaconBlockHeader, nextCommittee common.SyncCommittee, nextCommitteeBranch altair.SyncCommitteeProofBranch) bool {
leaf := nextCommittee.HashTreeRoot(configs.Mainnet, tree.GetHashFn())
root := attestedHeader.StateRoot
return merkle.VerifyMerkleBranch(leaf, nextCommitteeBranch[:], 5, 23, root)
Expand Down
95 changes: 95 additions & 0 deletions portalnetwork/beacon/light_client_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package beacon

import (
"encoding/json"
"os"
"testing"

"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/internal/testlog"
"github.com/ethereum/go-ethereum/log"
"github.com/protolambda/zrnt/eth2/beacon/capella"
"github.com/protolambda/zrnt/eth2/beacon/common"
"github.com/stretchr/testify/assert"
)

var _ ConsensusAPI = (*MockConsensusAPI)(nil)

type MockConsensusAPI struct {
testdataDir string
}

func NewMockConsensusAPI(path string) (ConsensusAPI, error) {
return &MockConsensusAPI{testdataDir: path}, nil
}

func (m MockConsensusAPI) GetUpdates(_, _ uint64) ([]*capella.LightClientUpdate, error) {
jsonStr, _ := os.ReadFile(m.testdataDir + "/updates.json")

updates := make([]*capella.LightClientUpdate, 0)
_ = json.Unmarshal(jsonStr, &updates)

return updates, nil
}

func (m MockConsensusAPI) GetCheckpointData(_ common.Root) (*capella.LightClientBootstrap, error) {
jsonStr, _ := os.ReadFile(m.testdataDir + "/bootstrap.json")

bootstrap := &capella.LightClientBootstrap{}
_ = json.Unmarshal(jsonStr, &bootstrap)

return bootstrap, nil
}

func (m MockConsensusAPI) GetFinalityData() (*capella.LightClientFinalityUpdate, error) {
jsonStr, _ := os.ReadFile(m.testdataDir + "/finality.json")

finality := &capella.LightClientFinalityUpdate{}
_ = json.Unmarshal(jsonStr, &finality)

return finality, nil
}

func (m MockConsensusAPI) GetOptimisticData() (*capella.LightClientOptimisticUpdate, error) {
jsonStr, _ := os.ReadFile(m.testdataDir + "/optimistic.json")

optimistic := &capella.LightClientOptimisticUpdate{}
_ = json.Unmarshal(jsonStr, &optimistic)

return optimistic, nil
}

func (m MockConsensusAPI) ChainID() uint64 {
panic("implement me")
}

func (m MockConsensusAPI) Name() string {
return "mock"
}

func getClient(strictCheckpointAge bool, t *testing.T) (*ConsensusLightClient, error) {
baseConfig := Mainnet()
api, err := NewMockConsensusAPI("testdata/mockdata")
assert.NoError(t, err)

config := &Config{
ConsensusAPI: api.Name(),
Chain: baseConfig.Chain,
Spec: baseConfig.Spec,
StrictCheckpointAge: strictCheckpointAge,
}

checkpoint := common.Root(hexutil.MustDecode("0xc62aa0de55e6f21230fa63713715e1a6c13e73005e89f6389da271955d819bde"))

client, err := NewConsensusLightClient(api, config, checkpoint, testlog.Logger(t, log.LvlTrace))
if err != nil {
return nil, err
}

return client, nil
}

func TestVerifyCheckpointAgeInvalid(t *testing.T) {
_, err := getClient(true, t)
assert.ErrorContains(t, err, "checkpoint is too old")
}
44 changes: 44 additions & 0 deletions portalnetwork/beacon/networks.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package beacon

import (
"errors"

"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/protolambda/zrnt/eth2/beacon/common"
"github.com/protolambda/zrnt/eth2/configs"
)

const MainnetType = iota

type BaseConfig struct {
APIPort uint64
API string
DefaultCheckpoint common.Root
Chain ChainConfig
Spec *common.Spec
MaxCheckpointAge uint64
}

func Mainnet() *BaseConfig {
return &BaseConfig{
APIPort: 8545,
API: "https://www.lightclientdata.org",
DefaultCheckpoint: common.Root(hexutil.MustDecode("0x766647f3c4e1fc91c0db9a9374032ae038778411fbff222974e11f2e3ce7dadf")),
Chain: ChainConfig{
ChainID: 1,
GenesisTime: 1606824023,
GenesisRoot: common.Root(hexutil.MustDecode("0x4b363db94e286120d76eb905340fdd4e54bfe9f06bf33ff6cf5ad27f511bfe95")),
},
Spec: configs.Mainnet,
MaxCheckpointAge: 1_209_600,
}
}

func ToBaseConfig(networkType int) (*BaseConfig, error) {
switch networkType {
case MainnetType:
return Mainnet(), nil
default:
return nil, errors.New("unknown network type")
}
}
2 changes: 1 addition & 1 deletion portalnetwork/beacon/portal_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func NewPortalLightApi() *PortalLightApi {
return &PortalLightApi{}
}

func (api *PortalLightApi) GetUpdates(firstPeriod, count uint64) (LightClientUpdateRange, error) {
func (api *PortalLightApi) GetUpdates(firstPeriod, count uint64) ([]*capella.LightClientUpdate, error) {
return api.bn.GetUpdates(firstPeriod, count)
}

Expand Down
1 change: 1 addition & 0 deletions portalnetwork/beacon/testdata/mockdata/bootstrap.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions portalnetwork/beacon/testdata/mockdata/finality.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"attested_header":{"beacon":{"slot":"7358726","proposer_index":"427162","parent_root":"0x1d7b8baa34c28a3e0d2230f8d459b92203324d1e1ec48e762c527b5ea7055612","state_root":"0x3b7be385013f0f43c12d2b5d42cedb6d7d18f854ce3b04853f526d0024034171","body_root":"0xb0bc8ce3ec58d241366aca78630803572d36ae24f9e9d52a4e21c6370585f60e"},"execution":{"parent_hash":"0x4ba3d43cc285b7774aca41a1cee5c4d4fda49e4d599065dc789c5e8d17d289ec","fee_recipient":"0x95222290dd7278aa3ddd389cc1e1d165cc4bafe5","state_root":"0x7dfc406a2c6b07312e554a3a34b75ba153196559c83b60556b01362e0bf190f0","receipts_root":"0x8e4a047603c7618479f2c243c4cb88fe6329cc7c552e53bbf79c02114a2eda48","logs_bloom":"0x0fedfc2d69e98b6a31ea1f7fd9fa9a70bfb96841daa484d4c7fb60c8c610f5f6ba6541cc2124c3e157185f3362dc0b18f2338e12ac357e661c57f959f9ee2b27531d5018d6d8b9fbacebffabd694c7bde11929f04e7c28eceb7dbe47887c8ec4fe24ef2613b67998e72453c1f621a877338225703e18b73fbf24091b3a596c647fdec25df39615a342fdf06c4392ee3667b0e38309dfc7b9c77b1b4669f6f13a8e2b05573bc070842c1a70e9dd183faecc8ecd8ef93adaafc1472a4fd8faf5711e50856a32a10ad92e8db429dd6f10c14e6e6933c07daf14f804e17219a1e8071df964883b22a6f53d56e4a8ea05a94147e79682ab0d8a7e2778d9e16cddb547","prev_randao":"0xe7a8aa63bfd300810ebb9fb0389f25b2f83ad3f859a2b6d6e8d10b5e9e8a9f14","block_number":"18170142","gas_limit":"30000000","gas_used":"19938147","timestamp":"1695128735","extra_data":"0x6265617665726275696c642e6f7267","base_fee_per_gas":"18458742656","block_hash":"0x91a4a0d4a27a88f264320a82cf87743a6dc1ad724a1ebe74db8169ceb314a1d3","transactions_root":"0x094cfda3b6d80ffc84dd5ba017ef5b30a9e2e94125fcee4d42c9cc92bc2238e1","withdrawals_root":"0x4a865418c1b6acbc014b0545e4af40fa7e3ca51b44f8afd9f12225edc5a3f121"},"execution_branch":["0xa632d98f70c821de565a89b080491cfd28905c68c6bb9230ec337d3f9d255d65","0x336488033fe5f3ef4ccc12af07b9370b92e553e35ecb4a337a1b1c0e4afe1e0e","0xdb56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71","0xbe0654721b70c4f82c3844f3877a123db4a49f8bcb417d6165faaccfbac17e99"]},"finalized_header":{"beacon":{"slot":"7358656","proposer_index":"584647","parent_root":"0x51bf31832358ee618a84c74193fdc1e58c810cdb006eaf82318edb4f2cfbc899","state_root":"0xca3dda0a7bcfade21f508a62562047dbfaccbf3b7b1e41e28177ff2f8ff6ae3f","body_root":"0xe5a8735e10bd19059a5af294fed39638eeb7344abf49d113bb25a2215d050f07"},"execution":{"parent_hash":"0x1a56b9cb321be8608d892a731fe44c829578888e3e67b38459e06d4b3885974f","fee_recipient":"0x4838b106fce9647bdf1e7877bf73ce8b0bad5f97","state_root":"0x2f3491f8eb43e0b0f1c526e53b29df6889ad90ad2d4b72d3201ec91d2d21cf24","receipts_root":"0x753f312a70a37fa8d1e55960c5b8be9f044db12faffe6549732b4f55699ff334","logs_bloom":"0x49bd937641fd2a48b2de33e0a228ec2013b84fb4309c98ad604d0702681081901012286fc320ded140110f24449c159426252041a8a26a395d10d98ec368a9707e6b430e4f64b9796806760fd417182e95980df60c6908b4913358069074025c9f0c800c1686830b640450a603603e63e73221602a9976846fc00d98a01a281400e62345ca80811a04e5b08216981fd398408a81ed28810d141920e190b2c72f8ba00054513a2a523e0a44ec599a94e04cba54245429b18b8044a0f804022423cd04118a00222a0a24491a40d4a21204007000d0040820d42b23940205d0ec5f1c18ac48940022aa400500e469264c618020b2925f3f1a422c9018712bb11c43","prev_randao":"0x0374fa31d1b5afaba63b7acd2de8352da04cab41e493193958672f96bcda04b3","block_number":"18170072","gas_limit":"30000000","gas_used":"15671422","timestamp":"1695127895","extra_data":"0x546974616e2028746974616e6275696c6465722e78797a29","base_fee_per_gas":"13939250676","block_hash":"0xca87151eee53057062520f13077a9d11185ad4a9d0cce2a8b4a3aea71a6d2426","transactions_root":"0x00ea0f91f1f7e41b0cf9b65bb0be1d8f4efa66fbc1ede6e84b603f645aed94d4","withdrawals_root":"0xb4aa6ed2229d997ca83f077c745165294afe093126915e439a32644921cc9038"},"execution_branch":["0x728b804a08a074ccfb89211fb48537ad0d033139c6e85031e818560bba0101bc","0x336488033fe5f3ef4ccc12af07b9370b92e553e35ecb4a337a1b1c0e4afe1e0e","0xdb56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71","0x6ef4b335fac95fd2c133a0c7f54f730fb05c60eda8003ecbb62f99b5225c5d19"]},"finality_branch":["0x4682030000000000000000000000000000000000000000000000000000000000","0x43b3c8708ddb8f57a75a131a951a4369a869a3b157ee7b8436196cf18fceb182","0x09e07670197a4694452b40964340029be53e70cedc772b1403943bb170b9e723","0x2b8a2b2c9383dd30341d90baa00d5e111de55a64a5fb8a33efcd43a07d3ffdb1","0xc58b9ac49bfe4b0f9776e91e3c29a18545a214a3da57fe7fae0d1949f4377878","0x863f1e7fff7ab79747f064586436cb3010817ef1e50a70b7fd7ef773b2af701b"],"sync_aggregate":{"sync_committee_bits":"0xfffffffffffff7dfffffbfdfffffff7ff7fffffffffffffffffffffffff6fffff7effffffffffffff7ffff7ffffff7fffe7fffffffffff7bffffff7fffffff7f","sync_committee_signature":"0x933b06c2d41a4e89b20dcc2d3313d420e9d1b975de79f4b89f0dffde5cf76f028356583ab5f6fa886a4b138b5855367c13c88d1d6851e2820296a800ec1b6d7bd5c6dd41037d11df3c160c96e843460d911f07f06b938a4e373e8f02f40e873b"},"signature_slot":"7358727"}
1 change: 1 addition & 0 deletions portalnetwork/beacon/testdata/mockdata/optimistic.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"attested_header":{"beacon":{"slot":"7358726","proposer_index":"427162","parent_root":"0x1d7b8baa34c28a3e0d2230f8d459b92203324d1e1ec48e762c527b5ea7055612","state_root":"0x3b7be385013f0f43c12d2b5d42cedb6d7d18f854ce3b04853f526d0024034171","body_root":"0xb0bc8ce3ec58d241366aca78630803572d36ae24f9e9d52a4e21c6370585f60e"},"execution":{"parent_hash":"0x4ba3d43cc285b7774aca41a1cee5c4d4fda49e4d599065dc789c5e8d17d289ec","fee_recipient":"0x95222290dd7278aa3ddd389cc1e1d165cc4bafe5","state_root":"0x7dfc406a2c6b07312e554a3a34b75ba153196559c83b60556b01362e0bf190f0","receipts_root":"0x8e4a047603c7618479f2c243c4cb88fe6329cc7c552e53bbf79c02114a2eda48","logs_bloom":"0x0fedfc2d69e98b6a31ea1f7fd9fa9a70bfb96841daa484d4c7fb60c8c610f5f6ba6541cc2124c3e157185f3362dc0b18f2338e12ac357e661c57f959f9ee2b27531d5018d6d8b9fbacebffabd694c7bde11929f04e7c28eceb7dbe47887c8ec4fe24ef2613b67998e72453c1f621a877338225703e18b73fbf24091b3a596c647fdec25df39615a342fdf06c4392ee3667b0e38309dfc7b9c77b1b4669f6f13a8e2b05573bc070842c1a70e9dd183faecc8ecd8ef93adaafc1472a4fd8faf5711e50856a32a10ad92e8db429dd6f10c14e6e6933c07daf14f804e17219a1e8071df964883b22a6f53d56e4a8ea05a94147e79682ab0d8a7e2778d9e16cddb547","prev_randao":"0xe7a8aa63bfd300810ebb9fb0389f25b2f83ad3f859a2b6d6e8d10b5e9e8a9f14","block_number":"18170142","gas_limit":"30000000","gas_used":"19938147","timestamp":"1695128735","extra_data":"0x6265617665726275696c642e6f7267","base_fee_per_gas":"18458742656","block_hash":"0x91a4a0d4a27a88f264320a82cf87743a6dc1ad724a1ebe74db8169ceb314a1d3","transactions_root":"0x094cfda3b6d80ffc84dd5ba017ef5b30a9e2e94125fcee4d42c9cc92bc2238e1","withdrawals_root":"0x4a865418c1b6acbc014b0545e4af40fa7e3ca51b44f8afd9f12225edc5a3f121"},"execution_branch":["0xa632d98f70c821de565a89b080491cfd28905c68c6bb9230ec337d3f9d255d65","0x336488033fe5f3ef4ccc12af07b9370b92e553e35ecb4a337a1b1c0e4afe1e0e","0xdb56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71","0xbe0654721b70c4f82c3844f3877a123db4a49f8bcb417d6165faaccfbac17e99"]},"sync_aggregate":{"sync_committee_bits":"0xfffffffffffff7dfffffbfdfffffff7ff7fffffffffffffffffffffffff6fffff7effffffffffffff7ffff7ffffff7fffe7fffffffffff7bffffff7fffffff7f","sync_committee_signature":"0x933b06c2d41a4e89b20dcc2d3313d420e9d1b975de79f4b89f0dffde5cf76f028356583ab5f6fa886a4b138b5855367c13c88d1d6851e2820296a800ec1b6d7bd5c6dd41037d11df3c160c96e843460d911f07f06b938a4e373e8f02f40e873b"},"signature_slot":"7358727"}
1 change: 1 addition & 0 deletions portalnetwork/beacon/testdata/mockdata/updates.json

Large diffs are not rendered by default.

0 comments on commit 831453a

Please sign in to comment.