Skip to content

Commit 9563c74

Browse files
Add fraud proof gossiping logic to light clients (cosmos#724)
Resolves rollkit/rollkit#673. --------- Co-authored-by: Manav Aggarwal <manavaggarwal1234@gmail.com>
1 parent b82de97 commit 9563c74

File tree

3 files changed

+108
-6
lines changed

3 files changed

+108
-6
lines changed

node/full.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,7 @@ func (n *FullNode) newHeaderValidator() p2p.GossipValidator {
369369
func (n *FullNode) newFraudProofValidator() p2p.GossipValidator {
370370
return func(fraudProofMsg *p2p.GossipMessage) bool {
371371
n.Logger.Debug("fraud proof received", "from", fraudProofMsg.From, "bytes", len(fraudProofMsg.Data))
372-
var fraudProof abci.FraudProof
372+
fraudProof := abci.FraudProof{}
373373
err := fraudProof.Unmarshal(fraudProofMsg.Data)
374374
if err != nil {
375375
n.Logger.Error("failed to deserialize fraud proof", "error", err)

node/light.go

+99-4
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,115 @@
11
package node
22

33
import (
4+
"context"
5+
6+
ds "github.com/ipfs/go-datastore"
7+
"github.com/libp2p/go-libp2p/core/crypto"
8+
abciclient "github.com/tendermint/tendermint/abci/client"
9+
abci "github.com/tendermint/tendermint/abci/types"
10+
"github.com/tendermint/tendermint/libs/log"
411
"github.com/tendermint/tendermint/libs/service"
512
rpcclient "github.com/tendermint/tendermint/rpc/client"
13+
tmtypes "github.com/tendermint/tendermint/types"
14+
15+
"github.com/rollkit/rollkit/config"
16+
"github.com/rollkit/rollkit/p2p"
17+
"github.com/rollkit/rollkit/store"
618
)
719

820
var _ Node = &LightNode{}
921

1022
type LightNode struct {
1123
service.BaseService
24+
25+
P2P *p2p.Client
26+
27+
app abciclient.Client
28+
29+
ctx context.Context
1230
}
1331

14-
func (n *LightNode) GetClient() rpcclient.Client {
15-
return NewLightClient(n)
32+
func (ln *LightNode) GetClient() rpcclient.Client {
33+
return NewLightClient(ln)
34+
}
35+
36+
func newLightNode(
37+
ctx context.Context,
38+
conf config.NodeConfig,
39+
p2pKey crypto.PrivKey,
40+
appClient abciclient.Client,
41+
genesis *tmtypes.GenesisDoc,
42+
logger log.Logger,
43+
) (*LightNode, error) {
44+
datastore, err := openDatastore(conf, logger)
45+
if err != nil {
46+
return nil, err
47+
}
48+
client, err := p2p.NewClient(conf.P2P, p2pKey, genesis.ChainID, datastore, logger.With("module", "p2p"))
49+
if err != nil {
50+
return nil, err
51+
}
52+
53+
node := &LightNode{
54+
P2P: client,
55+
app: appClient,
56+
ctx: ctx,
57+
}
58+
59+
node.P2P.SetTxValidator(node.falseValidator())
60+
node.P2P.SetHeaderValidator(node.falseValidator())
61+
node.P2P.SetFraudProofValidator(node.newFraudProofValidator())
62+
63+
node.BaseService = *service.NewBaseService(logger, "LightNode", node)
64+
65+
return node, nil
1666
}
1767

18-
func newLightNode() (Node, error) {
19-
return &LightNode{}, nil
68+
func openDatastore(conf config.NodeConfig, logger log.Logger) (ds.TxnDatastore, error) {
69+
if conf.RootDir == "" && conf.DBPath == "" { // this is used for testing
70+
logger.Info("WARNING: working in in-memory mode")
71+
return store.NewDefaultInMemoryKVStore()
72+
}
73+
return store.NewDefaultKVStore(conf.RootDir, conf.DBPath, "rollkit-light")
74+
}
75+
76+
func (ln *LightNode) OnStart() error {
77+
if err := ln.P2P.Start(ln.ctx); err != nil {
78+
return err
79+
}
80+
81+
return nil
82+
}
83+
84+
// Dummy validator that always returns a callback function with boolean `false`
85+
func (ln *LightNode) falseValidator() p2p.GossipValidator {
86+
return func(*p2p.GossipMessage) bool {
87+
return false
88+
}
89+
}
90+
91+
func (ln *LightNode) newFraudProofValidator() p2p.GossipValidator {
92+
return func(fraudProofMsg *p2p.GossipMessage) bool {
93+
ln.Logger.Info("fraud proof received", "from", fraudProofMsg.From, "bytes", len(fraudProofMsg.Data))
94+
fraudProof := abci.FraudProof{}
95+
err := fraudProof.Unmarshal(fraudProofMsg.Data)
96+
if err != nil {
97+
ln.Logger.Error("failed to deserialize fraud proof", "error", err)
98+
return false
99+
}
100+
101+
resp, err := ln.app.VerifyFraudProofSync(abci.RequestVerifyFraudProof{
102+
FraudProof: &fraudProof,
103+
ExpectedValidAppHash: fraudProof.ExpectedValidAppHash,
104+
})
105+
if err != nil {
106+
return false
107+
}
108+
109+
if resp.Success {
110+
panic("received valid fraud proof! halting light client")
111+
}
112+
113+
return false
114+
}
20115
}

node/node.go

+8-1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,13 @@ func NewNode(
4040
logger,
4141
)
4242
} else {
43-
return newLightNode()
43+
return newLightNode(
44+
ctx,
45+
conf,
46+
p2pKey,
47+
appClient,
48+
genesis,
49+
logger,
50+
)
4451
}
4552
}

0 commit comments

Comments
 (0)