mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-30 00: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
|
||||
|
||||
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))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -69,6 +70,52 @@ 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 {
|
||||
|
|
@ -76,9 +123,9 @@ func (bn *BeaconNetwork) getContent(contentType storage.ContentType, beaconConte
|
|||
}
|
||||
|
||||
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
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
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