mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-13 07:23:46 +00:00
Merge pull request #80 from GrapeBaBa/lc_api
feat:add light client types
This commit is contained in:
commit
d9d612d94a
4 changed files with 179 additions and 49 deletions
|
|
@ -1,57 +1,39 @@
|
||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/beacon/types"
|
"github.com/ethereum/go-ethereum/portalnetwork/beacon"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/protolambda/zrnt/eth2/beacon/capella"
|
||||||
|
zrntcommon "github.com/protolambda/zrnt/eth2/beacon/common"
|
||||||
|
"github.com/protolambda/ztyp/tree"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PortalLightApi struct {
|
type PortalLightApi struct {
|
||||||
|
bn *beacon.BeaconNetwork
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPortalLightApi() *PortalLightApi {
|
func NewPortalLightApi() *PortalLightApi {
|
||||||
return &PortalLightApi{}
|
return &PortalLightApi{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *PortalLightApi) GetBestUpdatesAndCommittees(firstPeriod, count uint64) ([]*types.LightClientUpdate, []*types.SerializedSyncCommittee, error) {
|
func (api *PortalLightApi) GetUpdates(firstPeriod, count uint64) (beacon.LightClientUpdateRange, error) {
|
||||||
//contentKey := &beacon.LightClientUpdateKey{
|
return api.bn.GetUpdates(firstPeriod, count)
|
||||||
// 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) GetCheckpointData(checkpointHash common.Hash) (*types.BootstrapData, error) {
|
func (api *PortalLightApi) GetCheckpointData(checkpointHash tree.Root) (*capella.LightClientBootstrap, error) {
|
||||||
return nil, errors.New("not implemented")
|
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))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,14 +19,15 @@ const (
|
||||||
LightClientFinalityUpdate storage.ContentType = 0x12
|
LightClientFinalityUpdate storage.ContentType = 0x12
|
||||||
LightClientOptimisticUpdate storage.ContentType = 0x13
|
LightClientOptimisticUpdate storage.ContentType = 0x13
|
||||||
HistoricalSummaries storage.ContentType = 0x14
|
HistoricalSummaries storage.ContentType = 0x14
|
||||||
|
BeaconGenesisTime uint64 = 1606824023
|
||||||
)
|
)
|
||||||
|
|
||||||
type BeaconNetwork struct {
|
type BeaconNetwork struct {
|
||||||
portalProtocol *discover.PortalProtocol
|
PortalProtocol *discover.PortalProtocol
|
||||||
spec *common.Spec
|
Spec *common.Spec
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bn *BeaconNetwork) GetBestUpdatesAndCommittees(firstPeriod, count uint64) (LightClientUpdateRange, error) {
|
func (bn *BeaconNetwork) GetUpdates(firstPeriod, count uint64) (LightClientUpdateRange, error) {
|
||||||
lightClientUpdateKey := &LightClientUpdateKey{
|
lightClientUpdateKey := &LightClientUpdateKey{
|
||||||
StartPeriod: firstPeriod,
|
StartPeriod: firstPeriod,
|
||||||
Count: count,
|
Count: count,
|
||||||
|
|
@ -38,7 +39,7 @@ func (bn *BeaconNetwork) GetBestUpdatesAndCommittees(firstPeriod, count uint64)
|
||||||
}
|
}
|
||||||
|
|
||||||
var lightClientUpdateRange LightClientUpdateRange = make([]ForkedLightClientUpdate, 0)
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -57,7 +58,7 @@ func (bn *BeaconNetwork) GetCheckpointData(checkpointHash tree.Root) (*capella.L
|
||||||
}
|
}
|
||||||
|
|
||||||
var forkedLightClientBootstrap ForkedLightClientBootstrap
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -69,6 +70,52 @@ func (bn *BeaconNetwork) GetCheckpointData(checkpointHash tree.Root) (*capella.L
|
||||||
return forkedLightClientBootstrap.Bootstrap.(*capella.LightClientBootstrap), nil
|
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) {
|
func (bn *BeaconNetwork) getContent(contentType storage.ContentType, beaconContentKey ssz.Marshaler) ([]byte, error) {
|
||||||
contentKeyBytes, err := beaconContentKey.MarshalSSZ()
|
contentKeyBytes, err := beaconContentKey.MarshalSSZ()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -76,9 +123,9 @@ func (bn *BeaconNetwork) getContent(contentType storage.ContentType, beaconConte
|
||||||
}
|
}
|
||||||
|
|
||||||
contentKey := storage.NewContentKey(contentType, contentKeyBytes).Encode()
|
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
|
// other error
|
||||||
if err != nil && !errors.Is(err, storage.ErrContentNotFound) {
|
if err != nil && !errors.Is(err, storage.ErrContentNotFound) {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -88,7 +135,7 @@ func (bn *BeaconNetwork) getContent(contentType storage.ContentType, beaconConte
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
content, _, err := bn.portalProtocol.ContentLookup(contentKey, contentId)
|
content, _, err := bn.PortalProtocol.ContentLookup(contentKey, contentId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
53
portalnetwork/beacon/light_client.go
Normal file
53
portalnetwork/beacon/light_client.go
Normal file
|
|
@ -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
portalnetwork/beacon/portal_api.go
Normal file
48
portalnetwork/beacon/portal_api.go
Normal file
|
|
@ -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"
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue