Skip to content

Commit

Permalink
Refactor app state query code
Browse files Browse the repository at this point in the history
  • Loading branch information
cloudhead committed Aug 4, 2017
1 parent 4df20df commit 391380b
Showing 1 changed file with 46 additions and 6 deletions.
52 changes: 46 additions & 6 deletions client/commands/proofs/state.go
Original file line number Diff line number Diff line change
@@ -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"
)
Expand All @@ -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)
}

0 comments on commit 391380b

Please sign in to comment.