diff --git a/libs/aarch64-unknown-linux-gnu/librln.a b/libs/aarch64-unknown-linux-gnu/librln.a index b0e5763..505730b 100644 Binary files a/libs/aarch64-unknown-linux-gnu/librln.a and b/libs/aarch64-unknown-linux-gnu/librln.a differ diff --git a/libs/arm-unknown-linux-gnueabi/librln.a b/libs/arm-unknown-linux-gnueabi/librln.a index 7b18f74..2955098 100644 Binary files a/libs/arm-unknown-linux-gnueabi/librln.a and b/libs/arm-unknown-linux-gnueabi/librln.a differ diff --git a/libs/arm-unknown-linux-gnueabihf/librln.a b/libs/arm-unknown-linux-gnueabihf/librln.a index 8baea7b..78a142f 100644 Binary files a/libs/arm-unknown-linux-gnueabihf/librln.a and b/libs/arm-unknown-linux-gnueabihf/librln.a differ diff --git a/libs/i686-unknown-linux-gnu/librln.a b/libs/i686-unknown-linux-gnu/librln.a index 7e68e5d..3baafa3 100644 Binary files a/libs/i686-unknown-linux-gnu/librln.a and b/libs/i686-unknown-linux-gnu/librln.a differ diff --git a/libs/x86_64-pc-windows-gnu/librln.a b/libs/x86_64-pc-windows-gnu/librln.a index 9e3bf8a..7b8776a 100644 Binary files a/libs/x86_64-pc-windows-gnu/librln.a and b/libs/x86_64-pc-windows-gnu/librln.a differ diff --git a/libs/x86_64-unknown-linux-gnu/librln.a b/libs/x86_64-unknown-linux-gnu/librln.a index dc7389e..d8e7f53 100644 Binary files a/libs/x86_64-unknown-linux-gnu/librln.a and b/libs/x86_64-unknown-linux-gnu/librln.a differ diff --git a/libs/x86_64-unknown-linux-musl/librln.a b/libs/x86_64-unknown-linux-musl/librln.a index 540f268..10ee96c 100644 Binary files a/libs/x86_64-unknown-linux-musl/librln.a and b/libs/x86_64-unknown-linux-musl/librln.a differ diff --git a/rln/librln.h b/rln/librln.h index f806475..f80acab 100644 --- a/rln/librln.h +++ b/rln/librln.h @@ -5,13 +5,20 @@ #define TEST_PARAMETERS_INDEX 2 +/** + * The RLN object. + * + * It implements the methods required to update the internal Merkle Tree, generate and verify RLN ZK proofs. + * + * I/O is mostly done using writers and readers implementing `std::io::Write` and `std::io::Read`, respectively. + */ typedef struct RLN RLN; /** * Buffer struct is taken from - * https://github.com/celo-org/celo-threshold-bls-rs/blob/master/crates/threshold-bls-ffi/src/ffi.rs + * * - * Also heavily inspired by https://github.com/kilic/rln/blob/master/src/ffi.rs + * Also heavily inspired by */ typedef struct Buffer { const uint8_t *ptr; @@ -34,7 +41,9 @@ bool set_leaf(struct RLN *ctx, uintptr_t index, const struct Buffer *input_buffe bool set_next_leaf(struct RLN *ctx, const struct Buffer *input_buffer); -bool set_leaves(struct RLN *ctx, const struct Buffer *input_buffer); +bool set_leaves_from(struct RLN *ctx, uintptr_t index, const struct Buffer *input_buffer); + +bool init_tree_with_leaves(struct RLN *ctx, const struct Buffer *input_buffer); bool get_root(const struct RLN *ctx, struct Buffer *output_buffer); diff --git a/rln/rln.go b/rln/rln.go index e8f9bf0..a264afc 100644 --- a/rln/rln.go +++ b/rln/rln.go @@ -9,7 +9,7 @@ import ( "errors" "unsafe" - "github.com/status-im/go-zerokit-rln/rln/resources" + "github.com/waku-org/go-zerokit-rln/rln/resources" ) // RLN represents the context used for rln. @@ -240,6 +240,23 @@ func serializeRoots(roots [][32]byte) []byte { return result } +func serializeCommitments(commitments []IDCommitment) []byte { + // serializes a seq of IDCommitments to a byte seq + // the serialization is based on https://github.com/status-im/nwaku/blob/37bd29fbc37ce5cf636734e7dd410b1ed27b88c8/waku/v2/protocol/waku_rln_relay/rln.nim#L142 + // the order of serialization is |id_commitment_len<8>|id_commitment| + var result []byte + + inputLen := make([]byte, 8) + binary.LittleEndian.PutUint64(inputLen, uint64(len(commitments))) + result = append(result, inputLen...) + + for _, idComm := range commitments { + result = append(result, idComm[:]...) + } + + return result +} + func (r *RLN) VerifyWithRoots(data []byte, proof RateLimitProof, roots [][32]byte) (bool, error) { proofBytes := proof.serialize(data) proofBuf := toCBufferPtr(proofBytes) @@ -265,6 +282,18 @@ func (r *RLN) InsertMember(idComm IDCommitment) error { return nil } +// Insert multiple members i.e., identity commitments starting from index +// This proc is atomic, i.e., if any of the insertions fails, all the previous insertions are rolled back +func (r *RLN) InsertMembers(index MembershipIndex, idComms []IDCommitment) error { + idCommBytes := serializeCommitments(idComms) + idCommBuffer := toCBufferPtr(idCommBytes) + insertionSuccess := bool(C.set_leaves_from(r.ptr, C.uintptr_t(index), idCommBuffer)) + if !insertionSuccess { + return errors.New("could not insert members") + } + return nil +} + // DeleteMember removes an IDCommitment key from the tree. The index // parameter is the position of the id commitment key to be deleted from the tree. // The deleted id commitment key is replaced with a zero leaf diff --git a/rln/rln_test.go b/rln/rln_test.go index 8afbb0b..4209f42 100644 --- a/rln/rln_test.go +++ b/rln/rln_test.go @@ -57,6 +57,17 @@ func (s *RLNSuite) TestInsertMember() { s.NoError(err) } +func (s *RLNSuite) TestInsertMembers() { + rln, err := NewRLN() + s.NoError(err) + + keypair, err := rln.MembershipKeyGen() + s.NoError(err) + + err = rln.InsertMembers(0, []IDCommitment{keypair.IDCommitment}) + s.NoError(err) +} + func (s *RLNSuite) TestRemoveMember() { rln, err := NewRLN() s.NoError(err) diff --git a/zerokit b/zerokit index b95b151..284e514 160000 --- a/zerokit +++ b/zerokit @@ -1 +1 @@ -Subproject commit b95b151a1c2407c897d486dbab2c480684ae2b7e +Subproject commit 284e51483c73e956c2c318fe6f69d735412bdc08