Merge pull request #265 from cosmos/feature/reorg-light-client
Reorg light client
This commit is contained in:
commit
8f9caa8907
|
@ -1,30 +1,32 @@
|
|||
package seeds
|
||||
package commits
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"github.com/tendermint/light-client/certifiers/files"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/commands"
|
||||
)
|
||||
|
||||
var exportCmd = &cobra.Command{
|
||||
Use: "export <file>",
|
||||
Short: "Export selected seeds to given file",
|
||||
Long: `Exports the most recent seed to a binary file.
|
||||
Short: "Export selected commits to given file",
|
||||
Long: `Exports the most recent commit to a binary file.
|
||||
If desired, you can select by an older height or validator hash.
|
||||
`,
|
||||
RunE: commands.RequireInit(exportSeed),
|
||||
RunE: commands.RequireInit(exportCommit),
|
||||
SilenceUsage: true,
|
||||
}
|
||||
|
||||
func init() {
|
||||
exportCmd.Flags().Int(heightFlag, 0, "Show the seed with closest height to this")
|
||||
exportCmd.Flags().String(hashFlag, "", "Show the seed matching the validator hash")
|
||||
exportCmd.Flags().Int(heightFlag, 0, "Show the commit with closest height to this")
|
||||
exportCmd.Flags().String(hashFlag, "", "Show the commit matching the validator hash")
|
||||
RootCmd.AddCommand(exportCmd)
|
||||
}
|
||||
|
||||
func exportSeed(cmd *cobra.Command, args []string) error {
|
||||
func exportCommit(cmd *cobra.Command, args []string) error {
|
||||
if len(args) != 1 || len(args[0]) == 0 {
|
||||
return errors.New("You must provide a filepath to output")
|
||||
}
|
||||
|
@ -34,11 +36,11 @@ func exportSeed(cmd *cobra.Command, args []string) error {
|
|||
trust, _ := commands.GetProviders()
|
||||
h := viper.GetInt(heightFlag)
|
||||
hash := viper.GetString(hashFlag)
|
||||
seed, err := loadSeed(trust, h, hash, "")
|
||||
fc, err := loadCommit(trust, h, hash, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// now get the output file and write it
|
||||
return seed.WriteJSON(path)
|
||||
return files.SaveFullCommitJSON(fc, path)
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package seeds
|
||||
package commits
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
@ -7,7 +7,7 @@ import (
|
|||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"github.com/tendermint/light-client/certifiers"
|
||||
"github.com/tendermint/light-client/certifiers/files"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/commands"
|
||||
)
|
||||
|
@ -18,9 +18,9 @@ const (
|
|||
|
||||
var importCmd = &cobra.Command{
|
||||
Use: "import <file>",
|
||||
Short: "Imports a new seed from the given file",
|
||||
Long: `Validate this file and update to the given seed if secure.`,
|
||||
RunE: commands.RequireInit(importSeed),
|
||||
Short: "Imports a new commit from the given file",
|
||||
Long: `Validate this file and update to the given commit if secure.`,
|
||||
RunE: commands.RequireInit(importCommit),
|
||||
SilenceUsage: true,
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,7 @@ func init() {
|
|||
RootCmd.AddCommand(importCmd)
|
||||
}
|
||||
|
||||
func importSeed(cmd *cobra.Command, args []string) error {
|
||||
func importCommit(cmd *cobra.Command, args []string) error {
|
||||
if len(args) != 1 || len(args[0]) == 0 {
|
||||
return errors.New("You must provide an input file")
|
||||
}
|
||||
|
@ -42,18 +42,18 @@ func importSeed(cmd *cobra.Command, args []string) error {
|
|||
|
||||
// parse the input file
|
||||
path := args[0]
|
||||
seed, err := certifiers.LoadSeedJSON(path)
|
||||
fc, err := files.LoadFullCommitJSON(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// just do simple checks in --dry-run
|
||||
if viper.GetBool(dryFlag) {
|
||||
fmt.Printf("Testing seed %d/%X\n", seed.Height(), seed.Hash())
|
||||
err = seed.ValidateBasic(cert.ChainID())
|
||||
fmt.Printf("Testing commit %d/%X\n", fc.Height(), fc.ValidatorsHash())
|
||||
err = fc.ValidateBasic(cert.ChainID())
|
||||
} else {
|
||||
fmt.Printf("Importing seed %d/%X\n", seed.Height(), seed.Hash())
|
||||
err = cert.Update(seed.Checkpoint, seed.Validators)
|
||||
fmt.Printf("Importing commit %d/%X\n", fc.Height(), fc.ValidatorsHash())
|
||||
err = cert.Update(fc)
|
||||
}
|
||||
return err
|
||||
}
|
|
@ -1,15 +1,15 @@
|
|||
package seeds
|
||||
package commits
|
||||
|
||||
import "github.com/spf13/cobra"
|
||||
|
||||
// RootCmd represents the base command when called without any subcommands
|
||||
var RootCmd = &cobra.Command{
|
||||
Use: "seeds",
|
||||
Short: "Verify seeds from your local store",
|
||||
Long: `Seeds allows you to inspect and update the validator set for the chain.
|
||||
Use: "commits",
|
||||
Short: "Verify commits from your local store",
|
||||
Long: `Commits allows you to inspect and update the validator set for the chain.
|
||||
|
||||
Since all security in a PoS system is based on having the correct validator
|
||||
set, it is important to inspect the seeds to maintain the security, which
|
||||
set, it is important to inspect the commits to maintain the security, which
|
||||
is used to verify all header and merkle proofs.
|
||||
`,
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package seeds
|
||||
package commits
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
|
@ -9,6 +9,7 @@ import (
|
|||
"github.com/spf13/viper"
|
||||
|
||||
"github.com/tendermint/light-client/certifiers"
|
||||
"github.com/tendermint/light-client/certifiers/files"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/commands"
|
||||
)
|
||||
|
@ -21,53 +22,53 @@ const (
|
|||
|
||||
var showCmd = &cobra.Command{
|
||||
Use: "show",
|
||||
Short: "Show the details of one selected seed",
|
||||
Short: "Show the details of one selected commit",
|
||||
Long: `Shows the most recent downloaded key by default.
|
||||
If desired, you can select by height, validator hash, or a file.
|
||||
`,
|
||||
RunE: commands.RequireInit(showSeed),
|
||||
RunE: commands.RequireInit(showCommit),
|
||||
SilenceUsage: true,
|
||||
}
|
||||
|
||||
func init() {
|
||||
showCmd.Flags().Int(heightFlag, 0, "Show the seed with closest height to this")
|
||||
showCmd.Flags().String(hashFlag, "", "Show the seed matching the validator hash")
|
||||
showCmd.Flags().String(fileFlag, "", "Show the seed stored in the given file")
|
||||
showCmd.Flags().Int(heightFlag, 0, "Show the commit with closest height to this")
|
||||
showCmd.Flags().String(hashFlag, "", "Show the commit matching the validator hash")
|
||||
showCmd.Flags().String(fileFlag, "", "Show the commit stored in the given file")
|
||||
RootCmd.AddCommand(showCmd)
|
||||
}
|
||||
|
||||
func loadSeed(p certifiers.Provider, h int, hash, file string) (seed certifiers.Seed, err error) {
|
||||
// load the seed from the proper place
|
||||
func loadCommit(p certifiers.Provider, h int, hash, file string) (fc certifiers.FullCommit, err error) {
|
||||
// load the commit from the proper place
|
||||
if h != 0 {
|
||||
seed, err = p.GetByHeight(h)
|
||||
fc, err = p.GetByHeight(h)
|
||||
} else if hash != "" {
|
||||
var vhash []byte
|
||||
vhash, err = hex.DecodeString(hash)
|
||||
if err == nil {
|
||||
seed, err = p.GetByHash(vhash)
|
||||
fc, err = p.GetByHash(vhash)
|
||||
}
|
||||
} else if file != "" {
|
||||
seed, err = certifiers.LoadSeedJSON(file)
|
||||
fc, err = files.LoadFullCommitJSON(file)
|
||||
} else {
|
||||
// default is latest seed
|
||||
seed, err = certifiers.LatestSeed(p)
|
||||
// default is latest commit
|
||||
fc, err = p.LatestCommit()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func showSeed(cmd *cobra.Command, args []string) error {
|
||||
func showCommit(cmd *cobra.Command, args []string) error {
|
||||
trust, _ := commands.GetProviders()
|
||||
|
||||
h := viper.GetInt(heightFlag)
|
||||
hash := viper.GetString(hashFlag)
|
||||
file := viper.GetString(fileFlag)
|
||||
seed, err := loadSeed(trust, h, hash, file)
|
||||
fc, err := loadCommit(trust, h, hash, file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// now render it!
|
||||
data, err := json.MarshalIndent(seed, "", " ")
|
||||
data, err := json.MarshalIndent(fc, "", " ")
|
||||
fmt.Println(string(data))
|
||||
return err
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package seeds
|
||||
package commits
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
@ -13,8 +13,8 @@ import (
|
|||
|
||||
var updateCmd = &cobra.Command{
|
||||
Use: "update",
|
||||
Short: "Update seed to current height if possible",
|
||||
RunE: commands.RequireInit(updateSeed),
|
||||
Short: "Update commit to current height if possible",
|
||||
RunE: commands.RequireInit(updateCommit),
|
||||
SilenceUsage: true,
|
||||
}
|
||||
|
||||
|
@ -23,27 +23,27 @@ func init() {
|
|||
RootCmd.AddCommand(updateCmd)
|
||||
}
|
||||
|
||||
func updateSeed(cmd *cobra.Command, args []string) error {
|
||||
func updateCommit(cmd *cobra.Command, args []string) error {
|
||||
cert, err := commands.GetCertifier()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
h := viper.GetInt(heightFlag)
|
||||
var seed certifiers.Seed
|
||||
var fc certifiers.FullCommit
|
||||
if h <= 0 {
|
||||
// get the lastest from our source
|
||||
seed, err = certifiers.LatestSeed(cert.SeedSource)
|
||||
fc, err = cert.Source.LatestCommit()
|
||||
} else {
|
||||
seed, err = cert.SeedSource.GetByHeight(h)
|
||||
fc, err = cert.Source.GetByHeight(h)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// let the certifier do it's magic to update....
|
||||
fmt.Printf("Trying to update to height: %d...\n", seed.Height())
|
||||
err = cert.Update(seed.Checkpoint, seed.Validators)
|
||||
fmt.Printf("Trying to update to height: %d...\n", fc.Height())
|
||||
err = cert.Update(fc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
|
@ -74,7 +74,7 @@ func GetProviders() (trusted certifiers.Provider, source certifiers.Provider) {
|
|||
}
|
||||
|
||||
// GetCertifier constructs a dynamic certifier from the config info
|
||||
func GetCertifier() (*certifiers.InquiringCertifier, error) {
|
||||
func GetCertifier() (*certifiers.Inquiring, error) {
|
||||
// load up the latest store....
|
||||
trust := GetTrustedProvider()
|
||||
source := GetSourceProvider()
|
||||
|
|
|
@ -29,7 +29,7 @@ var (
|
|||
|
||||
//nolint
|
||||
const (
|
||||
SeedFlag = "seed"
|
||||
CommitFlag = "commit"
|
||||
HashFlag = "valhash"
|
||||
GenesisFlag = "genesis"
|
||||
FlagTrustNode = "trust-node"
|
||||
|
@ -52,7 +52,7 @@ var ResetCmd = &cobra.Command{
|
|||
|
||||
func init() {
|
||||
InitCmd.Flags().Bool("force-reset", false, "Wipe clean an existing client store, except for keys")
|
||||
InitCmd.Flags().String(SeedFlag, "", "Seed file to import (optional)")
|
||||
InitCmd.Flags().String(CommitFlag, "", "Commit file to import (optional)")
|
||||
InitCmd.Flags().String(HashFlag, "", "Trusted validator hash (must match to accept)")
|
||||
InitCmd.Flags().String(GenesisFlag, "", "Genesis file with chainid and validators (optional)")
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ func doInit(cmd *cobra.Command, root string) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = initSeed()
|
||||
err = initTrust()
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -275,27 +275,27 @@ func initConfigFile(cmd *cobra.Command) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func initSeed() (err error) {
|
||||
func initTrust() (err error) {
|
||||
// create a provider....
|
||||
trust, source := GetProviders()
|
||||
|
||||
// load a seed file, or get data from the provider
|
||||
var seed certifiers.Seed
|
||||
seedFile := viper.GetString(SeedFlag)
|
||||
if seedFile == "" {
|
||||
// load a commit file, or get data from the provider
|
||||
var fc certifiers.FullCommit
|
||||
commitFile := viper.GetString(CommitFlag)
|
||||
if commitFile == "" {
|
||||
fmt.Println("Loading validator set from tendermint rpc...")
|
||||
seed, err = certifiers.LatestSeed(source)
|
||||
fc, err = source.LatestCommit()
|
||||
} else {
|
||||
fmt.Printf("Loading validators from file %s\n", seedFile)
|
||||
seed, err = certifiers.LoadSeed(seedFile)
|
||||
fmt.Printf("Loading validators from file %s\n", commitFile)
|
||||
fc, err = files.LoadFullCommit(commitFile)
|
||||
}
|
||||
// can't load the seed? abort!
|
||||
// can't load the commit? abort!
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// make sure it is a proper seed
|
||||
err = seed.ValidateBasic(viper.GetString(ChainFlag))
|
||||
// make sure it is a proper commit
|
||||
err = fc.ValidateBasic(viper.GetString(ChainFlag))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -305,30 +305,30 @@ func initSeed() (err error) {
|
|||
if hash != "" {
|
||||
var hashb []byte
|
||||
hashb, err = hex.DecodeString(hash)
|
||||
if err == nil && !bytes.Equal(hashb, seed.Hash()) {
|
||||
err = errors.Errorf("Seed hash doesn't match expectation: %X", seed.Hash())
|
||||
if err == nil && !bytes.Equal(hashb, fc.ValidatorsHash()) {
|
||||
err = errors.Errorf("Validator hash doesn't match expectation: %X", fc.ValidatorsHash())
|
||||
}
|
||||
} else {
|
||||
err = validateHash(seed)
|
||||
err = validateHash(fc)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// if accepted, store seed as current state
|
||||
trust.StoreSeed(seed)
|
||||
// if accepted, store commit as current state
|
||||
trust.StoreCommit(fc)
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateHash(seed certifiers.Seed) error {
|
||||
func validateHash(fc certifiers.FullCommit) error {
|
||||
// ask the user to verify the validator hash
|
||||
fmt.Println("\nImportant: if this is incorrect, all interaction with the chain will be insecure!")
|
||||
fmt.Printf(" Given validator hash valid: %X\n", seed.Hash())
|
||||
fmt.Printf(" Given validator hash valid: %X\n", fc.ValidatorsHash())
|
||||
fmt.Println("Is this valid (y/n)?")
|
||||
valid := askForConfirmation()
|
||||
if !valid {
|
||||
return errors.New("Invalid validator hash, try init with proper seed later")
|
||||
return errors.New("Invalid validator hash, try init with proper commit later")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
"github.com/tendermint/go-wire/data"
|
||||
"github.com/tendermint/iavl"
|
||||
"github.com/tendermint/light-client/proofs"
|
||||
|
||||
rpcclient "github.com/tendermint/tendermint/rpc/client"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
|
|
|
@ -52,7 +52,7 @@ func txQueryCmd(cmd *cobra.Command, args []string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
check, err := client.GetCertifiedCheckpoint(res.Height, node, cert)
|
||||
check, err := client.GetCertifiedCommit(res.Height, node, cert)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -5,8 +5,11 @@ import (
|
|||
|
||||
"github.com/tendermint/light-client/certifiers"
|
||||
certclient "github.com/tendermint/light-client/certifiers/client"
|
||||
certerr "github.com/tendermint/light-client/certifiers/errors"
|
||||
"github.com/tendermint/light-client/certifiers/files"
|
||||
|
||||
"github.com/tendermint/light-client/proofs"
|
||||
|
||||
rpcclient "github.com/tendermint/tendermint/rpc/client"
|
||||
)
|
||||
|
||||
|
@ -18,7 +21,7 @@ func GetNode(url string) rpcclient.Client {
|
|||
// GetRPCProvider retuns a certifier compatible data source using
|
||||
// tendermint RPC
|
||||
func GetRPCProvider(url string) certifiers.Provider {
|
||||
return certclient.NewHTTP(url)
|
||||
return certclient.NewHTTPProvider(url)
|
||||
}
|
||||
|
||||
// GetLocalProvider returns a reference to a file store of headers
|
||||
|
@ -33,22 +36,22 @@ func GetLocalProvider(dir string) certifiers.Provider {
|
|||
// GetCertifier initializes an inquiring certifier given a fixed chainID
|
||||
// and a local source of trusted data with at least one seed
|
||||
func GetCertifier(chainID string, trust certifiers.Provider,
|
||||
source certifiers.Provider) (*certifiers.InquiringCertifier, error) {
|
||||
source certifiers.Provider) (*certifiers.Inquiring, error) {
|
||||
|
||||
// this gets the most recent verified seed
|
||||
seed, err := certifiers.LatestSeed(trust)
|
||||
if certifiers.IsSeedNotFoundErr(err) {
|
||||
// this gets the most recent verified commit
|
||||
fc, err := trust.LatestCommit()
|
||||
if certerr.IsCommitNotFoundErr(err) {
|
||||
return nil, errors.New("Please run init first to establish a root of trust")
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cert := certifiers.NewInquiring(chainID, seed, trust, source)
|
||||
cert := certifiers.NewInquiring(chainID, fc, trust, source)
|
||||
return cert, nil
|
||||
}
|
||||
|
||||
// SecureClient uses a given certifier to wrap an connection to an untrusted
|
||||
// host and return a cryptographically secure rpc client.
|
||||
func SecureClient(c rpcclient.Client, cert *certifiers.InquiringCertifier) rpcclient.Client {
|
||||
return certclient.Wrap(c, cert)
|
||||
func SecureClient(c rpcclient.Client, cert *certifiers.Inquiring) rpcclient.Client {
|
||||
return proofs.Wrap(c, cert)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
//--------------------------------------------
|
||||
|
||||
var errNoData = fmt.Errorf("No data returned for query")
|
||||
|
||||
// IsNoDataErr checks whether an error is due to a query returning empty data
|
||||
func IsNoDataErr(err error) bool {
|
||||
return errors.Cause(err) == errNoData
|
||||
}
|
||||
|
||||
func ErrNoData() error {
|
||||
return errors.WithStack(errNoData)
|
||||
}
|
||||
|
||||
//--------------------------------------------
|
|
@ -0,0 +1,18 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestErrorNoData(t *testing.T) {
|
||||
e1 := ErrNoData()
|
||||
e1.Error()
|
||||
assert.True(t, IsNoDataErr(e1))
|
||||
|
||||
e2 := errors.New("foobar")
|
||||
assert.False(t, IsNoDataErr(e2))
|
||||
assert.False(t, IsNoDataErr(nil))
|
||||
}
|
|
@ -5,8 +5,8 @@ import (
|
|||
|
||||
"github.com/tendermint/go-wire/data"
|
||||
"github.com/tendermint/iavl"
|
||||
lc "github.com/tendermint/light-client"
|
||||
"github.com/tendermint/light-client/certifiers"
|
||||
certerr "github.com/tendermint/light-client/certifiers/errors"
|
||||
|
||||
"github.com/tendermint/tendermint/rpc/client"
|
||||
)
|
||||
|
@ -38,7 +38,7 @@ func GetWithProof(key []byte, reqHeight int, node client.Client,
|
|||
return
|
||||
}
|
||||
if len(resp.Key) == 0 || len(resp.Proof) == 0 {
|
||||
err = lc.ErrNoData()
|
||||
err = ErrNoData()
|
||||
return
|
||||
}
|
||||
if resp.Height == 0 {
|
||||
|
@ -47,8 +47,8 @@ func GetWithProof(key []byte, reqHeight int, node client.Client,
|
|||
}
|
||||
|
||||
// AppHash for height H is in header H+1
|
||||
var check lc.Checkpoint
|
||||
check, err = GetCertifiedCheckpoint(int(resp.Height+1), node, cert)
|
||||
var commit *certifiers.Commit
|
||||
commit, err = GetCertifiedCommit(int(resp.Height+1), node, cert)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ func GetWithProof(key []byte, reqHeight int, node client.Client,
|
|||
}
|
||||
|
||||
// Validate the proof against the certified header to ensure data integrity.
|
||||
err = eproof.Verify(resp.Key, resp.Value, check.Header.AppHash)
|
||||
err = eproof.Verify(resp.Key, resp.Value, commit.Header.AppHash)
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "Couldn't verify proof")
|
||||
return
|
||||
|
@ -79,12 +79,12 @@ func GetWithProof(key []byte, reqHeight int, node client.Client,
|
|||
return
|
||||
}
|
||||
// Validate the proof against the certified header to ensure data integrity.
|
||||
err = aproof.Verify(resp.Key, nil, check.Header.AppHash)
|
||||
err = aproof.Verify(resp.Key, nil, commit.Header.AppHash)
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "Couldn't verify proof")
|
||||
return
|
||||
}
|
||||
err = lc.ErrNoData()
|
||||
err = ErrNoData()
|
||||
proof = aproof
|
||||
}
|
||||
|
||||
|
@ -92,28 +92,25 @@ func GetWithProof(key []byte, reqHeight int, node client.Client,
|
|||
return
|
||||
}
|
||||
|
||||
// GetCertifiedCheckpoint gets the signed header for a given height
|
||||
// GetCertifiedCommit gets the signed header for a given height
|
||||
// and certifies it. Returns error if unable to get a proven header.
|
||||
func GetCertifiedCheckpoint(h int, node client.Client,
|
||||
cert certifiers.Certifier) (empty lc.Checkpoint, err error) {
|
||||
func GetCertifiedCommit(h int, node client.Client,
|
||||
cert certifiers.Certifier) (empty *certifiers.Commit, err error) {
|
||||
|
||||
// FIXME: cannot use cert.GetByHeight for now, as it also requires
|
||||
// Validators and will fail on querying tendermint for non-current height.
|
||||
// When this is supported, we should use it instead...
|
||||
client.WaitForHeight(node, h, nil)
|
||||
commit, err := node.Commit(&h)
|
||||
cresp, err := node.Commit(&h)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
check := lc.Checkpoint{
|
||||
Header: commit.Header,
|
||||
Commit: commit.Commit,
|
||||
}
|
||||
commit := certifiers.CommitFromResult(cresp)
|
||||
|
||||
// validate downloaded checkpoint with our request and trust store.
|
||||
if check.Height() != h {
|
||||
return empty, lc.ErrHeightMismatch(h, check.Height())
|
||||
if commit.Height() != h {
|
||||
return empty, certerr.ErrHeightMismatch(h, commit.Height())
|
||||
}
|
||||
err = cert.Certify(check)
|
||||
return check, nil
|
||||
err = cert.Certify(commit)
|
||||
return commit, nil
|
||||
}
|
||||
|
|
|
@ -9,14 +9,14 @@ import (
|
|||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/tendermint/go-wire"
|
||||
lc "github.com/tendermint/light-client"
|
||||
"github.com/tendermint/light-client/certifiers"
|
||||
certclient "github.com/tendermint/light-client/certifiers/client"
|
||||
"github.com/tendermint/tmlibs/log"
|
||||
|
||||
nm "github.com/tendermint/tendermint/node"
|
||||
"github.com/tendermint/tendermint/rpc/client"
|
||||
rpctest "github.com/tendermint/tendermint/rpc/test"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
"github.com/tendermint/tmlibs/log"
|
||||
|
||||
sdkapp "github.com/cosmos/cosmos-sdk/app"
|
||||
"github.com/cosmos/cosmos-sdk/modules/eyes"
|
||||
|
@ -59,13 +59,13 @@ func TestAppProofs(t *testing.T) {
|
|||
brh := br.Height
|
||||
|
||||
// This sets up our trust on the node based on some past point.
|
||||
source := certclient.New(cl)
|
||||
source := certclient.NewProvider(cl)
|
||||
seed, err := source.GetByHeight(br.Height - 2)
|
||||
require.NoError(err, "%+v", err)
|
||||
cert := certifiers.NewStatic("my-chain", seed.Validators)
|
||||
|
||||
client.WaitForHeight(cl, 3, nil)
|
||||
latest, err := source.GetLatestCommit()
|
||||
latest, err := source.LatestCommit()
|
||||
require.NoError(err, "%+v", err)
|
||||
rootHash := latest.Header.AppHash
|
||||
|
||||
|
@ -75,7 +75,7 @@ func TestAppProofs(t *testing.T) {
|
|||
// verify a query before the tx block has no data (and valid non-exist proof)
|
||||
bs, height, proof, err := GetWithProof(k, brh-1, cl, cert)
|
||||
require.NotNil(err)
|
||||
require.True(lc.IsNoDataErr(err))
|
||||
require.True(IsNoDataErr(err))
|
||||
require.Nil(bs)
|
||||
|
||||
// but given that block it is good
|
||||
|
@ -98,7 +98,7 @@ func TestAppProofs(t *testing.T) {
|
|||
// Test non-existing key.
|
||||
missing := []byte("my-missing-key")
|
||||
bs, _, proof, err = GetWithProof(missing, 0, cl, cert)
|
||||
require.True(lc.IsNoDataErr(err))
|
||||
require.True(IsNoDataErr(err))
|
||||
require.Nil(bs)
|
||||
require.NotNil(proof)
|
||||
err = proof.Verify(missing, nil, rootHash)
|
||||
|
@ -122,7 +122,7 @@ func TestTxProofs(t *testing.T) {
|
|||
require.EqualValues(0, br.DeliverTx.Code)
|
||||
fmt.Printf("tx height: %d\n", br.Height)
|
||||
|
||||
source := certclient.New(cl)
|
||||
source := certclient.NewProvider(cl)
|
||||
seed, err := source.GetByHeight(br.Height - 2)
|
||||
require.NoError(err, "%+v", err)
|
||||
cert := certifiers.NewStatic("my-chain", seed.Validators)
|
||||
|
@ -141,8 +141,8 @@ func TestTxProofs(t *testing.T) {
|
|||
err = res.Proof.Validate(key)
|
||||
assert.NoError(err, "%+v", err)
|
||||
|
||||
check, err := GetCertifiedCheckpoint(int(br.Height), cl, cert)
|
||||
commit, err := GetCertifiedCommit(int(br.Height), cl, cert)
|
||||
require.Nil(err, "%+v", err)
|
||||
require.Equal(res.Proof.RootHash, check.Header.DataHash)
|
||||
require.Equal(res.Proof.RootHash, commit.Header.DataHash)
|
||||
|
||||
}
|
||||
|
|
|
@ -237,7 +237,7 @@ info about self...
|
|||
}
|
||||
```
|
||||
|
||||
`/seeds`
|
||||
`/commits`
|
||||
|
||||
```
|
||||
{
|
||||
|
@ -246,4 +246,4 @@ info about self...
|
|||
}
|
||||
```
|
||||
|
||||
info on last seed
|
||||
info on last commit
|
||||
|
|
|
@ -9,11 +9,11 @@ import (
|
|||
|
||||
"github.com/cosmos/cosmos-sdk/client/commands"
|
||||
"github.com/cosmos/cosmos-sdk/client/commands/auto"
|
||||
"github.com/cosmos/cosmos-sdk/client/commands/commits"
|
||||
"github.com/cosmos/cosmos-sdk/client/commands/keys"
|
||||
"github.com/cosmos/cosmos-sdk/client/commands/proxy"
|
||||
"github.com/cosmos/cosmos-sdk/client/commands/query"
|
||||
rpccmd "github.com/cosmos/cosmos-sdk/client/commands/rpc"
|
||||
"github.com/cosmos/cosmos-sdk/client/commands/seeds"
|
||||
txcmd "github.com/cosmos/cosmos-sdk/client/commands/txs"
|
||||
authcmd "github.com/cosmos/cosmos-sdk/modules/auth/commands"
|
||||
basecmd "github.com/cosmos/cosmos-sdk/modules/base/commands"
|
||||
|
@ -77,7 +77,7 @@ func main() {
|
|||
commands.InitCmd,
|
||||
commands.ResetCmd,
|
||||
keys.RootCmd,
|
||||
seeds.RootCmd,
|
||||
commits.RootCmd,
|
||||
rpccmd.RootCmd,
|
||||
query.RootCmd,
|
||||
txcmd.RootCmd,
|
||||
|
|
|
@ -84,18 +84,18 @@ test00GetAccount() {
|
|||
}
|
||||
|
||||
test01RegisterChains() {
|
||||
# let's get the root seeds to cross-register them
|
||||
ROOT_1="$BASE_DIR_1/root_seed.json"
|
||||
${CLIENT_EXE} seeds export $ROOT_1 --home=${CLIENT_1}
|
||||
assertTrue "line=${LINENO}, export seed failed" $?
|
||||
# let's get the root commits to cross-register them
|
||||
ROOT_1="$BASE_DIR_1/root_commit.json"
|
||||
${CLIENT_EXE} commits export $ROOT_1 --home=${CLIENT_1}
|
||||
assertTrue "line=${LINENO}, export commit failed" $?
|
||||
|
||||
ROOT_2="$BASE_DIR_2/root_seed.json"
|
||||
${CLIENT_EXE} seeds export $ROOT_2 --home=${CLIENT_2}
|
||||
assertTrue "line=${LINENO}, export seed failed" $?
|
||||
ROOT_2="$BASE_DIR_2/root_commit.json"
|
||||
${CLIENT_EXE} commits export $ROOT_2 --home=${CLIENT_2}
|
||||
assertTrue "line=${LINENO}, export commit failed" $?
|
||||
|
||||
# register chain2 on chain1
|
||||
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx ibc-register \
|
||||
--sequence=1 --seed=${ROOT_2} --name=$POOR --home=${CLIENT_1})
|
||||
--sequence=1 --commit=${ROOT_2} --name=$POOR --home=${CLIENT_1})
|
||||
txSucceeded $? "$TX" "register chain2 on chain 1"
|
||||
# an example to quit early if there is no point in more tests
|
||||
if [ $? != 0 ]; then echo "aborting!"; return 1; fi
|
||||
|
@ -104,40 +104,40 @@ test01RegisterChains() {
|
|||
|
||||
# register chain1 on chain2 (no money needed... yet)
|
||||
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx ibc-register \
|
||||
--sequence=1 --seed=${ROOT_1} --name=$POOR --home=${CLIENT_2})
|
||||
--sequence=1 --commit=${ROOT_1} --name=$POOR --home=${CLIENT_2})
|
||||
txSucceeded $? "$TX" "register chain1 on chain 2"
|
||||
# an example to quit early if there is no point in more tests
|
||||
if [ $? != 0 ]; then echo "aborting!"; return 1; fi
|
||||
}
|
||||
|
||||
test02UpdateChains() {
|
||||
# let's get the root seeds to cross-register them
|
||||
# let's get the root commits to cross-register them
|
||||
UPDATE_1="$BASE_DIR_1/seed_1.json"
|
||||
${CLIENT_EXE} seeds update --home=${CLIENT_1} > /dev/null
|
||||
${CLIENT_EXE} seeds export $UPDATE_1 --home=${CLIENT_1}
|
||||
assertTrue "line=${LINENO}, export seed failed" $?
|
||||
${CLIENT_EXE} commits update --home=${CLIENT_1} > /dev/null
|
||||
${CLIENT_EXE} commits export $UPDATE_1 --home=${CLIENT_1}
|
||||
assertTrue "line=${LINENO}, export commit failed" $?
|
||||
# make sure it is newer than the other....
|
||||
assertNewHeight "line=${LINENO}" $ROOT_1 $UPDATE_1
|
||||
|
||||
UPDATE_2="$BASE_DIR_2/seed_2.json"
|
||||
${CLIENT_EXE} seeds update --home=${CLIENT_2} > /dev/null
|
||||
${CLIENT_EXE} seeds export $UPDATE_2 --home=${CLIENT_2}
|
||||
assertTrue "line=${LINENO}, export seed failed" $?
|
||||
${CLIENT_EXE} commits update --home=${CLIENT_2} > /dev/null
|
||||
${CLIENT_EXE} commits export $UPDATE_2 --home=${CLIENT_2}
|
||||
assertTrue "line=${LINENO}, export commit failed" $?
|
||||
assertNewHeight "line=${LINENO}" $ROOT_2 $UPDATE_2
|
||||
# this is used later to check query data
|
||||
REGISTER_2_HEIGHT=$(cat $ROOT_2 | jq .checkpoint.header.height)
|
||||
UPDATE_2_HEIGHT=$(cat $UPDATE_2 | jq .checkpoint.header.height)
|
||||
REGISTER_2_HEIGHT=$(cat $ROOT_2 | jq .commit.header.height)
|
||||
UPDATE_2_HEIGHT=$(cat $UPDATE_2 | jq .commit.header.height)
|
||||
|
||||
# update chain2 on chain1
|
||||
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx ibc-update \
|
||||
--sequence=2 --seed=${UPDATE_2} --name=$POOR --home=${CLIENT_1})
|
||||
--sequence=2 --commit=${UPDATE_2} --name=$POOR --home=${CLIENT_1})
|
||||
txSucceeded $? "$TX" "update chain2 on chain 1"
|
||||
# an example to quit early if there is no point in more tests
|
||||
if [ $? != 0 ]; then echo "aborting!"; return 1; fi
|
||||
|
||||
# update chain1 on chain2 (no money needed... yet)
|
||||
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx ibc-update \
|
||||
--sequence=2 --seed=${UPDATE_1} --name=$POOR --home=${CLIENT_2})
|
||||
--sequence=2 --commit=${UPDATE_1} --name=$POOR --home=${CLIENT_2})
|
||||
txSucceeded $? "$TX" "update chain1 on chain 2"
|
||||
# an example to quit early if there is no point in more tests
|
||||
if [ $? != 0 ]; then echo "aborting!"; return 1; fi
|
||||
|
@ -224,24 +224,24 @@ test05ReceiveIBCPacket() {
|
|||
|
||||
# now, we try to post it.... (this is PACKET from last test)
|
||||
|
||||
# get the seed with the proof and post it
|
||||
# get the commit with the proof and post it
|
||||
SRC_HEIGHT=$(echo $PACKET | jq .src_height)
|
||||
PROOF_HEIGHT=$(expr $SRC_HEIGHT + 1)
|
||||
# FIXME: this should auto-update on proofs...
|
||||
${CLIENT_EXE} seeds update --height=$PROOF_HEIGHT --home=${CLIENT_1} > /dev/null
|
||||
assertTrue "line=${LINENO}, update seed failed" $?
|
||||
${CLIENT_EXE} commits update --height=$PROOF_HEIGHT --home=${CLIENT_1} > /dev/null
|
||||
assertTrue "line=${LINENO}, update commit failed" $?
|
||||
|
||||
PACKET_SEED="$BASE_DIR_1/packet_seed.json"
|
||||
${CLIENT_EXE} seeds export $PACKET_SEED --home=${CLIENT_1} --height=$PROOF_HEIGHT
|
||||
assertTrue "line=${LINENO}, export seed failed" $?
|
||||
PACKET_COMMIT="$BASE_DIR_1/packet_commit.json"
|
||||
${CLIENT_EXE} commits export $PACKET_COMMIT --home=${CLIENT_1} --height=$PROOF_HEIGHT
|
||||
assertTrue "line=${LINENO}, export commit failed" $?
|
||||
if [ -n "$DEBUG" ]; then
|
||||
echo "**** SEED ****"
|
||||
cat $PACKET_SEED | jq .checkpoint.header
|
||||
cat $PACKET_COMMIT | jq .commit.header
|
||||
echo
|
||||
fi
|
||||
|
||||
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx ibc-update \
|
||||
--seed=${PACKET_SEED} --name=$POOR --sequence=3)
|
||||
--commit=${PACKET_COMMIT} --name=$POOR --sequence=3)
|
||||
txSucceeded $? "$TX" "prepare packet chain1 on chain 2"
|
||||
# an example to quit early if there is no point in more tests
|
||||
if [ $? != 0 ]; then echo "aborting!"; return 1; fi
|
||||
|
@ -268,11 +268,11 @@ test05ReceiveIBCPacket() {
|
|||
}
|
||||
|
||||
# XXX Ex Usage: assertNewHeight $MSG $SEED_1 $SEED_2
|
||||
# Desc: Asserts that seed2 has a higher block height than seed 1
|
||||
# Desc: Asserts that seed2 has a higher block height than commit 1
|
||||
assertNewHeight() {
|
||||
H1=$(cat $2 | jq .checkpoint.header.height)
|
||||
H2=$(cat $3 | jq .checkpoint.header.height)
|
||||
assertTrue "$MSG" "test $H2 -gt $H1"
|
||||
H1=$(cat $2 | jq .commit.header.height)
|
||||
H2=$(cat $3 | jq .commit.header.height)
|
||||
assertTrue "$1" "test $H2 -gt $H1"
|
||||
return $?
|
||||
}
|
||||
|
||||
|
|
|
@ -8,10 +8,10 @@ import (
|
|||
"github.com/tendermint/tmlibs/cli"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/commands"
|
||||
"github.com/cosmos/cosmos-sdk/client/commands/commits"
|
||||
"github.com/cosmos/cosmos-sdk/client/commands/keys"
|
||||
"github.com/cosmos/cosmos-sdk/client/commands/proxy"
|
||||
"github.com/cosmos/cosmos-sdk/client/commands/query"
|
||||
"github.com/cosmos/cosmos-sdk/client/commands/seeds"
|
||||
|
||||
txcmd "github.com/cosmos/cosmos-sdk/client/commands/txs"
|
||||
bcount "github.com/cosmos/cosmos-sdk/examples/counter/cmd/countercli/commands"
|
||||
|
@ -74,7 +74,7 @@ func main() {
|
|||
commands.ResetCmd,
|
||||
commands.VersionCmd,
|
||||
keys.RootCmd,
|
||||
seeds.RootCmd,
|
||||
commits.RootCmd,
|
||||
query.RootCmd,
|
||||
txcmd.RootCmd,
|
||||
proxy.RootCmd,
|
||||
|
|
|
@ -9,9 +9,9 @@ import (
|
|||
|
||||
"github.com/cosmos/cosmos-sdk/client/commands"
|
||||
"github.com/cosmos/cosmos-sdk/client/commands/auto"
|
||||
"github.com/cosmos/cosmos-sdk/client/commands/commits"
|
||||
"github.com/cosmos/cosmos-sdk/client/commands/query"
|
||||
rpccmd "github.com/cosmos/cosmos-sdk/client/commands/rpc"
|
||||
"github.com/cosmos/cosmos-sdk/client/commands/seeds"
|
||||
txcmd "github.com/cosmos/cosmos-sdk/client/commands/txs"
|
||||
eyescmd "github.com/cosmos/cosmos-sdk/modules/eyes/commands"
|
||||
)
|
||||
|
@ -50,7 +50,7 @@ func main() {
|
|||
// we use out own init command to not require address arg
|
||||
commands.InitCmd,
|
||||
commands.ResetCmd,
|
||||
seeds.RootCmd,
|
||||
commits.RootCmd,
|
||||
rpccmd.RootCmd,
|
||||
query.RootCmd,
|
||||
txcmd.RootCmd,
|
||||
|
|
|
@ -1,22 +1,24 @@
|
|||
hash: fbfdd03c0367bb0785ceb81ed34059df219e55d5a9c71c12597e505fbce14165
|
||||
updated: 2017-10-23T14:49:22.891642342+02:00
|
||||
updated: 2017-10-25T19:24:51.90002008+02:00
|
||||
imports:
|
||||
- name: github.com/bgentry/speakeasy
|
||||
version: 4aabc24848ce5fd31929f7d1e4ea74d3709c14cd
|
||||
- name: github.com/btcsuite/btcd
|
||||
version: b8df516b4b267acf2de46be593a9d948d1d2c420
|
||||
version: c7588cbf7690cd9f047a28efa2dcd8f2435a4e5e
|
||||
subpackages:
|
||||
- btcec
|
||||
- name: github.com/btcsuite/fastsha256
|
||||
version: 637e656429416087660c84436a2a035d69d54e2e
|
||||
- name: github.com/BurntSushi/toml
|
||||
version: a368813c5e648fee92e5f6c30e3944ff9d5e8895
|
||||
- name: github.com/ebuchman/fail-test
|
||||
version: 95f809107225be108efcf10a3509e4ea6ceef3c4
|
||||
- name: github.com/ethanfrey/ledger
|
||||
version: 5e432577be582bd18a3b4a9cd75dae7a317ade36
|
||||
- name: github.com/flynn/hid
|
||||
version: ed06a31c6245d4552e8dbba7e32e5b010b875d65
|
||||
- name: github.com/fsnotify/fsnotify
|
||||
version: 4da3e2cfbabc9f751898f250b49f2439785783a1
|
||||
- name: github.com/go-kit/kit
|
||||
version: d67bb4c202e3b91377d1079b110a6c9ce23ab2f8
|
||||
version: e2b298466b32c7cd5579a9b9b07e968fc9d9452c
|
||||
subpackages:
|
||||
- log
|
||||
- log/level
|
||||
|
@ -24,18 +26,21 @@ imports:
|
|||
- name: github.com/go-logfmt/logfmt
|
||||
version: 390ab7935ee28ec6b286364bba9b4dd6410cb3d5
|
||||
- name: github.com/go-playground/locales
|
||||
version: 1e5f1161c6416a5ff48840eb8724a394e48cc534
|
||||
version: e4cbcb5d0652150d40ad0646651076b6bd2be4f6
|
||||
subpackages:
|
||||
- currency
|
||||
- name: github.com/go-playground/universal-translator
|
||||
version: 71201497bace774495daed26a3874fd339e0b538
|
||||
- name: github.com/go-stack/stack
|
||||
version: 100eb0c0a9c5b306ca2fb4f165df21d80ada4b82
|
||||
version: 817915b46b97fd7bb80e8ab6b69f01a53ac3eebf
|
||||
- name: github.com/golang/protobuf
|
||||
version: 18c9bb3261723cd5401db4d0c9fbc5c3b6c70fe8
|
||||
version: 1643683e1b54a9e88ad26d98f81400c8c9d9f4f9
|
||||
subpackages:
|
||||
- proto
|
||||
- ptypes
|
||||
- ptypes/any
|
||||
- ptypes/duration
|
||||
- ptypes/timestamp
|
||||
- name: github.com/golang/snappy
|
||||
version: 553a641470496b2327abcac10b36396bd98e45c9
|
||||
- name: github.com/gorilla/context
|
||||
|
@ -43,9 +48,9 @@ imports:
|
|||
- name: github.com/gorilla/mux
|
||||
version: 24fca303ac6da784b9e8269f724ddeb0b2eea5e7
|
||||
- name: github.com/gorilla/websocket
|
||||
version: a91eba7f97777409bc2c443f5534d41dd20c5720
|
||||
version: 71fa72d4842364bc5f74185f4161e0099ea3624a
|
||||
- name: github.com/hashicorp/hcl
|
||||
version: 392dba7d905ed5d04a5794ba89f558b27e2ba1ca
|
||||
version: 23c074d0eceb2b8a5bfdbb271ab780cde70f05a8
|
||||
subpackages:
|
||||
- hcl/ast
|
||||
- hcl/parser
|
||||
|
@ -64,11 +69,11 @@ imports:
|
|||
- name: github.com/kr/logfmt
|
||||
version: b84e30acd515aadc4b783ad4ff83aff3299bdfe0
|
||||
- name: github.com/magiconair/properties
|
||||
version: 51463bfca2576e06c62a8504b5c0f06d61312647
|
||||
version: 8d7837e64d3c1ee4e54a880c5a920ab4316fc90a
|
||||
- name: github.com/mattn/go-isatty
|
||||
version: a5cdd64afdee435007ee3e9f6ed4684af949d568
|
||||
- name: github.com/mitchellh/mapstructure
|
||||
version: cc8532a8e9a55ea36402aa21efdf403a60d34096
|
||||
version: 06020f85339e21b2478f756a78e295255ffa4d6a
|
||||
- name: github.com/pelletier/go-buffruneio
|
||||
version: c37440a7cf42ac63b919c752ca73a85067e05992
|
||||
- name: github.com/pelletier/go-toml
|
||||
|
@ -78,21 +83,21 @@ imports:
|
|||
- name: github.com/rcrowley/go-metrics
|
||||
version: 1f30fe9094a513ce4c700b9a54458bbb0c96996c
|
||||
- name: github.com/spf13/afero
|
||||
version: 9be650865eab0c12963d8753212f4f9c66cdcf12
|
||||
version: 5660eeed305fe5f69c8fc6cf899132a459a97064
|
||||
subpackages:
|
||||
- mem
|
||||
- name: github.com/spf13/cast
|
||||
version: acbeb36b902d72a7a4c18e8f3241075e7ab763e4
|
||||
- name: github.com/spf13/cobra
|
||||
version: 4cdb38c072b86bf795d2c81de50784d9fdd6eb77
|
||||
version: 7b2c5ac9fc04fc5efafb60700713d4fa609b777b
|
||||
- name: github.com/spf13/jwalterweatherman
|
||||
version: 8f07c835e5cc1450c082fe3a439cf87b0cbb2d99
|
||||
version: 12bd96e66386c1960ab0f74ced1362f66f552f7b
|
||||
- name: github.com/spf13/pflag
|
||||
version: e57e3eeb33f795204c1ca35f56c44f83227c6e66
|
||||
version: 97afa5e7ca8a08a383cb259e06636b5e2cc7897f
|
||||
- name: github.com/spf13/viper
|
||||
version: 0967fc9aceab2ce9da34061253ac10fb99bba5b2
|
||||
version: 8ef37cbca71638bf32f3d5e194117d4cb46da163
|
||||
- name: github.com/syndtr/goleveldb
|
||||
version: 8c81ea47d4c41a385645e133e15510fc6a2a74b4
|
||||
version: b89cc31ef7977104127d34c1bd31ebd1a9db2199
|
||||
subpackages:
|
||||
- leveldb
|
||||
- leveldb/cache
|
||||
|
@ -119,7 +124,7 @@ imports:
|
|||
- edwards25519
|
||||
- extra25519
|
||||
- name: github.com/tendermint/go-crypto
|
||||
version: 8e7f0e7701f92206679ad093d013b9b162427631
|
||||
version: 0a5b1d979a1bc86200c9ff829fbbcd575799a1b6
|
||||
subpackages:
|
||||
- bcrypt
|
||||
- keys
|
||||
|
@ -127,22 +132,24 @@ imports:
|
|||
- keys/storage/filestorage
|
||||
- keys/storage/memstorage
|
||||
- keys/wordlist
|
||||
- nano
|
||||
- name: github.com/tendermint/go-wire
|
||||
version: 55ae61f1fc83cfaa57ab7d54250d7a1a2be0b83c
|
||||
version: 99d2169a1e39c65983eacaa1da867d6f3218e1c9
|
||||
subpackages:
|
||||
- data
|
||||
- data/base58
|
||||
- name: github.com/tendermint/iavl
|
||||
version: 721710e7aa59f61dbfbf558943a207ba3fe6b926
|
||||
version: 595f3dcd5b6cd4a292e90757ae6d367fd7a6e653
|
||||
- name: github.com/tendermint/light-client
|
||||
version: 569e1583da8a52e499764533f3a05d05be6d56d6
|
||||
version: 76313d625e662ed7b284d066d68ff71edd7a9fac
|
||||
subpackages:
|
||||
- certifiers
|
||||
- certifiers/client
|
||||
- certifiers/errors
|
||||
- certifiers/files
|
||||
- proofs
|
||||
- name: github.com/tendermint/tendermint
|
||||
version: fa56e8c0ce463f77c87ab17a3d7cf5431d9f2c0b
|
||||
version: b2d5546cf8f71e0e168072e118d9836862384e6c
|
||||
subpackages:
|
||||
- blockchain
|
||||
- cmd/tendermint/commands
|
||||
|
@ -170,7 +177,7 @@ imports:
|
|||
- types
|
||||
- version
|
||||
- name: github.com/tendermint/tmlibs
|
||||
version: 8e5266a9ef2527e68a1571f932db8228a331b556
|
||||
version: 0a652499ead7cd20a57a6a592f0491a2b493bb85
|
||||
subpackages:
|
||||
- autofile
|
||||
- cli
|
||||
|
@ -184,7 +191,7 @@ imports:
|
|||
- logger
|
||||
- merkle
|
||||
- name: golang.org/x/crypto
|
||||
version: c7af5bf2638a1164f2eb5467c39c6cffbd13a02e
|
||||
version: edd5e9b0879d13ee6970a50153d85b8fec9f7686
|
||||
subpackages:
|
||||
- blowfish
|
||||
- curve25519
|
||||
|
@ -196,7 +203,7 @@ imports:
|
|||
- ripemd160
|
||||
- salsa20/salsa
|
||||
- name: golang.org/x/net
|
||||
version: feeb485667d1fdabe727840fe00adc22431bc86e
|
||||
version: cd69bc3fc700721b709c3a59e16e24c67b58f6ff
|
||||
subpackages:
|
||||
- context
|
||||
- http2
|
||||
|
@ -206,43 +213,49 @@ imports:
|
|||
- lex/httplex
|
||||
- trace
|
||||
- name: golang.org/x/sys
|
||||
version: e62c3de784db939836898e5c19ffd41bece347da
|
||||
version: 8dbc5d05d6edcc104950cc299a1ce6641235bc86
|
||||
subpackages:
|
||||
- unix
|
||||
- name: golang.org/x/text
|
||||
version: 470f45bf29f4147d6fbd7dfd0a02a848e49f5bf4
|
||||
version: c01e4764d870b77f8abe5096ee19ad20d80e8075
|
||||
subpackages:
|
||||
- secure/bidirule
|
||||
- transform
|
||||
- unicode/bidi
|
||||
- unicode/norm
|
||||
- name: google.golang.org/genproto
|
||||
version: 411e09b969b1170a9f0c467558eb4c4c110d9c77
|
||||
version: f676e0f3ac6395ff1a529ae59a6670878a8371a6
|
||||
subpackages:
|
||||
- googleapis/rpc/status
|
||||
- name: google.golang.org/grpc
|
||||
version: 844f573616520565fdc6fb4db242321b5456fd6d
|
||||
version: a5986a5c88227370a9c0a82e5277167229c034cd
|
||||
subpackages:
|
||||
- balancer
|
||||
- balancer/roundrobin
|
||||
- codes
|
||||
- connectivity
|
||||
- credentials
|
||||
- grpclb/grpc_lb_v1
|
||||
- grpclb/grpc_lb_v1/messages
|
||||
- grpclog
|
||||
- internal
|
||||
- keepalive
|
||||
- metadata
|
||||
- naming
|
||||
- peer
|
||||
- resolver
|
||||
- resolver/dns
|
||||
- resolver/passthrough
|
||||
- stats
|
||||
- status
|
||||
- tap
|
||||
- transport
|
||||
- name: gopkg.in/go-playground/validator.v9
|
||||
version: 6d8c18553ea1ac493d049edd6f102f52e618f085
|
||||
version: 1304298bf10d085adec514b076772a79c9cadb6b
|
||||
- name: gopkg.in/yaml.v2
|
||||
version: cd8b52f8269e0feb286dfeef29f8fe4d5b397e0b
|
||||
version: eb3733d160e74a9c7e442f435eb3bea458e1d19f
|
||||
testImports:
|
||||
- name: github.com/davecgh/go-spew
|
||||
version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9
|
||||
version: 04cdfd42973bb9c8589fd6a731800cf222fde1a9
|
||||
subpackages:
|
||||
- spew
|
||||
- name: github.com/pmezard/go-difflib
|
||||
|
@ -250,7 +263,7 @@ testImports:
|
|||
subpackages:
|
||||
- difflib
|
||||
- name: github.com/stretchr/testify
|
||||
version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0
|
||||
version: 2aa2c176b9dab406a6970f6a55f513e8a8c8b18f
|
||||
subpackages:
|
||||
- assert
|
||||
- require
|
||||
|
|
|
@ -5,8 +5,7 @@ import (
|
|||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
lc "github.com/tendermint/light-client"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/commands"
|
||||
"github.com/cosmos/cosmos-sdk/client/commands/query"
|
||||
"github.com/cosmos/cosmos-sdk/modules/coin"
|
||||
|
@ -35,7 +34,7 @@ func accountQueryCmd(cmd *cobra.Command, args []string) error {
|
|||
acc := coin.Account{}
|
||||
prove := !viper.GetBool(commands.FlagTrustNode)
|
||||
height, err := query.GetParsed(key, &acc, query.GetHeight(), prove)
|
||||
if lc.IsNoDataErr(err) {
|
||||
if client.IsNoDataErr(err) {
|
||||
return errors.Errorf("Account bytes are empty for address %s ", addr)
|
||||
} else if err != nil {
|
||||
return err
|
||||
|
|
|
@ -252,7 +252,7 @@ func TestSetIssuer(t *testing.T) {
|
|||
}{
|
||||
{sdk.Actor{App: "sig", Address: []byte("gwkfgk")}},
|
||||
// and set back to empty (nil is valid, but assert.Equals doesn't match)
|
||||
{sdk.Actor{Address: []byte{}}},
|
||||
{sdk.Actor{}},
|
||||
{sdk.Actor{ChainID: "other", App: "role", Address: []byte("vote")}},
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/spf13/viper"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/commands"
|
||||
"github.com/cosmos/cosmos-sdk/client/commands/query"
|
||||
"github.com/cosmos/cosmos-sdk/modules/auth"
|
||||
|
@ -18,7 +19,6 @@ import (
|
|||
"github.com/cosmos/cosmos-sdk/modules/fee"
|
||||
"github.com/cosmos/cosmos-sdk/modules/nonce"
|
||||
"github.com/cosmos/cosmos-sdk/stack"
|
||||
lightclient "github.com/tendermint/light-client"
|
||||
"github.com/tendermint/tmlibs/common"
|
||||
)
|
||||
|
||||
|
@ -62,7 +62,7 @@ func doQueryAccount(w http.ResponseWriter, r *http.Request) {
|
|||
account := new(coin.Account)
|
||||
prove := !viper.GetBool(commands.FlagTrustNode)
|
||||
height, err := query.GetParsed(key, account, h, prove)
|
||||
if lightclient.IsNoDataErr(err) {
|
||||
if client.IsNoDataErr(err) {
|
||||
err := fmt.Errorf("account bytes are empty for address: %q", signature)
|
||||
common.WriteError(w, err)
|
||||
return
|
||||
|
|
|
@ -39,36 +39,36 @@ var PostPacketTxCmd = &cobra.Command{
|
|||
|
||||
//nolint
|
||||
const (
|
||||
FlagSeed = "seed"
|
||||
FlagCommit = "commit"
|
||||
FlagPacket = "packet"
|
||||
)
|
||||
|
||||
func init() {
|
||||
fs1 := RegisterChainTxCmd.Flags()
|
||||
fs1.String(FlagSeed, "", "Filename with a seed file")
|
||||
fs1.String(FlagCommit, "", "Filename with a commit file")
|
||||
|
||||
fs2 := UpdateChainTxCmd.Flags()
|
||||
fs2.String(FlagSeed, "", "Filename with a seed file")
|
||||
fs2.String(FlagCommit, "", "Filename with a commit file")
|
||||
|
||||
fs3 := PostPacketTxCmd.Flags()
|
||||
fs3.String(FlagPacket, "", "Filename with a packet to post")
|
||||
}
|
||||
|
||||
func registerChainTxCmd(cmd *cobra.Command, args []string) error {
|
||||
seed, err := readSeed()
|
||||
fc, err := readCommit()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tx := ibc.RegisterChainTx{seed}.Wrap()
|
||||
tx := ibc.RegisterChainTx{fc}.Wrap()
|
||||
return txcmd.DoTx(tx)
|
||||
}
|
||||
|
||||
func updateChainTxCmd(cmd *cobra.Command, args []string) error {
|
||||
seed, err := readSeed()
|
||||
fc, err := readCommit()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tx := ibc.UpdateChainTx{seed}.Wrap()
|
||||
tx := ibc.UpdateChainTx{fc}.Wrap()
|
||||
return txcmd.DoTx(tx)
|
||||
}
|
||||
|
||||
|
@ -80,13 +80,13 @@ func postPacketTxCmd(cmd *cobra.Command, args []string) error {
|
|||
return txcmd.DoTx(post.Wrap())
|
||||
}
|
||||
|
||||
func readSeed() (seed certifiers.Seed, err error) {
|
||||
name := viper.GetString(FlagSeed)
|
||||
func readCommit() (fc certifiers.FullCommit, err error) {
|
||||
name := viper.GetString(FlagCommit)
|
||||
if name == "" {
|
||||
return seed, errors.New("You must specify a seed file")
|
||||
return fc, errors.New("You must specify a commit file")
|
||||
}
|
||||
|
||||
err = readFile(name, &seed)
|
||||
err = readFile(name, &fc)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -100,20 +100,20 @@ func (h Handler) DeliverTx(ctx sdk.Context, store state.SimpleDB, tx sdk.Tx) (re
|
|||
|
||||
switch t := tx.Unwrap().(type) {
|
||||
case RegisterChainTx:
|
||||
return h.initSeed(ctx, store, t)
|
||||
return h.registerChain(ctx, store, t)
|
||||
case UpdateChainTx:
|
||||
return h.updateSeed(ctx, store, t)
|
||||
return h.updateChain(ctx, store, t)
|
||||
case CreatePacketTx:
|
||||
return h.createPacket(ctx, store, t)
|
||||
}
|
||||
return res, errors.ErrUnknownTxType(tx.Unwrap())
|
||||
}
|
||||
|
||||
// initSeed imports the first seed for this chain and
|
||||
// registerChain imports the first seed for this chain and
|
||||
// accepts it as the root of trust.
|
||||
//
|
||||
// only the registrar, if set, is allowed to do this
|
||||
func (h Handler) initSeed(ctx sdk.Context, store state.SimpleDB,
|
||||
func (h Handler) registerChain(ctx sdk.Context, store state.SimpleDB,
|
||||
t RegisterChainTx) (res sdk.DeliverResult, err error) {
|
||||
|
||||
info := LoadInfo(store)
|
||||
|
@ -124,20 +124,20 @@ func (h Handler) initSeed(ctx sdk.Context, store state.SimpleDB,
|
|||
// verify that the header looks reasonable
|
||||
chainID := t.ChainID()
|
||||
s := NewChainSet(store)
|
||||
err = s.Register(chainID, ctx.BlockHeight(), t.Seed.Height())
|
||||
err = s.Register(chainID, ctx.BlockHeight(), t.Commit.Height())
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
space := stack.PrefixedStore(chainID, store)
|
||||
provider := newDBProvider(space)
|
||||
err = provider.StoreSeed(t.Seed)
|
||||
err = provider.StoreCommit(t.Commit)
|
||||
return res, err
|
||||
}
|
||||
|
||||
// updateSeed checks the seed against the existing chain data and rejects it if it
|
||||
// updateChain checks the seed against the existing chain data and rejects it if it
|
||||
// doesn't fit (or no chain data)
|
||||
func (h Handler) updateSeed(ctx sdk.Context, store state.SimpleDB,
|
||||
func (h Handler) updateChain(ctx sdk.Context, store state.SimpleDB,
|
||||
t UpdateChainTx) (res sdk.DeliverResult, err error) {
|
||||
|
||||
chainID := t.ChainID()
|
||||
|
@ -147,21 +147,21 @@ func (h Handler) updateSeed(ctx sdk.Context, store state.SimpleDB,
|
|||
}
|
||||
|
||||
// load the certifier for this chain
|
||||
seed := t.Seed
|
||||
fc := t.Commit
|
||||
space := stack.PrefixedStore(chainID, store)
|
||||
cert, err := newCertifier(space, chainID, seed.Height())
|
||||
cert, err := newCertifier(space, chainID, fc.Height())
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
// this will import the seed if it is valid in the current context
|
||||
err = cert.Update(seed.Checkpoint, seed.Validators)
|
||||
// this will import the commit if it is valid in the current context
|
||||
err = cert.Update(fc)
|
||||
if err != nil {
|
||||
return res, ErrInvalidCommit(err)
|
||||
}
|
||||
|
||||
// update the tracked height in chain info
|
||||
err = s.Update(chainID, t.Seed.Height())
|
||||
err = s.Update(chainID, fc.Height())
|
||||
return res, err
|
||||
}
|
||||
|
||||
|
|
|
@ -27,28 +27,28 @@ func TestIBCRegister(t *testing.T) {
|
|||
appHash := []byte{0, 4, 7, 23}
|
||||
appHash2 := []byte{12, 34, 56, 78}
|
||||
|
||||
// badSeed doesn't validate
|
||||
badSeed := genEmptySeed(keys2, "chain-2", 123, appHash, len(keys2))
|
||||
badSeed.Header.AppHash = appHash2
|
||||
// badCommit doesn't validate
|
||||
badCommit := genEmptyCommit(keys2, "chain-2", 123, appHash, len(keys2))
|
||||
badCommit.Header.AppHash = appHash2
|
||||
|
||||
cases := []struct {
|
||||
seed certifiers.Seed
|
||||
fc certifiers.FullCommit
|
||||
checker errors.CheckErr
|
||||
}{
|
||||
{
|
||||
genEmptySeed(keys, "chain-1", 100, appHash, len(keys)),
|
||||
genEmptyCommit(keys, "chain-1", 100, appHash, len(keys)),
|
||||
errors.NoErr,
|
||||
},
|
||||
{
|
||||
genEmptySeed(keys, "chain-1", 200, appHash, len(keys)),
|
||||
genEmptyCommit(keys, "chain-1", 200, appHash, len(keys)),
|
||||
IsAlreadyRegisteredErr,
|
||||
},
|
||||
{
|
||||
badSeed,
|
||||
badCommit,
|
||||
IsInvalidCommitErr,
|
||||
},
|
||||
{
|
||||
genEmptySeed(keys2, "chain-2", 123, appHash2, 5),
|
||||
genEmptyCommit(keys2, "chain-2", 123, appHash2, 5),
|
||||
errors.NoErr,
|
||||
},
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ func TestIBCRegister(t *testing.T) {
|
|||
app := stack.New().Dispatch(stack.WrapHandler(NewHandler()))
|
||||
|
||||
for i, tc := range cases {
|
||||
tx := RegisterChainTx{tc.seed}.Wrap()
|
||||
tx := RegisterChainTx{tc.fc}.Wrap()
|
||||
_, err := app.DeliverTx(ctx, store, tx)
|
||||
assert.True(tc.checker(err), "%d: %+v", i, err)
|
||||
}
|
||||
|
@ -78,45 +78,45 @@ func TestIBCRegisterPermissions(t *testing.T) {
|
|||
foobaz := sdk.Actor{App: "foo", Address: []byte("baz")}
|
||||
|
||||
cases := []struct {
|
||||
seed certifiers.Seed
|
||||
seed certifiers.FullCommit
|
||||
registrar sdk.Actor
|
||||
signer sdk.Actor
|
||||
checker errors.CheckErr
|
||||
}{
|
||||
// no sig, no registrar
|
||||
{
|
||||
seed: genEmptySeed(keys, "chain-1", 100, appHash, len(keys)),
|
||||
seed: genEmptyCommit(keys, "chain-1", 100, appHash, len(keys)),
|
||||
checker: errors.NoErr,
|
||||
},
|
||||
// sig, no registrar
|
||||
{
|
||||
seed: genEmptySeed(keys, "chain-2", 100, appHash, len(keys)),
|
||||
seed: genEmptyCommit(keys, "chain-2", 100, appHash, len(keys)),
|
||||
signer: foobaz,
|
||||
checker: errors.NoErr,
|
||||
},
|
||||
// registrar, no sig
|
||||
{
|
||||
seed: genEmptySeed(keys, "chain-3", 100, appHash, len(keys)),
|
||||
seed: genEmptyCommit(keys, "chain-3", 100, appHash, len(keys)),
|
||||
registrar: foobar,
|
||||
checker: errors.IsUnauthorizedErr,
|
||||
},
|
||||
// registrar, wrong sig
|
||||
{
|
||||
seed: genEmptySeed(keys, "chain-4", 100, appHash, len(keys)),
|
||||
seed: genEmptyCommit(keys, "chain-4", 100, appHash, len(keys)),
|
||||
signer: foobaz,
|
||||
registrar: foobar,
|
||||
checker: errors.IsUnauthorizedErr,
|
||||
},
|
||||
// registrar, wrong sig
|
||||
{
|
||||
seed: genEmptySeed(keys, "chain-5", 100, appHash, len(keys)),
|
||||
seed: genEmptyCommit(keys, "chain-5", 100, appHash, len(keys)),
|
||||
signer: baz,
|
||||
registrar: foobar,
|
||||
checker: errors.IsUnauthorizedErr,
|
||||
},
|
||||
// registrar, proper sig
|
||||
{
|
||||
seed: genEmptySeed(keys, "chain-6", 100, appHash, len(keys)),
|
||||
seed: genEmptyCommit(keys, "chain-6", 100, appHash, len(keys)),
|
||||
signer: foobar,
|
||||
registrar: foobar,
|
||||
checker: errors.NoErr,
|
||||
|
@ -151,7 +151,7 @@ func TestIBCUpdate(t *testing.T) {
|
|||
keys := certifiers.GenValKeys(7)
|
||||
appHash := []byte{0, 4, 7, 23}
|
||||
start := 100 // initial height
|
||||
root := genEmptySeed(keys, "chain-1", 100, appHash, len(keys))
|
||||
root := genEmptyCommit(keys, "chain-1", 100, appHash, len(keys))
|
||||
|
||||
keys2 := keys.Extend(2)
|
||||
keys3 := keys2.Extend(2)
|
||||
|
@ -165,53 +165,53 @@ func TestIBCUpdate(t *testing.T) {
|
|||
require.Nil(err, "%+v", err)
|
||||
|
||||
cases := []struct {
|
||||
seed certifiers.Seed
|
||||
fc certifiers.FullCommit
|
||||
checker errors.CheckErr
|
||||
}{
|
||||
// same validator, higher up
|
||||
{
|
||||
genEmptySeed(keys, "chain-1", start+50, []byte{22}, len(keys)),
|
||||
genEmptyCommit(keys, "chain-1", start+50, []byte{22}, len(keys)),
|
||||
errors.NoErr,
|
||||
},
|
||||
// same validator, between existing (not most recent)
|
||||
{
|
||||
genEmptySeed(keys, "chain-1", start+5, []byte{15, 43}, len(keys)),
|
||||
genEmptyCommit(keys, "chain-1", start+5, []byte{15, 43}, len(keys)),
|
||||
errors.NoErr,
|
||||
},
|
||||
// same validators, before root of trust
|
||||
{
|
||||
genEmptySeed(keys, "chain-1", start-8, []byte{11, 77}, len(keys)),
|
||||
genEmptyCommit(keys, "chain-1", start-8, []byte{11, 77}, len(keys)),
|
||||
IsHeaderNotFoundErr,
|
||||
},
|
||||
// insufficient signatures
|
||||
{
|
||||
genEmptySeed(keys, "chain-1", start+60, []byte{24}, len(keys)/2),
|
||||
genEmptyCommit(keys, "chain-1", start+60, []byte{24}, len(keys)/2),
|
||||
IsInvalidCommitErr,
|
||||
},
|
||||
// unregistered chain
|
||||
{
|
||||
genEmptySeed(keys, "chain-2", start+60, []byte{24}, len(keys)/2),
|
||||
genEmptyCommit(keys, "chain-2", start+60, []byte{24}, len(keys)/2),
|
||||
IsNotRegisteredErr,
|
||||
},
|
||||
// too much change (keys -> keys3)
|
||||
{
|
||||
genEmptySeed(keys3, "chain-1", start+100, []byte{22}, len(keys3)),
|
||||
genEmptyCommit(keys3, "chain-1", start+100, []byte{22}, len(keys3)),
|
||||
IsInvalidCommitErr,
|
||||
},
|
||||
// legit update to validator set (keys -> keys2)
|
||||
{
|
||||
genEmptySeed(keys2, "chain-1", start+90, []byte{33}, len(keys2)),
|
||||
genEmptyCommit(keys2, "chain-1", start+90, []byte{33}, len(keys2)),
|
||||
errors.NoErr,
|
||||
},
|
||||
// now impossible jump works (keys -> keys2 -> keys3)
|
||||
{
|
||||
genEmptySeed(keys3, "chain-1", start+100, []byte{44}, len(keys3)),
|
||||
genEmptyCommit(keys3, "chain-1", start+100, []byte{44}, len(keys3)),
|
||||
errors.NoErr,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range cases {
|
||||
tx := UpdateChainTx{tc.seed}.Wrap()
|
||||
tx := UpdateChainTx{tc.fc}.Wrap()
|
||||
_, err := app.DeliverTx(ctx, store, tx)
|
||||
assert.True(tc.checker(err), "%d: %+v", i, err)
|
||||
}
|
||||
|
@ -227,7 +227,7 @@ func TestIBCCreatePacket(t *testing.T) {
|
|||
appHash := []byte{1, 2, 3, 4}
|
||||
start := 100 // initial height
|
||||
chainID := "cosmos-hub"
|
||||
root := genEmptySeed(keys, chainID, start, appHash, len(keys))
|
||||
root := genEmptyCommit(keys, chainID, start, appHash, len(keys))
|
||||
|
||||
// create the app and register the root of trust (for chain-1)
|
||||
ctx := stack.MockContext("hub", 50)
|
||||
|
|
|
@ -3,6 +3,7 @@ package ibc
|
|||
import (
|
||||
wire "github.com/tendermint/go-wire"
|
||||
"github.com/tendermint/light-client/certifiers"
|
||||
certerr "github.com/tendermint/light-client/certifiers/errors"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/stack"
|
||||
"github.com/cosmos/cosmos-sdk/state"
|
||||
|
@ -17,26 +18,26 @@ const (
|
|||
// newCertifier loads up the current state of this chain to make a proper certifier
|
||||
// it will load the most recent height before block h if h is positive
|
||||
// if h < 0, it will load the latest height
|
||||
func newCertifier(store state.SimpleDB, chainID string, h int) (*certifiers.InquiringCertifier, error) {
|
||||
func newCertifier(store state.SimpleDB, chainID string, h int) (*certifiers.Inquiring, error) {
|
||||
// each chain has their own prefixed subspace
|
||||
p := newDBProvider(store)
|
||||
|
||||
var seed certifiers.Seed
|
||||
var fc certifiers.FullCommit
|
||||
var err error
|
||||
if h > 0 {
|
||||
// this gets the most recent verified seed below the specified height
|
||||
seed, err = p.GetByHeight(h)
|
||||
// this gets the most recent verified commit below the specified height
|
||||
fc, err = p.GetByHeight(h)
|
||||
} else {
|
||||
// 0 or negative means start at latest seed
|
||||
seed, err = certifiers.LatestSeed(p)
|
||||
// 0 or negative means start at latest commit
|
||||
fc, err = p.LatestCommit()
|
||||
}
|
||||
if err != nil {
|
||||
return nil, ErrHeaderNotFound(h)
|
||||
}
|
||||
|
||||
// we have no source for untrusted keys, but use the db to load trusted history
|
||||
cert := certifiers.NewInquiring(chainID, seed, p,
|
||||
certifiers.MissingProvider{})
|
||||
cert := certifiers.NewInquiring(chainID, fc, p,
|
||||
certifiers.NewMissingProvider())
|
||||
return cert, nil
|
||||
}
|
||||
|
||||
|
@ -55,40 +56,49 @@ func newDBProvider(store state.SimpleDB) *dbProvider {
|
|||
|
||||
var _ certifiers.Provider = &dbProvider{}
|
||||
|
||||
func (d *dbProvider) StoreSeed(seed certifiers.Seed) error {
|
||||
func (d *dbProvider) StoreCommit(fc certifiers.FullCommit) error {
|
||||
// TODO: don't duplicate data....
|
||||
b := wire.BinaryBytes(seed)
|
||||
d.byHash.Set(seed.Hash(), b)
|
||||
d.byHeight.Set(uint64(seed.Height()), b)
|
||||
b := wire.BinaryBytes(fc)
|
||||
d.byHash.Set(fc.ValidatorsHash(), b)
|
||||
d.byHeight.Set(uint64(fc.Height()), b)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *dbProvider) GetByHeight(h int) (seed certifiers.Seed, err error) {
|
||||
b, _ := d.byHeight.LTE(uint64(h))
|
||||
func (d *dbProvider) LatestCommit() (fc certifiers.FullCommit, err error) {
|
||||
b, _ := d.byHeight.Top()
|
||||
if b == nil {
|
||||
return seed, certifiers.ErrSeedNotFound()
|
||||
return fc, certerr.ErrCommitNotFound()
|
||||
}
|
||||
err = wire.ReadBinaryBytes(b, &seed)
|
||||
err = wire.ReadBinaryBytes(b, &fc)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *dbProvider) GetByHash(hash []byte) (seed certifiers.Seed, err error) {
|
||||
func (d *dbProvider) GetByHeight(h int) (fc certifiers.FullCommit, err error) {
|
||||
b, _ := d.byHeight.LTE(uint64(h))
|
||||
if b == nil {
|
||||
return fc, certerr.ErrCommitNotFound()
|
||||
}
|
||||
err = wire.ReadBinaryBytes(b, &fc)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *dbProvider) GetByHash(hash []byte) (fc certifiers.FullCommit, err error) {
|
||||
b := d.byHash.Get(hash)
|
||||
if b == nil {
|
||||
return seed, certifiers.ErrSeedNotFound()
|
||||
return fc, certerr.ErrCommitNotFound()
|
||||
}
|
||||
err = wire.ReadBinaryBytes(b, &seed)
|
||||
err = wire.ReadBinaryBytes(b, &fc)
|
||||
return
|
||||
}
|
||||
|
||||
// GetExactHeight is like GetByHeight, but returns an error instead of
|
||||
// closest match if there is no exact match
|
||||
func (d *dbProvider) GetExactHeight(h int) (seed certifiers.Seed, err error) {
|
||||
seed, err = d.GetByHeight(h)
|
||||
func (d *dbProvider) GetExactHeight(h int) (fc certifiers.FullCommit, err error) {
|
||||
fc, err = d.GetByHeight(h)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if seed.Height() != h {
|
||||
if fc.Height() != h {
|
||||
err = ErrHeaderNotFound(h)
|
||||
}
|
||||
return
|
||||
|
|
|
@ -8,21 +8,22 @@ import (
|
|||
|
||||
"github.com/cosmos/cosmos-sdk/state"
|
||||
"github.com/tendermint/light-client/certifiers"
|
||||
certerr "github.com/tendermint/light-client/certifiers/errors"
|
||||
)
|
||||
|
||||
func assertSeedEqual(t *testing.T, s, s2 certifiers.Seed) {
|
||||
func assertCommitsEqual(t *testing.T, fc, fc2 certifiers.FullCommit) {
|
||||
assert := assert.New(t)
|
||||
assert.Equal(s.Height(), s2.Height())
|
||||
assert.Equal(s.Hash(), s2.Hash())
|
||||
assert.Equal(fc.Height(), fc2.Height())
|
||||
assert.Equal(fc.ValidatorsHash(), fc2.ValidatorsHash())
|
||||
// TODO: more
|
||||
}
|
||||
|
||||
func TestProviderStore(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
|
||||
// make a few seeds
|
||||
// make a few commits
|
||||
keys := certifiers.GenValKeys(2)
|
||||
seeds := makeSeeds(keys, 4, "some-chain", "demo-store")
|
||||
commits := makeCommits(keys, 4, "some-chain", "demo-store")
|
||||
|
||||
// make a provider
|
||||
store := state.NewMemKVStore()
|
||||
|
@ -31,41 +32,41 @@ func TestProviderStore(t *testing.T) {
|
|||
// check it...
|
||||
_, err := p.GetByHeight(20)
|
||||
require.NotNil(err)
|
||||
assert.True(certifiers.IsSeedNotFoundErr(err))
|
||||
assert.True(certerr.IsCommitNotFoundErr(err))
|
||||
|
||||
// add a seed
|
||||
for _, s := range seeds {
|
||||
err = p.StoreSeed(s)
|
||||
// add commits
|
||||
for _, fc := range commits {
|
||||
err = p.StoreCommit(fc)
|
||||
require.Nil(err)
|
||||
}
|
||||
|
||||
// make sure we get it...
|
||||
s := seeds[0]
|
||||
val, err := p.GetByHeight(s.Height())
|
||||
fc := commits[0]
|
||||
val, err := p.GetByHeight(fc.Height())
|
||||
if assert.Nil(err) {
|
||||
assertSeedEqual(t, s, val)
|
||||
assertCommitsEqual(t, fc, val)
|
||||
}
|
||||
|
||||
// make sure we get higher
|
||||
val, err = p.GetByHeight(s.Height() + 2)
|
||||
val, err = p.GetByHeight(fc.Height() + 2)
|
||||
if assert.Nil(err) {
|
||||
assertSeedEqual(t, s, val)
|
||||
assertCommitsEqual(t, fc, val)
|
||||
}
|
||||
|
||||
// below is nothing
|
||||
_, err = p.GetByHeight(s.Height() - 2)
|
||||
assert.True(certifiers.IsSeedNotFoundErr(err))
|
||||
_, err = p.GetByHeight(fc.Height() - 2)
|
||||
assert.True(certerr.IsCommitNotFoundErr(err))
|
||||
|
||||
// make sure we get highest
|
||||
val, err = certifiers.LatestSeed(p)
|
||||
val, err = p.LatestCommit()
|
||||
if assert.Nil(err) {
|
||||
assertSeedEqual(t, seeds[3], val)
|
||||
assertCommitsEqual(t, commits[3], val)
|
||||
}
|
||||
|
||||
// make sure by hash also (note all have same hash, so overwritten)
|
||||
val, err = p.GetByHash(seeds[1].Hash())
|
||||
val, err = p.GetByHash(commits[1].ValidatorsHash())
|
||||
if assert.Nil(err) {
|
||||
assertSeedEqual(t, seeds[3], val)
|
||||
assertCommitsEqual(t, commits[3], val)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,18 +76,17 @@ func TestDBProvider(t *testing.T) {
|
|||
checkProvider(t, p, "test-db", "bling")
|
||||
}
|
||||
|
||||
func makeSeeds(keys certifiers.ValKeys, count int, chainID, app string) []certifiers.Seed {
|
||||
func makeCommits(keys certifiers.ValKeys, count int, chainID, app string) []certifiers.FullCommit {
|
||||
appHash := []byte(app)
|
||||
seeds := make([]certifiers.Seed, count)
|
||||
commits := make([]certifiers.FullCommit, count)
|
||||
for i := 0; i < count; i++ {
|
||||
// two seeds for each validator, to check how we handle dups
|
||||
// two commits for each validator, to check how we handle dups
|
||||
// (10, 0), (10, 1), (10, 1), (10, 2), (10, 2), ...
|
||||
vals := keys.ToValidators(10, int64(count/2))
|
||||
h := 20 + 10*i
|
||||
check := keys.GenCheckpoint(chainID, h, nil, vals, appHash, 0, len(keys))
|
||||
seeds[i] = certifiers.Seed{check, vals}
|
||||
commits[i] = keys.GenFullCommit(chainID, h, nil, vals, appHash, 0, len(keys))
|
||||
}
|
||||
return seeds
|
||||
return commits
|
||||
}
|
||||
|
||||
func checkProvider(t *testing.T, p certifiers.Provider, chainID, app string) {
|
||||
|
@ -94,43 +94,43 @@ func checkProvider(t *testing.T, p certifiers.Provider, chainID, app string) {
|
|||
keys := certifiers.GenValKeys(5)
|
||||
count := 10
|
||||
|
||||
// make a bunch of seeds...
|
||||
seeds := makeSeeds(keys, count, chainID, app)
|
||||
// make a bunch of commits...
|
||||
commits := makeCommits(keys, count, chainID, app)
|
||||
|
||||
// check provider is empty
|
||||
seed, err := p.GetByHeight(20)
|
||||
fc, err := p.GetByHeight(20)
|
||||
require.NotNil(err)
|
||||
assert.True(certifiers.IsSeedNotFoundErr(err))
|
||||
assert.True(certerr.IsCommitNotFoundErr(err))
|
||||
|
||||
seed, err = p.GetByHash(seeds[3].Hash())
|
||||
fc, err = p.GetByHash(commits[3].ValidatorsHash())
|
||||
require.NotNil(err)
|
||||
assert.True(certifiers.IsSeedNotFoundErr(err))
|
||||
assert.True(certerr.IsCommitNotFoundErr(err))
|
||||
|
||||
// now add them all to the provider
|
||||
for _, s := range seeds {
|
||||
err = p.StoreSeed(s)
|
||||
for _, fc := range commits {
|
||||
err = p.StoreCommit(fc)
|
||||
require.Nil(err)
|
||||
// and make sure we can get it back
|
||||
s2, err := p.GetByHash(s.Hash())
|
||||
fc2, err := p.GetByHash(fc.ValidatorsHash())
|
||||
assert.Nil(err)
|
||||
assertSeedEqual(t, s, s2)
|
||||
assertCommitsEqual(t, fc, fc2)
|
||||
// by height as well
|
||||
s2, err = p.GetByHeight(s.Height())
|
||||
fc2, err = p.GetByHeight(fc.Height())
|
||||
assert.Nil(err)
|
||||
assertSeedEqual(t, s, s2)
|
||||
assertCommitsEqual(t, fc, fc2)
|
||||
}
|
||||
|
||||
// make sure we get the last hash if we overstep
|
||||
seed, err = p.GetByHeight(5000)
|
||||
fc, err = p.GetByHeight(5000)
|
||||
if assert.Nil(err) {
|
||||
assertSeedEqual(t, seeds[count-1], seed)
|
||||
assertCommitsEqual(t, commits[count-1], fc)
|
||||
}
|
||||
|
||||
// and middle ones as well
|
||||
seed, err = p.GetByHeight(47)
|
||||
fc, err = p.GetByHeight(47)
|
||||
if assert.Nil(err) {
|
||||
// we only step by 10, so 40 must be the one below this
|
||||
assert.Equal(40, seed.Height())
|
||||
assert.Equal(40, fc.Height())
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -32,8 +32,8 @@ func NewMockChain(chainID string, numKeys int) MockChain {
|
|||
|
||||
// GetRegistrationTx returns a valid tx to register this chain
|
||||
func (m MockChain) GetRegistrationTx(h int) RegisterChainTx {
|
||||
seed := genEmptySeed(m.keys, m.chainID, h, m.tree.Hash(), len(m.keys))
|
||||
return RegisterChainTx{seed}
|
||||
fc := genEmptyCommit(m.keys, m.chainID, h, m.tree.Hash(), len(m.keys))
|
||||
return RegisterChainTx{fc}
|
||||
}
|
||||
|
||||
// MakePostPacket commits the packet locally and returns the proof,
|
||||
|
@ -42,18 +42,17 @@ func (m MockChain) MakePostPacket(packet Packet, h int) (
|
|||
PostPacketTx, UpdateChainTx) {
|
||||
|
||||
post := makePostPacket(m.tree, packet, m.chainID, h)
|
||||
seed := genEmptySeed(m.keys, m.chainID, h+1, m.tree.Hash(), len(m.keys))
|
||||
update := UpdateChainTx{seed}
|
||||
fc := genEmptyCommit(m.keys, m.chainID, h+1, m.tree.Hash(), len(m.keys))
|
||||
update := UpdateChainTx{fc}
|
||||
|
||||
return post, update
|
||||
}
|
||||
|
||||
func genEmptySeed(keys certifiers.ValKeys, chain string, h int,
|
||||
appHash []byte, count int) certifiers.Seed {
|
||||
func genEmptyCommit(keys certifiers.ValKeys, chain string, h int,
|
||||
appHash []byte, count int) certifiers.FullCommit {
|
||||
|
||||
vals := keys.ToValidators(10, 0)
|
||||
cp := keys.GenCheckpoint(chain, h, nil, vals, appHash, 0, count)
|
||||
return certifiers.Seed{cp, vals}
|
||||
return keys.GenFullCommit(chain, h, nil, vals, appHash, 0, count)
|
||||
}
|
||||
|
||||
func makePostPacket(tree *iavl.Tree, packet Packet, fromID string, fromHeight int) PostPacketTx {
|
||||
|
|
|
@ -32,17 +32,17 @@ func init() {
|
|||
|
||||
// RegisterChainTx allows you to register a new chain on this blockchain
|
||||
type RegisterChainTx struct {
|
||||
Seed certifiers.Seed `json:"seed"`
|
||||
Commit certifiers.FullCommit `json:"seed"`
|
||||
}
|
||||
|
||||
// ChainID helps get the chain this tx refers to
|
||||
func (r RegisterChainTx) ChainID() string {
|
||||
return r.Seed.Header.ChainID
|
||||
return r.Commit.Header.ChainID
|
||||
}
|
||||
|
||||
// ValidateBasic makes sure this is consistent, without checking the sigs
|
||||
func (r RegisterChainTx) ValidateBasic() error {
|
||||
err := r.Seed.ValidateBasic(r.ChainID())
|
||||
err := r.Commit.ValidateBasic(r.ChainID())
|
||||
if err != nil {
|
||||
err = ErrInvalidCommit(err)
|
||||
}
|
||||
|
@ -56,17 +56,17 @@ func (r RegisterChainTx) Wrap() sdk.Tx {
|
|||
|
||||
// UpdateChainTx updates the state of this chain
|
||||
type UpdateChainTx struct {
|
||||
Seed certifiers.Seed `json:"seed"`
|
||||
Commit certifiers.FullCommit `json:"seed"`
|
||||
}
|
||||
|
||||
// ChainID helps get the chain this tx refers to
|
||||
func (u UpdateChainTx) ChainID() string {
|
||||
return u.Seed.Header.ChainID
|
||||
return u.Commit.Header.ChainID
|
||||
}
|
||||
|
||||
// ValidateBasic makes sure this is consistent, without checking the sigs
|
||||
func (u UpdateChainTx) ValidateBasic() error {
|
||||
err := u.Seed.ValidateBasic(u.ChainID())
|
||||
err := u.Commit.ValidateBasic(u.ChainID())
|
||||
if err != nil {
|
||||
err = ErrInvalidCommit(err)
|
||||
}
|
||||
|
|
|
@ -7,9 +7,8 @@ import (
|
|||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
lc "github.com/tendermint/light-client"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/commands"
|
||||
"github.com/cosmos/cosmos-sdk/client/commands/query"
|
||||
"github.com/cosmos/cosmos-sdk/modules/nonce"
|
||||
|
@ -46,7 +45,7 @@ func doNonceQuery(signers []sdk.Actor) (sequence uint32, height uint64, err erro
|
|||
key := stack.PrefixedKey(nonce.NameNonce, nonce.GetSeqKey(signers))
|
||||
prove := !viper.GetBool(commands.FlagTrustNode)
|
||||
height, err = query.GetParsed(key, &sequence, query.GetHeight(), prove)
|
||||
if lc.IsNoDataErr(err) {
|
||||
if client.IsNoDataErr(err) {
|
||||
// no data, return sequence 0
|
||||
return 0, 0, nil
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"github.com/spf13/viper"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/commands"
|
||||
"github.com/cosmos/cosmos-sdk/client/commands/query"
|
||||
"github.com/cosmos/cosmos-sdk/errors"
|
||||
|
@ -16,7 +17,6 @@ import (
|
|||
"github.com/cosmos/cosmos-sdk/modules/nonce"
|
||||
"github.com/cosmos/cosmos-sdk/stack"
|
||||
wire "github.com/tendermint/go-wire"
|
||||
lightclient "github.com/tendermint/light-client"
|
||||
"github.com/tendermint/tmlibs/common"
|
||||
)
|
||||
|
||||
|
@ -48,7 +48,7 @@ func doQueryNonce(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
// query sequence number
|
||||
data, height, err := query.Get(key, h, prove)
|
||||
if lightclient.IsNoDataErr(err) {
|
||||
if client.IsNoDataErr(err) {
|
||||
err = fmt.Errorf("nonce empty for address: %q", signature)
|
||||
common.WriteError(w, err)
|
||||
return
|
||||
|
|
Loading…
Reference in New Issue