From 391380bef2076f3a378c135a8964a3194f3b0fcc Mon Sep 17 00:00:00 2001 From: Alexis Sellier Date: Fri, 4 Aug 2017 18:36:35 +0200 Subject: [PATCH] Refactor app state query code --- client/commands/proofs/state.go | 52 +++++++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 6 deletions(-) diff --git a/client/commands/proofs/state.go b/client/commands/proofs/state.go index e55b5b5810..06c4ffe3dd 100644 --- a/client/commands/proofs/state.go +++ b/client/commands/proofs/state.go @@ -1,10 +1,14 @@ package proofs import ( + "github.com/pkg/errors" "github.com/spf13/cobra" + "github.com/spf13/viper" + wire "github.com/tendermint/go-wire" "github.com/tendermint/go-wire/data" - "github.com/tendermint/light-client/proofs" + lc "github.com/tendermint/light-client" + "github.com/tendermint/merkleeyes/iavl" "github.com/tendermint/basecoin/client/commands" ) @@ -24,24 +28,60 @@ If you want json output, use an app-specific command that knows key and value st // parse the object, but rather return the raw bytes func keyQueryCmd(cmd *cobra.Command, args []string) error { // parse cli - height := GetHeight() key, err := ParseHexKey(args, "key") if err != nil { return err } + prove := viper.GetBool(commands.FlagTrustNode) // get the proof -> this will be used by all prover commands node := commands.GetNode() - prover := proofs.NewAppProver(node) - proof, err := GetProof(node, prover, key, height) + + //////////////// + resp, err := node.ABCIQuery("/key", key, prove) + if err != nil { + return err + } + ph := int(resp.Height) + + // short-circuit with no proofs + if !prove { + return OutputProof(data.Bytes(resp.Value), resp.Height) + } + + // make sure the proof is the proper height + if !resp.Code.IsOK() { + return errors.Errorf("Query error %d: %s", resp.Code, resp.Code.String()) + } + // TODO: Handle null proofs + if len(resp.Key) == 0 || len(resp.Value) == 0 || len(resp.Proof) == 0 { + return lc.ErrNoData() + } + if ph != 0 && ph != int(resp.Height) { + return lc.ErrHeightMismatch(ph, int(resp.Height)) + } + + check, err := GetCertifiedCheckpoint(ph) + if err != nil { + return err + } + + proof := new(iavl.KeyExistsProof) + err = wire.ReadBinaryBytes(resp.Proof, &proof) + if err != nil { + return err + } + + // validate the proof against the certified header to ensure data integrity + err = proof.Verify(resp.Key, resp.Value, check.Header.AppHash) if err != nil { return err } // state just returns raw hex.... - info := data.Bytes(proof.Data()) + info := data.Bytes(resp.Value) // we can reuse this output for other commands for text/json // unless they do something special like store a file to disk - return OutputProof(info, proof.BlockHeight()) + return OutputProof(info, resp.Height) }