Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Certifiers from tendermint #270

Merged
merged 9 commits into from
Oct 27, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions client/block.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package client

import (
"bytes"

"github.com/pkg/errors"

"github.com/tendermint/tendermint/certifiers"
certerr "github.com/tendermint/tendermint/certifiers/errors"
"github.com/tendermint/tendermint/types"
)

func ValidateBlockMeta(meta *types.BlockMeta, check certifiers.Commit) error {
// TODO: check the BlockID??
return ValidateHeader(meta.Header, check)
}

func ValidateBlock(meta *types.Block, check certifiers.Commit) error {
err := ValidateHeader(meta.Header, check)
if err != nil {
return err
}
if !bytes.Equal(meta.Data.Hash(), meta.Header.DataHash) {
return errors.New("Data hash doesn't match header")
}
return nil
}

func ValidateHeader(head *types.Header, check certifiers.Commit) error {
// make sure they are for the same height (obvious fail)
if head.Height != check.Height() {
return certerr.ErrHeightMismatch(head.Height, check.Height())
}
// check if they are equal by using hashes
chead := check.Header
if !bytes.Equal(head.Hash(), chead.Hash()) {
return errors.New("Headers don't match")
}
return nil
}
2 changes: 1 addition & 1 deletion client/commands/commits/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"github.com/spf13/cobra"
"github.com/spf13/viper"

"github.com/tendermint/light-client/certifiers/files"
"github.com/tendermint/tendermint/certifiers/files"

"github.com/cosmos/cosmos-sdk/client/commands"
)
Expand Down
2 changes: 1 addition & 1 deletion client/commands/commits/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"github.com/spf13/cobra"
"github.com/spf13/viper"

"github.com/tendermint/light-client/certifiers/files"
"github.com/tendermint/tendermint/certifiers/files"

"github.com/cosmos/cosmos-sdk/client/commands"
)
Expand Down
4 changes: 2 additions & 2 deletions client/commands/commits/show.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import (
"github.com/spf13/cobra"
"github.com/spf13/viper"

"github.com/tendermint/light-client/certifiers"
"github.com/tendermint/light-client/certifiers/files"
"github.com/tendermint/tendermint/certifiers"
"github.com/tendermint/tendermint/certifiers/files"

"github.com/cosmos/cosmos-sdk/client/commands"
)
Expand Down
2 changes: 1 addition & 1 deletion client/commands/commits/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"github.com/spf13/cobra"
"github.com/spf13/viper"

"github.com/tendermint/light-client/certifiers"
"github.com/tendermint/tendermint/certifiers"

"github.com/cosmos/cosmos-sdk/client/commands"
)
Expand Down
2 changes: 1 addition & 1 deletion client/commands/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
"github.com/spf13/cobra"
"github.com/spf13/viper"

"github.com/tendermint/light-client/certifiers"
"github.com/tendermint/tendermint/certifiers"
"github.com/tendermint/tmlibs/cli"
cmn "github.com/tendermint/tmlibs/common"

Expand Down
4 changes: 2 additions & 2 deletions client/commands/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ import (
"github.com/spf13/pflag"
"github.com/spf13/viper"

"github.com/tendermint/light-client/certifiers"
"github.com/tendermint/light-client/certifiers/files"
"github.com/tendermint/tendermint/certifiers"
"github.com/tendermint/tendermint/certifiers/files"
"github.com/tendermint/tmlibs/cli"
cmn "github.com/tendermint/tmlibs/common"

Expand Down
6 changes: 4 additions & 2 deletions client/commands/query/get.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package query

import (
"encoding/hex"
"fmt"
"io"
"os"
Expand All @@ -11,7 +12,7 @@ import (
wire "github.com/tendermint/go-wire"
"github.com/tendermint/go-wire/data"
"github.com/tendermint/iavl"
"github.com/tendermint/light-client/proofs"
cmn "github.com/tendermint/tmlibs/common"

rpcclient "github.com/tendermint/tendermint/rpc/client"

Expand Down Expand Up @@ -87,7 +88,8 @@ func ParseHexKey(args []string, argname string) ([]byte, error) {
return nil, errors.Errorf("[%s] argument must be non-empty ", argname)
}
// with tx, we always just parse key as hex and use to lookup
return proofs.ParseHexKey(rawkey)
key, err := hex.DecodeString(cmn.StripHex(rawkey))
return key, errors.WithStack(err)
}

// GetHeight reads the viper config for the query height
Expand Down
16 changes: 4 additions & 12 deletions client/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@ package client
import (
"errors"

"github.com/tendermint/light-client/certifiers"
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/proofs"
"github.com/tendermint/tendermint/certifiers"
certclient "github.com/tendermint/tendermint/certifiers/client"
certerr "github.com/tendermint/tendermint/certifiers/errors"
"github.com/tendermint/tendermint/certifiers/files"

rpcclient "github.com/tendermint/tendermint/rpc/client"
)
Expand Down Expand Up @@ -49,9 +47,3 @@ func GetCertifier(chainID string, trust certifiers.Provider,
cert := certifiers.NewInquiring(chainID, fc, trust, source)
return cert, nil
}

// SecureClient uses a given certifier to wrap an connection to an untrusted
// host and return a cryptographically secure rpc client.
func SecureClient(c rpcclient.Client, cert *certifiers.Inquiring) rpcclient.Client {
return proofs.Wrap(c, cert)
}
1 change: 0 additions & 1 deletion client/errors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (

func TestErrorNoData(t *testing.T) {
e1 := ErrNoData()
e1.Error()
assert.True(t, IsNoDataErr(e1))

e2 := errors.New("foobar")
Expand Down
92 changes: 47 additions & 45 deletions client/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ import (

"github.com/tendermint/go-wire/data"
"github.com/tendermint/iavl"
"github.com/tendermint/light-client/certifiers"
certerr "github.com/tendermint/light-client/certifiers/errors"

"github.com/tendermint/tendermint/rpc/client"
"github.com/tendermint/tendermint/certifiers"
"github.com/tendermint/tendermint/certifiers/client"
certerr "github.com/tendermint/tendermint/certifiers/errors"
rpcclient "github.com/tendermint/tendermint/rpc/client"
ctypes "github.com/tendermint/tendermint/rpc/core/types"
)

// GetWithProof will query the key on the given node, and verify it has
Expand All @@ -17,7 +19,7 @@ import (
// If there is any error in checking, returns an error.
// If val is non-empty, proof should be KeyExistsProof
// If val is empty, proof should be KeyMissingProof
func GetWithProof(key []byte, reqHeight int, node client.Client,
func GetWithProof(key []byte, reqHeight int, node rpcclient.Client,
cert certifiers.Certifier) (
val data.Bytes, height uint64, proof iavl.KeyProof, err error) {

Expand All @@ -26,86 +28,86 @@ func GetWithProof(key []byte, reqHeight int, node client.Client,
return
}

resp, err := node.ABCIQueryWithOptions("/key", key,
client.ABCIQueryOptions{Height: uint64(reqHeight)})
resp, proof, err := GetWithProofOptions("/key", key,
rpcclient.ABCIQueryOptions{Height: uint64(reqHeight)},
node, cert)
if resp != nil {
val, height = resp.Value, resp.Height
}
return val, height, proof, err
}

// GetWithProofOptions is useful if you want full access to the ABCIQueryOptions
func GetWithProofOptions(path string, key []byte, opts rpcclient.ABCIQueryOptions,
node rpcclient.Client, cert certifiers.Certifier) (
*ctypes.ResultABCIQuery, iavl.KeyProof, error) {

resp, err := node.ABCIQueryWithOptions(path, key, opts)
if err != nil {
return
return nil, nil, err
}

// make sure the proof is the proper height
if !resp.Code.IsOK() {
err = errors.Errorf("Query error %d: %s", resp.Code, resp.Code.String())
return
return nil, nil, err
}
if len(resp.Key) == 0 || len(resp.Proof) == 0 {
err = ErrNoData()
return
return nil, nil, ErrNoData()
}
if resp.Height == 0 {
err = errors.New("Height returned is zero")
return
return nil, nil, errors.New("Height returned is zero")
}

// AppHash for height H is in header H+1
var commit *certifiers.Commit
commit, err = GetCertifiedCommit(int(resp.Height+1), node, cert)
commit, err := GetCertifiedCommit(int(resp.Height+1), node, cert)
if err != nil {
return
return nil, nil, err
}

if len(resp.Value) > 0 {
// The key was found, construct a proof of existence.
var eproof *iavl.KeyExistsProof
eproof, err = iavl.ReadKeyExistsProof(resp.Proof)
eproof, err := iavl.ReadKeyExistsProof(resp.Proof)
if err != nil {
err = errors.Wrap(err, "Error reading proof")
return
return nil, nil, errors.Wrap(err, "Error reading proof")
}

// Validate the proof against the certified header to ensure data integrity.
err = eproof.Verify(resp.Key, resp.Value, commit.Header.AppHash)
if err != nil {
err = errors.Wrap(err, "Couldn't verify proof")
return
return nil, nil, errors.Wrap(err, "Couldn't verify proof")
}
val = data.Bytes(resp.Value)
proof = eproof
} else {
// The key wasn't found, construct a proof of non-existence.
var aproof *iavl.KeyAbsentProof
aproof, err = iavl.ReadKeyAbsentProof(resp.Proof)
if err != nil {
err = errors.Wrap(err, "Error reading proof")
return
}
// Validate the proof against the certified header to ensure data integrity.
err = aproof.Verify(resp.Key, nil, commit.Header.AppHash)
if err != nil {
err = errors.Wrap(err, "Couldn't verify proof")
return
}
err = ErrNoData()
proof = aproof
return resp, eproof, nil
}

height = resp.Height
return
// The key wasn't found, construct a proof of non-existence.
var aproof *iavl.KeyAbsentProof
aproof, err = iavl.ReadKeyAbsentProof(resp.Proof)
if err != nil {
return nil, nil, errors.Wrap(err, "Error reading proof")
}
// Validate the proof against the certified header to ensure data integrity.
err = aproof.Verify(resp.Key, nil, commit.Header.AppHash)
if err != nil {
return nil, nil, errors.Wrap(err, "Couldn't verify proof")
}
return resp, aproof, ErrNoData()
}

// GetCertifiedCommit gets the signed header for a given height
// and certifies it. Returns error if unable to get a proven header.
func GetCertifiedCommit(h int, node client.Client,
cert certifiers.Certifier) (empty *certifiers.Commit, err error) {
func GetCertifiedCommit(h int, node rpcclient.Client,
cert certifiers.Certifier) (empty certifiers.Commit, err error) {

// FIXME: cannot use cert.GetByHeight for now, as it also requires
// Validators and will fail on querying tendermint for non-current height.
// When this is supported, we should use it instead...
client.WaitForHeight(node, h, nil)
rpcclient.WaitForHeight(node, h, nil)
cresp, err := node.Commit(&h)
if err != nil {
return
}
commit := certifiers.CommitFromResult(cresp)
commit := client.CommitFromResult(cresp)

// validate downloaded checkpoint with our request and trust store.
if commit.Height() != h {
Expand Down
4 changes: 2 additions & 2 deletions client/query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import (
"github.com/stretchr/testify/require"

"github.com/tendermint/go-wire"
"github.com/tendermint/light-client/certifiers"
certclient "github.com/tendermint/light-client/certifiers/client"
"github.com/tendermint/tendermint/certifiers"
certclient "github.com/tendermint/tendermint/certifiers/client"
"github.com/tendermint/tmlibs/log"

nm "github.com/tendermint/tendermint/node"
Expand Down
Loading