From 7083a62a82f18203460742072e045a8767337d35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Zdyba=C5=82?= Date: Fri, 13 Jan 2023 10:13:00 +0100 Subject: [PATCH 1/3] Light client fraud proofs --- node/light.go | 89 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 87 insertions(+), 2 deletions(-) diff --git a/node/light.go b/node/light.go index a8ce6ad395..928cd1e836 100644 --- a/node/light.go +++ b/node/light.go @@ -1,18 +1,103 @@ package node import ( + "context" + abci "github.com/tendermint/tendermint/abci/types" + + "github.com/libp2p/go-libp2p/core/crypto" + abciclient "github.com/tendermint/tendermint/abci/client" + "github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/libs/service" rpcclient "github.com/tendermint/tendermint/rpc/client" + tmtypes "github.com/tendermint/tendermint/types" + + "github.com/celestiaorg/rollmint/config" + "github.com/celestiaorg/rollmint/p2p" ) var _ Node = &LightNode{} type LightNode struct { service.BaseService + + P2P *p2p.Client + + app abciclient.Client + + ctx context.Context } -func (n *LightNode) GetClient() rpcclient.Client { - return NewLightClient(n) +func (ln *LightNode) GetClient() rpcclient.Client { + return NewLightClient(ln) +} + +func newLightNode( + ctx context.Context, + conf config.NodeConfig, + p2pKey crypto.PrivKey, + appClient abciclient.Client, + genesis *tmtypes.GenesisDoc, + logger log.Logger, +) (*LightNode, error) { + client, err := p2p.NewClient(conf.P2P, p2pKey, genesis.ChainID, logger.With("module", "p2p")) + if err != nil { + return nil, err + } + + node := &LightNode{ + P2P: client, + app: appClient, + ctx: ctx, + } + + node.P2P.SetTxValidator(node.falseValidator()) + node.P2P.SetHeaderValidator(node.falseValidator()) + node.P2P.SetCommitValidator(node.falseValidator()) + node.P2P.SetFraudProofValidator(node.newFraudProofValidator()) + + node.BaseService = *service.NewBaseService(logger, "LightNode", node) + + return node, nil +} + +func (ln *LightNode) OnStart() error { + if err := ln.P2P.Start(ln.ctx); err != nil { + return err + } + + return nil +} + +func (ln *LightNode) falseValidator() p2p.GossipValidator { + return func(*p2p.GossipMessage) bool { + return false + } +} + +func (ln *LightNode) newFraudProofValidator() p2p.GossipValidator { + return func(fraudProofMsg *p2p.GossipMessage) bool { + ln.Logger.Info("fraud proof received", "from", fraudProofMsg.From, "bytes", len(fraudProofMsg.Data)) + var fraudProof abci.FraudProof + err := fraudProof.Unmarshal(fraudProofMsg.Data) + if err != nil { + ln.Logger.Error("failed to deserialize fraud proof", "error", err) + return false + } + + resp, err := ln.app.VerifyFraudProofSync(abci.RequestVerifyFraudProof{ + FraudProof: &fraudProof, + ExpectedValidAppHash: fraudProof.ExpectedValidAppHash, + }) + if err != nil { + return false + } + + if resp.Success { + panic("received valid fraud proof! halting light client") + } + + return false + } } func newLightNode() (Node, error) { From 8b300ea2361d8305c20d6caf26ce9551e0ca4783 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Zdyba=C5=82?= Date: Wed, 1 Feb 2023 22:56:44 +0100 Subject: [PATCH 2/3] fix code after rebasing :xa --- node/light.go | 27 ++++++++++++++++++--------- node/node.go | 9 ++++++++- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/node/light.go b/node/light.go index 928cd1e836..ae134aef6b 100644 --- a/node/light.go +++ b/node/light.go @@ -2,17 +2,19 @@ package node import ( "context" - abci "github.com/tendermint/tendermint/abci/types" + ds "github.com/ipfs/go-datastore" "github.com/libp2p/go-libp2p/core/crypto" abciclient "github.com/tendermint/tendermint/abci/client" + abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/libs/service" rpcclient "github.com/tendermint/tendermint/rpc/client" tmtypes "github.com/tendermint/tendermint/types" - "github.com/celestiaorg/rollmint/config" - "github.com/celestiaorg/rollmint/p2p" + "github.com/rollkit/rollkit/config" + "github.com/rollkit/rollkit/p2p" + "github.com/rollkit/rollkit/store" ) var _ Node = &LightNode{} @@ -39,7 +41,11 @@ func newLightNode( genesis *tmtypes.GenesisDoc, logger log.Logger, ) (*LightNode, error) { - client, err := p2p.NewClient(conf.P2P, p2pKey, genesis.ChainID, logger.With("module", "p2p")) + datastore, err := openDatastore(conf, logger) + if err != nil { + return nil, err + } + client, err := p2p.NewClient(conf.P2P, p2pKey, genesis.ChainID, datastore, logger.With("module", "p2p")) if err != nil { return nil, err } @@ -52,7 +58,6 @@ func newLightNode( node.P2P.SetTxValidator(node.falseValidator()) node.P2P.SetHeaderValidator(node.falseValidator()) - node.P2P.SetCommitValidator(node.falseValidator()) node.P2P.SetFraudProofValidator(node.newFraudProofValidator()) node.BaseService = *service.NewBaseService(logger, "LightNode", node) @@ -60,6 +65,14 @@ func newLightNode( return node, nil } +func openDatastore(conf config.NodeConfig, logger log.Logger) (ds.TxnDatastore, error) { + if conf.RootDir == "" && conf.DBPath == "" { // this is used for testing + logger.Info("WARNING: working in in-memory mode") + return store.NewDefaultInMemoryKVStore() + } + return store.NewDefaultKVStore(conf.RootDir, conf.DBPath, "rollkit-light") +} + func (ln *LightNode) OnStart() error { if err := ln.P2P.Start(ln.ctx); err != nil { return err @@ -99,7 +112,3 @@ func (ln *LightNode) newFraudProofValidator() p2p.GossipValidator { return false } } - -func newLightNode() (Node, error) { - return &LightNode{}, nil -} diff --git a/node/node.go b/node/node.go index dc6aff3193..2960d5b776 100644 --- a/node/node.go +++ b/node/node.go @@ -40,6 +40,13 @@ func NewNode( logger, ) } else { - return newLightNode() + return newLightNode( + ctx, + conf, + p2pKey, + appClient, + genesis, + logger, + ) } } From bf2938850421f30d68049a286528ce05fe166629 Mon Sep 17 00:00:00 2001 From: Manav Aggarwal Date: Thu, 2 Feb 2023 20:06:15 -0500 Subject: [PATCH 3/3] Suggest changes --- node/full.go | 2 +- node/light.go | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/node/full.go b/node/full.go index d97d477243..5a6dd0601f 100644 --- a/node/full.go +++ b/node/full.go @@ -369,7 +369,7 @@ func (n *FullNode) newHeaderValidator() p2p.GossipValidator { func (n *FullNode) newFraudProofValidator() p2p.GossipValidator { return func(fraudProofMsg *p2p.GossipMessage) bool { n.Logger.Debug("fraud proof received", "from", fraudProofMsg.From, "bytes", len(fraudProofMsg.Data)) - var fraudProof abci.FraudProof + fraudProof := abci.FraudProof{} err := fraudProof.Unmarshal(fraudProofMsg.Data) if err != nil { n.Logger.Error("failed to deserialize fraud proof", "error", err) diff --git a/node/light.go b/node/light.go index ae134aef6b..a95cacb28e 100644 --- a/node/light.go +++ b/node/light.go @@ -81,6 +81,7 @@ func (ln *LightNode) OnStart() error { return nil } +// Dummy validator that always returns a callback function with boolean `false` func (ln *LightNode) falseValidator() p2p.GossipValidator { return func(*p2p.GossipMessage) bool { return false @@ -90,7 +91,7 @@ func (ln *LightNode) falseValidator() p2p.GossipValidator { func (ln *LightNode) newFraudProofValidator() p2p.GossipValidator { return func(fraudProofMsg *p2p.GossipMessage) bool { ln.Logger.Info("fraud proof received", "from", fraudProofMsg.From, "bytes", len(fraudProofMsg.Data)) - var fraudProof abci.FraudProof + fraudProof := abci.FraudProof{} err := fraudProof.Unmarshal(fraudProofMsg.Data) if err != nil { ln.Logger.Error("failed to deserialize fraud proof", "error", err)