From ff786515b8cc56dae299326040dd1bd65c829fbf Mon Sep 17 00:00:00 2001 From: Callum Waters Date: Tue, 3 Mar 2020 13:00:06 +0100 Subject: [PATCH] lite: add helper functions for initiating the light client (#4486) * add new net client * hijack example test * lint fixes * reorganised file structure * renamed funcs and added documentation * implemented suggested changes * restored example tests * edited comments * Update lite2/setup.go Co-Authored-By: Bot from GolangCI <42910462+golangcibot@users.noreply.github.com> * Update lite2/client.go * lite cmds use HTTP client * better naming * Delete go.sum * Delete go.mod * restore go mod * restore go.sum * fix double import Co-authored-by: Anton Kaliaev Co-authored-by: Bot from GolangCI <42910462+golangcibot@users.noreply.github.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- cmd/tendermint/commands/lite.go | 44 +++++++------------ lite2/client.go | 7 +-- lite2/example_test.go | 2 +- lite2/setup.go | 77 +++++++++++++++++++++++++++++++++ 4 files changed, 95 insertions(+), 35 deletions(-) create mode 100644 lite2/setup.go diff --git a/cmd/tendermint/commands/lite.go b/cmd/tendermint/commands/lite.go index 2d1798920..447c6d92b 100644 --- a/cmd/tendermint/commands/lite.go +++ b/cmd/tendermint/commands/lite.go @@ -9,14 +9,12 @@ import ( "github.com/pkg/errors" "github.com/spf13/cobra" - amino "github.com/tendermint/go-amino" + "github.com/tendermint/go-amino" dbm "github.com/tendermint/tm-db" "github.com/tendermint/tendermint/libs/log" tmos "github.com/tendermint/tendermint/libs/os" lite "github.com/tendermint/tendermint/lite2" - "github.com/tendermint/tendermint/lite2/provider" - httpp "github.com/tendermint/tendermint/lite2/provider/http" lproxy "github.com/tendermint/tendermint/lite2/proxy" lrpc "github.com/tendermint/tendermint/lite2/rpc" dbs "github.com/tendermint/tendermint/lite2/store/db" @@ -54,9 +52,9 @@ lite cosmoshub-3 -p 52.57.29.196:26657 -w public-seed-node.cosmoshub.certus.one: var ( listenAddr string primaryAddr string + witnessAddrsJoined string chainID string home string - witnessesAddrs string maxOpenConnections int trustingPeriod time.Duration @@ -71,7 +69,7 @@ func init() { "Serve the proxy on the given address") LiteCmd.Flags().StringVarP(&primaryAddr, "primary", "p", "", "Connect to a Tendermint node at this address") - LiteCmd.Flags().StringVarP(&witnessesAddrs, "witnesses", "w", "", + LiteCmd.Flags().StringVarP(&witnessAddrsJoined, "witnesses", "w", "", "Tendermint nodes to cross-check the primary node, comma-separated") LiteCmd.Flags().StringVar(&home, "home-dir", ".tendermint-lite", "Specify the home directory") LiteCmd.Flags().IntVar( @@ -98,26 +96,10 @@ func runProxy(cmd *cobra.Command, args []string) error { logger = log.NewFilter(logger, option) chainID = args[0] + logger.Info("Creating client...", "chainID", chainID) - logger.Info("Creating HTTP client for primary...", "addr", primaryAddr) - rpcClient, err := rpcclient.NewHTTP(primaryAddr, "/websocket") - if err != nil { - return errors.Wrapf(err, "http client for %s", primaryAddr) - } - primary := httpp.NewWithClient(chainID, rpcClient) - - // TODO: use NewNetClient once we have it - addrs := strings.Split(witnessesAddrs, ",") - witnesses := make([]provider.Provider, len(addrs)) - for i, addr := range addrs { - p, err := httpp.New(chainID, addr) - if err != nil { - return errors.Wrapf(err, "http provider for %s", addr) - } - witnesses[i] = p - } + witnessesAddrs := strings.Split(witnessAddrsJoined, ",") - logger.Info("Creating client...", "chainID", chainID) db, err := dbm.NewGoLevelDB("lite-client-db", home) if err != nil { return err @@ -125,24 +107,24 @@ func runProxy(cmd *cobra.Command, args []string) error { var c *lite.Client if trustedHeight > 0 && len(trustedHash) > 0 { // fresh installation - c, err = lite.NewClient( + c, err = lite.NewHTTPClient( chainID, lite.TrustOptions{ Period: trustingPeriod, Height: trustedHeight, Hash: trustedHash, }, - primary, - witnesses, + primaryAddr, + witnessesAddrs, dbs.New(db, chainID), lite.Logger(logger), ) } else { // continue from latest state - c, err = lite.NewClientFromTrustedStore( + c, err = lite.NewHTTPClientFromTrustedStore( chainID, trustingPeriod, - primary, - witnesses, + primaryAddr, + witnessesAddrs, dbs.New(db, chainID), lite.Logger(logger), ) @@ -158,6 +140,10 @@ func runProxy(cmd *cobra.Command, args []string) error { } defer c.Stop() + rpcClient, err := rpcclient.NewHTTP(primaryAddr, "/websocket") + if err != nil { + return errors.Wrapf(err, "http client for %s", primaryAddr) + } p := lproxy.Proxy{ Addr: listenAddr, Config: &rpcserver.Config{MaxOpenConnections: maxOpenConnections}, diff --git a/lite2/client.go b/lite2/client.go index 5272f1b3a..d65ed8ddb 100644 --- a/lite2/client.go +++ b/lite2/client.go @@ -953,11 +953,8 @@ func (c *Client) autoUpdateRoutine() { } } -// Update attempts to advance the state making exponential steps (note: -// when SequentialVerification is being used, the client will still be -// downloading all intermediate headers). -// -// Exposed for testing. +// Update attempts to advance the state by downloading the latest header and +// comparing it with the existing one. func (c *Client) Update(now time.Time) error { lastTrustedHeight, err := c.LastTrustedHeight() if err != nil { diff --git a/lite2/example_test.go b/lite2/example_test.go index 65997f906..e6839386f 100644 --- a/lite2/example_test.go +++ b/lite2/example_test.go @@ -135,7 +135,7 @@ func ExampleClient_VerifyHeaderAtHeight() { Hash: header.Hash(), }, primary, - []provider.Provider{primary}, // TODO: primary should not be used here + []provider.Provider{primary}, // NOTE: primary should not be used here dbs.New(db, chainID), UpdatePeriod(0), // Logger(log.TestingLogger()), diff --git a/lite2/setup.go b/lite2/setup.go new file mode 100644 index 000000000..50a4a9d21 --- /dev/null +++ b/lite2/setup.go @@ -0,0 +1,77 @@ +package lite + +import ( + "time" + + "github.com/tendermint/tendermint/lite2/provider" + "github.com/tendermint/tendermint/lite2/provider/http" + "github.com/tendermint/tendermint/lite2/store" +) + +// NewHTTPClient initiates an instance of a lite client using HTTP addresses +// for both the primary provider and witnesses of the lite client. A trusted +// header and hash must be passed to initialize the client. +// +// See all Option(s) for the additional configuration. +// See NewClient. +func NewHTTPClient( + chainID string, + trustOptions TrustOptions, + primaryAddress string, + witnessesAddresses []string, + trustedStore store.Store, + options ...Option) (*Client, error) { + + providers, err := providersFromAddresses(append(witnessesAddresses, primaryAddress), chainID) + if err != nil { + return nil, err + } + + return NewClient( + chainID, + trustOptions, + providers[len(providers)-1], + providers[:len(providers)-1], + trustedStore, + options...) +} + +// NewHTTPClientFromTrustedStore initiates an instance of a lite client using +// HTTP addresses for both the primary provider and witnesses and uses a +// trusted store as the root of trust. +// +// See all Option(s) for the additional configuration. +// See NewClientFromTrustedStore. +func NewHTTPClientFromTrustedStore( + chainID string, + trustingPeriod time.Duration, + primaryAddress string, + witnessesAddresses []string, + trustedStore store.Store, + options ...Option) (*Client, error) { + + providers, err := providersFromAddresses(append(witnessesAddresses, primaryAddress), chainID) + if err != nil { + return nil, err + } + + return NewClientFromTrustedStore( + chainID, + trustingPeriod, + providers[len(providers)-1], + providers[:len(providers)-1], + trustedStore, + options...) +} + +func providersFromAddresses(addrs []string, chainID string) ([]provider.Provider, error) { + providers := make([]provider.Provider, len(addrs)) + for idx, address := range addrs { + p, err := http.New(chainID, address) + if err != nil { + return nil, err + } + providers[idx] = p + } + return providers, nil +}