mirror of
https://github.com/tendermint/tendermint.git
synced 2026-01-03 11:45:18 +00:00
cmd/lite: switch to new lite2 package (#4300)
* cmd/lite: switch to new lite2 package * update changelog * shorten the trusting period explanation
This commit is contained in:
@@ -17,6 +17,11 @@ information in `Block#LastCommit`. `Commit` now mainly consists of a signature
|
||||
and a validator address plus a timestamp. Note we may remove the validator
|
||||
address & timestamp fields in the future (see ADR-25).
|
||||
|
||||
`lite2` package has been added to solve `lite` issues and introduce weak
|
||||
subjectivity interface
|
||||
https://github.com/tendermint/spec/blob/master/spec/consensus/light-client.md).
|
||||
`lite` package is now deprecated and will be removed in v0.34 release.
|
||||
|
||||
Special thanks to external contributors on this release:
|
||||
@erikgrinaker, @PSalant726, @gchaincl, @gregzaitsev, @princesinha19, @Stumble
|
||||
|
||||
@@ -60,6 +65,9 @@ program](https://hackerone.com/tendermint).
|
||||
- You will have to generate a new config for your Tendermint node(s)
|
||||
- [genesis] \#2565 Add `consensus_params.evidence.max_age_duration`. Rename
|
||||
`consensus_params.evidence.max_age` to `max_age_num_blocks`.
|
||||
- [cli] \#1771 `tendermint lite` now uses new light client package (`lite2`)
|
||||
and has 3 more flags: `--trusting-period`, `--trusted-height` and
|
||||
`--trusted-hash`
|
||||
|
||||
- Apps
|
||||
|
||||
@@ -124,6 +132,7 @@ program](https://hackerone.com/tendermint).
|
||||
- `consensus_validator_missed_blocks`: total amount of missed blocks for a validator
|
||||
as gauges in prometheus for validator specific metrics
|
||||
- [rpc/lib] [\#4248](https://github.com/tendermint/tendermint/issues/4248) RPC client basic authentication support (@greg-szabo)
|
||||
- [lite2] \#1771 Light client with weak subjectivity
|
||||
|
||||
### IMPROVEMENTS:
|
||||
|
||||
|
||||
@@ -1,15 +1,23 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
amino "github.com/tendermint/go-amino"
|
||||
dbm "github.com/tendermint/tm-db"
|
||||
|
||||
tmos "github.com/tendermint/tendermint/libs/os"
|
||||
"github.com/tendermint/tendermint/lite/proxy"
|
||||
lite "github.com/tendermint/tendermint/lite2"
|
||||
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"
|
||||
rpcclient "github.com/tendermint/tendermint/rpc/client"
|
||||
rpcserver "github.com/tendermint/tendermint/rpc/lib/server"
|
||||
)
|
||||
|
||||
// LiteCmd represents the base command when called without any subcommands
|
||||
@@ -32,7 +40,10 @@ var (
|
||||
chainID string
|
||||
home string
|
||||
maxOpenConnections int
|
||||
cacheSize int
|
||||
|
||||
trustingPeriod time.Duration
|
||||
trustedHeight int64
|
||||
trustedHash []byte
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -45,60 +56,59 @@ func init() {
|
||||
"max-open-connections",
|
||||
900,
|
||||
"Maximum number of simultaneous connections (including WebSocket).")
|
||||
LiteCmd.Flags().IntVar(&cacheSize, "cache-size", 10, "Specify the memory trust store cache size")
|
||||
}
|
||||
|
||||
func EnsureAddrHasSchemeOrDefaultToTCP(addr string) (string, error) {
|
||||
u, err := url.Parse(addr)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
switch u.Scheme {
|
||||
case "tcp", "unix":
|
||||
case "":
|
||||
u.Scheme = "tcp"
|
||||
default:
|
||||
return "", fmt.Errorf("unknown scheme %q, use either tcp or unix", u.Scheme)
|
||||
}
|
||||
return u.String(), nil
|
||||
LiteCmd.Flags().DurationVar(&trustingPeriod, "trusting-period", 168*time.Hour, "Trusting period. Should be significantly less than the unbonding period")
|
||||
LiteCmd.Flags().Int64Var(&trustedHeight, "trusted-height", 1, "Trusted header's height")
|
||||
LiteCmd.Flags().BytesHexVar(&trustedHash, "trusted-hash", []byte{}, "Trusted header's hash")
|
||||
}
|
||||
|
||||
func runProxy(cmd *cobra.Command, args []string) error {
|
||||
// Stop upon receiving SIGTERM or CTRL-C.
|
||||
tmos.TrapSignal(logger, func() {
|
||||
// TODO: close up shop
|
||||
})
|
||||
|
||||
nodeAddr, err := EnsureAddrHasSchemeOrDefaultToTCP(nodeAddr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
listenAddr, err := EnsureAddrHasSchemeOrDefaultToTCP(listenAddr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
liteLogger := logger.With("module", "lite")
|
||||
|
||||
logger.Info("Connecting to Tendermint node...")
|
||||
// First, connect a client
|
||||
logger.Info("Connecting to source HTTP client...")
|
||||
node, err := rpcclient.NewHTTP(nodeAddr, "/websocket")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "new HTTP client")
|
||||
}
|
||||
|
||||
logger.Info("Constructing Verifier...")
|
||||
cert, err := proxy.NewVerifier(chainID, home, node, logger, cacheSize)
|
||||
logger.Info("Creating client...")
|
||||
db, err := dbm.NewGoLevelDB("lite-client-db", home)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "constructing Verifier")
|
||||
return err
|
||||
}
|
||||
cert.SetLogger(logger)
|
||||
sc := proxy.SecureClient(node, cert)
|
||||
c, err := lite.NewClient(
|
||||
chainID,
|
||||
lite.TrustOptions{
|
||||
Period: trustingPeriod,
|
||||
Height: trustedHeight,
|
||||
Hash: trustedHash,
|
||||
},
|
||||
httpp.NewWithClient(chainID, node),
|
||||
dbs.New(db, chainID),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.SetLogger(liteLogger)
|
||||
|
||||
p := lproxy.Proxy{
|
||||
Addr: listenAddr,
|
||||
Config: &rpcserver.Config{MaxOpenConnections: maxOpenConnections},
|
||||
Codec: amino.NewCodec(),
|
||||
Client: lrpc.NewClient(node, c),
|
||||
Logger: liteLogger,
|
||||
}
|
||||
// Stop upon receiving SIGTERM or CTRL-C.
|
||||
tmos.TrapSignal(liteLogger, func() {
|
||||
p.Listener.Close()
|
||||
})
|
||||
|
||||
logger.Info("Starting proxy...")
|
||||
err = proxy.StartProxy(sc, listenAddr, logger, maxOpenConnections)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "starting proxy")
|
||||
if err := p.ListenAndServe(); err != http.ErrServerClosed {
|
||||
// Error starting or closing listener:
|
||||
logger.Error("proxy ListenAndServe", "err", err)
|
||||
}
|
||||
|
||||
// Run forever
|
||||
select {}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
/*
|
||||
Package lite is deprecated and will be removed in v0.34!
|
||||
|
||||
Package lite allows you to securely validate headers without a full node.
|
||||
|
||||
This library pulls together all the crypto and algorithms, so given a
|
||||
|
||||
@@ -214,6 +214,8 @@ func (c *Client) restoreTrustedHeaderAndNextVals() error {
|
||||
|
||||
c.trustedHeader = trustedHeader
|
||||
c.trustedNextVals = trustedNextVals
|
||||
|
||||
c.logger.Debug("Restored trusted header and next vals", lastHeight)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -249,6 +251,10 @@ func (c *Client) checkTrustedHeaderUsingOptions(options TrustOptions) error {
|
||||
case options.Height == c.trustedHeader.Height:
|
||||
primaryHash = options.Hash
|
||||
case options.Height < c.trustedHeader.Height:
|
||||
c.logger.Info("Client initialized with old header (trusted is more recent)",
|
||||
"old", options.Height,
|
||||
"trusted", c.trustedHeader.Height)
|
||||
|
||||
action := fmt.Sprintf(
|
||||
"Rollback to %d (%X)? Note this will remove newer headers up to %d (%X)",
|
||||
options.Height, options.Hash,
|
||||
@@ -258,6 +264,9 @@ func (c *Client) checkTrustedHeaderUsingOptions(options TrustOptions) error {
|
||||
c.cleanup(options.Height + 1)
|
||||
// set c.trustedHeader to one at options.Height
|
||||
c.restoreTrustedHeaderAndNextVals()
|
||||
|
||||
c.logger.Info("Rolled back to older header (newer headers were removed)",
|
||||
"old", options.Height)
|
||||
} else {
|
||||
return errors.New("rollback aborted")
|
||||
}
|
||||
@@ -266,8 +275,8 @@ func (c *Client) checkTrustedHeaderUsingOptions(options TrustOptions) error {
|
||||
}
|
||||
|
||||
if !bytes.Equal(primaryHash, c.trustedHeader.Hash()) {
|
||||
c.logger.Info("Prev. trusted header's hash %X doesn't match hash %X from primary provider",
|
||||
c.trustedHeader.Hash(), primaryHash)
|
||||
c.logger.Info("Prev. trusted header's hash (h1) doesn't match hash from primary provider (h2)",
|
||||
"h1", c.trustedHeader.Hash(), "h1", primaryHash)
|
||||
|
||||
action := fmt.Sprintf(
|
||||
"Prev. trusted header's hash %X doesn't match hash %X from primary provider. Remove all the stored headers?",
|
||||
@@ -398,6 +407,8 @@ func (c *Client) ChainID() string {
|
||||
//
|
||||
// If the trusted header is more recent than one here, an error is returned.
|
||||
func (c *Client) VerifyHeaderAtHeight(height int64, now time.Time) (*types.SignedHeader, error) {
|
||||
c.logger.Info("VerifyHeaderAtHeight", "height", height)
|
||||
|
||||
if c.trustedHeader.Height >= height {
|
||||
return nil, errors.Errorf("header at more recent height #%d exists", c.trustedHeader.Height)
|
||||
}
|
||||
@@ -425,6 +436,8 @@ func (c *Client) VerifyHeaderAtHeight(height int64, now time.Time) (*types.Signe
|
||||
//
|
||||
// If the trusted header is more recent than one here, an error is returned.
|
||||
func (c *Client) VerifyHeader(newHeader *types.SignedHeader, newVals *types.ValidatorSet, now time.Time) error {
|
||||
c.logger.Info("VerifyHeader", "height", newHeader.Hash(), "newVals", newVals.Hash())
|
||||
|
||||
if c.trustedHeader.Height >= newHeader.Height {
|
||||
return errors.Errorf("header at more recent height #%d exists", c.trustedHeader.Height)
|
||||
}
|
||||
@@ -458,6 +471,7 @@ func (c *Client) VerifyHeader(newHeader *types.SignedHeader, newVals *types.Vali
|
||||
|
||||
// Cleanup removes all the data (headers and validator sets) stored.
|
||||
func (c *Client) Cleanup() error {
|
||||
c.logger.Info("Cleanup everything")
|
||||
return c.cleanup(0)
|
||||
}
|
||||
|
||||
@@ -507,6 +521,11 @@ func (c *Client) sequence(newHeader *types.SignedHeader, newVals *types.Validato
|
||||
return errors.Wrapf(err, "failed to obtain the header #%d", height)
|
||||
}
|
||||
|
||||
c.logger.Debug("Verify newHeader against lastHeader",
|
||||
"lastHeight", c.trustedHeader.Height,
|
||||
"lastHash", c.trustedHeader.Hash(),
|
||||
"newHeight", interimHeader.Height,
|
||||
"newHash", interimHeader.Hash())
|
||||
err = Verify(c.chainID, c.trustedHeader, c.trustedNextVals, interimHeader, c.trustedNextVals,
|
||||
c.trustingPeriod, now, c.trustLevel)
|
||||
if err != nil {
|
||||
@@ -540,6 +559,11 @@ func (c *Client) bisection(
|
||||
newVals *types.ValidatorSet,
|
||||
now time.Time) error {
|
||||
|
||||
c.logger.Debug("Verify newHeader against lastHeader",
|
||||
"lastHeight", lastHeader.Height,
|
||||
"lastHash", lastHeader.Hash(),
|
||||
"newHeight", newHeader.Height,
|
||||
"newHash", newHeader.Hash())
|
||||
err := Verify(c.chainID, lastHeader, lastVals, newHeader, newVals, c.trustingPeriod, now, c.trustLevel)
|
||||
switch err.(type) {
|
||||
case nil:
|
||||
|
||||
@@ -18,11 +18,12 @@ import (
|
||||
|
||||
// A Proxy defines parameters for running an HTTP server proxy.
|
||||
type Proxy struct {
|
||||
Addr string // TCP address to listen on, ":http" if empty
|
||||
Config *rpcserver.Config
|
||||
Codec *amino.Codec
|
||||
Client *lrpc.Client
|
||||
Logger log.Logger
|
||||
Addr string // TCP address to listen on, ":http" if empty
|
||||
Config *rpcserver.Config
|
||||
Codec *amino.Codec
|
||||
Client *lrpc.Client
|
||||
Logger log.Logger
|
||||
Listener net.Listener
|
||||
}
|
||||
|
||||
// ListenAndServe configures the rpcserver.WebsocketManager, sets up the RPC
|
||||
@@ -34,6 +35,7 @@ func (p *Proxy) ListenAndServe() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.Listener = listener
|
||||
|
||||
return rpcserver.StartHTTPServer(
|
||||
listener,
|
||||
@@ -51,6 +53,7 @@ func (p *Proxy) ListenAndServeTLS(certFile, keyFile string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.Listener = listener
|
||||
|
||||
return rpcserver.StartHTTPAndTLSServer(
|
||||
listener,
|
||||
|
||||
@@ -19,7 +19,7 @@ var (
|
||||
// Verify verifies the new header (h2) against the old header (h1). It ensures that:
|
||||
//
|
||||
// a) h1 can still be trusted (if not, ErrOldHeaderExpired is returned);
|
||||
// b) h2 is valid (if not, ErrInvalidNewHeader is returned);
|
||||
// b) h2 is valid;
|
||||
// c) either h2.ValidatorsHash equals h1NextVals.Hash()
|
||||
// OR trustLevel ([1/3, 1]) of last trusted validators (h1NextVals) signed
|
||||
// correctly (if not, ErrNewValSetCantBeTrusted is returned);
|
||||
|
||||
Reference in New Issue
Block a user