Skip to content

Commit

Permalink
Merge pull request #80 from GrapeBaBa/lc_api
Browse files Browse the repository at this point in the history
feat:add light client types
  • Loading branch information
fearlessfe authored Apr 9, 2024
2 parents 75a9bc1 + 23a502a commit d9d612d
Show file tree
Hide file tree
Showing 4 changed files with 179 additions and 49 deletions.
64 changes: 23 additions & 41 deletions beacon/light/api/portal_api.go
Original file line number Diff line number Diff line change
@@ -1,57 +1,39 @@
package api

import (
"errors"
"time"

"github.com/ethereum/go-ethereum/beacon/types"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/portalnetwork/beacon"
"github.com/protolambda/zrnt/eth2/beacon/capella"
zrntcommon "github.com/protolambda/zrnt/eth2/beacon/common"
"github.com/protolambda/ztyp/tree"
)

type PortalLightApi struct {
bn *beacon.BeaconNetwork
}

func NewPortalLightApi() *PortalLightApi {
return &PortalLightApi{}
}

func (api *PortalLightApi) GetBestUpdatesAndCommittees(firstPeriod, count uint64) ([]*types.LightClientUpdate, []*types.SerializedSyncCommittee, error) {
//contentKey := &beacon.LightClientUpdateKey{
// StartPeriod: firstPeriod,
// Count: count,
//}

//resp, err := api.httpGetf("/eth/v1/beacon/light_client/updates?start_period=%d&count=%d", firstPeriod, count)
//if err != nil {
// return nil, nil, err
//}
//
//var data []CommitteeUpdate
//if err := json.Unmarshal(resp, &data); err != nil {
// return nil, nil, err
//}
//if len(data) != int(count) {
// return nil, nil, errors.New("invalid number of committee updates")
//}
//updates := make([]*types.LightClientUpdate, int(count))
//committees := make([]*types.SerializedSyncCommittee, int(count))
//for i, d := range data {
// if d.Update.AttestedHeader.Header.SyncPeriod() != firstPeriod+uint64(i) {
// return nil, nil, errors.New("wrong committee update header period")
// }
// if err := d.Update.Validate(); err != nil {
// return nil, nil, err
// }
// if d.NextSyncCommittee.Root() != d.Update.NextSyncCommitteeRoot {
// return nil, nil, errors.New("wrong sync committee root")
// }
// updates[i], committees[i] = new(types.LightClientUpdate), new(types.SerializedSyncCommittee)
// *updates[i], *committees[i] = d.Update, d.NextSyncCommittee
//}
//return updates, committees, nil

return nil, nil, errors.New("not implemented")
func (api *PortalLightApi) GetUpdates(firstPeriod, count uint64) (beacon.LightClientUpdateRange, error) {
return api.bn.GetUpdates(firstPeriod, count)
}

func (api *PortalLightApi) GetCheckpointData(checkpointHash common.Hash) (*types.BootstrapData, error) {
return nil, errors.New("not implemented")
func (api *PortalLightApi) GetCheckpointData(checkpointHash tree.Root) (*capella.LightClientBootstrap, error) {
return api.bn.GetCheckpointData(checkpointHash)
}

func (api *PortalLightApi) GetFinalityData() (*capella.LightClientFinalityUpdate, error) {
expectedCurrentSlot := api.bn.Spec.TimeToSlot(zrntcommon.Timestamp(time.Now().Unix()), zrntcommon.Timestamp(beacon.BeaconGenesisTime))
recentEpochStart := expectedCurrentSlot - (expectedCurrentSlot % api.bn.Spec.SLOTS_PER_EPOCH) + 1

return api.bn.GetFinalityUpdate(uint64(recentEpochStart))
}

func (api *PortalLightApi) GetOptimisticData() (*capella.LightClientOptimisticUpdate, error) {
expectedCurrentSlot := api.bn.Spec.TimeToSlot(zrntcommon.Timestamp(time.Now().Unix()), zrntcommon.Timestamp(beacon.BeaconGenesisTime))

return api.bn.GetOptimisticUpdate(uint64(expectedCurrentSlot))
}
63 changes: 55 additions & 8 deletions portalnetwork/beacon/beacon_network.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,15 @@ const (
LightClientFinalityUpdate storage.ContentType = 0x12
LightClientOptimisticUpdate storage.ContentType = 0x13
HistoricalSummaries storage.ContentType = 0x14
BeaconGenesisTime uint64 = 1606824023
)

type BeaconNetwork struct {
portalProtocol *discover.PortalProtocol
spec *common.Spec
PortalProtocol *discover.PortalProtocol
Spec *common.Spec
}

func (bn *BeaconNetwork) GetBestUpdatesAndCommittees(firstPeriod, count uint64) (LightClientUpdateRange, error) {
func (bn *BeaconNetwork) GetUpdates(firstPeriod, count uint64) (LightClientUpdateRange, error) {
lightClientUpdateKey := &LightClientUpdateKey{
StartPeriod: firstPeriod,
Count: count,
Expand All @@ -38,7 +39,7 @@ func (bn *BeaconNetwork) GetBestUpdatesAndCommittees(firstPeriod, count uint64)
}

var lightClientUpdateRange LightClientUpdateRange = make([]ForkedLightClientUpdate, 0)
err = lightClientUpdateRange.Deserialize(bn.spec, codec.NewDecodingReader(bytes.NewReader(lightClientUpdateRangeContent), uint64(len(lightClientUpdateRangeContent))))
err = lightClientUpdateRange.Deserialize(bn.Spec, codec.NewDecodingReader(bytes.NewReader(lightClientUpdateRangeContent), uint64(len(lightClientUpdateRangeContent))))
if err != nil {
return nil, err
}
Expand All @@ -57,7 +58,7 @@ func (bn *BeaconNetwork) GetCheckpointData(checkpointHash tree.Root) (*capella.L
}

var forkedLightClientBootstrap ForkedLightClientBootstrap
err = forkedLightClientBootstrap.Deserialize(bn.spec, codec.NewDecodingReader(bytes.NewReader(bootstrapValue), uint64(len(bootstrapValue))))
err = forkedLightClientBootstrap.Deserialize(bn.Spec, codec.NewDecodingReader(bytes.NewReader(bootstrapValue), uint64(len(bootstrapValue))))
if err != nil {
return nil, err
}
Expand All @@ -69,16 +70,62 @@ func (bn *BeaconNetwork) GetCheckpointData(checkpointHash tree.Root) (*capella.L
return forkedLightClientBootstrap.Bootstrap.(*capella.LightClientBootstrap), nil
}

func (bn *BeaconNetwork) GetFinalityUpdate(finalizedSlot uint64) (*capella.LightClientFinalityUpdate, error) {
finalityUpdateKey := &LightClientFinalityUpdateKey{
FinalizedSlot: finalizedSlot,
}

finalityUpdateValue, err := bn.getContent(LightClientFinalityUpdate, finalityUpdateKey)
if err != nil {
return nil, err
}

var forkedLightClientFinalityUpdate ForkedLightClientFinalityUpdate
err = forkedLightClientFinalityUpdate.Deserialize(bn.Spec, codec.NewDecodingReader(bytes.NewReader(finalityUpdateValue), uint64(len(finalityUpdateValue))))
if err != nil {
return nil, err
}

if forkedLightClientFinalityUpdate.ForkDigest != Capella {
return nil, errors.New("unknown fork digest")
}

return forkedLightClientFinalityUpdate.LightClientFinalityUpdate.(*capella.LightClientFinalityUpdate), nil
}

func (bn *BeaconNetwork) GetOptimisticUpdate(optimisticSlot uint64) (*capella.LightClientOptimisticUpdate, error) {
optimisticUpdateKey := &LightClientOptimisticUpdateKey{
OptimisticSlot: optimisticSlot,
}

optimisticUpdateValue, err := bn.getContent(LightClientOptimisticUpdate, optimisticUpdateKey)
if err != nil {
return nil, err
}

var forkedLightClientOptimisticUpdate ForkedLightClientOptimisticUpdate
err = forkedLightClientOptimisticUpdate.Deserialize(bn.Spec, codec.NewDecodingReader(bytes.NewReader(optimisticUpdateValue), uint64(len(optimisticUpdateValue))))
if err != nil {
return nil, err
}

if forkedLightClientOptimisticUpdate.ForkDigest != Capella {
return nil, errors.New("unknown fork digest")
}

return forkedLightClientOptimisticUpdate.LightClientOptimisticUpdate.(*capella.LightClientOptimisticUpdate), nil
}

func (bn *BeaconNetwork) getContent(contentType storage.ContentType, beaconContentKey ssz.Marshaler) ([]byte, error) {
contentKeyBytes, err := beaconContentKey.MarshalSSZ()
if err != nil {
return nil, err
}

contentKey := storage.NewContentKey(contentType, contentKeyBytes).Encode()
contentId := bn.portalProtocol.ToContentId(contentKey)
contentId := bn.PortalProtocol.ToContentId(contentKey)

res, err := bn.portalProtocol.Get(contentKey, contentId)
res, err := bn.PortalProtocol.Get(contentKey, contentId)
// other error
if err != nil && !errors.Is(err, storage.ErrContentNotFound) {
return nil, err
Expand All @@ -88,7 +135,7 @@ func (bn *BeaconNetwork) getContent(contentType storage.ContentType, beaconConte
return res, nil
}

content, _, err := bn.portalProtocol.ContentLookup(contentKey, contentId)
content, _, err := bn.PortalProtocol.ContentLookup(contentKey, contentId)
if err != nil {
return nil, err
}
Expand Down
53 changes: 53 additions & 0 deletions portalnetwork/beacon/light_client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package beacon

import (
"github.com/protolambda/zrnt/eth2/beacon/capella"
"github.com/protolambda/zrnt/eth2/beacon/common"
"github.com/protolambda/ztyp/view"
)

type ConsensusAPI interface {
GetUpdates(firstPeriod, count uint64) (LightClientUpdateRange, error)
GetCheckpointData(checkpointHash common.Root) (*capella.LightClientBootstrap, error)
GetFinalityData() (*capella.LightClientFinalityUpdate, error)
GetOptimisticData() (*capella.LightClientOptimisticUpdate, error)
ChainID() uint64
Name() string
}

type LightClientStore struct {
FinalizedHeader common.BeaconBlockHeader
CurrentSyncCommittee common.SyncCommittee
NextSyncCommittee common.SyncCommittee
OptimisticHeader common.BeaconBlockHeader
PreviousMaxActiveParticipants view.Uint64View
CurrentMaxActiveParticipants view.Uint64View
}

type ConsensusLightClient struct {
Store LightClientStore
API ConsensusAPI
InitialCheckpoint common.Root
LastCheckpoint common.Root
Config Config
}

type Config struct {
ConsensusAPI string
Port uint64
DefaultCheckpoint common.Root
Checkpoint common.Root
DataDir string
ChainConfig ChainConfig
Spec *common.Spec
MaxCheckpointAge uint64
Fallback string
LoadExternalFallback bool
StrictCheckpointAge bool
}

type ChainConfig struct {
ChainID uint64
GenesisTime uint64
GenesisRoot common.Root
}
48 changes: 48 additions & 0 deletions portalnetwork/beacon/portal_api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package beacon

import (
"time"

"github.com/protolambda/zrnt/eth2/beacon/capella"
zrntcommon "github.com/protolambda/zrnt/eth2/beacon/common"
"github.com/protolambda/ztyp/tree"
)

var _ ConsensusAPI = &PortalLightApi{}

type PortalLightApi struct {
bn *BeaconNetwork
}

func NewPortalLightApi() *PortalLightApi {
return &PortalLightApi{}
}

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

func (api *PortalLightApi) GetCheckpointData(checkpointHash tree.Root) (*capella.LightClientBootstrap, error) {
return api.bn.GetCheckpointData(checkpointHash)
}

func (api *PortalLightApi) GetFinalityData() (*capella.LightClientFinalityUpdate, error) {
expectedCurrentSlot := api.bn.Spec.TimeToSlot(zrntcommon.Timestamp(time.Now().Unix()), zrntcommon.Timestamp(BeaconGenesisTime))
recentEpochStart := expectedCurrentSlot - (expectedCurrentSlot % api.bn.Spec.SLOTS_PER_EPOCH) + 1

return api.bn.GetFinalityUpdate(uint64(recentEpochStart))
}

func (api *PortalLightApi) GetOptimisticData() (*capella.LightClientOptimisticUpdate, error) {
expectedCurrentSlot := api.bn.Spec.TimeToSlot(zrntcommon.Timestamp(time.Now().Unix()), zrntcommon.Timestamp(BeaconGenesisTime))

return api.bn.GetOptimisticUpdate(uint64(expectedCurrentSlot))
}

func (api *PortalLightApi) ChainID() uint64 {
return 1
}

func (api *PortalLightApi) Name() string {
return "portal"
}

0 comments on commit d9d612d

Please sign in to comment.