Refactor app state query code

This commit is contained in:
Alexis Sellier 2017-08-04 18:36:35 +02:00
parent 4df20df62a
commit 391380bef2
1 changed files with 46 additions and 6 deletions

View File

@ -1,10 +1,14 @@
package proofs package proofs
import ( import (
"github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper"
wire "github.com/tendermint/go-wire"
"github.com/tendermint/go-wire/data" "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" "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 // parse the object, but rather return the raw bytes
func keyQueryCmd(cmd *cobra.Command, args []string) error { func keyQueryCmd(cmd *cobra.Command, args []string) error {
// parse cli // parse cli
height := GetHeight()
key, err := ParseHexKey(args, "key") key, err := ParseHexKey(args, "key")
if err != nil { if err != nil {
return err return err
} }
prove := viper.GetBool(commands.FlagTrustNode)
// get the proof -> this will be used by all prover commands // get the proof -> this will be used by all prover commands
node := commands.GetNode() 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 { if err != nil {
return err return err
} }
// state just returns raw hex.... // 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 // we can reuse this output for other commands for text/json
// unless they do something special like store a file to disk // unless they do something special like store a file to disk
return OutputProof(info, proof.BlockHeight()) return OutputProof(info, resp.Height)
} }