2022-09-07 15:15:43 -04:00
|
|
|
package rln
|
|
|
|
|
2024-01-24 16:31:36 +01:00
|
|
|
import (
|
|
|
|
"encoding/binary"
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"math/big"
|
|
|
|
)
|
2022-09-07 15:15:43 -04:00
|
|
|
|
|
|
|
// serialize converts a RateLimitProof and the data to a byte seq
|
2024-05-24 10:17:29 +02:00
|
|
|
// format taken from: https://github.com/vacp2p/zerokit/blob/v0.5.0/rln/src/public.rs#L747
|
|
|
|
// [identity_secret<32> | id_index<8> | user_message_limit<32> | message_id<32> | external_nullifier<32> | signal_len<8> | signal<var> ]
|
|
|
|
func serialize(
|
|
|
|
idKey IDSecretHash,
|
|
|
|
memIndex MembershipIndex,
|
|
|
|
userMessageLimit uint32,
|
|
|
|
messageId uint32,
|
|
|
|
externalNullifier [32]byte,
|
|
|
|
msg []byte) []byte {
|
2022-09-07 15:15:43 -04:00
|
|
|
|
|
|
|
memIndexBytes := make([]byte, 8)
|
|
|
|
binary.LittleEndian.PutUint64(memIndexBytes, uint64(memIndex))
|
|
|
|
|
|
|
|
lenPrefMsg := appendLength(msg)
|
|
|
|
|
2024-05-24 10:17:29 +02:00
|
|
|
var userMessageLimitByte [32]byte
|
|
|
|
var messageIdByte [32]byte
|
|
|
|
binary.LittleEndian.PutUint32(userMessageLimitByte[0:], userMessageLimit)
|
|
|
|
binary.LittleEndian.PutUint32(messageIdByte[0:], messageId)
|
|
|
|
|
2022-09-07 15:15:43 -04:00
|
|
|
output := append(idKey[:], memIndexBytes...)
|
2024-05-24 10:17:29 +02:00
|
|
|
output = append(output, userMessageLimitByte[:]...)
|
|
|
|
output = append(output, messageIdByte[:]...)
|
|
|
|
output = append(output, externalNullifier[:]...)
|
2022-09-07 15:15:43 -04:00
|
|
|
output = append(output, lenPrefMsg...)
|
|
|
|
|
|
|
|
return output
|
|
|
|
}
|
|
|
|
|
|
|
|
// serialize converts a RateLimitProof and data to a byte seq
|
|
|
|
// this conversion is used in the proof verification proc
|
|
|
|
// the order of serialization is based on https://github.com/kilic/rln/blob/7ac74183f8b69b399e3bc96c1ae8ab61c026dc43/src/public.rs#L205
|
2024-05-24 10:17:29 +02:00
|
|
|
// [ proof<128> | root<32> | external_nullifier<32> | x<32> | y<32> | nullifier<32> | signal_len<8> | signal<var> ]
|
2023-07-26 14:01:45 -04:00
|
|
|
func (r RateLimitProof) serializeWithData(data []byte) []byte {
|
2022-09-07 15:15:43 -04:00
|
|
|
lenPrefMsg := appendLength(data)
|
2023-07-26 14:01:45 -04:00
|
|
|
proofBytes := r.serialize()
|
|
|
|
proofBytes = append(proofBytes, lenPrefMsg...)
|
|
|
|
return proofBytes
|
|
|
|
}
|
|
|
|
|
|
|
|
// serialize converts a RateLimitProof to a byte seq
|
2024-05-24 10:17:29 +02:00
|
|
|
// [ proof<128> | root<32> | external_nullifier<32> | x<32> | y<32> | nullifier<32>]
|
2023-07-26 14:01:45 -04:00
|
|
|
func (r RateLimitProof) serialize() []byte {
|
2022-09-07 15:15:43 -04:00
|
|
|
proofBytes := append(r.Proof[:], r.MerkleRoot[:]...)
|
2024-05-24 10:17:29 +02:00
|
|
|
proofBytes = append(proofBytes, r.ExternalNullifier[:]...)
|
2022-09-07 15:15:43 -04:00
|
|
|
proofBytes = append(proofBytes, r.ShareX[:]...)
|
|
|
|
proofBytes = append(proofBytes, r.ShareY[:]...)
|
|
|
|
proofBytes = append(proofBytes, r.Nullifier[:]...)
|
|
|
|
return proofBytes
|
|
|
|
}
|
2024-01-24 16:31:36 +01:00
|
|
|
|
|
|
|
func (r *RLNWitnessInput) serialize() []byte {
|
|
|
|
output := make([]byte, 0)
|
|
|
|
|
|
|
|
output = append(output, r.IDSecretHash[:]...)
|
|
|
|
output = append(output, r.MerkleProof.serialize()...)
|
|
|
|
output = append(output, r.X[:]...)
|
|
|
|
output = append(output, r.Epoch[:]...)
|
|
|
|
output = append(output, r.RlnIdentifier[:]...)
|
|
|
|
|
|
|
|
return output
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *RLNWitnessInput) deserialize(b []byte) error {
|
|
|
|
|
|
|
|
return errors.New("not implemented")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *MerkleProof) serialize() []byte {
|
|
|
|
output := make([]byte, 0)
|
|
|
|
|
|
|
|
output = append(output, appendLength32(Flatten(r.PathElements))...)
|
|
|
|
output = append(output, appendLength(r.PathIndexes)...)
|
|
|
|
|
|
|
|
return output
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *MerkleProof) deserialize(b []byte) error {
|
|
|
|
|
|
|
|
// Check if we can read the first byte
|
|
|
|
if len(b) < 8 {
|
|
|
|
return errors.New(fmt.Sprintf("wrong input size: %d", len(b)))
|
|
|
|
}
|
|
|
|
|
|
|
|
var numElements big.Int
|
|
|
|
var numIndexes big.Int
|
|
|
|
|
|
|
|
offset := 0
|
|
|
|
|
|
|
|
// Get amounf of elements in the proof
|
|
|
|
numElements.SetBytes(revert(b[offset : offset+8]))
|
|
|
|
offset += 8
|
|
|
|
|
|
|
|
// With numElements we can determine the expected length of the proof.
|
|
|
|
expectedLen := 8 + int(32*numElements.Uint64()) + 8 + int(numElements.Uint64())
|
|
|
|
if len(b) != expectedLen {
|
|
|
|
return errors.New(fmt.Sprintf("wrong input size expected: %d, current: %d",
|
|
|
|
expectedLen,
|
|
|
|
len(b)))
|
|
|
|
}
|
|
|
|
|
|
|
|
r.PathElements = make([]MerkleNode, numElements.Uint64())
|
|
|
|
|
|
|
|
for i := uint64(0); i < numElements.Uint64(); i++ {
|
|
|
|
copy(r.PathElements[i][:], b[offset:offset+32])
|
|
|
|
offset += 32
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get amount of indexes in the path
|
|
|
|
numIndexes.SetBytes(revert(b[offset : offset+8]))
|
|
|
|
offset += 8
|
|
|
|
|
|
|
|
// Both numElements and numIndexes shall be equal and match the tree depth.
|
|
|
|
if numIndexes.Uint64() != numElements.Uint64() {
|
|
|
|
return errors.New(fmt.Sprintf("amount of values in path and indexes do not match: %s vs %s",
|
|
|
|
numElements.String(), numIndexes.String()))
|
|
|
|
}
|
|
|
|
|
|
|
|
r.PathIndexes = make([]uint8, numIndexes.Uint64())
|
|
|
|
|
|
|
|
for i := uint64(0); i < numIndexes.Uint64(); i++ {
|
|
|
|
r.PathIndexes[i] = b[offset]
|
|
|
|
offset += 1
|
|
|
|
}
|
|
|
|
|
|
|
|
if offset != len(b) {
|
|
|
|
return errors.New(
|
|
|
|
fmt.Sprintf("error parsing proof read: %d, length; %d", offset, len(b)))
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|