in progress

This commit is contained in:
mossid 2018-07-12 23:50:39 -07:00
parent 7495528fb8
commit b16ce7e0c2
6 changed files with 80 additions and 61 deletions

View File

@ -1,4 +1,4 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: merkle.proto
/*
@ -11,10 +11,9 @@ It has these top-level messages:
ProofOp
Proof
*/
//nolint: gas
package merkle
import proto "github.com/gogo/protobuf/proto"
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
import _ "github.com/gogo/protobuf/gogoproto"
@ -28,18 +27,18 @@ var _ = math.Inf
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
type ProofOp struct {
Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"`
Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
Type string `protobuf:"bytes,1,opt,name=type" json:"type,omitempty"`
Key []byte `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
Data []byte `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"`
}
func (m *ProofOp) Reset() { *m = ProofOp{} }
func (m *ProofOp) String() string { return proto.CompactTextString(m) }
func (*ProofOp) ProtoMessage() {}
func (*ProofOp) Descriptor() ([]byte, []int) { return fileDescriptorMerkle, []int{0} }
func (*ProofOp) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
func (m *ProofOp) GetType() string {
if m != nil {
@ -48,11 +47,11 @@ func (m *ProofOp) GetType() string {
return ""
}
func (m *ProofOp) GetKey() string {
func (m *ProofOp) GetKey() []byte {
if m != nil {
return m.Key
}
return ""
return nil
}
func (m *ProofOp) GetData() []byte {
@ -63,15 +62,15 @@ func (m *ProofOp) GetData() []byte {
}
type Proof struct {
Ops []ProofOp `protobuf:"bytes,1,rep,name=ops" json:"ops"`
Ops []*ProofOp `protobuf:"bytes,1,rep,name=ops" json:"ops,omitempty"`
}
func (m *Proof) Reset() { *m = Proof{} }
func (m *Proof) String() string { return proto.CompactTextString(m) }
func (*Proof) ProtoMessage() {}
func (*Proof) Descriptor() ([]byte, []int) { return fileDescriptorMerkle, []int{1} }
func (*Proof) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
func (m *Proof) GetOps() []ProofOp {
func (m *Proof) GetOps() []*ProofOp {
if m != nil {
return m.Ops
}
@ -83,19 +82,19 @@ func init() {
proto.RegisterType((*Proof)(nil), "merkle.Proof")
}
func init() { proto.RegisterFile("merkle.proto", fileDescriptorMerkle) }
func init() { proto.RegisterFile("merkle.proto", fileDescriptor0) }
var fileDescriptorMerkle = []byte{
var fileDescriptor0 = []byte{
// 168 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0xc9, 0x4d, 0x2d, 0xca,
0xce, 0x49, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x83, 0xf0, 0xa4, 0x74, 0xd3, 0x33,
0x4b, 0x32, 0x4a, 0x93, 0xf4, 0x92, 0xf3, 0x73, 0xf5, 0xd3, 0xf3, 0xd3, 0xf3, 0xf5, 0xc1, 0xd2,
0x49, 0xa5, 0x69, 0x60, 0x1e, 0x98, 0x03, 0x66, 0x41, 0xb4, 0x29, 0x39, 0x73, 0xb1, 0x07, 0x14,
0xe5, 0xe7, 0xa7, 0xf9, 0x17, 0x08, 0x09, 0x71, 0xb1, 0x94, 0x54, 0x16, 0xa4, 0x4a, 0x30, 0x2a,
0x30, 0x6a, 0x70, 0x06, 0x81, 0xd9, 0x42, 0x02, 0x5c, 0xcc, 0xd9, 0xa9, 0x95, 0x12, 0x4c, 0x60,
0x21, 0x10, 0x13, 0xa4, 0x2a, 0x25, 0xb1, 0x24, 0x51, 0x82, 0x59, 0x81, 0x51, 0x83, 0x27, 0x08,
0x30, 0x6a, 0x70, 0x06, 0x81, 0xd9, 0x42, 0x02, 0x5c, 0xcc, 0xd9, 0xa9, 0x95, 0x12, 0x4c, 0x0a,
0x8c, 0x1a, 0x3c, 0x41, 0x20, 0x26, 0x48, 0x55, 0x4a, 0x62, 0x49, 0xa2, 0x04, 0x33, 0x58, 0x08,
0xcc, 0x56, 0x32, 0xe0, 0x62, 0x05, 0x1b, 0x22, 0xa4, 0xce, 0xc5, 0x9c, 0x5f, 0x50, 0x2c, 0xc1,
0xa8, 0xc0, 0xac, 0xc1, 0x6d, 0xc4, 0xaf, 0x07, 0x75, 0x20, 0xd4, 0x02, 0x27, 0x96, 0x13, 0xf7,
0xe4, 0x19, 0x82, 0x40, 0x2a, 0x92, 0xd8, 0xc0, 0xb6, 0x1b, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff,
0x52, 0x58, 0x00, 0xa7, 0xc4, 0x00, 0x00, 0x00,
0xe0, 0x7d, 0x7c, 0x4e, 0xc4, 0x00, 0x00, 0x00,
}

View File

@ -10,7 +10,7 @@ import "github.com/gogo/protobuf/gogoproto/gogo.proto";
message ProofOp {
string type = 1;
string key = 2;
bytes key = 2;
bytes data = 3;
}

View File

@ -3,27 +3,15 @@ package merkle
import (
"bytes"
"github.com/tendermint/go-amino"
cmn "github.com/tendermint/tmlibs/common"
)
//----------------------------------------
// Extension of ProofOp (defined in merkle.proto)
func (po ProofOp) Bytes() []byte {
bz, err := amino.MarshalBinary(po)
if err != nil {
panic(err)
}
return bz
}
//----------------------------------------
// ProofOp gets converted to an instance of ProofOperator:
type ProofOperator interface {
Run([][]byte) ([][]byte, error)
GetKey() string
GetKey() []byte
ProofOp() ProofOp
}
@ -32,18 +20,20 @@ type ProofOperator interface {
type ProofOperators []ProofOperator
// XXX Reorder value/keys.
// XXX Replace keys with keyString (the result of KeyPath.String())
func (poz ProofOperators) VerifyValue(root []byte, value []byte, keys ...string) (err error) {
return poz.Verify(root, [][]byte{value}, keys...)
func (poz ProofOperators) VerifyValue(root []byte, keypath string, value []byte) (err error) {
return poz.Verify(root, keypath, [][]byte{value})
}
// XXX Replace keys with keyString (the result of KeyPath.String())
func (poz ProofOperators) Verify(root []byte, args [][]byte, keys ...string) (err error) {
func (poz ProofOperators) Verify(root []byte, keypath string, args [][]byte) (err error) {
keys, err := KeyPathToKeys(keypath)
if err != nil {
return
}
for i, op := range poz {
key := op.GetKey()
if key != "" {
if keys[0] != key {
if len(key) != 0 {
if !bytes.Equal(keys[0], key) {
return cmn.NewError("Key mismatch on operation #%d: expected %+v but %+v", i, []byte(keys[0]), []byte(key))
}
keys = keys[1:]
@ -93,7 +83,7 @@ func (prt *ProofRuntime) Decode(pop ProofOp) (ProofOperator, error) {
func (prt *ProofRuntime) DecodeProof(proof *Proof) (poz ProofOperators, err error) {
poz = ProofOperators(nil)
for _, pop := range proof.Ops {
operator, err := prt.Decode(pop)
operator, err := prt.Decode(*pop)
if err != nil {
return nil, cmn.ErrorWrap(err, "decoding a proof operator")
}
@ -104,26 +94,26 @@ func (prt *ProofRuntime) DecodeProof(proof *Proof) (poz ProofOperators, err erro
// XXX Reorder value/keys.
// XXX Replace keys with keyString (the result of KeyPath.String()).
func (prt *ProofRuntime) VerifyValue(proof *Proof, root []byte, value []byte, keys ...string) (err error) {
return prt.Verify(proof, root, [][]byte{value}, keys...)
func (prt *ProofRuntime) VerifyValue(proof *Proof, root []byte, keypath string, value []byte) (err error) {
return prt.Verify(proof, root, keypath, [][]byte{value})
}
// XXX Reorder value/keys.
// XXX Replace keys with keyString (the result of KeyPath.String()).
// TODO In the long run we'll need a method of classifcation of ops,
// whether existence or absence or perhaps a third?
func (prt *ProofRuntime) VerifyAbsence(proof *Proof, root []byte, keys ...string) (err error) {
return prt.Verify(proof, root, nil, keys...)
func (prt *ProofRuntime) VerifyAbsence(proof *Proof, keypath string, root []byte) (err error) {
return prt.Verify(proof, root, keypath, nil)
}
// XXX Reorder value/keys.
// XXX Replace keys with keyString (the result of KeyPath.String()).
func (prt *ProofRuntime) Verify(proof *Proof, root []byte, args [][]byte, keys ...string) (err error) {
func (prt *ProofRuntime) Verify(proof *Proof, root []byte, keypath string, args [][]byte) (err error) {
poz, err := prt.DecodeProof(proof)
if err != nil {
return cmn.ErrorWrap(err, "decoding proof")
}
return poz.Verify(root, args, keys...)
return poz.Verify(root, keypath, args)
}
// DefaultProofRuntime only knows about Simple value

View File

@ -52,27 +52,28 @@ type keyEncoding int
const (
KeyEncodingURL keyEncoding = iota
KeyEncodingHex
KeyEncodingMax
)
type KeyPath struct {
keys [][]byte
encs []keyEncoding
type Key struct {
name []byte
enc keyEncoding
}
func (pth *KeyPath) AppendKey(key []byte, enc keyEncoding) {
pth.keys = append(pth.keys, key)
pth.encs = append(pth.encs, enc)
type KeyPath []Key
func (pth KeyPath) AppendKey(key []byte, enc keyEncoding) KeyPath {
return append(pth, Key{key, enc})
}
func (pth *KeyPath) String() string {
func (pth KeyPath) String() string {
res := ""
for i := 0; i < len(pth.keys); i++ {
key, enc := pth.keys[i], pth.encs[i]
switch enc {
for _, key := range pth {
switch key.enc {
case KeyEncodingURL:
res += "/" + url.PathEscape(string(key))
res += "/" + url.PathEscape(string(key.name))
case KeyEncodingHex:
res += "/x:" + fmt.Sprintf("%X", key)
res += "/x:" + fmt.Sprintf("%X", key.name)
default:
panic("unexpected key encoding type")
}

View File

@ -0,0 +1,29 @@
package merkle
import (
"math/rand"
"testing"
"github.com/stretchr/testify/require"
)
func TestKeyPath(t *testing.T) {
var path KeyPath
keys := make([][]byte, 10)
for d := 0; d < 20; d++ {
for i := range keys {
keys[i] = make([]byte, rand.Uint32()%20)
rand.Read(keys[i])
enc := keyEncoding(rand.Intn(int(KeyEncodingMax)))
path = path.AppendKey(keys[i], enc)
}
res, err := KeyPathToKeys(path.String())
require.Nil(t, err)
for i, key := range keys {
require.Equal(t, key, res[i])
}
}
}

View File

@ -22,7 +22,7 @@ const ProofOpSimpleValue = "simple:v"
// proof is good.
type SimpleValueOp struct {
// Encoded in ProofOp.Key.
key string
key []byte
// To encode in ProofOp.Data
Proof *SimpleProof `json:"simple-proof"`
@ -30,7 +30,7 @@ type SimpleValueOp struct {
var _ ProofOperator = SimpleValueOp{}
func NewSimpleValueOp(key string, proof *SimpleProof) SimpleValueOp {
func NewSimpleValueOp(key []byte, proof *SimpleProof) SimpleValueOp {
return SimpleValueOp{
key: key,
Proof: proof,
@ -86,6 +86,6 @@ func (op SimpleValueOp) Run(args [][]byte) ([][]byte, error) {
}, nil
}
func (op SimpleValueOp) GetKey() string {
func (op SimpleValueOp) GetKey() []byte {
return op.key
}