Skip to content

Commit

Permalink
feat: go bindings use zencode-exec
Browse files Browse the repository at this point in the history
  • Loading branch information
albertolerda authored and jaromil committed Aug 9, 2023
1 parent 4316ddd commit 09f607f
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 266 deletions.
4 changes: 4 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,7 @@ indent_size = 4
[src/lua/zencode_data.lua]
indent_style = space
indent_size = 2

[**/*.go]
indent_style = tab
indent_size = 4
5 changes: 0 additions & 5 deletions bindings/golang/zenroom/lib/doc.go

This file was deleted.

Binary file removed bindings/golang/zenroom/lib/libzenroom.a
Binary file not shown.
Binary file removed bindings/golang/zenroom/lib/libzenroom.so
Binary file not shown.
159 changes: 58 additions & 101 deletions bindings/golang/zenroom/zenroom.go
Original file line number Diff line number Diff line change
@@ -1,122 +1,79 @@
// Package zenroom is a CGO wrapper for the Zenroom virtual machine, which aims
// to make Zenroom easily usable from Go programs. Currently the C binary we
// wrap is only available for Linux.
package zenroom

// #cgo CFLAGS: -I${SRCDIR}/src
// #cgo LDFLAGS: -L${SRCDIR}/lib -Wl,-rpath=${SRCDIR}/lib -lzenroom
// #include <stdio.h>
// #include <stdlib.h>
// #include <string.h>
// #include "zenroom.h"
// typedef int(*fun)(char*, char*, char*, char*, char*, size_t, char*, size_t);
//
// int wrapper(fun exec, char* script, char* conf, char* data, char* keys, char* stdout, size_t stdout_size, char* stderr, size_t stderr_size) {
// return exec(script, conf, data, keys, stdout, stdout_size, stderr, stderr_size);
// }
import "C"

import (
"unsafe"
"io"
"log"
"os/exec"
"strings"
b64 "encoding/base64"
)

// maxString is zenroom defined buffer MAX_STRING size
const BUFSIZE = 2 * 1024 * 1024

type ZenResult struct {
Output string;
Logs string;
}

// ZenroomExec is our primary public API method, and it is here that we call Zenroom's
// zenroom_exec_tobuf function. This method attempts to pass a required script,
// and some optional extra parameters to the Zenroom virtual machine, where
// cryptographic operations are performed with the result being returned to the
// caller. The method signature has been tweaked slightly from the original
// function defined by Zenroom; rather than making all parameters required,
// instead we have just included as a required parameter the input SCRIPT, while
// all other properties must be supplied via one of the previously defined
// Option helpers.
//
// Returns the output of the execution of the Zenroom virtual machine, or an
// error.
func ZenroomExec(script string, conf string, keys string, data string) (ZenResult, bool) {
exec := C.fun(C.zenroom_exec_tobuf)
return wrapper(exec, script, conf, keys, data)
Output string;
Logs string;
}

func ZencodeExec(script string, conf string, keys string, data string) (ZenResult, bool) {
exec := C.fun(C.zencode_exec_tobuf)
return wrapper(exec, script, conf, keys, data)
}
execCmd := exec.Command("zencode-exec")

func wrapper(fun C.fun, script string, conf string, keys string, data string) (ZenResult, bool) {
var (
cScript, cConf, cKeys, cData *C.char
)

cScript = C.CString(script)
defer C.free(unsafe.Pointer(cScript))
stdout, err := execCmd.StdoutPipe()
if err != nil {
log.Fatalf("Failed to create stdout pipe: %v", err)
}

if conf != "" {
cConf = C.CString(conf)
defer C.free(unsafe.Pointer(cConf))
} else {
cConf = nil
stderr, err := execCmd.StderrPipe()
if err != nil {
log.Fatalf("Failed to create stderr pipe: %v", err)
}

stdin, err := execCmd.StdinPipe()
if err != nil {
log.Fatalf("Failed to create stdin pipe: %v", err)
}
defer stdin.Close()

if data != "" {
cData = C.CString(data)
defer C.free(unsafe.Pointer(cData))
} else {
cData = nil
}

if keys != "" {
cKeys = C.CString(keys)
defer C.free(unsafe.Pointer(cKeys))
} else {
cKeys = nil
}

// create empty strings to capture zenroom's output
stdout := emptyString(BUFSIZE)
stderr := emptyString(BUFSIZE)
defer C.free(unsafe.Pointer(stdout))
defer C.free(unsafe.Pointer(stderr))

res := C.wrapper(
fun,
cScript,
cConf, cKeys, cData,
stdout, BUFSIZE,
stderr, BUFSIZE,
)

zen_res := ZenResult{
Output: C.GoString(stdout),
Logs: C.GoString(stderr),
io.WriteString(stdin, conf)
io.WriteString(stdin, "\n")

b64script := b64.StdEncoding.EncodeToString([]byte(script))
io.WriteString(stdin, b64script)
io.WriteString(stdin, "\n")

b64keys := b64.StdEncoding.EncodeToString([]byte(keys))
io.WriteString(stdin, b64keys)
io.WriteString(stdin, "\n")

b64data := b64.StdEncoding.EncodeToString([]byte(data))
io.WriteString(stdin, b64data)
io.WriteString(stdin, "\n")

err = execCmd.Start()
if err != nil {
log.Fatalf("Failed to start command: %v", err)
}
stdoutOutput := make(chan string)
stderrOutput := make(chan string)
go captureOutput(stdout, stdoutOutput)
go captureOutput(stderr, stderrOutput)

return zen_res, res == 0
stdoutStr := <-stdoutOutput
stderrStr := <-stderrOutput

err = execCmd.Wait()

return ZenResult{Output: stdoutStr, Logs: stderrStr}, err == nil
}

// ZencodeExec is our primary public API method, and it is here that we call Zenroom's
// zencode_exec_tobuf function. This method attempts to pass a required script,
// and some optional extra parameters to the Zenroom virtual machine, where
// cryptographic operations are performed with the result being returned to the
// caller. The method signature has been tweaked slightly from the original
// function defined by Zenroom; rather than making all parameters required,
// instead we have just included as a required parameter the input SCRIPT, while
// all other properties must be supplied via one of the previously defined
// Option helpers.
//
// Returns the output of the execution of the Zenroom virtual machine, or an
// error.

// reimplementation of https://golang.org/src/strings/strings.go?s=13172:13211#L522
func emptyString(size int) *C.char {
p := C.malloc(C.size_t(size))
return (*C.char)(p)
func captureOutput(pipe io.ReadCloser, output chan<- string) {
defer close(output)

buf := new(strings.Builder)
_, err := io.Copy(buf, pipe)
if err != nil {
log.Printf("Failed to capture output: %v", err)
return
}
output <- buf.String()
}
157 changes: 0 additions & 157 deletions bindings/golang/zenroom/zenroom.h

This file was deleted.

12 changes: 9 additions & 3 deletions bindings/golang/zenroom/zenroom_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"testing"
)

func TestBasicCall(t *testing.T) {
/*func TestBasicCall(t *testing.T) {
script := "print (1)"
res, _ := ZenroomExec(script, "", "", "")
if res.Output == "1" {
Expand Down Expand Up @@ -45,14 +45,20 @@ func TestCallStrings(t *testing.T) {
}
})
}
}
}*/

func TestZencode(t *testing.T) {
script := `Scenario 'ecdh': Create the keypair
Given that I am known as 'Alice'
When I create the ecdh key
Then print my data`
and debug
Then print my data
Then print my keyring`
res, success := ZencodeExec(script, "", "", "")
fmt.Println("Result")
fmt.Println(res)
fmt.Println("Logs")
fmt.Println(res.Logs)
if !success {
t.Error(res.Logs)
}
Expand Down

0 comments on commit 09f607f

Please sign in to comment.