Merge pull request #265 from cosmos/feature/reorg-light-client

Reorg light client
This commit is contained in:
Ethan Frey 2017-10-25 19:54:10 +02:00 committed by GitHub
commit 8f9caa8907
32 changed files with 390 additions and 326 deletions

View File

@ -1,30 +1,32 @@
package seeds package commits
import ( import (
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
"github.com/tendermint/light-client/certifiers/files"
"github.com/cosmos/cosmos-sdk/client/commands" "github.com/cosmos/cosmos-sdk/client/commands"
) )
var exportCmd = &cobra.Command{ var exportCmd = &cobra.Command{
Use: "export <file>", Use: "export <file>",
Short: "Export selected seeds to given file", Short: "Export selected commits to given file",
Long: `Exports the most recent seed to a binary file. Long: `Exports the most recent commit to a binary file.
If desired, you can select by an older height or validator hash. If desired, you can select by an older height or validator hash.
`, `,
RunE: commands.RequireInit(exportSeed), RunE: commands.RequireInit(exportCommit),
SilenceUsage: true, SilenceUsage: true,
} }
func init() { func init() {
exportCmd.Flags().Int(heightFlag, 0, "Show the seed with closest height to this") exportCmd.Flags().Int(heightFlag, 0, "Show the commit with closest height to this")
exportCmd.Flags().String(hashFlag, "", "Show the seed matching the validator hash") exportCmd.Flags().String(hashFlag, "", "Show the commit matching the validator hash")
RootCmd.AddCommand(exportCmd) 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 { if len(args) != 1 || len(args[0]) == 0 {
return errors.New("You must provide a filepath to output") 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() trust, _ := commands.GetProviders()
h := viper.GetInt(heightFlag) h := viper.GetInt(heightFlag)
hash := viper.GetString(hashFlag) hash := viper.GetString(hashFlag)
seed, err := loadSeed(trust, h, hash, "") fc, err := loadCommit(trust, h, hash, "")
if err != nil { if err != nil {
return err return err
} }
// now get the output file and write it // now get the output file and write it
return seed.WriteJSON(path) return files.SaveFullCommitJSON(fc, path)
} }

View File

@ -1,4 +1,4 @@
package seeds package commits
import ( import (
"fmt" "fmt"
@ -7,7 +7,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
"github.com/tendermint/light-client/certifiers" "github.com/tendermint/light-client/certifiers/files"
"github.com/cosmos/cosmos-sdk/client/commands" "github.com/cosmos/cosmos-sdk/client/commands"
) )
@ -18,9 +18,9 @@ const (
var importCmd = &cobra.Command{ var importCmd = &cobra.Command{
Use: "import <file>", Use: "import <file>",
Short: "Imports a new seed from the given file", Short: "Imports a new commit from the given file",
Long: `Validate this file and update to the given seed if secure.`, Long: `Validate this file and update to the given commit if secure.`,
RunE: commands.RequireInit(importSeed), RunE: commands.RequireInit(importCommit),
SilenceUsage: true, SilenceUsage: true,
} }
@ -29,7 +29,7 @@ func init() {
RootCmd.AddCommand(importCmd) 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 { if len(args) != 1 || len(args[0]) == 0 {
return errors.New("You must provide an input file") 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 // parse the input file
path := args[0] path := args[0]
seed, err := certifiers.LoadSeedJSON(path) fc, err := files.LoadFullCommitJSON(path)
if err != nil { if err != nil {
return err return err
} }
// just do simple checks in --dry-run // just do simple checks in --dry-run
if viper.GetBool(dryFlag) { if viper.GetBool(dryFlag) {
fmt.Printf("Testing seed %d/%X\n", seed.Height(), seed.Hash()) fmt.Printf("Testing commit %d/%X\n", fc.Height(), fc.ValidatorsHash())
err = seed.ValidateBasic(cert.ChainID()) err = fc.ValidateBasic(cert.ChainID())
} else { } else {
fmt.Printf("Importing seed %d/%X\n", seed.Height(), seed.Hash()) fmt.Printf("Importing commit %d/%X\n", fc.Height(), fc.ValidatorsHash())
err = cert.Update(seed.Checkpoint, seed.Validators) err = cert.Update(fc)
} }
return err return err
} }

View File

@ -1,15 +1,15 @@
package seeds package commits
import "github.com/spf13/cobra" import "github.com/spf13/cobra"
// RootCmd represents the base command when called without any subcommands // RootCmd represents the base command when called without any subcommands
var RootCmd = &cobra.Command{ var RootCmd = &cobra.Command{
Use: "seeds", Use: "commits",
Short: "Verify seeds from your local store", Short: "Verify commits from your local store",
Long: `Seeds allows you to inspect and update the validator set for the chain. 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 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. is used to verify all header and merkle proofs.
`, `,
} }

View File

@ -1,4 +1,4 @@
package seeds package commits
import ( import (
"encoding/hex" "encoding/hex"
@ -9,6 +9,7 @@ import (
"github.com/spf13/viper" "github.com/spf13/viper"
"github.com/tendermint/light-client/certifiers" "github.com/tendermint/light-client/certifiers"
"github.com/tendermint/light-client/certifiers/files"
"github.com/cosmos/cosmos-sdk/client/commands" "github.com/cosmos/cosmos-sdk/client/commands"
) )
@ -21,53 +22,53 @@ const (
var showCmd = &cobra.Command{ var showCmd = &cobra.Command{
Use: "show", 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. Long: `Shows the most recent downloaded key by default.
If desired, you can select by height, validator hash, or a file. If desired, you can select by height, validator hash, or a file.
`, `,
RunE: commands.RequireInit(showSeed), RunE: commands.RequireInit(showCommit),
SilenceUsage: true, SilenceUsage: true,
} }
func init() { func init() {
showCmd.Flags().Int(heightFlag, 0, "Show the seed with closest height to this") showCmd.Flags().Int(heightFlag, 0, "Show the commit with closest height to this")
showCmd.Flags().String(hashFlag, "", "Show the seed matching the validator hash") showCmd.Flags().String(hashFlag, "", "Show the commit matching the validator hash")
showCmd.Flags().String(fileFlag, "", "Show the seed stored in the given file") showCmd.Flags().String(fileFlag, "", "Show the commit stored in the given file")
RootCmd.AddCommand(showCmd) RootCmd.AddCommand(showCmd)
} }
func loadSeed(p certifiers.Provider, h int, hash, file string) (seed certifiers.Seed, err error) { func loadCommit(p certifiers.Provider, h int, hash, file string) (fc certifiers.FullCommit, err error) {
// load the seed from the proper place // load the commit from the proper place
if h != 0 { if h != 0 {
seed, err = p.GetByHeight(h) fc, err = p.GetByHeight(h)
} else if hash != "" { } else if hash != "" {
var vhash []byte var vhash []byte
vhash, err = hex.DecodeString(hash) vhash, err = hex.DecodeString(hash)
if err == nil { if err == nil {
seed, err = p.GetByHash(vhash) fc, err = p.GetByHash(vhash)
} }
} else if file != "" { } else if file != "" {
seed, err = certifiers.LoadSeedJSON(file) fc, err = files.LoadFullCommitJSON(file)
} else { } else {
// default is latest seed // default is latest commit
seed, err = certifiers.LatestSeed(p) fc, err = p.LatestCommit()
} }
return return
} }
func showSeed(cmd *cobra.Command, args []string) error { func showCommit(cmd *cobra.Command, args []string) error {
trust, _ := commands.GetProviders() trust, _ := commands.GetProviders()
h := viper.GetInt(heightFlag) h := viper.GetInt(heightFlag)
hash := viper.GetString(hashFlag) hash := viper.GetString(hashFlag)
file := viper.GetString(fileFlag) file := viper.GetString(fileFlag)
seed, err := loadSeed(trust, h, hash, file) fc, err := loadCommit(trust, h, hash, file)
if err != nil { if err != nil {
return err return err
} }
// now render it! // now render it!
data, err := json.MarshalIndent(seed, "", " ") data, err := json.MarshalIndent(fc, "", " ")
fmt.Println(string(data)) fmt.Println(string(data))
return err return err
} }

View File

@ -1,4 +1,4 @@
package seeds package commits
import ( import (
"fmt" "fmt"
@ -13,8 +13,8 @@ import (
var updateCmd = &cobra.Command{ var updateCmd = &cobra.Command{
Use: "update", Use: "update",
Short: "Update seed to current height if possible", Short: "Update commit to current height if possible",
RunE: commands.RequireInit(updateSeed), RunE: commands.RequireInit(updateCommit),
SilenceUsage: true, SilenceUsage: true,
} }
@ -23,27 +23,27 @@ func init() {
RootCmd.AddCommand(updateCmd) RootCmd.AddCommand(updateCmd)
} }
func updateSeed(cmd *cobra.Command, args []string) error { func updateCommit(cmd *cobra.Command, args []string) error {
cert, err := commands.GetCertifier() cert, err := commands.GetCertifier()
if err != nil { if err != nil {
return err return err
} }
h := viper.GetInt(heightFlag) h := viper.GetInt(heightFlag)
var seed certifiers.Seed var fc certifiers.FullCommit
if h <= 0 { if h <= 0 {
// get the lastest from our source // get the lastest from our source
seed, err = certifiers.LatestSeed(cert.SeedSource) fc, err = cert.Source.LatestCommit()
} else { } else {
seed, err = cert.SeedSource.GetByHeight(h) fc, err = cert.Source.GetByHeight(h)
} }
if err != nil { if err != nil {
return err return err
} }
// let the certifier do it's magic to update.... // let the certifier do it's magic to update....
fmt.Printf("Trying to update to height: %d...\n", seed.Height()) fmt.Printf("Trying to update to height: %d...\n", fc.Height())
err = cert.Update(seed.Checkpoint, seed.Validators) err = cert.Update(fc)
if err != nil { if err != nil {
return err return err
} }

View File

@ -74,7 +74,7 @@ func GetProviders() (trusted certifiers.Provider, source certifiers.Provider) {
} }
// GetCertifier constructs a dynamic certifier from the config info // GetCertifier constructs a dynamic certifier from the config info
func GetCertifier() (*certifiers.InquiringCertifier, error) { func GetCertifier() (*certifiers.Inquiring, error) {
// load up the latest store.... // load up the latest store....
trust := GetTrustedProvider() trust := GetTrustedProvider()
source := GetSourceProvider() source := GetSourceProvider()

View File

@ -29,7 +29,7 @@ var (
//nolint //nolint
const ( const (
SeedFlag = "seed" CommitFlag = "commit"
HashFlag = "valhash" HashFlag = "valhash"
GenesisFlag = "genesis" GenesisFlag = "genesis"
FlagTrustNode = "trust-node" FlagTrustNode = "trust-node"
@ -52,7 +52,7 @@ var ResetCmd = &cobra.Command{
func init() { func init() {
InitCmd.Flags().Bool("force-reset", false, "Wipe clean an existing client store, except for keys") 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(HashFlag, "", "Trusted validator hash (must match to accept)")
InitCmd.Flags().String(GenesisFlag, "", "Genesis file with chainid and validators (optional)") 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 { if err != nil {
return err return err
} }
err = initSeed() err = initTrust()
return err return err
} }
@ -275,27 +275,27 @@ func initConfigFile(cmd *cobra.Command) error {
return nil return nil
} }
func initSeed() (err error) { func initTrust() (err error) {
// create a provider.... // create a provider....
trust, source := GetProviders() trust, source := GetProviders()
// load a seed file, or get data from the provider // load a commit file, or get data from the provider
var seed certifiers.Seed var fc certifiers.FullCommit
seedFile := viper.GetString(SeedFlag) commitFile := viper.GetString(CommitFlag)
if seedFile == "" { if commitFile == "" {
fmt.Println("Loading validator set from tendermint rpc...") fmt.Println("Loading validator set from tendermint rpc...")
seed, err = certifiers.LatestSeed(source) fc, err = source.LatestCommit()
} else { } else {
fmt.Printf("Loading validators from file %s\n", seedFile) fmt.Printf("Loading validators from file %s\n", commitFile)
seed, err = certifiers.LoadSeed(seedFile) fc, err = files.LoadFullCommit(commitFile)
} }
// can't load the seed? abort! // can't load the commit? abort!
if err != nil { if err != nil {
return err return err
} }
// make sure it is a proper seed // make sure it is a proper commit
err = seed.ValidateBasic(viper.GetString(ChainFlag)) err = fc.ValidateBasic(viper.GetString(ChainFlag))
if err != nil { if err != nil {
return err return err
} }
@ -305,30 +305,30 @@ func initSeed() (err error) {
if hash != "" { if hash != "" {
var hashb []byte var hashb []byte
hashb, err = hex.DecodeString(hash) hashb, err = hex.DecodeString(hash)
if err == nil && !bytes.Equal(hashb, seed.Hash()) { if err == nil && !bytes.Equal(hashb, fc.ValidatorsHash()) {
err = errors.Errorf("Seed hash doesn't match expectation: %X", seed.Hash()) err = errors.Errorf("Validator hash doesn't match expectation: %X", fc.ValidatorsHash())
} }
} else { } else {
err = validateHash(seed) err = validateHash(fc)
} }
if err != nil { if err != nil {
return err return err
} }
// if accepted, store seed as current state // if accepted, store commit as current state
trust.StoreSeed(seed) trust.StoreCommit(fc)
return nil return nil
} }
func validateHash(seed certifiers.Seed) error { func validateHash(fc certifiers.FullCommit) error {
// ask the user to verify the validator hash // ask the user to verify the validator hash
fmt.Println("\nImportant: if this is incorrect, all interaction with the chain will be insecure!") 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)?") fmt.Println("Is this valid (y/n)?")
valid := askForConfirmation() valid := askForConfirmation()
if !valid { 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 return nil
} }

View File

@ -12,6 +12,7 @@ import (
"github.com/tendermint/go-wire/data" "github.com/tendermint/go-wire/data"
"github.com/tendermint/iavl" "github.com/tendermint/iavl"
"github.com/tendermint/light-client/proofs" "github.com/tendermint/light-client/proofs"
rpcclient "github.com/tendermint/tendermint/rpc/client" rpcclient "github.com/tendermint/tendermint/rpc/client"
"github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client"

View File

@ -52,7 +52,7 @@ func txQueryCmd(cmd *cobra.Command, args []string) error {
return err return err
} }
check, err := client.GetCertifiedCheckpoint(res.Height, node, cert) check, err := client.GetCertifiedCommit(res.Height, node, cert)
if err != nil { if err != nil {
return err return err
} }

View File

@ -5,8 +5,11 @@ import (
"github.com/tendermint/light-client/certifiers" "github.com/tendermint/light-client/certifiers"
certclient "github.com/tendermint/light-client/certifiers/client" 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/certifiers/files"
"github.com/tendermint/light-client/proofs"
rpcclient "github.com/tendermint/tendermint/rpc/client" 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 // GetRPCProvider retuns a certifier compatible data source using
// tendermint RPC // tendermint RPC
func GetRPCProvider(url string) certifiers.Provider { func GetRPCProvider(url string) certifiers.Provider {
return certclient.NewHTTP(url) return certclient.NewHTTPProvider(url)
} }
// GetLocalProvider returns a reference to a file store of headers // 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 // GetCertifier initializes an inquiring certifier given a fixed chainID
// and a local source of trusted data with at least one seed // and a local source of trusted data with at least one seed
func GetCertifier(chainID string, trust certifiers.Provider, 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 // this gets the most recent verified commit
seed, err := certifiers.LatestSeed(trust) fc, err := trust.LatestCommit()
if certifiers.IsSeedNotFoundErr(err) { if certerr.IsCommitNotFoundErr(err) {
return nil, errors.New("Please run init first to establish a root of trust") return nil, errors.New("Please run init first to establish a root of trust")
} }
if err != nil { if err != nil {
return nil, err return nil, err
} }
cert := certifiers.NewInquiring(chainID, seed, trust, source) cert := certifiers.NewInquiring(chainID, fc, trust, source)
return cert, nil return cert, nil
} }
// SecureClient uses a given certifier to wrap an connection to an untrusted // SecureClient uses a given certifier to wrap an connection to an untrusted
// host and return a cryptographically secure rpc client. // host and return a cryptographically secure rpc client.
func SecureClient(c rpcclient.Client, cert *certifiers.InquiringCertifier) rpcclient.Client { func SecureClient(c rpcclient.Client, cert *certifiers.Inquiring) rpcclient.Client {
return certclient.Wrap(c, cert) return proofs.Wrap(c, cert)
} }

22
client/errors.go Normal file
View File

@ -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)
}
//--------------------------------------------

18
client/errors_test.go Normal file
View File

@ -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))
}

View File

@ -5,8 +5,8 @@ import (
"github.com/tendermint/go-wire/data" "github.com/tendermint/go-wire/data"
"github.com/tendermint/iavl" "github.com/tendermint/iavl"
lc "github.com/tendermint/light-client"
"github.com/tendermint/light-client/certifiers" "github.com/tendermint/light-client/certifiers"
certerr "github.com/tendermint/light-client/certifiers/errors"
"github.com/tendermint/tendermint/rpc/client" "github.com/tendermint/tendermint/rpc/client"
) )
@ -38,7 +38,7 @@ func GetWithProof(key []byte, reqHeight int, node client.Client,
return return
} }
if len(resp.Key) == 0 || len(resp.Proof) == 0 { if len(resp.Key) == 0 || len(resp.Proof) == 0 {
err = lc.ErrNoData() err = ErrNoData()
return return
} }
if resp.Height == 0 { 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 // AppHash for height H is in header H+1
var check lc.Checkpoint var commit *certifiers.Commit
check, err = GetCertifiedCheckpoint(int(resp.Height+1), node, cert) commit, err = GetCertifiedCommit(int(resp.Height+1), node, cert)
if err != nil { if err != nil {
return 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. // 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 { if err != nil {
err = errors.Wrap(err, "Couldn't verify proof") err = errors.Wrap(err, "Couldn't verify proof")
return return
@ -79,12 +79,12 @@ func GetWithProof(key []byte, reqHeight int, node client.Client,
return return
} }
// Validate the proof against the certified header to ensure data integrity. // 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 { if err != nil {
err = errors.Wrap(err, "Couldn't verify proof") err = errors.Wrap(err, "Couldn't verify proof")
return return
} }
err = lc.ErrNoData() err = ErrNoData()
proof = aproof proof = aproof
} }
@ -92,28 +92,25 @@ func GetWithProof(key []byte, reqHeight int, node client.Client,
return 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. // and certifies it. Returns error if unable to get a proven header.
func GetCertifiedCheckpoint(h int, node client.Client, func GetCertifiedCommit(h int, node client.Client,
cert certifiers.Certifier) (empty lc.Checkpoint, err error) { cert certifiers.Certifier) (empty *certifiers.Commit, err error) {
// FIXME: cannot use cert.GetByHeight for now, as it also requires // FIXME: cannot use cert.GetByHeight for now, as it also requires
// Validators and will fail on querying tendermint for non-current height. // Validators and will fail on querying tendermint for non-current height.
// When this is supported, we should use it instead... // When this is supported, we should use it instead...
client.WaitForHeight(node, h, nil) client.WaitForHeight(node, h, nil)
commit, err := node.Commit(&h) cresp, err := node.Commit(&h)
if err != nil { if err != nil {
return return
} }
check := lc.Checkpoint{ commit := certifiers.CommitFromResult(cresp)
Header: commit.Header,
Commit: commit.Commit,
}
// validate downloaded checkpoint with our request and trust store. // validate downloaded checkpoint with our request and trust store.
if check.Height() != h { if commit.Height() != h {
return empty, lc.ErrHeightMismatch(h, check.Height()) return empty, certerr.ErrHeightMismatch(h, commit.Height())
} }
err = cert.Certify(check) err = cert.Certify(commit)
return check, nil return commit, nil
} }

View File

@ -9,14 +9,14 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/tendermint/go-wire" "github.com/tendermint/go-wire"
lc "github.com/tendermint/light-client"
"github.com/tendermint/light-client/certifiers" "github.com/tendermint/light-client/certifiers"
certclient "github.com/tendermint/light-client/certifiers/client" certclient "github.com/tendermint/light-client/certifiers/client"
"github.com/tendermint/tmlibs/log"
nm "github.com/tendermint/tendermint/node" nm "github.com/tendermint/tendermint/node"
"github.com/tendermint/tendermint/rpc/client" "github.com/tendermint/tendermint/rpc/client"
rpctest "github.com/tendermint/tendermint/rpc/test" rpctest "github.com/tendermint/tendermint/rpc/test"
"github.com/tendermint/tendermint/types" "github.com/tendermint/tendermint/types"
"github.com/tendermint/tmlibs/log"
sdkapp "github.com/cosmos/cosmos-sdk/app" sdkapp "github.com/cosmos/cosmos-sdk/app"
"github.com/cosmos/cosmos-sdk/modules/eyes" "github.com/cosmos/cosmos-sdk/modules/eyes"
@ -59,13 +59,13 @@ func TestAppProofs(t *testing.T) {
brh := br.Height brh := br.Height
// This sets up our trust on the node based on some past point. // 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) seed, err := source.GetByHeight(br.Height - 2)
require.NoError(err, "%+v", err) require.NoError(err, "%+v", err)
cert := certifiers.NewStatic("my-chain", seed.Validators) cert := certifiers.NewStatic("my-chain", seed.Validators)
client.WaitForHeight(cl, 3, nil) client.WaitForHeight(cl, 3, nil)
latest, err := source.GetLatestCommit() latest, err := source.LatestCommit()
require.NoError(err, "%+v", err) require.NoError(err, "%+v", err)
rootHash := latest.Header.AppHash 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) // 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) bs, height, proof, err := GetWithProof(k, brh-1, cl, cert)
require.NotNil(err) require.NotNil(err)
require.True(lc.IsNoDataErr(err)) require.True(IsNoDataErr(err))
require.Nil(bs) require.Nil(bs)
// but given that block it is good // but given that block it is good
@ -98,7 +98,7 @@ func TestAppProofs(t *testing.T) {
// Test non-existing key. // Test non-existing key.
missing := []byte("my-missing-key") missing := []byte("my-missing-key")
bs, _, proof, err = GetWithProof(missing, 0, cl, cert) bs, _, proof, err = GetWithProof(missing, 0, cl, cert)
require.True(lc.IsNoDataErr(err)) require.True(IsNoDataErr(err))
require.Nil(bs) require.Nil(bs)
require.NotNil(proof) require.NotNil(proof)
err = proof.Verify(missing, nil, rootHash) err = proof.Verify(missing, nil, rootHash)
@ -122,7 +122,7 @@ func TestTxProofs(t *testing.T) {
require.EqualValues(0, br.DeliverTx.Code) require.EqualValues(0, br.DeliverTx.Code)
fmt.Printf("tx height: %d\n", br.Height) fmt.Printf("tx height: %d\n", br.Height)
source := certclient.New(cl) source := certclient.NewProvider(cl)
seed, err := source.GetByHeight(br.Height - 2) seed, err := source.GetByHeight(br.Height - 2)
require.NoError(err, "%+v", err) require.NoError(err, "%+v", err)
cert := certifiers.NewStatic("my-chain", seed.Validators) cert := certifiers.NewStatic("my-chain", seed.Validators)
@ -141,8 +141,8 @@ func TestTxProofs(t *testing.T) {
err = res.Proof.Validate(key) err = res.Proof.Validate(key)
assert.NoError(err, "%+v", err) 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.Nil(err, "%+v", err)
require.Equal(res.Proof.RootHash, check.Header.DataHash) require.Equal(res.Proof.RootHash, commit.Header.DataHash)
} }

View File

@ -237,7 +237,7 @@ info about self...
} }
``` ```
`/seeds` `/commits`
``` ```
{ {
@ -246,4 +246,4 @@ info about self...
} }
``` ```
info on last seed info on last commit

View File

@ -9,11 +9,11 @@ import (
"github.com/cosmos/cosmos-sdk/client/commands" "github.com/cosmos/cosmos-sdk/client/commands"
"github.com/cosmos/cosmos-sdk/client/commands/auto" "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/keys"
"github.com/cosmos/cosmos-sdk/client/commands/proxy" "github.com/cosmos/cosmos-sdk/client/commands/proxy"
"github.com/cosmos/cosmos-sdk/client/commands/query" "github.com/cosmos/cosmos-sdk/client/commands/query"
rpccmd "github.com/cosmos/cosmos-sdk/client/commands/rpc" 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" txcmd "github.com/cosmos/cosmos-sdk/client/commands/txs"
authcmd "github.com/cosmos/cosmos-sdk/modules/auth/commands" authcmd "github.com/cosmos/cosmos-sdk/modules/auth/commands"
basecmd "github.com/cosmos/cosmos-sdk/modules/base/commands" basecmd "github.com/cosmos/cosmos-sdk/modules/base/commands"
@ -77,7 +77,7 @@ func main() {
commands.InitCmd, commands.InitCmd,
commands.ResetCmd, commands.ResetCmd,
keys.RootCmd, keys.RootCmd,
seeds.RootCmd, commits.RootCmd,
rpccmd.RootCmd, rpccmd.RootCmd,
query.RootCmd, query.RootCmd,
txcmd.RootCmd, txcmd.RootCmd,

View File

@ -84,18 +84,18 @@ test00GetAccount() {
} }
test01RegisterChains() { test01RegisterChains() {
# let's get the root seeds to cross-register them # let's get the root commits to cross-register them
ROOT_1="$BASE_DIR_1/root_seed.json" ROOT_1="$BASE_DIR_1/root_commit.json"
${CLIENT_EXE} seeds export $ROOT_1 --home=${CLIENT_1} ${CLIENT_EXE} commits export $ROOT_1 --home=${CLIENT_1}
assertTrue "line=${LINENO}, export seed failed" $? assertTrue "line=${LINENO}, export commit failed" $?
ROOT_2="$BASE_DIR_2/root_seed.json" ROOT_2="$BASE_DIR_2/root_commit.json"
${CLIENT_EXE} seeds export $ROOT_2 --home=${CLIENT_2} ${CLIENT_EXE} commits export $ROOT_2 --home=${CLIENT_2}
assertTrue "line=${LINENO}, export seed failed" $? assertTrue "line=${LINENO}, export commit failed" $?
# register chain2 on chain1 # register chain2 on chain1
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx ibc-register \ 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" txSucceeded $? "$TX" "register chain2 on chain 1"
# an example to quit early if there is no point in more tests # an example to quit early if there is no point in more tests
if [ $? != 0 ]; then echo "aborting!"; return 1; fi if [ $? != 0 ]; then echo "aborting!"; return 1; fi
@ -104,40 +104,40 @@ test01RegisterChains() {
# register chain1 on chain2 (no money needed... yet) # register chain1 on chain2 (no money needed... yet)
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx ibc-register \ 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" txSucceeded $? "$TX" "register chain1 on chain 2"
# an example to quit early if there is no point in more tests # an example to quit early if there is no point in more tests
if [ $? != 0 ]; then echo "aborting!"; return 1; fi if [ $? != 0 ]; then echo "aborting!"; return 1; fi
} }
test02UpdateChains() { 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" UPDATE_1="$BASE_DIR_1/seed_1.json"
${CLIENT_EXE} seeds update --home=${CLIENT_1} > /dev/null ${CLIENT_EXE} commits update --home=${CLIENT_1} > /dev/null
${CLIENT_EXE} seeds export $UPDATE_1 --home=${CLIENT_1} ${CLIENT_EXE} commits export $UPDATE_1 --home=${CLIENT_1}
assertTrue "line=${LINENO}, export seed failed" $? assertTrue "line=${LINENO}, export commit failed" $?
# make sure it is newer than the other.... # make sure it is newer than the other....
assertNewHeight "line=${LINENO}" $ROOT_1 $UPDATE_1 assertNewHeight "line=${LINENO}" $ROOT_1 $UPDATE_1
UPDATE_2="$BASE_DIR_2/seed_2.json" UPDATE_2="$BASE_DIR_2/seed_2.json"
${CLIENT_EXE} seeds update --home=${CLIENT_2} > /dev/null ${CLIENT_EXE} commits update --home=${CLIENT_2} > /dev/null
${CLIENT_EXE} seeds export $UPDATE_2 --home=${CLIENT_2} ${CLIENT_EXE} commits export $UPDATE_2 --home=${CLIENT_2}
assertTrue "line=${LINENO}, export seed failed" $? assertTrue "line=${LINENO}, export commit failed" $?
assertNewHeight "line=${LINENO}" $ROOT_2 $UPDATE_2 assertNewHeight "line=${LINENO}" $ROOT_2 $UPDATE_2
# this is used later to check query data # this is used later to check query data
REGISTER_2_HEIGHT=$(cat $ROOT_2 | jq .checkpoint.header.height) REGISTER_2_HEIGHT=$(cat $ROOT_2 | jq .commit.header.height)
UPDATE_2_HEIGHT=$(cat $UPDATE_2 | jq .checkpoint.header.height) UPDATE_2_HEIGHT=$(cat $UPDATE_2 | jq .commit.header.height)
# update chain2 on chain1 # update chain2 on chain1
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx ibc-update \ 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" txSucceeded $? "$TX" "update chain2 on chain 1"
# an example to quit early if there is no point in more tests # an example to quit early if there is no point in more tests
if [ $? != 0 ]; then echo "aborting!"; return 1; fi if [ $? != 0 ]; then echo "aborting!"; return 1; fi
# update chain1 on chain2 (no money needed... yet) # update chain1 on chain2 (no money needed... yet)
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx ibc-update \ 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" txSucceeded $? "$TX" "update chain1 on chain 2"
# an example to quit early if there is no point in more tests # an example to quit early if there is no point in more tests
if [ $? != 0 ]; then echo "aborting!"; return 1; fi 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) # 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) SRC_HEIGHT=$(echo $PACKET | jq .src_height)
PROOF_HEIGHT=$(expr $SRC_HEIGHT + 1) PROOF_HEIGHT=$(expr $SRC_HEIGHT + 1)
# FIXME: this should auto-update on proofs... # FIXME: this should auto-update on proofs...
${CLIENT_EXE} seeds update --height=$PROOF_HEIGHT --home=${CLIENT_1} > /dev/null ${CLIENT_EXE} commits update --height=$PROOF_HEIGHT --home=${CLIENT_1} > /dev/null
assertTrue "line=${LINENO}, update seed failed" $? assertTrue "line=${LINENO}, update commit failed" $?
PACKET_SEED="$BASE_DIR_1/packet_seed.json" PACKET_COMMIT="$BASE_DIR_1/packet_commit.json"
${CLIENT_EXE} seeds export $PACKET_SEED --home=${CLIENT_1} --height=$PROOF_HEIGHT ${CLIENT_EXE} commits export $PACKET_COMMIT --home=${CLIENT_1} --height=$PROOF_HEIGHT
assertTrue "line=${LINENO}, export seed failed" $? assertTrue "line=${LINENO}, export commit failed" $?
if [ -n "$DEBUG" ]; then if [ -n "$DEBUG" ]; then
echo "**** SEED ****" echo "**** SEED ****"
cat $PACKET_SEED | jq .checkpoint.header cat $PACKET_COMMIT | jq .commit.header
echo echo
fi fi
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx ibc-update \ 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" txSucceeded $? "$TX" "prepare packet chain1 on chain 2"
# an example to quit early if there is no point in more tests # an example to quit early if there is no point in more tests
if [ $? != 0 ]; then echo "aborting!"; return 1; fi if [ $? != 0 ]; then echo "aborting!"; return 1; fi
@ -268,11 +268,11 @@ test05ReceiveIBCPacket() {
} }
# XXX Ex Usage: assertNewHeight $MSG $SEED_1 $SEED_2 # 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() { assertNewHeight() {
H1=$(cat $2 | jq .checkpoint.header.height) H1=$(cat $2 | jq .commit.header.height)
H2=$(cat $3 | jq .checkpoint.header.height) H2=$(cat $3 | jq .commit.header.height)
assertTrue "$MSG" "test $H2 -gt $H1" assertTrue "$1" "test $H2 -gt $H1"
return $? return $?
} }

View File

@ -8,10 +8,10 @@ import (
"github.com/tendermint/tmlibs/cli" "github.com/tendermint/tmlibs/cli"
"github.com/cosmos/cosmos-sdk/client/commands" "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/keys"
"github.com/cosmos/cosmos-sdk/client/commands/proxy" "github.com/cosmos/cosmos-sdk/client/commands/proxy"
"github.com/cosmos/cosmos-sdk/client/commands/query" "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" txcmd "github.com/cosmos/cosmos-sdk/client/commands/txs"
bcount "github.com/cosmos/cosmos-sdk/examples/counter/cmd/countercli/commands" bcount "github.com/cosmos/cosmos-sdk/examples/counter/cmd/countercli/commands"
@ -74,7 +74,7 @@ func main() {
commands.ResetCmd, commands.ResetCmd,
commands.VersionCmd, commands.VersionCmd,
keys.RootCmd, keys.RootCmd,
seeds.RootCmd, commits.RootCmd,
query.RootCmd, query.RootCmd,
txcmd.RootCmd, txcmd.RootCmd,
proxy.RootCmd, proxy.RootCmd,

View File

@ -9,9 +9,9 @@ import (
"github.com/cosmos/cosmos-sdk/client/commands" "github.com/cosmos/cosmos-sdk/client/commands"
"github.com/cosmos/cosmos-sdk/client/commands/auto" "github.com/cosmos/cosmos-sdk/client/commands/auto"
"github.com/cosmos/cosmos-sdk/client/commands/commits"
"github.com/cosmos/cosmos-sdk/client/commands/query" "github.com/cosmos/cosmos-sdk/client/commands/query"
rpccmd "github.com/cosmos/cosmos-sdk/client/commands/rpc" 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" txcmd "github.com/cosmos/cosmos-sdk/client/commands/txs"
eyescmd "github.com/cosmos/cosmos-sdk/modules/eyes/commands" 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 // we use out own init command to not require address arg
commands.InitCmd, commands.InitCmd,
commands.ResetCmd, commands.ResetCmd,
seeds.RootCmd, commits.RootCmd,
rpccmd.RootCmd, rpccmd.RootCmd,
query.RootCmd, query.RootCmd,
txcmd.RootCmd, txcmd.RootCmd,

83
glide.lock generated
View File

@ -1,22 +1,24 @@
hash: fbfdd03c0367bb0785ceb81ed34059df219e55d5a9c71c12597e505fbce14165 hash: fbfdd03c0367bb0785ceb81ed34059df219e55d5a9c71c12597e505fbce14165
updated: 2017-10-23T14:49:22.891642342+02:00 updated: 2017-10-25T19:24:51.90002008+02:00
imports: imports:
- name: github.com/bgentry/speakeasy - name: github.com/bgentry/speakeasy
version: 4aabc24848ce5fd31929f7d1e4ea74d3709c14cd version: 4aabc24848ce5fd31929f7d1e4ea74d3709c14cd
- name: github.com/btcsuite/btcd - name: github.com/btcsuite/btcd
version: b8df516b4b267acf2de46be593a9d948d1d2c420 version: c7588cbf7690cd9f047a28efa2dcd8f2435a4e5e
subpackages: subpackages:
- btcec - btcec
- name: github.com/btcsuite/fastsha256
version: 637e656429416087660c84436a2a035d69d54e2e
- name: github.com/BurntSushi/toml - name: github.com/BurntSushi/toml
version: a368813c5e648fee92e5f6c30e3944ff9d5e8895 version: a368813c5e648fee92e5f6c30e3944ff9d5e8895
- name: github.com/ebuchman/fail-test - name: github.com/ebuchman/fail-test
version: 95f809107225be108efcf10a3509e4ea6ceef3c4 version: 95f809107225be108efcf10a3509e4ea6ceef3c4
- name: github.com/ethanfrey/ledger
version: 5e432577be582bd18a3b4a9cd75dae7a317ade36
- name: github.com/flynn/hid
version: ed06a31c6245d4552e8dbba7e32e5b010b875d65
- name: github.com/fsnotify/fsnotify - name: github.com/fsnotify/fsnotify
version: 4da3e2cfbabc9f751898f250b49f2439785783a1 version: 4da3e2cfbabc9f751898f250b49f2439785783a1
- name: github.com/go-kit/kit - name: github.com/go-kit/kit
version: d67bb4c202e3b91377d1079b110a6c9ce23ab2f8 version: e2b298466b32c7cd5579a9b9b07e968fc9d9452c
subpackages: subpackages:
- log - log
- log/level - log/level
@ -24,18 +26,21 @@ imports:
- name: github.com/go-logfmt/logfmt - name: github.com/go-logfmt/logfmt
version: 390ab7935ee28ec6b286364bba9b4dd6410cb3d5 version: 390ab7935ee28ec6b286364bba9b4dd6410cb3d5
- name: github.com/go-playground/locales - name: github.com/go-playground/locales
version: 1e5f1161c6416a5ff48840eb8724a394e48cc534 version: e4cbcb5d0652150d40ad0646651076b6bd2be4f6
subpackages: subpackages:
- currency - currency
- name: github.com/go-playground/universal-translator - name: github.com/go-playground/universal-translator
version: 71201497bace774495daed26a3874fd339e0b538 version: 71201497bace774495daed26a3874fd339e0b538
- name: github.com/go-stack/stack - name: github.com/go-stack/stack
version: 100eb0c0a9c5b306ca2fb4f165df21d80ada4b82 version: 817915b46b97fd7bb80e8ab6b69f01a53ac3eebf
- name: github.com/golang/protobuf - name: github.com/golang/protobuf
version: 18c9bb3261723cd5401db4d0c9fbc5c3b6c70fe8 version: 1643683e1b54a9e88ad26d98f81400c8c9d9f4f9
subpackages: subpackages:
- proto - proto
- ptypes
- ptypes/any - ptypes/any
- ptypes/duration
- ptypes/timestamp
- name: github.com/golang/snappy - name: github.com/golang/snappy
version: 553a641470496b2327abcac10b36396bd98e45c9 version: 553a641470496b2327abcac10b36396bd98e45c9
- name: github.com/gorilla/context - name: github.com/gorilla/context
@ -43,9 +48,9 @@ imports:
- name: github.com/gorilla/mux - name: github.com/gorilla/mux
version: 24fca303ac6da784b9e8269f724ddeb0b2eea5e7 version: 24fca303ac6da784b9e8269f724ddeb0b2eea5e7
- name: github.com/gorilla/websocket - name: github.com/gorilla/websocket
version: a91eba7f97777409bc2c443f5534d41dd20c5720 version: 71fa72d4842364bc5f74185f4161e0099ea3624a
- name: github.com/hashicorp/hcl - name: github.com/hashicorp/hcl
version: 392dba7d905ed5d04a5794ba89f558b27e2ba1ca version: 23c074d0eceb2b8a5bfdbb271ab780cde70f05a8
subpackages: subpackages:
- hcl/ast - hcl/ast
- hcl/parser - hcl/parser
@ -64,11 +69,11 @@ imports:
- name: github.com/kr/logfmt - name: github.com/kr/logfmt
version: b84e30acd515aadc4b783ad4ff83aff3299bdfe0 version: b84e30acd515aadc4b783ad4ff83aff3299bdfe0
- name: github.com/magiconair/properties - name: github.com/magiconair/properties
version: 51463bfca2576e06c62a8504b5c0f06d61312647 version: 8d7837e64d3c1ee4e54a880c5a920ab4316fc90a
- name: github.com/mattn/go-isatty - name: github.com/mattn/go-isatty
version: a5cdd64afdee435007ee3e9f6ed4684af949d568 version: a5cdd64afdee435007ee3e9f6ed4684af949d568
- name: github.com/mitchellh/mapstructure - name: github.com/mitchellh/mapstructure
version: cc8532a8e9a55ea36402aa21efdf403a60d34096 version: 06020f85339e21b2478f756a78e295255ffa4d6a
- name: github.com/pelletier/go-buffruneio - name: github.com/pelletier/go-buffruneio
version: c37440a7cf42ac63b919c752ca73a85067e05992 version: c37440a7cf42ac63b919c752ca73a85067e05992
- name: github.com/pelletier/go-toml - name: github.com/pelletier/go-toml
@ -78,21 +83,21 @@ imports:
- name: github.com/rcrowley/go-metrics - name: github.com/rcrowley/go-metrics
version: 1f30fe9094a513ce4c700b9a54458bbb0c96996c version: 1f30fe9094a513ce4c700b9a54458bbb0c96996c
- name: github.com/spf13/afero - name: github.com/spf13/afero
version: 9be650865eab0c12963d8753212f4f9c66cdcf12 version: 5660eeed305fe5f69c8fc6cf899132a459a97064
subpackages: subpackages:
- mem - mem
- name: github.com/spf13/cast - name: github.com/spf13/cast
version: acbeb36b902d72a7a4c18e8f3241075e7ab763e4 version: acbeb36b902d72a7a4c18e8f3241075e7ab763e4
- name: github.com/spf13/cobra - name: github.com/spf13/cobra
version: 4cdb38c072b86bf795d2c81de50784d9fdd6eb77 version: 7b2c5ac9fc04fc5efafb60700713d4fa609b777b
- name: github.com/spf13/jwalterweatherman - name: github.com/spf13/jwalterweatherman
version: 8f07c835e5cc1450c082fe3a439cf87b0cbb2d99 version: 12bd96e66386c1960ab0f74ced1362f66f552f7b
- name: github.com/spf13/pflag - name: github.com/spf13/pflag
version: e57e3eeb33f795204c1ca35f56c44f83227c6e66 version: 97afa5e7ca8a08a383cb259e06636b5e2cc7897f
- name: github.com/spf13/viper - name: github.com/spf13/viper
version: 0967fc9aceab2ce9da34061253ac10fb99bba5b2 version: 8ef37cbca71638bf32f3d5e194117d4cb46da163
- name: github.com/syndtr/goleveldb - name: github.com/syndtr/goleveldb
version: 8c81ea47d4c41a385645e133e15510fc6a2a74b4 version: b89cc31ef7977104127d34c1bd31ebd1a9db2199
subpackages: subpackages:
- leveldb - leveldb
- leveldb/cache - leveldb/cache
@ -119,7 +124,7 @@ imports:
- edwards25519 - edwards25519
- extra25519 - extra25519
- name: github.com/tendermint/go-crypto - name: github.com/tendermint/go-crypto
version: 8e7f0e7701f92206679ad093d013b9b162427631 version: 0a5b1d979a1bc86200c9ff829fbbcd575799a1b6
subpackages: subpackages:
- bcrypt - bcrypt
- keys - keys
@ -127,22 +132,24 @@ imports:
- keys/storage/filestorage - keys/storage/filestorage
- keys/storage/memstorage - keys/storage/memstorage
- keys/wordlist - keys/wordlist
- nano
- name: github.com/tendermint/go-wire - name: github.com/tendermint/go-wire
version: 55ae61f1fc83cfaa57ab7d54250d7a1a2be0b83c version: 99d2169a1e39c65983eacaa1da867d6f3218e1c9
subpackages: subpackages:
- data - data
- data/base58 - data/base58
- name: github.com/tendermint/iavl - name: github.com/tendermint/iavl
version: 721710e7aa59f61dbfbf558943a207ba3fe6b926 version: 595f3dcd5b6cd4a292e90757ae6d367fd7a6e653
- name: github.com/tendermint/light-client - name: github.com/tendermint/light-client
version: 569e1583da8a52e499764533f3a05d05be6d56d6 version: 76313d625e662ed7b284d066d68ff71edd7a9fac
subpackages: subpackages:
- certifiers - certifiers
- certifiers/client - certifiers/client
- certifiers/errors
- certifiers/files - certifiers/files
- proofs - proofs
- name: github.com/tendermint/tendermint - name: github.com/tendermint/tendermint
version: fa56e8c0ce463f77c87ab17a3d7cf5431d9f2c0b version: b2d5546cf8f71e0e168072e118d9836862384e6c
subpackages: subpackages:
- blockchain - blockchain
- cmd/tendermint/commands - cmd/tendermint/commands
@ -170,7 +177,7 @@ imports:
- types - types
- version - version
- name: github.com/tendermint/tmlibs - name: github.com/tendermint/tmlibs
version: 8e5266a9ef2527e68a1571f932db8228a331b556 version: 0a652499ead7cd20a57a6a592f0491a2b493bb85
subpackages: subpackages:
- autofile - autofile
- cli - cli
@ -184,7 +191,7 @@ imports:
- logger - logger
- merkle - merkle
- name: golang.org/x/crypto - name: golang.org/x/crypto
version: c7af5bf2638a1164f2eb5467c39c6cffbd13a02e version: edd5e9b0879d13ee6970a50153d85b8fec9f7686
subpackages: subpackages:
- blowfish - blowfish
- curve25519 - curve25519
@ -196,7 +203,7 @@ imports:
- ripemd160 - ripemd160
- salsa20/salsa - salsa20/salsa
- name: golang.org/x/net - name: golang.org/x/net
version: feeb485667d1fdabe727840fe00adc22431bc86e version: cd69bc3fc700721b709c3a59e16e24c67b58f6ff
subpackages: subpackages:
- context - context
- http2 - http2
@ -206,43 +213,49 @@ imports:
- lex/httplex - lex/httplex
- trace - trace
- name: golang.org/x/sys - name: golang.org/x/sys
version: e62c3de784db939836898e5c19ffd41bece347da version: 8dbc5d05d6edcc104950cc299a1ce6641235bc86
subpackages: subpackages:
- unix - unix
- name: golang.org/x/text - name: golang.org/x/text
version: 470f45bf29f4147d6fbd7dfd0a02a848e49f5bf4 version: c01e4764d870b77f8abe5096ee19ad20d80e8075
subpackages: subpackages:
- secure/bidirule - secure/bidirule
- transform - transform
- unicode/bidi - unicode/bidi
- unicode/norm - unicode/norm
- name: google.golang.org/genproto - name: google.golang.org/genproto
version: 411e09b969b1170a9f0c467558eb4c4c110d9c77 version: f676e0f3ac6395ff1a529ae59a6670878a8371a6
subpackages: subpackages:
- googleapis/rpc/status - googleapis/rpc/status
- name: google.golang.org/grpc - name: google.golang.org/grpc
version: 844f573616520565fdc6fb4db242321b5456fd6d version: a5986a5c88227370a9c0a82e5277167229c034cd
subpackages: subpackages:
- balancer
- balancer/roundrobin
- codes - codes
- connectivity
- credentials - credentials
- grpclb/grpc_lb_v1 - grpclb/grpc_lb_v1/messages
- grpclog - grpclog
- internal - internal
- keepalive - keepalive
- metadata - metadata
- naming - naming
- peer - peer
- resolver
- resolver/dns
- resolver/passthrough
- stats - stats
- status - status
- tap - tap
- transport - transport
- name: gopkg.in/go-playground/validator.v9 - name: gopkg.in/go-playground/validator.v9
version: 6d8c18553ea1ac493d049edd6f102f52e618f085 version: 1304298bf10d085adec514b076772a79c9cadb6b
- name: gopkg.in/yaml.v2 - name: gopkg.in/yaml.v2
version: cd8b52f8269e0feb286dfeef29f8fe4d5b397e0b version: eb3733d160e74a9c7e442f435eb3bea458e1d19f
testImports: testImports:
- name: github.com/davecgh/go-spew - name: github.com/davecgh/go-spew
version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9 version: 04cdfd42973bb9c8589fd6a731800cf222fde1a9
subpackages: subpackages:
- spew - spew
- name: github.com/pmezard/go-difflib - name: github.com/pmezard/go-difflib
@ -250,7 +263,7 @@ testImports:
subpackages: subpackages:
- difflib - difflib
- name: github.com/stretchr/testify - name: github.com/stretchr/testify
version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0 version: 2aa2c176b9dab406a6970f6a55f513e8a8c8b18f
subpackages: subpackages:
- assert - assert
- require - require

View File

@ -5,8 +5,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "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"
"github.com/cosmos/cosmos-sdk/client/commands/query" "github.com/cosmos/cosmos-sdk/client/commands/query"
"github.com/cosmos/cosmos-sdk/modules/coin" "github.com/cosmos/cosmos-sdk/modules/coin"
@ -35,7 +34,7 @@ func accountQueryCmd(cmd *cobra.Command, args []string) error {
acc := coin.Account{} acc := coin.Account{}
prove := !viper.GetBool(commands.FlagTrustNode) prove := !viper.GetBool(commands.FlagTrustNode)
height, err := query.GetParsed(key, &acc, query.GetHeight(), prove) 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) return errors.Errorf("Account bytes are empty for address %s ", addr)
} else if err != nil { } else if err != nil {
return err return err

View File

@ -252,7 +252,7 @@ func TestSetIssuer(t *testing.T) {
}{ }{
{sdk.Actor{App: "sig", Address: []byte("gwkfgk")}}, {sdk.Actor{App: "sig", Address: []byte("gwkfgk")}},
// and set back to empty (nil is valid, but assert.Equals doesn't match) // 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")}}, {sdk.Actor{ChainID: "other", App: "role", Address: []byte("vote")}},
} }

View File

@ -10,6 +10,7 @@ import (
"github.com/spf13/viper" "github.com/spf13/viper"
sdk "github.com/cosmos/cosmos-sdk" 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"
"github.com/cosmos/cosmos-sdk/client/commands/query" "github.com/cosmos/cosmos-sdk/client/commands/query"
"github.com/cosmos/cosmos-sdk/modules/auth" "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/fee"
"github.com/cosmos/cosmos-sdk/modules/nonce" "github.com/cosmos/cosmos-sdk/modules/nonce"
"github.com/cosmos/cosmos-sdk/stack" "github.com/cosmos/cosmos-sdk/stack"
lightclient "github.com/tendermint/light-client"
"github.com/tendermint/tmlibs/common" "github.com/tendermint/tmlibs/common"
) )
@ -62,7 +62,7 @@ func doQueryAccount(w http.ResponseWriter, r *http.Request) {
account := new(coin.Account) account := new(coin.Account)
prove := !viper.GetBool(commands.FlagTrustNode) prove := !viper.GetBool(commands.FlagTrustNode)
height, err := query.GetParsed(key, account, h, prove) 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) err := fmt.Errorf("account bytes are empty for address: %q", signature)
common.WriteError(w, err) common.WriteError(w, err)
return return

View File

@ -39,36 +39,36 @@ var PostPacketTxCmd = &cobra.Command{
//nolint //nolint
const ( const (
FlagSeed = "seed" FlagCommit = "commit"
FlagPacket = "packet" FlagPacket = "packet"
) )
func init() { func init() {
fs1 := RegisterChainTxCmd.Flags() fs1 := RegisterChainTxCmd.Flags()
fs1.String(FlagSeed, "", "Filename with a seed file") fs1.String(FlagCommit, "", "Filename with a commit file")
fs2 := UpdateChainTxCmd.Flags() fs2 := UpdateChainTxCmd.Flags()
fs2.String(FlagSeed, "", "Filename with a seed file") fs2.String(FlagCommit, "", "Filename with a commit file")
fs3 := PostPacketTxCmd.Flags() fs3 := PostPacketTxCmd.Flags()
fs3.String(FlagPacket, "", "Filename with a packet to post") fs3.String(FlagPacket, "", "Filename with a packet to post")
} }
func registerChainTxCmd(cmd *cobra.Command, args []string) error { func registerChainTxCmd(cmd *cobra.Command, args []string) error {
seed, err := readSeed() fc, err := readCommit()
if err != nil { if err != nil {
return err return err
} }
tx := ibc.RegisterChainTx{seed}.Wrap() tx := ibc.RegisterChainTx{fc}.Wrap()
return txcmd.DoTx(tx) return txcmd.DoTx(tx)
} }
func updateChainTxCmd(cmd *cobra.Command, args []string) error { func updateChainTxCmd(cmd *cobra.Command, args []string) error {
seed, err := readSeed() fc, err := readCommit()
if err != nil { if err != nil {
return err return err
} }
tx := ibc.UpdateChainTx{seed}.Wrap() tx := ibc.UpdateChainTx{fc}.Wrap()
return txcmd.DoTx(tx) return txcmd.DoTx(tx)
} }
@ -80,13 +80,13 @@ func postPacketTxCmd(cmd *cobra.Command, args []string) error {
return txcmd.DoTx(post.Wrap()) return txcmd.DoTx(post.Wrap())
} }
func readSeed() (seed certifiers.Seed, err error) { func readCommit() (fc certifiers.FullCommit, err error) {
name := viper.GetString(FlagSeed) name := viper.GetString(FlagCommit)
if name == "" { 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 return
} }

View File

@ -100,20 +100,20 @@ func (h Handler) DeliverTx(ctx sdk.Context, store state.SimpleDB, tx sdk.Tx) (re
switch t := tx.Unwrap().(type) { switch t := tx.Unwrap().(type) {
case RegisterChainTx: case RegisterChainTx:
return h.initSeed(ctx, store, t) return h.registerChain(ctx, store, t)
case UpdateChainTx: case UpdateChainTx:
return h.updateSeed(ctx, store, t) return h.updateChain(ctx, store, t)
case CreatePacketTx: case CreatePacketTx:
return h.createPacket(ctx, store, t) return h.createPacket(ctx, store, t)
} }
return res, errors.ErrUnknownTxType(tx.Unwrap()) 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. // accepts it as the root of trust.
// //
// only the registrar, if set, is allowed to do this // 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) { t RegisterChainTx) (res sdk.DeliverResult, err error) {
info := LoadInfo(store) info := LoadInfo(store)
@ -124,20 +124,20 @@ func (h Handler) initSeed(ctx sdk.Context, store state.SimpleDB,
// verify that the header looks reasonable // verify that the header looks reasonable
chainID := t.ChainID() chainID := t.ChainID()
s := NewChainSet(store) s := NewChainSet(store)
err = s.Register(chainID, ctx.BlockHeight(), t.Seed.Height()) err = s.Register(chainID, ctx.BlockHeight(), t.Commit.Height())
if err != nil { if err != nil {
return res, err return res, err
} }
space := stack.PrefixedStore(chainID, store) space := stack.PrefixedStore(chainID, store)
provider := newDBProvider(space) provider := newDBProvider(space)
err = provider.StoreSeed(t.Seed) err = provider.StoreCommit(t.Commit)
return res, err 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) // 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) { t UpdateChainTx) (res sdk.DeliverResult, err error) {
chainID := t.ChainID() chainID := t.ChainID()
@ -147,21 +147,21 @@ func (h Handler) updateSeed(ctx sdk.Context, store state.SimpleDB,
} }
// load the certifier for this chain // load the certifier for this chain
seed := t.Seed fc := t.Commit
space := stack.PrefixedStore(chainID, store) space := stack.PrefixedStore(chainID, store)
cert, err := newCertifier(space, chainID, seed.Height()) cert, err := newCertifier(space, chainID, fc.Height())
if err != nil { if err != nil {
return res, err return res, err
} }
// this will import the seed if it is valid in the current context // this will import the commit if it is valid in the current context
err = cert.Update(seed.Checkpoint, seed.Validators) err = cert.Update(fc)
if err != nil { if err != nil {
return res, ErrInvalidCommit(err) return res, ErrInvalidCommit(err)
} }
// update the tracked height in chain info // update the tracked height in chain info
err = s.Update(chainID, t.Seed.Height()) err = s.Update(chainID, fc.Height())
return res, err return res, err
} }

View File

@ -27,28 +27,28 @@ func TestIBCRegister(t *testing.T) {
appHash := []byte{0, 4, 7, 23} appHash := []byte{0, 4, 7, 23}
appHash2 := []byte{12, 34, 56, 78} appHash2 := []byte{12, 34, 56, 78}
// badSeed doesn't validate // badCommit doesn't validate
badSeed := genEmptySeed(keys2, "chain-2", 123, appHash, len(keys2)) badCommit := genEmptyCommit(keys2, "chain-2", 123, appHash, len(keys2))
badSeed.Header.AppHash = appHash2 badCommit.Header.AppHash = appHash2
cases := []struct { cases := []struct {
seed certifiers.Seed fc certifiers.FullCommit
checker errors.CheckErr checker errors.CheckErr
}{ }{
{ {
genEmptySeed(keys, "chain-1", 100, appHash, len(keys)), genEmptyCommit(keys, "chain-1", 100, appHash, len(keys)),
errors.NoErr, errors.NoErr,
}, },
{ {
genEmptySeed(keys, "chain-1", 200, appHash, len(keys)), genEmptyCommit(keys, "chain-1", 200, appHash, len(keys)),
IsAlreadyRegisteredErr, IsAlreadyRegisteredErr,
}, },
{ {
badSeed, badCommit,
IsInvalidCommitErr, IsInvalidCommitErr,
}, },
{ {
genEmptySeed(keys2, "chain-2", 123, appHash2, 5), genEmptyCommit(keys2, "chain-2", 123, appHash2, 5),
errors.NoErr, errors.NoErr,
}, },
} }
@ -58,7 +58,7 @@ func TestIBCRegister(t *testing.T) {
app := stack.New().Dispatch(stack.WrapHandler(NewHandler())) app := stack.New().Dispatch(stack.WrapHandler(NewHandler()))
for i, tc := range cases { for i, tc := range cases {
tx := RegisterChainTx{tc.seed}.Wrap() tx := RegisterChainTx{tc.fc}.Wrap()
_, err := app.DeliverTx(ctx, store, tx) _, err := app.DeliverTx(ctx, store, tx)
assert.True(tc.checker(err), "%d: %+v", i, err) 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")} foobaz := sdk.Actor{App: "foo", Address: []byte("baz")}
cases := []struct { cases := []struct {
seed certifiers.Seed seed certifiers.FullCommit
registrar sdk.Actor registrar sdk.Actor
signer sdk.Actor signer sdk.Actor
checker errors.CheckErr checker errors.CheckErr
}{ }{
// no sig, no registrar // 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, checker: errors.NoErr,
}, },
// sig, no registrar // sig, no registrar
{ {
seed: genEmptySeed(keys, "chain-2", 100, appHash, len(keys)), seed: genEmptyCommit(keys, "chain-2", 100, appHash, len(keys)),
signer: foobaz, signer: foobaz,
checker: errors.NoErr, checker: errors.NoErr,
}, },
// registrar, no sig // registrar, no sig
{ {
seed: genEmptySeed(keys, "chain-3", 100, appHash, len(keys)), seed: genEmptyCommit(keys, "chain-3", 100, appHash, len(keys)),
registrar: foobar, registrar: foobar,
checker: errors.IsUnauthorizedErr, checker: errors.IsUnauthorizedErr,
}, },
// registrar, wrong sig // registrar, wrong sig
{ {
seed: genEmptySeed(keys, "chain-4", 100, appHash, len(keys)), seed: genEmptyCommit(keys, "chain-4", 100, appHash, len(keys)),
signer: foobaz, signer: foobaz,
registrar: foobar, registrar: foobar,
checker: errors.IsUnauthorizedErr, checker: errors.IsUnauthorizedErr,
}, },
// registrar, wrong sig // registrar, wrong sig
{ {
seed: genEmptySeed(keys, "chain-5", 100, appHash, len(keys)), seed: genEmptyCommit(keys, "chain-5", 100, appHash, len(keys)),
signer: baz, signer: baz,
registrar: foobar, registrar: foobar,
checker: errors.IsUnauthorizedErr, checker: errors.IsUnauthorizedErr,
}, },
// registrar, proper sig // registrar, proper sig
{ {
seed: genEmptySeed(keys, "chain-6", 100, appHash, len(keys)), seed: genEmptyCommit(keys, "chain-6", 100, appHash, len(keys)),
signer: foobar, signer: foobar,
registrar: foobar, registrar: foobar,
checker: errors.NoErr, checker: errors.NoErr,
@ -151,7 +151,7 @@ func TestIBCUpdate(t *testing.T) {
keys := certifiers.GenValKeys(7) keys := certifiers.GenValKeys(7)
appHash := []byte{0, 4, 7, 23} appHash := []byte{0, 4, 7, 23}
start := 100 // initial height 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) keys2 := keys.Extend(2)
keys3 := keys2.Extend(2) keys3 := keys2.Extend(2)
@ -165,53 +165,53 @@ func TestIBCUpdate(t *testing.T) {
require.Nil(err, "%+v", err) require.Nil(err, "%+v", err)
cases := []struct { cases := []struct {
seed certifiers.Seed fc certifiers.FullCommit
checker errors.CheckErr checker errors.CheckErr
}{ }{
// same validator, higher up // 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, errors.NoErr,
}, },
// same validator, between existing (not most recent) // 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, errors.NoErr,
}, },
// same validators, before root of trust // 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, IsHeaderNotFoundErr,
}, },
// insufficient signatures // 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, IsInvalidCommitErr,
}, },
// unregistered chain // 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, IsNotRegisteredErr,
}, },
// too much change (keys -> keys3) // 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, IsInvalidCommitErr,
}, },
// legit update to validator set (keys -> keys2) // 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, errors.NoErr,
}, },
// now impossible jump works (keys -> keys2 -> keys3) // 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, errors.NoErr,
}, },
} }
for i, tc := range cases { for i, tc := range cases {
tx := UpdateChainTx{tc.seed}.Wrap() tx := UpdateChainTx{tc.fc}.Wrap()
_, err := app.DeliverTx(ctx, store, tx) _, err := app.DeliverTx(ctx, store, tx)
assert.True(tc.checker(err), "%d: %+v", i, err) assert.True(tc.checker(err), "%d: %+v", i, err)
} }
@ -227,7 +227,7 @@ func TestIBCCreatePacket(t *testing.T) {
appHash := []byte{1, 2, 3, 4} appHash := []byte{1, 2, 3, 4}
start := 100 // initial height start := 100 // initial height
chainID := "cosmos-hub" 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) // create the app and register the root of trust (for chain-1)
ctx := stack.MockContext("hub", 50) ctx := stack.MockContext("hub", 50)

View File

@ -3,6 +3,7 @@ package ibc
import ( import (
wire "github.com/tendermint/go-wire" wire "github.com/tendermint/go-wire"
"github.com/tendermint/light-client/certifiers" "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/stack"
"github.com/cosmos/cosmos-sdk/state" "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 // 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 // it will load the most recent height before block h if h is positive
// if h < 0, it will load the latest height // 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 // each chain has their own prefixed subspace
p := newDBProvider(store) p := newDBProvider(store)
var seed certifiers.Seed var fc certifiers.FullCommit
var err error var err error
if h > 0 { if h > 0 {
// this gets the most recent verified seed below the specified height // this gets the most recent verified commit below the specified height
seed, err = p.GetByHeight(h) fc, err = p.GetByHeight(h)
} else { } else {
// 0 or negative means start at latest seed // 0 or negative means start at latest commit
seed, err = certifiers.LatestSeed(p) fc, err = p.LatestCommit()
} }
if err != nil { if err != nil {
return nil, ErrHeaderNotFound(h) return nil, ErrHeaderNotFound(h)
} }
// we have no source for untrusted keys, but use the db to load trusted history // we have no source for untrusted keys, but use the db to load trusted history
cert := certifiers.NewInquiring(chainID, seed, p, cert := certifiers.NewInquiring(chainID, fc, p,
certifiers.MissingProvider{}) certifiers.NewMissingProvider())
return cert, nil return cert, nil
} }
@ -55,40 +56,49 @@ func newDBProvider(store state.SimpleDB) *dbProvider {
var _ certifiers.Provider = &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.... // TODO: don't duplicate data....
b := wire.BinaryBytes(seed) b := wire.BinaryBytes(fc)
d.byHash.Set(seed.Hash(), b) d.byHash.Set(fc.ValidatorsHash(), b)
d.byHeight.Set(uint64(seed.Height()), b) d.byHeight.Set(uint64(fc.Height()), b)
return nil return nil
} }
func (d *dbProvider) GetByHeight(h int) (seed certifiers.Seed, err error) { func (d *dbProvider) LatestCommit() (fc certifiers.FullCommit, err error) {
b, _ := d.byHeight.LTE(uint64(h)) b, _ := d.byHeight.Top()
if b == nil { if b == nil {
return seed, certifiers.ErrSeedNotFound() return fc, certerr.ErrCommitNotFound()
} }
err = wire.ReadBinaryBytes(b, &seed) err = wire.ReadBinaryBytes(b, &fc)
return 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) b := d.byHash.Get(hash)
if b == nil { if b == nil {
return seed, certifiers.ErrSeedNotFound() return fc, certerr.ErrCommitNotFound()
} }
err = wire.ReadBinaryBytes(b, &seed) err = wire.ReadBinaryBytes(b, &fc)
return return
} }
// GetExactHeight is like GetByHeight, but returns an error instead of // GetExactHeight is like GetByHeight, but returns an error instead of
// closest match if there is no exact match // closest match if there is no exact match
func (d *dbProvider) GetExactHeight(h int) (seed certifiers.Seed, err error) { func (d *dbProvider) GetExactHeight(h int) (fc certifiers.FullCommit, err error) {
seed, err = d.GetByHeight(h) fc, err = d.GetByHeight(h)
if err != nil { if err != nil {
return return
} }
if seed.Height() != h { if fc.Height() != h {
err = ErrHeaderNotFound(h) err = ErrHeaderNotFound(h)
} }
return return

View File

@ -8,21 +8,22 @@ import (
"github.com/cosmos/cosmos-sdk/state" "github.com/cosmos/cosmos-sdk/state"
"github.com/tendermint/light-client/certifiers" "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 := assert.New(t)
assert.Equal(s.Height(), s2.Height()) assert.Equal(fc.Height(), fc2.Height())
assert.Equal(s.Hash(), s2.Hash()) assert.Equal(fc.ValidatorsHash(), fc2.ValidatorsHash())
// TODO: more // TODO: more
} }
func TestProviderStore(t *testing.T) { func TestProviderStore(t *testing.T) {
assert, require := assert.New(t), require.New(t) assert, require := assert.New(t), require.New(t)
// make a few seeds // make a few commits
keys := certifiers.GenValKeys(2) keys := certifiers.GenValKeys(2)
seeds := makeSeeds(keys, 4, "some-chain", "demo-store") commits := makeCommits(keys, 4, "some-chain", "demo-store")
// make a provider // make a provider
store := state.NewMemKVStore() store := state.NewMemKVStore()
@ -31,41 +32,41 @@ func TestProviderStore(t *testing.T) {
// check it... // check it...
_, err := p.GetByHeight(20) _, err := p.GetByHeight(20)
require.NotNil(err) require.NotNil(err)
assert.True(certifiers.IsSeedNotFoundErr(err)) assert.True(certerr.IsCommitNotFoundErr(err))
// add a seed // add commits
for _, s := range seeds { for _, fc := range commits {
err = p.StoreSeed(s) err = p.StoreCommit(fc)
require.Nil(err) require.Nil(err)
} }
// make sure we get it... // make sure we get it...
s := seeds[0] fc := commits[0]
val, err := p.GetByHeight(s.Height()) val, err := p.GetByHeight(fc.Height())
if assert.Nil(err) { if assert.Nil(err) {
assertSeedEqual(t, s, val) assertCommitsEqual(t, fc, val)
} }
// make sure we get higher // make sure we get higher
val, err = p.GetByHeight(s.Height() + 2) val, err = p.GetByHeight(fc.Height() + 2)
if assert.Nil(err) { if assert.Nil(err) {
assertSeedEqual(t, s, val) assertCommitsEqual(t, fc, val)
} }
// below is nothing // below is nothing
_, err = p.GetByHeight(s.Height() - 2) _, err = p.GetByHeight(fc.Height() - 2)
assert.True(certifiers.IsSeedNotFoundErr(err)) assert.True(certerr.IsCommitNotFoundErr(err))
// make sure we get highest // make sure we get highest
val, err = certifiers.LatestSeed(p) val, err = p.LatestCommit()
if assert.Nil(err) { 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) // 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) { 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") 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) appHash := []byte(app)
seeds := make([]certifiers.Seed, count) commits := make([]certifiers.FullCommit, count)
for i := 0; i < count; i++ { 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), ... // (10, 0), (10, 1), (10, 1), (10, 2), (10, 2), ...
vals := keys.ToValidators(10, int64(count/2)) vals := keys.ToValidators(10, int64(count/2))
h := 20 + 10*i h := 20 + 10*i
check := keys.GenCheckpoint(chainID, h, nil, vals, appHash, 0, len(keys)) commits[i] = keys.GenFullCommit(chainID, h, nil, vals, appHash, 0, len(keys))
seeds[i] = certifiers.Seed{check, vals}
} }
return seeds return commits
} }
func checkProvider(t *testing.T, p certifiers.Provider, chainID, app string) { 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) keys := certifiers.GenValKeys(5)
count := 10 count := 10
// make a bunch of seeds... // make a bunch of commits...
seeds := makeSeeds(keys, count, chainID, app) commits := makeCommits(keys, count, chainID, app)
// check provider is empty // check provider is empty
seed, err := p.GetByHeight(20) fc, err := p.GetByHeight(20)
require.NotNil(err) 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) require.NotNil(err)
assert.True(certifiers.IsSeedNotFoundErr(err)) assert.True(certerr.IsCommitNotFoundErr(err))
// now add them all to the provider // now add them all to the provider
for _, s := range seeds { for _, fc := range commits {
err = p.StoreSeed(s) err = p.StoreCommit(fc)
require.Nil(err) require.Nil(err)
// and make sure we can get it back // and make sure we can get it back
s2, err := p.GetByHash(s.Hash()) fc2, err := p.GetByHash(fc.ValidatorsHash())
assert.Nil(err) assert.Nil(err)
assertSeedEqual(t, s, s2) assertCommitsEqual(t, fc, fc2)
// by height as well // by height as well
s2, err = p.GetByHeight(s.Height()) fc2, err = p.GetByHeight(fc.Height())
assert.Nil(err) assert.Nil(err)
assertSeedEqual(t, s, s2) assertCommitsEqual(t, fc, fc2)
} }
// make sure we get the last hash if we overstep // make sure we get the last hash if we overstep
seed, err = p.GetByHeight(5000) fc, err = p.GetByHeight(5000)
if assert.Nil(err) { if assert.Nil(err) {
assertSeedEqual(t, seeds[count-1], seed) assertCommitsEqual(t, commits[count-1], fc)
} }
// and middle ones as well // and middle ones as well
seed, err = p.GetByHeight(47) fc, err = p.GetByHeight(47)
if assert.Nil(err) { if assert.Nil(err) {
// we only step by 10, so 40 must be the one below this // we only step by 10, so 40 must be the one below this
assert.Equal(40, seed.Height()) assert.Equal(40, fc.Height())
} }
} }

View File

@ -32,8 +32,8 @@ func NewMockChain(chainID string, numKeys int) MockChain {
// GetRegistrationTx returns a valid tx to register this chain // GetRegistrationTx returns a valid tx to register this chain
func (m MockChain) GetRegistrationTx(h int) RegisterChainTx { func (m MockChain) GetRegistrationTx(h int) RegisterChainTx {
seed := genEmptySeed(m.keys, m.chainID, h, m.tree.Hash(), len(m.keys)) fc := genEmptyCommit(m.keys, m.chainID, h, m.tree.Hash(), len(m.keys))
return RegisterChainTx{seed} return RegisterChainTx{fc}
} }
// MakePostPacket commits the packet locally and returns the proof, // MakePostPacket commits the packet locally and returns the proof,
@ -42,18 +42,17 @@ func (m MockChain) MakePostPacket(packet Packet, h int) (
PostPacketTx, UpdateChainTx) { PostPacketTx, UpdateChainTx) {
post := makePostPacket(m.tree, packet, m.chainID, h) post := makePostPacket(m.tree, packet, m.chainID, h)
seed := genEmptySeed(m.keys, m.chainID, h+1, m.tree.Hash(), len(m.keys)) fc := genEmptyCommit(m.keys, m.chainID, h+1, m.tree.Hash(), len(m.keys))
update := UpdateChainTx{seed} update := UpdateChainTx{fc}
return post, update return post, update
} }
func genEmptySeed(keys certifiers.ValKeys, chain string, h int, func genEmptyCommit(keys certifiers.ValKeys, chain string, h int,
appHash []byte, count int) certifiers.Seed { appHash []byte, count int) certifiers.FullCommit {
vals := keys.ToValidators(10, 0) vals := keys.ToValidators(10, 0)
cp := keys.GenCheckpoint(chain, h, nil, vals, appHash, 0, count) return keys.GenFullCommit(chain, h, nil, vals, appHash, 0, count)
return certifiers.Seed{cp, vals}
} }
func makePostPacket(tree *iavl.Tree, packet Packet, fromID string, fromHeight int) PostPacketTx { func makePostPacket(tree *iavl.Tree, packet Packet, fromID string, fromHeight int) PostPacketTx {

View File

@ -32,17 +32,17 @@ func init() {
// RegisterChainTx allows you to register a new chain on this blockchain // RegisterChainTx allows you to register a new chain on this blockchain
type RegisterChainTx struct { type RegisterChainTx struct {
Seed certifiers.Seed `json:"seed"` Commit certifiers.FullCommit `json:"seed"`
} }
// ChainID helps get the chain this tx refers to // ChainID helps get the chain this tx refers to
func (r RegisterChainTx) ChainID() string { 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 // ValidateBasic makes sure this is consistent, without checking the sigs
func (r RegisterChainTx) ValidateBasic() error { func (r RegisterChainTx) ValidateBasic() error {
err := r.Seed.ValidateBasic(r.ChainID()) err := r.Commit.ValidateBasic(r.ChainID())
if err != nil { if err != nil {
err = ErrInvalidCommit(err) err = ErrInvalidCommit(err)
} }
@ -56,17 +56,17 @@ func (r RegisterChainTx) Wrap() sdk.Tx {
// UpdateChainTx updates the state of this chain // UpdateChainTx updates the state of this chain
type UpdateChainTx struct { type UpdateChainTx struct {
Seed certifiers.Seed `json:"seed"` Commit certifiers.FullCommit `json:"seed"`
} }
// ChainID helps get the chain this tx refers to // ChainID helps get the chain this tx refers to
func (u UpdateChainTx) ChainID() string { 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 // ValidateBasic makes sure this is consistent, without checking the sigs
func (u UpdateChainTx) ValidateBasic() error { func (u UpdateChainTx) ValidateBasic() error {
err := u.Seed.ValidateBasic(u.ChainID()) err := u.Commit.ValidateBasic(u.ChainID())
if err != nil { if err != nil {
err = ErrInvalidCommit(err) err = ErrInvalidCommit(err)
} }

View File

@ -7,9 +7,8 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
lc "github.com/tendermint/light-client"
sdk "github.com/cosmos/cosmos-sdk" 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"
"github.com/cosmos/cosmos-sdk/client/commands/query" "github.com/cosmos/cosmos-sdk/client/commands/query"
"github.com/cosmos/cosmos-sdk/modules/nonce" "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)) key := stack.PrefixedKey(nonce.NameNonce, nonce.GetSeqKey(signers))
prove := !viper.GetBool(commands.FlagTrustNode) prove := !viper.GetBool(commands.FlagTrustNode)
height, err = query.GetParsed(key, &sequence, query.GetHeight(), prove) height, err = query.GetParsed(key, &sequence, query.GetHeight(), prove)
if lc.IsNoDataErr(err) { if client.IsNoDataErr(err) {
// no data, return sequence 0 // no data, return sequence 0
return 0, 0, nil return 0, 0, nil
} }

View File

@ -9,6 +9,7 @@ import (
"github.com/spf13/viper" "github.com/spf13/viper"
sdk "github.com/cosmos/cosmos-sdk" 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"
"github.com/cosmos/cosmos-sdk/client/commands/query" "github.com/cosmos/cosmos-sdk/client/commands/query"
"github.com/cosmos/cosmos-sdk/errors" "github.com/cosmos/cosmos-sdk/errors"
@ -16,7 +17,6 @@ import (
"github.com/cosmos/cosmos-sdk/modules/nonce" "github.com/cosmos/cosmos-sdk/modules/nonce"
"github.com/cosmos/cosmos-sdk/stack" "github.com/cosmos/cosmos-sdk/stack"
wire "github.com/tendermint/go-wire" wire "github.com/tendermint/go-wire"
lightclient "github.com/tendermint/light-client"
"github.com/tendermint/tmlibs/common" "github.com/tendermint/tmlibs/common"
) )
@ -48,7 +48,7 @@ func doQueryNonce(w http.ResponseWriter, r *http.Request) {
// query sequence number // query sequence number
data, height, err := query.Get(key, h, prove) 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) err = fmt.Errorf("nonce empty for address: %q", signature)
common.WriteError(w, err) common.WriteError(w, err)
return return