Skip to content

Commit

Permalink
Added persistence in LightClient (ledgerwatch#6056)
Browse files Browse the repository at this point in the history
  • Loading branch information
Giulio2002 authored and michaelneuder committed Nov 20, 2022
1 parent 3534b19 commit eac2cfb
Show file tree
Hide file tree
Showing 9 changed files with 100 additions and 16 deletions.
45 changes: 39 additions & 6 deletions cmd/lightclient/lightclient/lightclient.go
Expand Up @@ -20,10 +20,12 @@ import (

lru "github.com/hashicorp/golang-lru"
"github.com/ledgerwatch/erigon-lib/gointerfaces/remote"
"github.com/ledgerwatch/erigon-lib/kv"
"github.com/ledgerwatch/erigon/cl/clparams"
"github.com/ledgerwatch/erigon/cl/cltypes"
"github.com/ledgerwatch/erigon/cl/rpc/consensusrpc"
"github.com/ledgerwatch/erigon/cl/utils"
"github.com/ledgerwatch/erigon/core/rawdb"
"github.com/ledgerwatch/log/v3"
)

Expand All @@ -39,13 +41,13 @@ type LightClient struct {
verbose bool
highestSeen uint64 // Highest ETH1 block seen
recentHashesCache *lru.Cache
db kv.RwDB
sentinel consensusrpc.SentinelClient
execution remote.ETHBACKENDServer
store *LightClientStore
lastValidated *cltypes.LightClientUpdate
}

func NewLightClient(ctx context.Context, genesisConfig *clparams.GenesisConfig, beaconConfig *clparams.BeaconChainConfig,
func NewLightClient(ctx context.Context, db kv.RwDB, genesisConfig *clparams.GenesisConfig, beaconConfig *clparams.BeaconChainConfig,
execution remote.ETHBACKENDServer, sentinel consensusrpc.SentinelClient,
highestSeen uint64, verbose bool) (*LightClient, error) {
recentHashesCache, err := lru.New(maxRecentHashes)
Expand All @@ -59,6 +61,7 @@ func NewLightClient(ctx context.Context, genesisConfig *clparams.GenesisConfig,
execution: execution,
verbose: verbose,
highestSeen: highestSeen,
db: db,
}, err
}

Expand All @@ -67,6 +70,12 @@ func (l *LightClient) Start() {
log.Error("No trusted setup")
return
}
tx, err := l.db.BeginRw(l.ctx)
if err != nil {
log.Error("Could not open MDBX transaction", "err", err)
return
}
defer tx.Rollback()
logPeers := time.NewTicker(time.Minute)
go l.chainTip.StartLoop()
for {
Expand Down Expand Up @@ -126,18 +135,42 @@ func (l *LightClient) Start() {
}
// log new validated segment
if len(updates) > 0 {
l.lastValidated = updates[len(updates)-1]
lastValidated := updates[len(updates)-1]
// Save to Database
if lastValidated.HasNextSyncCommittee() {
if err := rawdb.WriteLightClientUpdate(tx, lastValidated); err != nil {
log.Warn("Could not write lightclient update to db", "err", err)
}
// Process it as a full LightClientUpdate
} else if lastValidated.IsFinalityUpdate() {
if err := rawdb.WriteLightClientFinalityUpdate(tx, &cltypes.LightClientFinalityUpdate{
AttestedHeader: lastValidated.AttestedHeader,
FinalizedHeader: lastValidated.FinalizedHeader,
FinalityBranch: lastValidated.FinalityBranch,
SyncAggregate: lastValidated.SyncAggregate,
SignatureSlot: lastValidated.SignatureSlot,
}); err != nil {
log.Warn("Could not write finality lightclient update to db", "err", err)
}
} else if err := rawdb.WriteLightClientOptimisticUpdate(tx, &cltypes.LightClientOptimisticUpdate{
AttestedHeader: lastValidated.AttestedHeader,
SyncAggregate: lastValidated.SyncAggregate,
SignatureSlot: lastValidated.SignatureSlot,
}); err != nil {
log.Warn("Could not write optimistic lightclient update to db", "err", err)
}

if l.verbose {
log.Info("[LightClient] Validated Chain Segments",
"elapsed", time.Since(start), "from", updates[0].AttestedHeader.Slot-1,
"to", l.lastValidated.AttestedHeader.Slot)
"to", lastValidated.AttestedHeader.Slot)
}
prev, curr := l.chainTip.GetLastBlocks()
if prev == nil {
continue
}
// Skip if we went out of sync and weird network stuff happen
if prev.Slot != l.lastValidated.AttestedHeader.Slot {
if prev.Slot != lastValidated.AttestedHeader.Slot {
continue
}
// Validate update against block N-1
Expand All @@ -146,7 +179,7 @@ func (l *LightClient) Start() {
log.Warn("[LightClient] Could not retrive body root of block N-1", "err", err)
continue
}
if !bytes.Equal(prevRoot[:], l.lastValidated.AttestedHeader.BodyRoot[:]) {
if !bytes.Equal(prevRoot[:], lastValidated.AttestedHeader.BodyRoot[:]) {
log.Warn("[LightClient] Could validate block N-1")
continue
}
Expand Down
6 changes: 4 additions & 2 deletions cmd/lightclient/main.go
Expand Up @@ -18,6 +18,7 @@ import (
"fmt"
"os"

"github.com/ledgerwatch/erigon-lib/kv/memdb"
"github.com/ledgerwatch/log/v3"
"github.com/urfave/cli/v2"

Expand Down Expand Up @@ -50,6 +51,7 @@ func runLightClientNode(cliCtx *cli.Context) error {
log.Root().SetHandler(log.LvlFilterHandler(log.Lvl(lcCfg.LogLvl), log.StderrHandler))
log.Info("[LightClient]", "chain", cliCtx.String(flags.LightClientChain.Name))
log.Info("[LightClient] Running lightclient", "cfg", lcCfg)
db := memdb.New()
sentinel, err := service.StartSentinelService(&sentinel.SentinelConfig{
IpAddr: lcCfg.Addr,
Port: int(lcCfg.Port),
Expand All @@ -58,7 +60,7 @@ func runLightClientNode(cliCtx *cli.Context) error {
NetworkConfig: lcCfg.NetworkCfg,
BeaconConfig: lcCfg.BeaconCfg,
NoDiscovery: lcCfg.NoDiscovery,
}, &service.ServerConfig{Network: lcCfg.ServerProtocol, Addr: lcCfg.ServerAddr}, nil)
}, db, &service.ServerConfig{Network: lcCfg.ServerProtocol, Addr: lcCfg.ServerAddr}, nil)
if err != nil {
log.Error("Could not start sentinel", "err", err)
}
Expand All @@ -71,7 +73,7 @@ func runLightClientNode(cliCtx *cli.Context) error {
return err
}
log.Info("Finalized Checkpoint", "Epoch", bs.FinalizedCheckpoint.Epoch)
lc, err := lightclient.NewLightClient(ctx, lcCfg.GenesisCfg, lcCfg.BeaconCfg, nil, sentinel, 0, true)
lc, err := lightclient.NewLightClient(ctx, db, lcCfg.GenesisCfg, lcCfg.BeaconCfg, nil, sentinel, 0, true)
if err != nil {
log.Error("Could not make Lightclient", "err", err)
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/sentinel/main.go
Expand Up @@ -87,7 +87,7 @@ func runSentinelNode(cliCtx *cli.Context) error {
NetworkConfig: lcCfg.NetworkCfg,
BeaconConfig: lcCfg.BeaconCfg,
NoDiscovery: lcCfg.NoDiscovery,
}, &service.ServerConfig{Network: lcCfg.ServerProtocol, Addr: lcCfg.ServerAddr}, nil)
}, nil, &service.ServerConfig{Network: lcCfg.ServerProtocol, Addr: lcCfg.ServerAddr}, nil)
if err != nil {
log.Error("Could not start sentinel", "err", err)
return err
Expand Down
4 changes: 4 additions & 0 deletions cmd/sentinel/sentinel/sentinel.go
Expand Up @@ -20,6 +20,7 @@ import (
"net"
"strings"

"github.com/ledgerwatch/erigon-lib/kv"
"github.com/ledgerwatch/erigon/cl/cltypes"
"github.com/ledgerwatch/erigon/cl/fork"
"github.com/ledgerwatch/erigon/cmd/sentinel/sentinel/communication"
Expand All @@ -46,6 +47,7 @@ type Sentinel struct {
cfg *SentinelConfig
peers *peers.Peers
MetadataV2 *cltypes.MetadataV2
db kv.RoDB

discoverConfig discover.Config
pubsub *pubsub.PubSub
Expand Down Expand Up @@ -160,10 +162,12 @@ func (s *Sentinel) pubsubOptions() []pubsub.Option {
func New(
ctx context.Context,
cfg *SentinelConfig,
db kv.RoDB,
) (*Sentinel, error) {
s := &Sentinel{
ctx: ctx,
cfg: cfg,
db: db,
}

// Setup discovery
Expand Down
5 changes: 3 additions & 2 deletions cmd/sentinel/sentinel/service/start.go
Expand Up @@ -6,6 +6,7 @@ import (
"net"
"time"

"github.com/ledgerwatch/erigon-lib/kv"
"github.com/ledgerwatch/erigon/cl/rpc/consensusrpc"
"github.com/ledgerwatch/erigon/cmd/sentinel/sentinel"
"github.com/ledgerwatch/log/v3"
Expand All @@ -19,9 +20,9 @@ type ServerConfig struct {
Addr string
}

func StartSentinelService(cfg *sentinel.SentinelConfig, srvCfg *ServerConfig, creds credentials.TransportCredentials) (consensusrpc.SentinelClient, error) {
func StartSentinelService(cfg *sentinel.SentinelConfig, db kv.RoDB, srvCfg *ServerConfig, creds credentials.TransportCredentials) (consensusrpc.SentinelClient, error) {
ctx := context.Background()
sent, err := sentinel.New(context.Background(), cfg)
sent, err := sentinel.New(context.Background(), cfg, db)
if err != nil {
return nil, err
}
Expand Down
43 changes: 43 additions & 0 deletions core/rawdb/accessors_chain.go
Expand Up @@ -32,6 +32,7 @@ import (
libcommon "github.com/ledgerwatch/erigon-lib/common/cmp"
"github.com/ledgerwatch/erigon-lib/common/dbg"
"github.com/ledgerwatch/erigon-lib/kv"
"github.com/ledgerwatch/erigon/cl/cltypes"
"github.com/ledgerwatch/erigon/common"
"github.com/ledgerwatch/erigon/common/dbutils"
"github.com/ledgerwatch/erigon/core/types"
Expand Down Expand Up @@ -1869,3 +1870,45 @@ func ReadVerkleNode(tx kv.RwTx, root common.Hash) (verkle.VerkleNode, error) {
}
return verkle.ParseNode(encoded, 0, root[:])
}

func WriteLightClientUpdate(tx kv.RwTx, update *cltypes.LightClientUpdate) error {
key := make([]byte, 4)
binary.BigEndian.PutUint32(key, uint32(update.SignatureSlot/8192))

encoded, err := update.MarshalSSZ()
if err != nil {
return err
}
return tx.Put(kv.LightClientUpdates, key, encoded)
}

func WriteLightClientFinalityUpdate(tx kv.RwTx, update *cltypes.LightClientFinalityUpdate) error {
encoded, err := update.MarshalSSZ()
if err != nil {
return err
}
return tx.Put(kv.LightClient, kv.LightClientFinalityUpdate, encoded)
}

func WriteLightClientOptimisticUpdate(tx kv.RwTx, update *cltypes.LightClientOptimisticUpdate) error {
encoded, err := update.MarshalSSZ()
if err != nil {
return err
}
return tx.Put(kv.LightClient, kv.LightClientOptimisticUpdate, encoded)
}

func ReadLightClientUpdate(tx kv.RwTx, period uint32) (*cltypes.LightClientUpdate, error) {
key := make([]byte, 4)
binary.BigEndian.PutUint32(key, period)

encoded, err := tx.GetOne(kv.LightClientUpdates, key)
if err != nil {
return nil, err
}
update := &cltypes.LightClientUpdate{}
if err = update.UnmarshalSSZ(encoded); err != nil {
return nil, err
}
return update, nil
}
5 changes: 3 additions & 2 deletions eth/backend.go
Expand Up @@ -42,6 +42,7 @@ import (
prototypes "github.com/ledgerwatch/erigon-lib/gointerfaces/types"
"github.com/ledgerwatch/erigon-lib/kv"
"github.com/ledgerwatch/erigon-lib/kv/kvcache"
"github.com/ledgerwatch/erigon-lib/kv/memdb"
"github.com/ledgerwatch/erigon-lib/kv/remotedbserver"
libstate "github.com/ledgerwatch/erigon-lib/state"
txpool2 "github.com/ledgerwatch/erigon-lib/txpool"
Expand Down Expand Up @@ -509,12 +510,12 @@ func New(stack *node.Node, config *ethconfig.Config, logger log.Logger) (*Ethere
GenesisConfig: genesisCfg,
NetworkConfig: networkCfg,
BeaconConfig: beaconCfg,
}, &service.ServerConfig{Network: "tcp", Addr: fmt.Sprintf("%s:%d", config.SentinelAddr, config.SentinelPort)}, creds)
}, chainKv, &service.ServerConfig{Network: "tcp", Addr: fmt.Sprintf("%s:%d", config.SentinelAddr, config.SentinelPort)}, creds)
if err != nil {
return nil, err
}

lc, err := lightclient.NewLightClient(ctx, genesisCfg, beaconCfg, ethBackendRPC, client, currentBlockNumber, false)
lc, err := lightclient.NewLightClient(ctx, memdb.New(), genesisCfg, beaconCfg, ethBackendRPC, client, currentBlockNumber, false)
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Expand Up @@ -3,7 +3,7 @@ module github.com/ledgerwatch/erigon
go 1.18

require (
github.com/ledgerwatch/erigon-lib v0.0.0-20221114105902-10e842853bb4
github.com/ledgerwatch/erigon-lib v0.0.0-20221115124415-2e09a741f07b
github.com/ledgerwatch/erigon-snapshot v1.1.1-0.20221026024915-f6abfe5c120e
github.com/ledgerwatch/log/v3 v3.6.0
github.com/ledgerwatch/secp256k1 v1.0.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Expand Up @@ -558,8 +558,8 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v0.0.0-20170224010052-a616ab194758 h1:0D5M2HQSGD3PYPwICLl+/9oulQauOuETfgFvhBDffs0=
github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c=
github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8=
github.com/ledgerwatch/erigon-lib v0.0.0-20221114105902-10e842853bb4 h1:lUsHWLgwyCV+9G5/g6pML/bwWFwWsEz72PuqrUfm6kw=
github.com/ledgerwatch/erigon-lib v0.0.0-20221114105902-10e842853bb4/go.mod h1:NJybmPjoS9/TbvwTn3bJww3lrxxc7i8Ny+zq2EmDIpg=
github.com/ledgerwatch/erigon-lib v0.0.0-20221115124415-2e09a741f07b h1:LN3EjK0/Iw4o0b9trWFei96GVNeGmGMXJdYdB7m1N2U=
github.com/ledgerwatch/erigon-lib v0.0.0-20221115124415-2e09a741f07b/go.mod h1:NJybmPjoS9/TbvwTn3bJww3lrxxc7i8Ny+zq2EmDIpg=
github.com/ledgerwatch/erigon-snapshot v1.1.1-0.20221026024915-f6abfe5c120e h1:VRfm6Ylg0WTnjzFs7mU5qOyZGZTPhnlpwtMPrcD7n+U=
github.com/ledgerwatch/erigon-snapshot v1.1.1-0.20221026024915-f6abfe5c120e/go.mod h1:3AuPxZc85jkehh/HA9h8gabv5MSi3kb/ddtzBsTVJFo=
github.com/ledgerwatch/log/v3 v3.6.0 h1:JBUSK1epPyutUrz7KYDTcJtQLEHnehECRpKbM1ugy5M=
Expand Down

0 comments on commit eac2cfb

Please sign in to comment.