Skip to content

Commit ba4f2f5

Browse files
committed
Add bindings to multiset
1 parent 3134905 commit ba4f2f5

File tree

1 file changed

+100
-0
lines changed

1 file changed

+100
-0
lines changed

multiset.go

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package secp256k1
2+
3+
// #include "./depend/secp256k1/include/secp256k1_multiset.h"
4+
import "C"
5+
import "github.com/pkg/errors"
6+
7+
// MultiSet is a type used to create an Elliptic Curve Multiset Hash
8+
// which is a rolling(homomorphic) hash that you can add and remove elements from
9+
// and receiving the same resulting hash as-if you never hashed that element.
10+
// Because of that the order of adding and removing elements doesn't matter.
11+
// Use NewMultiset to initialize a MultiSet, or DeserializeMultiSet to parse a MultiSet.
12+
type MultiSet struct {
13+
set C.secp256k1_multiset
14+
}
15+
16+
// NewMultiset return an empty initialized set.
17+
// when finalized it should be equal to a finalized set with all elements removed.
18+
func NewMultiset() MultiSet {
19+
multiset := MultiSet{}
20+
ret := C.secp256k1_multiset_init(context, &multiset.set)
21+
if ret != 1 {
22+
panic("failed initializing a multiset. Should never happen")
23+
}
24+
return multiset
25+
}
26+
27+
// Reset clears the multiset from all data. Equivalent to creating a new empty set
28+
func (multiset *MultiSet) Reset() {
29+
ret := C.secp256k1_multiset_init(context, &multiset.set)
30+
if ret != 1 {
31+
panic("failed resetting a multiset. Should never happen")
32+
}
33+
}
34+
35+
// Add a data element to the multiset. This will hash the data onto the curve and add it.
36+
// Supports arbitrary length data (subject to the underlying hash function(SHA256) limits)
37+
func (multiset *MultiSet) Add(data []byte) {
38+
cPtrData := (*C.uchar)(&data[0])
39+
CLenData := (C.size_t)(len(data))
40+
ret := C.secp256k1_multiset_add(context, &multiset.set, cPtrData, CLenData)
41+
if ret != 1 {
42+
panic("failed adding to the multiset. Should never happen")
43+
}
44+
}
45+
46+
// Remove a data element from the multiset. this will hash the data onto the curve and remove it.
47+
// Supports arbitrary length data (subject to the underlying hash function(SHA256) limits)
48+
func (multiset *MultiSet) Remove(data []byte) {
49+
cPtrData := (*C.uchar)(&data[0])
50+
CLenData := (C.size_t)(len(data))
51+
ret := C.secp256k1_multiset_remove(context, &multiset.set, cPtrData, CLenData)
52+
if ret != 1 {
53+
panic("failed removing from the multiset. Should never happen")
54+
}
55+
}
56+
57+
// Combine 2 MultiSets together. is equivalent to manually adding all the data elements
58+
// from one set to the other.
59+
func (multiset *MultiSet) Combine(input MultiSet) {
60+
ret := C.secp256k1_multiset_combine(context, &multiset.set, &input.set)
61+
if ret != 1 {
62+
panic("failed combining 2 multisets. Should never happen")
63+
}
64+
}
65+
66+
// Finalize the multiset. This will hash the set into a 32 byte hash(SHA256)
67+
// Because the returned value is a hash of a multiset you cannot "Un-Finalize" it.
68+
// If this is meant for storage then Serialize should be used instead.
69+
func (multiset *MultiSet) Finalize() [32]byte {
70+
hash := [32]byte{}
71+
cPtrHash := (*C.uchar)(&hash[0])
72+
ret := C.secp256k1_multiset_finalize(context, cPtrHash, &multiset.set)
73+
if ret != 1 {
74+
panic("failed finalizing the multiset. Should never happen")
75+
}
76+
return hash
77+
}
78+
79+
// Serialize the multiset. This is the only right way to serialize a multiset for storage.
80+
// This multiset is not finalized, this is meant for storage.
81+
func (multiset *MultiSet) Serialize() [64]byte {
82+
serialized := [64]byte{}
83+
cPtrData := (*C.uchar)(&serialized[0])
84+
ret := C.secp256k1_multiset_serialize(context, cPtrData, &multiset.set)
85+
if ret != 1 {
86+
panic("failed serializing the multiset. Should never happen")
87+
}
88+
return serialized
89+
}
90+
91+
// DeserializeMultiSet this will deserialize the multiset that `Serialize()` serialized.
92+
func DeserializeMultiSet(serialized [64]byte) (multiset *MultiSet, err error) {
93+
multiset = &MultiSet{}
94+
cPtrData := (*C.uchar)(&serialized[0])
95+
ret := C.secp256k1_multiset_parse(context, &multiset.set, cPtrData)
96+
if ret != 1 {
97+
return nil, errors.New("failed parsing the multiset")
98+
}
99+
return
100+
}

0 commit comments

Comments
 (0)