feat: change portal api

This commit is contained in:
fearlessfe 2024-04-20 21:03:23 +08:00
parent c6b57fdff7
commit 73612bf661
7 changed files with 240 additions and 115 deletions

View file

@ -140,7 +140,7 @@ func initDiscV5(config Config, conn discover.UDPConn) (*discover.UDPv5, *enode.L
PrivateKey: config.PrivateKey, PrivateKey: config.PrivateKey,
NetRestrict: config.Protocol.NetRestrict, NetRestrict: config.Protocol.NetRestrict,
Bootnodes: config.Protocol.BootstrapNodes, Bootnodes: config.Protocol.BootstrapNodes,
Log: log.New("discV5"), Log: log.New("protocol", "discV5"),
} }
nodeDB, err := enode.OpenDB(config.Protocol.NodeDBPath) nodeDB, err := enode.OpenDB(config.Protocol.NodeDBPath)

2
go.mod
View file

@ -153,4 +153,6 @@ require (
rsc.io/tmplfunc v0.0.3 // indirect rsc.io/tmplfunc v0.0.3 // indirect
) )
// replace github.com/protolambda/zrnt v0.32.2 => ../zrnt-fork
replace github.com/protolambda/zrnt v0.32.2 => github.com/optimism-java/zrnt v0.32.4-0.20240415084906-d9dbf06b32f7 replace github.com/protolambda/zrnt v0.32.2 => github.com/optimism-java/zrnt v0.32.4-0.20240415084906-d9dbf06b32f7

View file

@ -11,7 +11,6 @@ import (
"github.com/ethereum/go-ethereum/p2p/discover" "github.com/ethereum/go-ethereum/p2p/discover"
"github.com/ethereum/go-ethereum/portalnetwork/storage" "github.com/ethereum/go-ethereum/portalnetwork/storage"
ssz "github.com/ferranbt/fastssz" ssz "github.com/ferranbt/fastssz"
"github.com/protolambda/zrnt/eth2/beacon/capella"
"github.com/protolambda/zrnt/eth2/beacon/common" "github.com/protolambda/zrnt/eth2/beacon/common"
"github.com/protolambda/zrnt/eth2/configs" "github.com/protolambda/zrnt/eth2/configs"
"github.com/protolambda/ztyp/codec" "github.com/protolambda/ztyp/codec"
@ -62,100 +61,82 @@ func (bn *BeaconNetwork) Stop() {
bn.portalProtocol.Stop() bn.portalProtocol.Stop()
} }
func (bn *BeaconNetwork) GetUpdates(firstPeriod, count uint64) ([]*capella.LightClientUpdate, error) { func (bn *BeaconNetwork) GetUpdates(firstPeriod, count uint64) ([]common.SpecObj, error) {
lightClientUpdateKey := &LightClientUpdateKey{ lightClientUpdateKey := &LightClientUpdateKey{
StartPeriod: firstPeriod, StartPeriod: firstPeriod,
Count: count, Count: count,
} }
lightClientUpdateRangeContent, err := bn.getContent(LightClientUpdate, lightClientUpdateKey) data, err := bn.getContent(LightClientUpdate, lightClientUpdateKey)
if err != nil { if err != nil {
return nil, err return nil, err
} }
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(data), uint64(len(data))))
if err != nil { if err != nil {
return nil, err return nil, err
} }
res := make([]common.SpecObj, len(lightClientUpdateRange))
updates := make([]*capella.LightClientUpdate, len(lightClientUpdateRange)) for i, item := range lightClientUpdateRange {
for i, update := range lightClientUpdateRange { res[i] = item.LightClientUpdate
if update.ForkDigest != Capella {
return nil, errors.New("unknown fork digest")
}
updates[i] = update.LightClientUpdate.(*capella.LightClientUpdate)
} }
return updates, nil return res, nil
} }
func (bn *BeaconNetwork) GetCheckpointData(checkpointHash tree.Root) (*capella.LightClientBootstrap, error) { func (bn *BeaconNetwork) GetCheckpointData(checkpointHash tree.Root) (common.SpecObj, error) {
bootstrapKey := &LightClientBootstrapKey{ bootstrapKey := &LightClientBootstrapKey{
BlockHash: checkpointHash[:], BlockHash: checkpointHash[:],
} }
bootstrapValue, err := bn.getContent(LightClientBootstrap, bootstrapKey) data, err := bn.getContent(LightClientBootstrap, bootstrapKey)
if err != nil { if err != nil {
return nil, err return nil, err
} }
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(data), uint64(len(data))))
if err != nil { if err != nil {
return nil, err return nil, err
} }
return forkedLightClientBootstrap.Bootstrap, nil
if forkedLightClientBootstrap.ForkDigest != Capella {
return nil, errors.New("unknown fork digest")
}
return forkedLightClientBootstrap.Bootstrap.(*capella.LightClientBootstrap), nil
} }
func (bn *BeaconNetwork) GetFinalityUpdate(finalizedSlot uint64) (*capella.LightClientFinalityUpdate, error) { func (bn *BeaconNetwork) GetFinalityUpdate(finalizedSlot uint64) (common.SpecObj, error) {
finalityUpdateKey := &LightClientFinalityUpdateKey{ finalityUpdateKey := &LightClientFinalityUpdateKey{
FinalizedSlot: finalizedSlot, FinalizedSlot: finalizedSlot,
} }
data, err := bn.getContent(LightClientFinalityUpdate, finalityUpdateKey)
finalityUpdateValue, err := bn.getContent(LightClientFinalityUpdate, finalityUpdateKey)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var forkedLightClientFinalityUpdate ForkedLightClientFinalityUpdate var forkedLightClientFinalityUpdate *ForkedLightClientFinalityUpdate
err = forkedLightClientFinalityUpdate.Deserialize(bn.spec, codec.NewDecodingReader(bytes.NewReader(finalityUpdateValue), uint64(len(finalityUpdateValue)))) err = forkedLightClientFinalityUpdate.Deserialize(bn.spec, codec.NewDecodingReader(bytes.NewReader(data), uint64(len(data))))
if err != nil { if err != nil {
return nil, err return nil, err
} }
if forkedLightClientFinalityUpdate.ForkDigest != Capella { return forkedLightClientFinalityUpdate.LightClientFinalityUpdate, nil
return nil, errors.New("unknown fork digest")
}
return forkedLightClientFinalityUpdate.LightClientFinalityUpdate.(*capella.LightClientFinalityUpdate), nil
} }
func (bn *BeaconNetwork) GetOptimisticUpdate(optimisticSlot uint64) (*capella.LightClientOptimisticUpdate, error) { func (bn *BeaconNetwork) GetOptimisticUpdate(optimisticSlot uint64) (common.SpecObj, error) {
optimisticUpdateKey := &LightClientOptimisticUpdateKey{ optimisticUpdateKey := &LightClientOptimisticUpdateKey{
OptimisticSlot: optimisticSlot, OptimisticSlot: optimisticSlot,
} }
optimisticUpdateValue, err := bn.getContent(LightClientOptimisticUpdate, optimisticUpdateKey) data, err := bn.getContent(LightClientOptimisticUpdate, optimisticUpdateKey)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var forkedLightClientOptimisticUpdate ForkedLightClientOptimisticUpdate var forkedLightClientOptimisticUpdate *ForkedLightClientOptimisticUpdate
err = forkedLightClientOptimisticUpdate.Deserialize(bn.spec, codec.NewDecodingReader(bytes.NewReader(optimisticUpdateValue), uint64(len(optimisticUpdateValue)))) err = forkedLightClientOptimisticUpdate.Deserialize(bn.spec, codec.NewDecodingReader(bytes.NewReader(data), uint64(len(data))))
if err != nil { if err != nil {
return nil, err return nil, err
} }
if forkedLightClientOptimisticUpdate.ForkDigest != Capella { return forkedLightClientOptimisticUpdate.LightClientOptimisticUpdate, nil
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) {

View file

@ -9,6 +9,7 @@ import (
"github.com/protolambda/zrnt/eth2/beacon/altair" "github.com/protolambda/zrnt/eth2/beacon/altair"
"github.com/protolambda/zrnt/eth2/beacon/capella" "github.com/protolambda/zrnt/eth2/beacon/capella"
"github.com/protolambda/zrnt/eth2/beacon/common" "github.com/protolambda/zrnt/eth2/beacon/common"
"github.com/protolambda/zrnt/eth2/beacon/deneb"
"github.com/protolambda/zrnt/eth2/configs" "github.com/protolambda/zrnt/eth2/configs"
"github.com/protolambda/zrnt/eth2/util/merkle" "github.com/protolambda/zrnt/eth2/util/merkle"
@ -29,10 +30,10 @@ var (
) )
type ConsensusAPI interface { type ConsensusAPI interface {
GetUpdates(firstPeriod, count uint64) ([]*capella.LightClientUpdate, error) GetUpdates(firstPeriod, count uint64) ([]common.SpecObj, error)
GetCheckpointData(checkpointHash common.Root) (*capella.LightClientBootstrap, error) GetCheckpointData(checkpointHash common.Root) (common.SpecObj, error)
GetFinalityData() (*capella.LightClientFinalityUpdate, error) GetFinalityData() (common.SpecObj, error)
GetOptimisticData() (*capella.LightClientOptimisticUpdate, error) GetOptimisticData() (common.SpecObj, error)
ChainID() uint64 ChainID() uint64
Name() string Name() string
} }
@ -85,6 +86,36 @@ type GenericUpdate struct {
FinalityBranch *altair.FinalizedRootProofBranch FinalityBranch *altair.FinalizedRootProofBranch
} }
type GenericBootstrap struct {
Header *common.BeaconBlockHeader
CurrentSyncCommittee common.SyncCommittee
CurrentSyncCommitteeBranch altair.SyncCommitteeProofBranch
}
func FromBootstrap(commonBootstrap common.SpecObj) (*GenericBootstrap, error) {
switch bootstrap := commonBootstrap.(type) {
case *deneb.LightClientBootstrap:
return &GenericBootstrap{
Header: &bootstrap.Header.Beacon,
CurrentSyncCommittee: bootstrap.CurrentSyncCommittee,
CurrentSyncCommitteeBranch: bootstrap.CurrentSyncCommitteeBranch,
}, nil
case *capella.LightClientBootstrap:
return &GenericBootstrap{
Header: &bootstrap.Header.Beacon,
CurrentSyncCommittee: bootstrap.CurrentSyncCommittee,
CurrentSyncCommitteeBranch: bootstrap.CurrentSyncCommitteeBranch,
}, nil
case *altair.LightClientBootstrap:
return &GenericBootstrap{
Header: &bootstrap.Header.Beacon,
CurrentSyncCommittee: bootstrap.CurrentSyncCommittee,
CurrentSyncCommitteeBranch: bootstrap.CurrentSyncCommitteeBranch,
}, nil
}
return nil, errors.New("unknown bootstrap type")
}
func NewConsensusLightClient(api ConsensusAPI, config *Config, checkpointBlockRoot common.Root, logger log.Logger) (*ConsensusLightClient, error) { func NewConsensusLightClient(api ConsensusAPI, config *Config, checkpointBlockRoot common.Root, logger log.Logger) (*ConsensusLightClient, error) {
client := &ConsensusLightClient{ client := &ConsensusLightClient{
API: api, API: api,
@ -117,7 +148,7 @@ func (c *ConsensusLightClient) Sync() error {
bootstrapPeriod := CalcSyncPeriod(uint64(c.Store.FinalizedHeader.Slot)) bootstrapPeriod := CalcSyncPeriod(uint64(c.Store.FinalizedHeader.Slot))
updates := make([]*capella.LightClientUpdate, 0) updates := make([]common.SpecObj, 0)
if c.API.Name() == "portal" { if c.API.Name() == "portal" {
currentPeriod := CalcSyncPeriod(uint64(c.expectedCurrentSlot())) currentPeriod := CalcSyncPeriod(uint64(c.expectedCurrentSlot()))
@ -209,12 +240,15 @@ func (c *ConsensusLightClient) Advance() error {
} }
func (c *ConsensusLightClient) bootstrap() error { func (c *ConsensusLightClient) bootstrap() error {
bootstrap, err := c.API.GetCheckpointData(c.InitialCheckpoint) forkedBootstrap, err := c.API.GetCheckpointData(c.InitialCheckpoint)
if err != nil { if err != nil {
return err return err
} }
bootstrap, err := FromBootstrap(forkedBootstrap)
isValid := c.isValidCheckpoint(bootstrap.Header.Beacon.Slot) if err != nil {
return err
}
isValid := c.isValidCheckpoint(bootstrap.Header.Slot)
if !isValid { if !isValid {
if c.Config.StrictCheckpointAge { if c.Config.StrictCheckpointAge {
return errors.New("checkpoint is too old") return errors.New("checkpoint is too old")
@ -223,9 +257,9 @@ func (c *ConsensusLightClient) bootstrap() error {
} }
} }
committeeValid := c.isCurrentCommitteeProofValid(bootstrap.Header.Beacon, bootstrap.CurrentSyncCommittee, bootstrap.CurrentSyncCommitteeBranch) committeeValid := c.isCurrentCommitteeProofValid(*bootstrap.Header, bootstrap.CurrentSyncCommittee, bootstrap.CurrentSyncCommitteeBranch)
headerHash := bootstrap.Header.Beacon.HashTreeRoot(tree.GetHashFn()).String() headerHash := bootstrap.Header.HashTreeRoot(tree.GetHashFn()).String()
expectedHash := c.InitialCheckpoint.String() expectedHash := c.InitialCheckpoint.String()
headerValid := headerHash == expectedHash headerValid := headerHash == expectedHash
@ -239,9 +273,9 @@ func (c *ConsensusLightClient) bootstrap() error {
} }
c.Store = LightClientStore{ c.Store = LightClientStore{
FinalizedHeader: &bootstrap.Header.Beacon, FinalizedHeader: bootstrap.Header,
CurrentSyncCommittee: &bootstrap.CurrentSyncCommittee, CurrentSyncCommittee: &bootstrap.CurrentSyncCommittee,
OptimisticHeader: &bootstrap.Header.Beacon, OptimisticHeader: bootstrap.Header,
PreviousMaxActiveParticipants: view.Uint64View(0), PreviousMaxActiveParticipants: view.Uint64View(0),
CurrentMaxActiveParticipants: view.Uint64View(0), CurrentMaxActiveParticipants: view.Uint64View(0),
} }
@ -329,18 +363,27 @@ func (c *ConsensusLightClient) VerifyGenericUpdate(update *GenericUpdate) error
return nil return nil
} }
func (c *ConsensusLightClient) VerifyUpdate(update *capella.LightClientUpdate) error { func (c *ConsensusLightClient) VerifyUpdate(update common.SpecObj) error {
genericUpdate := FromLightClientUpdate(update) genericUpdate, err := FromLightClientUpdate(update)
if err != nil {
return err
}
return c.VerifyGenericUpdate(genericUpdate) return c.VerifyGenericUpdate(genericUpdate)
} }
func (c *ConsensusLightClient) VerifyFinalityUpdate(update *capella.LightClientFinalityUpdate) error { func (c *ConsensusLightClient) VerifyFinalityUpdate(update common.SpecObj) error {
genericUpdate := FromLightClientFinalityUpdate(update) genericUpdate, err := FromLightClientFinalityUpdate(update)
if err != nil {
return err
}
return c.VerifyGenericUpdate(genericUpdate) return c.VerifyGenericUpdate(genericUpdate)
} }
func (c *ConsensusLightClient) VerifyOptimisticUpdate(update *capella.LightClientOptimisticUpdate) error { func (c *ConsensusLightClient) VerifyOptimisticUpdate(update common.SpecObj) error {
genericUpdate := FromLightClientOptimisticUpdate(update) genericUpdate, err := FromLightClientOptimisticUpdate(update)
if err != nil {
return err
}
return c.VerifyGenericUpdate(genericUpdate) return c.VerifyGenericUpdate(genericUpdate)
} }
@ -407,19 +450,31 @@ func (c *ConsensusLightClient) ApplyGenericUpdate(update *GenericUpdate) {
} }
} }
func (c *ConsensusLightClient) ApplyUpdate(update *capella.LightClientUpdate) { func (c *ConsensusLightClient) ApplyUpdate(update common.SpecObj) error {
genericUpdate := FromLightClientUpdate(update) genericUpdate, err := FromLightClientUpdate(update)
if err != nil {
return err
}
c.ApplyGenericUpdate(genericUpdate) c.ApplyGenericUpdate(genericUpdate)
return nil
} }
func (c *ConsensusLightClient) ApplyFinalityUpdate(update *capella.LightClientFinalityUpdate) { func (c *ConsensusLightClient) ApplyFinalityUpdate(update common.SpecObj) error {
genericUpdate := FromLightClientFinalityUpdate(update) genericUpdate, err := FromLightClientFinalityUpdate(update)
if err != nil {
return err
}
c.ApplyGenericUpdate(genericUpdate) c.ApplyGenericUpdate(genericUpdate)
return nil
} }
func (c *ConsensusLightClient) ApplyOptimisticUpdate(update *capella.LightClientOptimisticUpdate) { func (c *ConsensusLightClient) ApplyOptimisticUpdate(update common.SpecObj) error {
genericUpdate := FromLightClientOptimisticUpdate(update) genericUpdate, err := FromLightClientOptimisticUpdate(update)
if err != nil {
return err
}
c.ApplyGenericUpdate(genericUpdate) c.ApplyGenericUpdate(genericUpdate)
return nil
} }
func (c *ConsensusLightClient) VerifySyncCommitteeSignature(pks []common.BLSPubkey, attestedHeader common.BeaconBlockHeader, signature common.BLSSignature, signatureSlot common.Slot) (bool, error) { func (c *ConsensusLightClient) VerifySyncCommitteeSignature(pks []common.BLSPubkey, attestedHeader common.BeaconBlockHeader, signature common.BLSSignature, signatureSlot common.Slot) (bool, error) {
@ -532,34 +587,94 @@ func (c *ConsensusLightClient) getParticipatingKeys(committee common.SyncCommitt
return res return res
} }
func FromLightClientUpdate(update *capella.LightClientUpdate) *GenericUpdate { func FromLightClientUpdate(commonUpdate common.SpecObj) (*GenericUpdate, error) {
return &GenericUpdate{ switch update := commonUpdate.(type) {
AttestedHeader: &update.AttestedHeader.Beacon, case *deneb.LightClientUpdate:
SyncAggregate: &update.SyncAggregate, return &GenericUpdate{
SignatureSlot: update.SignatureSlot, AttestedHeader: &update.AttestedHeader.Beacon,
NextSyncCommittee: &update.NextSyncCommittee, SyncAggregate: &update.SyncAggregate,
NextSyncCommitteeBranch: &update.NextSyncCommitteeBranch, SignatureSlot: update.SignatureSlot,
FinalizedHeader: &update.FinalizedHeader.Beacon, NextSyncCommittee: &update.NextSyncCommittee,
FinalityBranch: &update.FinalityBranch, NextSyncCommitteeBranch: &update.NextSyncCommitteeBranch,
FinalizedHeader: &update.FinalizedHeader.Beacon,
FinalityBranch: &update.FinalityBranch,
}, nil
case *capella.LightClientUpdate:
return &GenericUpdate{
AttestedHeader: &update.AttestedHeader.Beacon,
SyncAggregate: &update.SyncAggregate,
SignatureSlot: update.SignatureSlot,
NextSyncCommittee: &update.NextSyncCommittee,
NextSyncCommitteeBranch: &update.NextSyncCommitteeBranch,
FinalizedHeader: &update.FinalizedHeader.Beacon,
FinalityBranch: &update.FinalityBranch,
}, nil
case *altair.LightClientUpdate:
return &GenericUpdate{
AttestedHeader: &update.AttestedHeader.Beacon,
SyncAggregate: &update.SyncAggregate,
SignatureSlot: update.SignatureSlot,
NextSyncCommittee: &update.NextSyncCommittee,
NextSyncCommitteeBranch: &update.NextSyncCommitteeBranch,
FinalizedHeader: &update.FinalizedHeader.Beacon,
FinalityBranch: &update.FinalityBranch,
}, nil
} }
return nil, errors.New("unknown update type")
} }
func FromLightClientFinalityUpdate(update *capella.LightClientFinalityUpdate) *GenericUpdate { func FromLightClientFinalityUpdate(commonFinalityUpdate common.SpecObj) (*GenericUpdate, error) {
return &GenericUpdate{ switch update := commonFinalityUpdate.(type) {
AttestedHeader: &update.AttestedHeader.Beacon, case *deneb.LightClientFinalityUpdate:
SyncAggregate: &update.SyncAggregate, return &GenericUpdate{
SignatureSlot: update.SignatureSlot, AttestedHeader: &update.AttestedHeader.Beacon,
FinalizedHeader: &update.FinalizedHeader.Beacon, SyncAggregate: &update.SyncAggregate,
FinalityBranch: &update.FinalityBranch, SignatureSlot: update.SignatureSlot,
FinalizedHeader: &update.FinalizedHeader.Beacon,
FinalityBranch: &update.FinalityBranch,
}, nil
case *capella.LightClientFinalityUpdate:
return &GenericUpdate{
AttestedHeader: &update.AttestedHeader.Beacon,
SyncAggregate: &update.SyncAggregate,
SignatureSlot: update.SignatureSlot,
FinalizedHeader: &update.FinalizedHeader.Beacon,
FinalityBranch: &update.FinalityBranch,
}, nil
case *altair.LightClientFinalityUpdate:
return &GenericUpdate{
AttestedHeader: &update.AttestedHeader.Beacon,
SyncAggregate: &update.SyncAggregate,
SignatureSlot: update.SignatureSlot,
FinalizedHeader: &update.FinalizedHeader,
FinalityBranch: &update.FinalityBranch,
}, nil
} }
return nil, errors.New("unknown finality update type")
} }
func FromLightClientOptimisticUpdate(update *capella.LightClientOptimisticUpdate) *GenericUpdate { func FromLightClientOptimisticUpdate(commonOptimisticUpdate common.SpecObj) (*GenericUpdate, error) {
return &GenericUpdate{ switch update := commonOptimisticUpdate.(type) {
AttestedHeader: &update.AttestedHeader.Beacon, case *deneb.LightClientOptimisticUpdate:
SyncAggregate: &update.SyncAggregate, return &GenericUpdate{
SignatureSlot: update.SignatureSlot, AttestedHeader: &update.AttestedHeader.Beacon,
SyncAggregate: &update.SyncAggregate,
SignatureSlot: update.SignatureSlot,
}, nil
case *capella.LightClientOptimisticUpdate:
return &GenericUpdate{
AttestedHeader: &update.AttestedHeader.Beacon,
SyncAggregate: &update.SyncAggregate,
SignatureSlot: update.SignatureSlot,
}, nil
case *altair.LightClientOptimisticUpdate:
return &GenericUpdate{
AttestedHeader: &update.AttestedHeader.Beacon,
SyncAggregate: &update.SyncAggregate,
SignatureSlot: update.SignatureSlot,
}, nil
} }
return nil, errors.New("unknown optimistic update type")
} }
func ComputeSigningRoot(root common.Root, domain common.BLSDomain) common.Root { func ComputeSigningRoot(root common.Root, domain common.BLSDomain) common.Root {

View file

@ -24,16 +24,21 @@ func NewMockConsensusAPI(path string) (ConsensusAPI, error) {
return &MockConsensusAPI{testdataDir: path}, nil return &MockConsensusAPI{testdataDir: path}, nil
} }
func (m MockConsensusAPI) GetUpdates(_, _ uint64) ([]*capella.LightClientUpdate, error) { func (m MockConsensusAPI) GetUpdates(_, _ uint64) ([]common.SpecObj, error) {
jsonStr, _ := os.ReadFile(m.testdataDir + "/updates.json") jsonStr, _ := os.ReadFile(m.testdataDir + "/updates.json")
updates := make([]*capella.LightClientUpdate, 0) updates := make([]*capella.LightClientUpdate, 0)
_ = json.Unmarshal(jsonStr, &updates) _ = json.Unmarshal(jsonStr, &updates)
return updates, nil res := make([]common.SpecObj, 0)
for _, item := range updates {
res = append(res, item)
}
return res, nil
} }
func (m MockConsensusAPI) GetCheckpointData(_ common.Root) (*capella.LightClientBootstrap, error) { func (m MockConsensusAPI) GetCheckpointData(_ common.Root) (common.SpecObj, error) {
jsonStr, _ := os.ReadFile(m.testdataDir + "/bootstrap.json") jsonStr, _ := os.ReadFile(m.testdataDir + "/bootstrap.json")
bootstrap := &capella.LightClientBootstrap{} bootstrap := &capella.LightClientBootstrap{}
@ -42,7 +47,7 @@ func (m MockConsensusAPI) GetCheckpointData(_ common.Root) (*capella.LightClient
return bootstrap, nil return bootstrap, nil
} }
func (m MockConsensusAPI) GetFinalityData() (*capella.LightClientFinalityUpdate, error) { func (m MockConsensusAPI) GetFinalityData() (common.SpecObj, error) {
jsonStr, _ := os.ReadFile(m.testdataDir + "/finality.json") jsonStr, _ := os.ReadFile(m.testdataDir + "/finality.json")
finality := &capella.LightClientFinalityUpdate{} finality := &capella.LightClientFinalityUpdate{}
@ -51,7 +56,7 @@ func (m MockConsensusAPI) GetFinalityData() (*capella.LightClientFinalityUpdate,
return finality, nil return finality, nil
} }
func (m MockConsensusAPI) GetOptimisticData() (*capella.LightClientOptimisticUpdate, error) { func (m MockConsensusAPI) GetOptimisticData() (common.SpecObj, error) {
jsonStr, _ := os.ReadFile(m.testdataDir + "/optimistic.json") jsonStr, _ := os.ReadFile(m.testdataDir + "/optimistic.json")
optimistic := &capella.LightClientOptimisticUpdate{} optimistic := &capella.LightClientOptimisticUpdate{}
@ -107,21 +112,27 @@ func TestVerifyUpdate(t *testing.T) {
err = client.VerifyUpdate(updates[0]) err = client.VerifyUpdate(updates[0])
require.NoError(t, err) require.NoError(t, err)
// ErrInvalidNextSyncCommitteeProof // ErrInvalidNextSyncCommitteeProof
updates[0].NextSyncCommittee.Pubkeys[0] = common.BLSPubkey{} genericUpdate, err := FromLightClientUpdate(updates[0])
err = client.VerifyUpdate(updates[0]) require.NoError(t, err)
genericUpdate.NextSyncCommittee.Pubkeys[0] = common.BLSPubkey{}
err = client.VerifyGenericUpdate(genericUpdate)
require.Equal(t, ErrInvalidNextSyncCommitteeProof, err) require.Equal(t, ErrInvalidNextSyncCommitteeProof, err)
// ErrInvalidFinalityProof // ErrInvalidFinalityProof
updates, err = client.API.GetUpdates(period, MaxRequestLightClientUpdates) updates, err = client.API.GetUpdates(period, MaxRequestLightClientUpdates)
require.NoError(t, err) require.NoError(t, err)
updates[0].FinalizedHeader.Beacon = common.BeaconBlockHeader{} genericUpdate, err = FromLightClientUpdate(updates[0])
err = client.VerifyUpdate(updates[0]) require.NoError(t, err)
genericUpdate.FinalizedHeader = &common.BeaconBlockHeader{}
err = client.VerifyGenericUpdate(genericUpdate)
require.Equal(t, ErrInvalidFinalityProof, err) require.Equal(t, ErrInvalidFinalityProof, err)
// ErrInvalidSignature // ErrInvalidSignature
updates, err = client.API.GetUpdates(period, MaxRequestLightClientUpdates) updates, err = client.API.GetUpdates(period, MaxRequestLightClientUpdates)
require.NoError(t, err) require.NoError(t, err)
updates[0].SyncAggregate.SyncCommitteeSignature[1] = 0xFE genericUpdate, err = FromLightClientUpdate(updates[0])
err = client.VerifyUpdate(updates[0]) require.NoError(t, err)
genericUpdate.SyncAggregate.SyncCommitteeSignature[1] = 0xFE
err = client.VerifyGenericUpdate(genericUpdate)
require.Error(t, err) require.Error(t, err)
} }
@ -136,14 +147,20 @@ func TestVerifyFinalityUpdate(t *testing.T) {
err = client.VerifyFinalityUpdate(update) err = client.VerifyFinalityUpdate(update)
require.NoError(t, err) require.NoError(t, err)
update.FinalizedHeader.Beacon = common.BeaconBlockHeader{} genericUpdate, err := FromLightClientFinalityUpdate(update)
err = client.VerifyFinalityUpdate(update) require.NoError(t, err)
genericUpdate.FinalizedHeader = &common.BeaconBlockHeader{}
err = client.VerifyGenericUpdate(genericUpdate)
require.Equal(t, ErrInvalidFinalityProof, err) require.Equal(t, ErrInvalidFinalityProof, err)
// ErrInvalidSignature // ErrInvalidSignature
update, err = client.API.GetFinalityData() update, err = client.API.GetFinalityData()
require.NoError(t, err) require.NoError(t, err)
update.SyncAggregate.SyncCommitteeSignature[1] = 0xFE
err = client.VerifyFinalityUpdate(update) genericUpdate, err = FromLightClientFinalityUpdate(update)
require.NoError(t, err)
genericUpdate.SyncAggregate.SyncCommitteeSignature[1] = 0xFE
err = client.VerifyGenericUpdate(genericUpdate)
require.Error(t, err) require.Error(t, err)
} }
@ -158,8 +175,11 @@ func TestVerifyOptimisticUpdate(t *testing.T) {
err = client.VerifyOptimisticUpdate(update) err = client.VerifyOptimisticUpdate(update)
require.NoError(t, err) require.NoError(t, err)
update.SyncAggregate.SyncCommitteeSignature = common.BLSSignature{} genericUpdate, err := FromLightClientOptimisticUpdate(update)
err = client.VerifyOptimisticUpdate(update) require.NoError(t, err)
genericUpdate.SyncAggregate.SyncCommitteeSignature = common.BLSSignature{}
err = client.VerifyGenericUpdate(genericUpdate)
require.Error(t, err) require.Error(t, err)
} }

View file

@ -3,7 +3,6 @@ package beacon
import ( import (
"time" "time"
"github.com/protolambda/zrnt/eth2/beacon/capella"
zrntcommon "github.com/protolambda/zrnt/eth2/beacon/common" zrntcommon "github.com/protolambda/zrnt/eth2/beacon/common"
"github.com/protolambda/ztyp/tree" "github.com/protolambda/ztyp/tree"
) )
@ -18,24 +17,22 @@ func NewPortalLightApi() *PortalLightApi {
return &PortalLightApi{} return &PortalLightApi{}
} }
func (api *PortalLightApi) GetUpdates(firstPeriod, count uint64) ([]*capella.LightClientUpdate, error) { func (api *PortalLightApi) GetUpdates(firstPeriod, count uint64) ([]zrntcommon.SpecObj, error) {
return api.bn.GetUpdates(firstPeriod, count) return api.bn.GetUpdates(firstPeriod, count)
} }
func (api *PortalLightApi) GetCheckpointData(checkpointHash tree.Root) (*capella.LightClientBootstrap, error) { func (api *PortalLightApi) GetCheckpointData(checkpointHash tree.Root) (zrntcommon.SpecObj, error) {
return api.bn.GetCheckpointData(checkpointHash) return api.bn.GetCheckpointData(checkpointHash)
} }
func (api *PortalLightApi) GetFinalityData() (*capella.LightClientFinalityUpdate, error) { func (api *PortalLightApi) GetFinalityData() (zrntcommon.SpecObj, error) {
expectedCurrentSlot := api.bn.spec.TimeToSlot(zrntcommon.Timestamp(time.Now().Unix()), zrntcommon.Timestamp(BeaconGenesisTime)) expectedCurrentSlot := api.bn.spec.TimeToSlot(zrntcommon.Timestamp(time.Now().Unix()), zrntcommon.Timestamp(BeaconGenesisTime))
recentEpochStart := expectedCurrentSlot - (expectedCurrentSlot % api.bn.spec.SLOTS_PER_EPOCH) + 1 recentEpochStart := expectedCurrentSlot - (expectedCurrentSlot % api.bn.spec.SLOTS_PER_EPOCH) + 1
return api.bn.GetFinalityUpdate(uint64(recentEpochStart)) return api.bn.GetFinalityUpdate(uint64(recentEpochStart))
} }
func (api *PortalLightApi) GetOptimisticData() (*capella.LightClientOptimisticUpdate, error) { func (api *PortalLightApi) GetOptimisticData() (zrntcommon.SpecObj, error) {
expectedCurrentSlot := api.bn.spec.TimeToSlot(zrntcommon.Timestamp(time.Now().Unix()), zrntcommon.Timestamp(BeaconGenesisTime)) expectedCurrentSlot := api.bn.spec.TimeToSlot(zrntcommon.Timestamp(time.Now().Unix()), zrntcommon.Timestamp(BeaconGenesisTime))
return api.bn.GetOptimisticUpdate(uint64(expectedCurrentSlot)) return api.bn.GetOptimisticUpdate(uint64(expectedCurrentSlot))
} }

View file

@ -6,6 +6,7 @@ import (
"github.com/protolambda/zrnt/eth2/beacon/altair" "github.com/protolambda/zrnt/eth2/beacon/altair"
"github.com/protolambda/zrnt/eth2/beacon/capella" "github.com/protolambda/zrnt/eth2/beacon/capella"
"github.com/protolambda/zrnt/eth2/beacon/common" "github.com/protolambda/zrnt/eth2/beacon/common"
"github.com/protolambda/zrnt/eth2/beacon/deneb"
"github.com/protolambda/ztyp/codec" "github.com/protolambda/ztyp/codec"
"github.com/protolambda/ztyp/tree" "github.com/protolambda/ztyp/tree"
) )
@ -15,6 +16,7 @@ const MaxRequestLightClientUpdates = 128
var ( var (
Bellatrix common.ForkDigest = [4]byte{0x0, 0x0, 0x0, 0x0} Bellatrix common.ForkDigest = [4]byte{0x0, 0x0, 0x0, 0x0}
Capella common.ForkDigest = [4]byte{0xbb, 0xa4, 0xda, 0x96} Capella common.ForkDigest = [4]byte{0xbb, 0xa4, 0xda, 0x96}
Deneb common.ForkDigest = [4]byte{0x6a, 0x95, 0xa1, 0xa9}
) )
//go:generate sszgen --path types.go --exclude-objs ForkedLightClientBootstrap,ForkedLightClientUpdate,LightClientUpdateRange //go:generate sszgen --path types.go --exclude-objs ForkedLightClientBootstrap,ForkedLightClientUpdate,LightClientUpdateRange
@ -51,6 +53,8 @@ func (flcb *ForkedLightClientBootstrap) Deserialize(spec *common.Spec, dr *codec
flcb.Bootstrap = &altair.LightClientBootstrap{} flcb.Bootstrap = &altair.LightClientBootstrap{}
} else if flcb.ForkDigest == Capella { } else if flcb.ForkDigest == Capella {
flcb.Bootstrap = &capella.LightClientBootstrap{} flcb.Bootstrap = &capella.LightClientBootstrap{}
} else if flcb.ForkDigest == Deneb {
flcb.Bootstrap = &deneb.LightClientBootstrap{}
} else { } else {
return errors.New("unknown fork digest") return errors.New("unknown fork digest")
} }
@ -64,7 +68,7 @@ func (flcb *ForkedLightClientBootstrap) Deserialize(spec *common.Spec, dr *codec
} }
func (flcb *ForkedLightClientBootstrap) Serialize(spec *common.Spec, w *codec.EncodingWriter) error { func (flcb *ForkedLightClientBootstrap) Serialize(spec *common.Spec, w *codec.EncodingWriter) error {
return w.Container(flcb.ForkDigest, spec.Wrap(flcb.Bootstrap)) return w.FixedLenContainer(flcb.ForkDigest, spec.Wrap(flcb.Bootstrap))
} }
func (flcb *ForkedLightClientBootstrap) FixedLength(_ *common.Spec) uint64 { func (flcb *ForkedLightClientBootstrap) FixedLength(_ *common.Spec) uint64 {
@ -94,6 +98,8 @@ func (flcu *ForkedLightClientUpdate) Deserialize(spec *common.Spec, dr *codec.De
flcu.LightClientUpdate = &altair.LightClientUpdate{} flcu.LightClientUpdate = &altair.LightClientUpdate{}
} else if flcu.ForkDigest == Capella { } else if flcu.ForkDigest == Capella {
flcu.LightClientUpdate = &capella.LightClientUpdate{} flcu.LightClientUpdate = &capella.LightClientUpdate{}
} else if flcu.ForkDigest == Deneb {
flcu.LightClientUpdate = &deneb.LightClientUpdate{}
} else { } else {
return errors.New("unknown fork digest") return errors.New("unknown fork digest")
} }
@ -107,7 +113,7 @@ func (flcu *ForkedLightClientUpdate) Deserialize(spec *common.Spec, dr *codec.De
} }
func (flcu *ForkedLightClientUpdate) Serialize(spec *common.Spec, w *codec.EncodingWriter) error { func (flcu *ForkedLightClientUpdate) Serialize(spec *common.Spec, w *codec.EncodingWriter) error {
return w.Container(flcu.ForkDigest, spec.Wrap(flcu.LightClientUpdate)) return w.FixedLenContainer(flcu.ForkDigest, spec.Wrap(flcu.LightClientUpdate))
} }
func (flcu *ForkedLightClientUpdate) FixedLength(_ *common.Spec) uint64 { func (flcu *ForkedLightClientUpdate) FixedLength(_ *common.Spec) uint64 {
@ -174,6 +180,8 @@ func (flcou *ForkedLightClientOptimisticUpdate) Deserialize(spec *common.Spec, d
flcou.LightClientOptimisticUpdate = &altair.LightClientOptimisticUpdate{} flcou.LightClientOptimisticUpdate = &altair.LightClientOptimisticUpdate{}
} else if flcou.ForkDigest == Capella { } else if flcou.ForkDigest == Capella {
flcou.LightClientOptimisticUpdate = &capella.LightClientOptimisticUpdate{} flcou.LightClientOptimisticUpdate = &capella.LightClientOptimisticUpdate{}
} else if flcou.ForkDigest == Deneb {
flcou.LightClientOptimisticUpdate = &deneb.LightClientOptimisticUpdate{}
} else { } else {
return errors.New("unknown fork digest") return errors.New("unknown fork digest")
} }
@ -187,7 +195,7 @@ func (flcou *ForkedLightClientOptimisticUpdate) Deserialize(spec *common.Spec, d
} }
func (flcou *ForkedLightClientOptimisticUpdate) Serialize(spec *common.Spec, w *codec.EncodingWriter) error { func (flcou *ForkedLightClientOptimisticUpdate) Serialize(spec *common.Spec, w *codec.EncodingWriter) error {
return w.Container(flcou.ForkDigest, spec.Wrap(flcou.LightClientOptimisticUpdate)) return w.FixedLenContainer(flcou.ForkDigest, spec.Wrap(flcou.LightClientOptimisticUpdate))
} }
func (flcou *ForkedLightClientOptimisticUpdate) FixedLength(_ *common.Spec) uint64 { func (flcou *ForkedLightClientOptimisticUpdate) FixedLength(_ *common.Spec) uint64 {
@ -217,6 +225,8 @@ func (flcfu *ForkedLightClientFinalityUpdate) Deserialize(spec *common.Spec, dr
flcfu.LightClientFinalityUpdate = &altair.LightClientFinalityUpdate{} flcfu.LightClientFinalityUpdate = &altair.LightClientFinalityUpdate{}
} else if flcfu.ForkDigest == Capella { } else if flcfu.ForkDigest == Capella {
flcfu.LightClientFinalityUpdate = &capella.LightClientFinalityUpdate{} flcfu.LightClientFinalityUpdate = &capella.LightClientFinalityUpdate{}
} else if flcfu.ForkDigest == Deneb {
flcfu.LightClientFinalityUpdate = &deneb.LightClientFinalityUpdate{}
} else { } else {
return errors.New("unknown fork digest") return errors.New("unknown fork digest")
} }
@ -230,7 +240,7 @@ func (flcfu *ForkedLightClientFinalityUpdate) Deserialize(spec *common.Spec, dr
} }
func (flcfu *ForkedLightClientFinalityUpdate) Serialize(spec *common.Spec, w *codec.EncodingWriter) error { func (flcfu *ForkedLightClientFinalityUpdate) Serialize(spec *common.Spec, w *codec.EncodingWriter) error {
return w.Container(flcfu.ForkDigest, spec.Wrap(flcfu.LightClientFinalityUpdate)) return w.FixedLenContainer(flcfu.ForkDigest, spec.Wrap(flcfu.LightClientFinalityUpdate))
} }
func (flcfu *ForkedLightClientFinalityUpdate) FixedLength(_ *common.Spec) uint64 { func (flcfu *ForkedLightClientFinalityUpdate) FixedLength(_ *common.Spec) uint64 {