go-rln/rln/rln.go
2021-09-13 23:15:01 +02:00

114 lines
2.6 KiB
Go

// Package rln contains bindings for https://github.com/kilic/rln
package rln
/*
#include "./librln.h"
*/
import "C"
import (
"errors"
"unsafe"
)
// RLN represents the context used for rln.
type RLN struct {
ptr *C.RLN_Bn256
}
// KeyPair generated by the GenerateKey function for RLN values.
type KeyPair struct {
// Key represents the secret key.
Key [32]byte
// Commitment hash of the Key generated by a hash function in the rln lib.
Commitment [32]byte
}
// New returns a new RLN generated from the passed depth and parameters.
func New(depth int, parameters []byte) (*RLN, error) {
r := &RLN{}
buf := toBuffer(parameters)
size := int(unsafe.Sizeof(buf))
in := (*C.Buffer)(C.malloc(C.size_t(size)))
*in = buf
if !bool(C.new_circuit_from_params(C.ulong(depth), in, &r.ptr)) {
return nil, errors.New("failed to initialize")
}
return r, nil
}
// GenerateKey generates a KeyPair for an RLN.
func (r *RLN) GenerateKey() (*KeyPair, error) {
buffer := toBuffer([]byte{})
if !bool(C.key_gen(r.ptr, &buffer)) {
return nil, errors.New("failed to genenrate key")
}
key := &KeyPair{
Key: [32]byte{},
Commitment: [32]byte{},
}
b := C.GoBytes(unsafe.Pointer(buffer.ptr), C.int(buffer.len))
copy(key.Key[:], b[:32])
copy(key.Commitment[:], b[32:64])
return key, nil
}
// Hash hashes a given input using the underlying function.
func (r *RLN) Hash(input []byte) ([]byte, error) {
size := int(unsafe.Sizeof(C.Buffer{}))
in := (*C.Buffer)(C.malloc(C.size_t(size)))
*in = toBuffer(input)
out := (*C.Buffer)(C.malloc(C.size_t(size)))
if !bool(C.hash(r.ptr, in, &in.len, out)) {
return nil, errors.New("failed to hash")
}
return C.GoBytes(unsafe.Pointer(out.ptr), C.int(out.len)), nil
}
func (r *RLN) CircuitFromParams(depth int, parameters []byte) bool {
ptr := r.ptr
buf := toBuffer(parameters)
return bool(C.new_circuit_from_params(C.ulong(depth), &buf, &ptr))
}
func (r *RLN) GenerateProof(input, output []byte) bool {
inputBuf := toBuffer(input)
outputBuf := toBuffer(output)
return bool(C.generate_proof(r.ptr, &inputBuf, &outputBuf))
}
func (r *RLN) Verify(proof []byte, publicInputs []byte, result uint32) bool {
proofBuf := toBuffer(proof)
inputs := toBuffer(publicInputs)
res := C.uint(result)
return bool(C.verify(r.ptr, &proofBuf, &inputs, &res))
}
func toBuffer(data []byte) C.Buffer {
dataPtr, dataLen := sliceToPtr(data)
return C.Buffer{
ptr: dataPtr,
len: C.ulong(dataLen),
}
}
func sliceToPtr(slice []byte) (*C.uchar, C.int) {
if len(slice) == 0 {
return nil, 0
} else {
return (*C.uchar)(unsafe.Pointer(&slice[0])), C.int(len(slice))
}
}