Skip to content

Commit 0584aa4

Browse files
authored
Support for Enums (#42)
* add support for enums * fix tests * fix tests
1 parent 48de918 commit 0584aa4

File tree

7 files changed

+359
-290
lines changed

7 files changed

+359
-290
lines changed

examples/documents/documents.go

+29-27
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package documentspb
22

3-
//go:generate protoc -I $PROTOBUF/src/ -I. -I $GOPATH/src --go_out=$GOPATH/src/ examples.proto
3+
//go:generate protoc -I $PROTOBUF/src/ -I. -I $GOPATH/src --go_out=$GOPATH/src/ example.proto
44

55
import (
66
"time"
@@ -26,6 +26,8 @@ var ExampleDocumentSalts SaltedExampleDocument = SaltedExampleDocument{
2626
ValueBytes1: salt,
2727
ValueCamelCased: salt,
2828
ValueNotIgnored: salt,
29+
ValueMap: salt,
30+
EnumType: salt,
2931
}
3032

3133
var ExampleTimeString string = "2018-04-10T01:23:12.697116Z"
@@ -79,32 +81,32 @@ var ExampleSaltedNestedRepeatedDocument = SaltedNestedRepeatedDocument{
7981
ValueD: &SaltedTwoLevelItem{ValueA: &SaltedSimpleItem{ValueA: salt}, ValueB: salt},
8082
}
8183

82-
var ExampleSimpleMapDocument = SimpleMapDocument {
83-
ValueA: "ValueAA",
84-
ValueB: "ValueBB",
85-
ValueC: map[string]string{
86-
"ValueCAKey": "ValueCAValue",
87-
"ValueCBKey": "ValueCBValue",
88-
},
89-
ValueD: map[int32]string{
90-
-1: "negative one",
91-
0: "zero",
92-
1: "one",
93-
},
84+
var ExampleSimpleMapDocument = SimpleMapDocument{
85+
ValueA: "ValueAA",
86+
ValueB: "ValueBB",
87+
ValueC: map[string]string{
88+
"ValueCAKey": "ValueCAValue",
89+
"ValueCBKey": "ValueCBValue",
90+
},
91+
ValueD: map[int32]string{
92+
-1: "negative one",
93+
0: "zero",
94+
1: "one",
95+
},
9496
}
9597

96-
var ExampleSaltedSimpleMapDocument = SaltedSimpleMapDocument {
97-
ValueA: salt,
98-
ValueB: salt,
99-
ValueC: map[string][]byte{
100-
"ValueCAKey": salt,
101-
"ValueCBKey": salt,
102-
},
103-
ValueCLength: salt,
104-
ValueD: map[int32][]byte{
105-
-1: salt,
106-
0: salt,
107-
1: salt,
108-
},
109-
ValueDLength: salt,
98+
var ExampleSaltedSimpleMapDocument = SaltedSimpleMapDocument{
99+
ValueA: salt,
100+
ValueB: salt,
101+
ValueC: map[string][]byte{
102+
"ValueCAKey": salt,
103+
"ValueCBKey": salt,
104+
},
105+
ValueCLength: salt,
106+
ValueD: map[int32][]byte{
107+
-1: salt,
108+
0: salt,
109+
1: salt,
110+
},
111+
ValueDLength: salt,
110112
}

examples/documents/example.pb.go

+245-201
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/documents/example.proto

+7
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ message ExampleDocument {
2626
bytes value_not_hashed = 9 [
2727
(proofs.hashed_field) = true
2828
];
29+
Enum enum_type = 10;
2930
}
3031

3132
message AllFieldTypes {
@@ -274,4 +275,10 @@ message SaltedExampleDocument {
274275
bytes ValueCamelCased = 6;
275276
bytes value_not_ignored = 7;
276277
bytes valueMap = 10;
278+
bytes enum_type = 11;
279+
}
280+
281+
enum Enum {
282+
type_one = 0;
283+
type_two = 1;
277284
}

examples/simple.go

+13-12
Original file line numberDiff line numberDiff line change
@@ -11,42 +11,43 @@ import (
1111
"github.com/centrifuge/precise-proofs/proofs"
1212
)
1313

14-
func printError(err error) {
15-
if err != nil {
16-
fmt.Printf("There was an error: [%v]\n", err)
17-
}
18-
}
19-
2014
func main() {
2115
// ExampleDocument is a protobuf message
2216
document := documentspb.ExampleDocument{
2317
Value1: 1,
2418
ValueA: "Foo",
2519
ValueB: "Bar",
2620
ValueBytes1: []byte("foobar"),
21+
EnumType: documentspb.Enum_type_two,
2722
}
2823

2924
// The FillSalts method is a helper function that fills all fields with 32
3025
// random bytes. SaltedExampleDocument is a protobuf message that has the
3126
// same structure as ExampleDocument but has all `bytes` field types.
3227
salts := documentspb.SaltedExampleDocument{}
33-
proofs.FillSalts(&document, &salts)
28+
checkErr(proofs.FillSalts(&document, &salts))
3429

3530
doctree := proofs.NewDocumentTree(proofs.TreeOptions{Hash: sha256.New()})
3631

37-
doctree.AddLeavesFromDocument(&document, &salts)
38-
doctree.Generate()
32+
checkErr(doctree.AddLeavesFromDocument(&document, &salts))
33+
checkErr(doctree.Generate())
3934
fmt.Printf("Generated tree: %s\n", doctree.String())
4035

4136
// Generate the actual proof for a field. In this case the field called "ValueA".
42-
proof, err := doctree.CreateProof("valueA")
43-
printError(err)
37+
proof, err := doctree.CreateProof("enum_type")
38+
checkErr(err)
4439
proofJson, _ := json.Marshal(proof)
4540
fmt.Println("Proof:\n", string(proofJson))
4641

4742
// Validate the proof that was just generated
4843
valid, err := doctree.ValidateProof(&proof)
49-
printError(err)
44+
checkErr(err)
5045

5146
fmt.Printf("Proof validated: %v\n", valid)
5247
}
48+
49+
func checkErr(err error) {
50+
if err != nil {
51+
panic(err)
52+
}
53+
}

proofs/flatten.go

+6
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,12 @@ func (f *messageFlattener) valueToString(value interface{}) (s string, err error
188188
}
189189
return ptypes.TimestampString(v), nil
190190
default:
191+
// special case for enums
192+
rv := reflect.ValueOf(value)
193+
if rv.Kind() == reflect.Int32 {
194+
return strconv.FormatInt(rv.Int(), 10), nil
195+
}
196+
191197
return "", errors.Errorf("Got unsupported value of type %T", v)
192198
}
193199
}

proofs/tree.go

+10-15
Original file line numberDiff line numberDiff line change
@@ -306,8 +306,8 @@ func (doctree *DocumentTree) AddLeavesFromDocument(document, salts proto.Message
306306
if err != nil {
307307
return err
308308
}
309-
err = doctree.AddLeaves(leaves)
310-
return err
309+
310+
return doctree.AddLeaves(leaves)
311311
}
312312

313313
// Generate calculated the merkle root with all supplied leaves. This method can only be called once and makes
@@ -319,9 +319,13 @@ func (doctree *DocumentTree) Generate() error {
319319

320320
hashes := make([][]byte, len(doctree.leaves))
321321
for i, leaf := range doctree.leaves {
322-
if (!leaf.Hashed) || (len(leaf.Hash) == 0) {
323-
leaf.HashNode(doctree.hash, doctree.compactProperties)
322+
if len(leaf.Hash) < 1 || leaf.Hashed {
323+
err := leaf.HashNode(doctree.hash, doctree.compactProperties)
324+
if err != nil {
325+
return err
326+
}
324327
}
328+
325329
hashes[i] = leaf.Hash
326330
}
327331
err := doctree.merkleTree.Generate(hashes, doctree.hash)
@@ -413,7 +417,6 @@ func (doctree *DocumentTree) CreateProof(prop string) (proof proofspb.Proof, err
413417
// pickHashesFromMerkleTree takes the required hashes needed to create a proof
414418
func (doctree *DocumentTree) pickHashesFromMerkleTree(leaf uint64) (hashes []*proofspb.MerkleHash, err error) {
415419
proofNodes, err := CalculateProofNodeList(leaf, uint64(len(doctree.merkleTree.Leaves())))
416-
417420
if err != nil {
418421
return hashes, err
419422
}
@@ -466,15 +469,6 @@ func (doctree *DocumentTree) ValidateProof(proof *proofspb.Proof) (valid bool, e
466469
return
467470
}
468471

469-
func dereferencePointer(value interface{}) interface{} {
470-
reflectValue := reflect.Indirect(reflect.ValueOf(value))
471-
if !reflectValue.IsValid() {
472-
return nil
473-
}
474-
475-
return reflectValue.Interface()
476-
}
477-
478472
// LeafNode represents a field that can be hashed to create a merkle tree
479473
type LeafNode struct {
480474
Property Property
@@ -490,13 +484,14 @@ type LeafNode struct {
490484
// HashNode calculates the hash of a node provided it isn't already calculated.
491485
func (n *LeafNode) HashNode(h hash.Hash, compact bool) error {
492486
if len(n.Hash) > 0 || n.Hashed {
493-
return errors.New("Hash already set")
487+
return nil
494488
}
495489

496490
payload, err := ConcatValues(n.Property.Name(compact), n.Value, n.Salt)
497491
if err != nil {
498492
return err
499493
}
494+
500495
defer h.Reset()
501496
_, err = h.Write(payload)
502497
if err != nil {

0 commit comments

Comments
 (0)