From 15d2e2525fd6468787d2897cd75e3a8725cb2294 Mon Sep 17 00:00:00 2001 From: Alexis Sellier Date: Mon, 7 Aug 2017 17:15:16 +0200 Subject: [PATCH] Start working on proof tests --- client/commands/query/get.go | 26 ++++++--- client/commands/query/query_test.go | 85 +++++++++++++++++++++++++++++ client/commands/query/tx.go | 7 ++- 3 files changed, 108 insertions(+), 10 deletions(-) create mode 100644 client/commands/query/query_test.go diff --git a/client/commands/query/get.go b/client/commands/query/get.go index 91831892d9..f608c71acc 100644 --- a/client/commands/query/get.go +++ b/client/commands/query/get.go @@ -18,6 +18,10 @@ import ( "github.com/tendermint/basecoin/client/commands" ) +type Certifier interface { + Certify(check lc.Checkpoint) error +} + // GetParsed does most of the work of the query commands, but is quite // opinionated, so if you want more control about parsing, call Get // directly. @@ -60,6 +64,16 @@ func Get(key []byte, prove bool) (data.Bytes, uint64, error) { // proof for the key-value pair if it exists, and all checks pass. func GetWithProof(key []byte) (data.Bytes, uint64, *iavl.KeyExistsProof, error) { node := commands.GetNode() + cert, err := commands.GetCertifier() + if err != nil { + return nil, 0, nil, err + } + return CustomGetWithProof(key, node, cert) +} + +// TODO: fix this up alexis +func CustomGetWithProof(key []byte, node client.Client, + cert Certifier) (data.Bytes, uint64, *iavl.KeyExistsProof, error) { resp, err := node.ABCIQuery("/key", key, true) if err != nil { @@ -79,7 +93,7 @@ func GetWithProof(key []byte) (data.Bytes, uint64, *iavl.KeyExistsProof, error) return nil, 0, nil, lc.ErrHeightMismatch(ph, int(resp.Height)) } - check, err := GetCertifiedCheckpoint(ph) + check, err := GetCertifiedCheckpoint(ph, node, cert) if err != nil { return nil, 0, nil, err } @@ -101,14 +115,8 @@ func GetWithProof(key []byte) (data.Bytes, uint64, *iavl.KeyExistsProof, error) // GetCertifiedCheckpoint gets the signed header for a given height // and certifies it. Returns error if unable to get a proven header. -func GetCertifiedCheckpoint(h int) (empty lc.Checkpoint, err error) { - // here is the certifier, root of all trust - node := commands.GetNode() - cert, err := commands.GetCertifier() - if err != nil { - return - } - +func GetCertifiedCheckpoint(h int, node client.Client, + cert Certifier) (empty lc.Checkpoint, err error) { // get the checkpoint for this height // FIXME: cannot use cert.GetByHeight for now, as it also requires diff --git a/client/commands/query/query_test.go b/client/commands/query/query_test.go new file mode 100644 index 0000000000..5915198fb3 --- /dev/null +++ b/client/commands/query/query_test.go @@ -0,0 +1,85 @@ +package query + +import ( + "os" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/tendermint/go-wire" + "github.com/tendermint/light-client/certifiers" + certclient "github.com/tendermint/light-client/certifiers/client" + nm "github.com/tendermint/tendermint/node" + "github.com/tendermint/tendermint/rpc/client" + rpctest "github.com/tendermint/tendermint/rpc/test" + "github.com/tendermint/tmlibs/log" + + "github.com/tendermint/basecoin/app" + "github.com/tendermint/basecoin/modules/etc" +) + +var node *nm.Node + +func TestMain(m *testing.M) { + logger := log.TestingLogger() + store, err := app.NewStore("", 0, logger) + if err != nil { + panic(err) + } + app := app.NewBasecoin(etc.NewHandler(), store, logger) + node = rpctest.StartTendermint(app) + + code := m.Run() + + node.Stop() + node.Wait() + os.Exit(code) +} + +func TestAppProofs(t *testing.T) { + assert, require := assert.New(t), require.New(t) + + cl := client.NewLocal(node) + time.Sleep(200 * time.Millisecond) + + k := []byte("my-key") + v := []byte("my-value") + + tx := etc.SetTx{Key: k, Value: v}.Wrap() + btx := wire.BinaryBytes(tx) + br, err := cl.BroadcastTxCommit(btx) + require.Nil(err, "%+v", err) + require.EqualValues(0, br.CheckTx.Code, "%#v", br.CheckTx) + require.EqualValues(0, br.DeliverTx.Code) + + // this sets up our trust on the node based on some past point. + // maybe this can be cleaned up and made easy to reuse + source := certclient.New(cl) + trusted := certifiers.NewMemStoreProvider() + // let's start with some trust before the query... + seed, err := source.GetByHeight(br.Height - 2) + require.Nil(err, "%+v", err) + cert := certifiers.NewInquiring("my-chain", seed, trusted, source) + + // Test existing key. + + bs, _, proof, err := CustomGetWithProof(k, cl, cert) + require.Nil(err, "%+v", err) + require.NotNil(proof) + + var data etc.Data + err = wire.ReadBinaryBytes(bs, &data) + require.Nil(err, "%+v", err) + assert.EqualValues(v, data.Value) + + // Test non-existing key. + + // TODO: This currently fails. + missing := []byte("my-missing-key") + bs, _, proof, err = CustomGetWithProof(missing, cl, cert) + require.Nil(err, "%+v", err) + require.Nil(bs) + require.NotNil(proof) +} diff --git a/client/commands/query/tx.go b/client/commands/query/tx.go index 873deb8666..1d520f89e5 100644 --- a/client/commands/query/tx.go +++ b/client/commands/query/tx.go @@ -46,7 +46,12 @@ func txQueryCmd(cmd *cobra.Command, args []string) error { return showTx(res.Height, res.Tx) } - check, err := GetCertifiedCheckpoint(res.Height) + cert, err := commands.GetCertifier() + if err != nil { + return err + } + + check, err := GetCertifiedCheckpoint(res.Height, node, cert) if err != nil { return err }