mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-29 16:13:47 +00:00
Merge pull request #82 from GrapeBaBa/portal1
feat:light client init bootstrap
This commit is contained in:
commit
d02baa292f
2 changed files with 84 additions and 39 deletions
|
|
@ -1,39 +0,0 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"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) GetUpdates(firstPeriod, count uint64) (beacon.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(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))
|
||||
}
|
||||
|
|
@ -1,8 +1,16 @@
|
|||
package beacon
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/protolambda/zrnt/eth2/beacon/altair"
|
||||
"github.com/protolambda/zrnt/eth2/beacon/capella"
|
||||
"github.com/protolambda/zrnt/eth2/beacon/common"
|
||||
"github.com/protolambda/zrnt/eth2/util/merkle"
|
||||
"github.com/protolambda/ztyp/tree"
|
||||
"github.com/protolambda/ztyp/view"
|
||||
)
|
||||
|
||||
|
|
@ -30,6 +38,7 @@ type ConsensusLightClient struct {
|
|||
InitialCheckpoint common.Root
|
||||
LastCheckpoint common.Root
|
||||
Config Config
|
||||
Logger log.Logger
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
|
|
@ -51,3 +60,78 @@ type ChainConfig struct {
|
|||
GenesisTime uint64
|
||||
GenesisRoot common.Root
|
||||
}
|
||||
|
||||
//lint:ignore U1000 placeholder function
|
||||
func (c *ConsensusLightClient) bootstrap() error {
|
||||
bootstrap, err := c.API.GetCheckpointData(c.InitialCheckpoint)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
isValid := c.isValidCheckpoint(bootstrap.Header.Beacon.Slot)
|
||||
if !isValid {
|
||||
if c.Config.StrictCheckpointAge {
|
||||
return errors.New("checkpoint is too old")
|
||||
} else {
|
||||
c.Logger.Warn("checkpoint is too old")
|
||||
}
|
||||
}
|
||||
|
||||
committeeValid := c.isCurrentCommitteeProofValid(bootstrap.Header.Beacon, bootstrap.CurrentSyncCommittee, bootstrap.CurrentSyncCommitteeBranch)
|
||||
|
||||
headerHash := bootstrap.Header.Beacon.HashTreeRoot(tree.GetHashFn()).String()
|
||||
expectedHash := c.InitialCheckpoint.String()
|
||||
|
||||
headerValid := headerHash == expectedHash
|
||||
|
||||
if !headerValid {
|
||||
return fmt.Errorf("header hash %s does not match expected hash %s", headerHash, expectedHash)
|
||||
}
|
||||
|
||||
if !committeeValid {
|
||||
return errors.New("committee proof is invalid")
|
||||
}
|
||||
|
||||
c.Store = LightClientStore{
|
||||
FinalizedHeader: bootstrap.Header.Beacon,
|
||||
CurrentSyncCommittee: bootstrap.CurrentSyncCommittee,
|
||||
OptimisticHeader: bootstrap.Header.Beacon,
|
||||
PreviousMaxActiveParticipants: view.Uint64View(0),
|
||||
CurrentMaxActiveParticipants: view.Uint64View(0),
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *ConsensusLightClient) isValidCheckpoint(blockHashSlot common.Slot) bool {
|
||||
currentSlot := c.expectedCurrentSlot()
|
||||
currentSlotTimestamp, err := c.slotTimestamp(currentSlot)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
blockHashSlotTimestamp, err := c.slotTimestamp(blockHashSlot)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
slotAge := currentSlotTimestamp - blockHashSlotTimestamp
|
||||
|
||||
return uint64(slotAge) < c.Config.MaxCheckpointAge
|
||||
}
|
||||
|
||||
func (c *ConsensusLightClient) expectedCurrentSlot() common.Slot {
|
||||
return c.Config.Spec.TimeToSlot(common.Timestamp(time.Now().Unix()), common.Timestamp(c.Config.ChainConfig.GenesisTime))
|
||||
}
|
||||
|
||||
func (c *ConsensusLightClient) slotTimestamp(slot common.Slot) (common.Timestamp, error) {
|
||||
atSlot, err := c.Config.Spec.TimeAtSlot(slot, common.Timestamp(c.Config.ChainConfig.GenesisTime))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return atSlot, nil
|
||||
}
|
||||
|
||||
func (c *ConsensusLightClient) isCurrentCommitteeProofValid(attestedHeader common.BeaconBlockHeader, currentCommittee common.SyncCommittee, currentCommitteeBranch altair.SyncCommitteeProofBranch) bool {
|
||||
return merkle.VerifyMerkleBranch(currentCommittee.HashTreeRoot(c.Config.Spec, tree.GetHashFn()), currentCommitteeBranch[:], 5, 22, attestedHeader.StateRoot)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue