-
Notifications
You must be signed in to change notification settings - Fork 54
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add read/commit API for go runtime (#158)
* feat: add read/commit API for go runtime * update README * fix clippy * fix bugs in zkmips * update zkmips based on comments * update comment in add.go * simplify zkmips commands * fix fmt and clippy * fix seg number * remove blink line
- Loading branch information
Showing
13 changed files
with
532 additions
and
131 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
package zkm_runtime | ||
|
||
import ( | ||
"encoding/binary" | ||
"fmt" | ||
"reflect" | ||
) | ||
|
||
func DeserializeData(data []byte, e any) { | ||
if e == nil { | ||
return | ||
} | ||
value := reflect.ValueOf(e) | ||
// If e represents a value as opposed to a pointer, the answer won't | ||
// get back to the caller. Make sure it's a pointer. | ||
if value.Type().Kind() != reflect.Pointer { | ||
panic("attempt to deserialize into a non-pointer") | ||
} | ||
|
||
if value.IsValid() { | ||
if value.Kind() == reflect.Pointer && !value.IsNil() { | ||
// That's okay, we'll store through the pointer. | ||
} else if !value.CanSet() { | ||
panic("gob: DecodeValue of unassignable value") | ||
} | ||
} | ||
|
||
index, err := deserializeData(data, value.Elem(), 0) | ||
if err != nil { | ||
panic(err) | ||
} | ||
if index != len(data) { | ||
panic("deserialize failed") | ||
} | ||
} | ||
|
||
func deserializeData(data []byte, v reflect.Value, index int) (int, error) { | ||
switch v.Kind() { | ||
case reflect.Bool: | ||
v.SetBool(data[index] == 1) | ||
return index + 1, nil | ||
case reflect.Int8: | ||
v.SetInt(int64(int8(data[index]))) | ||
return index + 1, nil | ||
case reflect.Uint8: | ||
v.SetUint(uint64(data[index])) | ||
return index + 1, nil | ||
case reflect.Int16: | ||
b := []byte{data[index], data[index+1]} | ||
a := binary.LittleEndian.Uint16(b) | ||
v.SetInt(int64(int16(a))) | ||
return index + 2, nil | ||
case reflect.Uint16: | ||
b := []byte{data[index], data[index+1]} | ||
a := binary.LittleEndian.Uint16(b) | ||
v.SetUint(uint64(a)) | ||
return index + 2, nil | ||
case reflect.Int32: | ||
b := []byte{data[index], data[index+1], data[index+2], data[index+3]} | ||
a := binary.LittleEndian.Uint32(b) | ||
v.SetInt(int64(int32(a))) | ||
return index + 4, nil | ||
case reflect.Uint32: | ||
b := []byte{data[index], data[index+1], data[index+2], data[index+3]} | ||
a := binary.LittleEndian.Uint32(b) | ||
v.SetUint(uint64(a)) | ||
return index + 4, nil | ||
case reflect.Int64: | ||
b := []byte{data[index], data[index+1], data[index+2], data[index+3], | ||
data[index+4], data[index+5], data[index+6], data[index+7]} | ||
a := binary.LittleEndian.Uint64(b) | ||
v.SetInt(int64(a)) | ||
return index + 8, nil | ||
case reflect.Uint64: | ||
b := []byte{data[index], data[index+1], data[index+2], data[index+3], | ||
data[index+4], data[index+5], data[index+6], data[index+7]} | ||
a := binary.LittleEndian.Uint64(b) | ||
v.SetUint(a) | ||
return index + 8, nil | ||
case reflect.Slice: | ||
b := []byte{data[index], data[index+1], data[index+2], data[index+3], | ||
data[index+4], data[index+5], data[index+6], data[index+7]} | ||
|
||
length := binary.LittleEndian.Uint64(b) | ||
index += 8 | ||
switch v.Type().Elem().Kind() { | ||
case reflect.Uint8: | ||
bytes := data[index : index+int(length)] | ||
v.SetBytes(bytes) | ||
return index + int(length), nil | ||
} | ||
return index, fmt.Errorf("unsupport type: %v, elem: %v", v.Kind(), v.Elem().Kind()) | ||
case reflect.Array: | ||
for i := 0; i < v.Len(); i++ { | ||
var err error | ||
index, err = deserializeData(data, v.Index(i), index) | ||
if err != nil { | ||
return index, err | ||
} | ||
} | ||
return index, nil | ||
case reflect.String: | ||
b := []byte{data[index], data[index+1], data[index+2], data[index+3], | ||
data[index+4], data[index+5], data[index+6], data[index+7]} | ||
l := binary.LittleEndian.Uint64(b) | ||
index += 8 | ||
length := int(l) | ||
str := make([]byte, length) | ||
copy(str[:], data[index:index+length]) | ||
v.SetString(string(str)) | ||
return index + length, nil | ||
case reflect.Ptr: | ||
if data[index] == 0 { | ||
v.SetZero() | ||
return index + 1, nil | ||
} | ||
return deserializeData(data, v.Elem(), index+1) | ||
case reflect.Struct: | ||
for i := 0; i < v.NumField(); i++ { | ||
field := v.Field(i) | ||
var err error | ||
index, err = deserializeData(data, field, index) | ||
if err != nil { | ||
return index, err | ||
} | ||
} | ||
return index, nil | ||
} | ||
return index, fmt.Errorf("unsupport type: %v", v.Kind()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module github.com/zkMIPS/zkm/go-runtime/zkm_runtime | ||
|
||
go 1.22.5 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
//go:build mips | ||
// +build mips | ||
|
||
package zkm_runtime | ||
|
||
func SyscallWrite(fd int, write_buf []byte, nbytes int) int | ||
func SyscallHintLen() int | ||
func SyscallHintRead(ptr []byte, len int) | ||
|
||
func Read[T any]() T { | ||
len := SyscallHintLen() | ||
var value []byte | ||
capacity := (len + 3) / 4 * 4 | ||
value = make([]byte, capacity) | ||
var result T | ||
SyscallHintRead(value, len) | ||
DeserializeData(value[0:len], &result) | ||
return result | ||
} | ||
|
||
func Commit[T any](value T) { | ||
bytes := MustSerializeData(value) | ||
length := len(bytes) | ||
if (length & 3) != 0 { | ||
d := make([]byte, 4-(length&3)) | ||
bytes = append(bytes, d...) | ||
} | ||
|
||
SyscallWrite(3, bytes, length) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
// ported from https://github.com/blocto/solana-go-sdk/blob/v1.30.0/pkg/bincode/serialize.go | ||
|
||
package zkm_runtime | ||
|
||
import ( | ||
"encoding/binary" | ||
"fmt" | ||
"reflect" | ||
) | ||
|
||
func SerializeData(data any) ([]byte, error) { | ||
return serializeData(reflect.ValueOf(data)) | ||
} | ||
|
||
func MustSerializeData(data interface{}) []byte { | ||
serializedData, err := serializeData(reflect.ValueOf(data)) | ||
if err != nil { | ||
panic(err) | ||
} | ||
return serializedData | ||
} | ||
|
||
func serializeData(v reflect.Value) ([]byte, error) { | ||
switch v.Kind() { | ||
case reflect.Bool: | ||
if v.Bool() { | ||
return []byte{1}, nil | ||
} | ||
return []byte{0}, nil | ||
case reflect.Int8: | ||
return []byte{uint8(v.Int())}, nil | ||
case reflect.Uint8: | ||
return []byte{uint8(v.Uint())}, nil | ||
case reflect.Int16: | ||
b := make([]byte, 2) | ||
binary.LittleEndian.PutUint16(b, uint16(v.Int())) | ||
return b, nil | ||
case reflect.Uint16: | ||
b := make([]byte, 2) | ||
binary.LittleEndian.PutUint16(b, uint16(v.Uint())) | ||
return b, nil | ||
case reflect.Int32: | ||
b := make([]byte, 4) | ||
binary.LittleEndian.PutUint32(b, uint32(v.Int())) | ||
return b, nil | ||
case reflect.Uint32: | ||
b := make([]byte, 4) | ||
binary.LittleEndian.PutUint32(b, uint32(v.Uint())) | ||
return b, nil | ||
case reflect.Int64: | ||
b := make([]byte, 8) | ||
binary.LittleEndian.PutUint64(b, uint64(v.Int())) | ||
return b, nil | ||
case reflect.Uint64: | ||
b := make([]byte, 8) | ||
binary.LittleEndian.PutUint64(b, uint64(v.Uint())) | ||
return b, nil | ||
case reflect.Slice: | ||
switch v.Type().Elem().Kind() { | ||
case reflect.Uint8: | ||
output := make([]byte, 8) | ||
binary.LittleEndian.PutUint64(output, uint64(v.Len())) | ||
|
||
for i := 0; i < v.Len(); i++ { | ||
d, err := serializeData(v.Index(i)) | ||
if err != nil { | ||
return nil, err | ||
} | ||
output = append(output, d...) | ||
} | ||
return output, nil | ||
} | ||
return nil, fmt.Errorf("unsupport type: %v, elem: %v", v.Kind(), v.Elem().Kind()) | ||
case reflect.Array: | ||
switch v.Type().Elem().Kind() { | ||
case reflect.Uint8: | ||
b := make([]byte, 0, v.Len()) | ||
for i := 0; i < v.Len(); i++ { | ||
b = append(b, byte(v.Index(i).Uint())) | ||
} | ||
return b, nil | ||
} | ||
return nil, fmt.Errorf("unsupport type: %v, elem: %v", v.Kind(), v.Elem().Kind()) | ||
case reflect.String: | ||
b := make([]byte, 8+len(v.String())) | ||
binary.LittleEndian.PutUint64(b, uint64(len(v.String()))) | ||
copy(b[8:], []byte(v.String())) | ||
return b, nil | ||
case reflect.Ptr: | ||
if v.IsNil() { | ||
return []byte{0}, nil | ||
} | ||
d, err := serializeData(v.Elem()) | ||
if err != nil { | ||
return nil, err | ||
} | ||
b := make([]byte, 1+len(d)) | ||
b[0] = 1 | ||
copy(b[1:], d[:]) | ||
return b, nil | ||
case reflect.Struct: | ||
data := make([]byte, 0, 1024) | ||
for i := 0; i < v.NumField(); i++ { | ||
field := v.Field(i) | ||
d, err := serializeData(field) | ||
if err != nil { | ||
return nil, err | ||
} | ||
data = append(data, d...) | ||
} | ||
return data, nil | ||
} | ||
return nil, fmt.Errorf("unsupport type: %v", v.Kind()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
//go:build mips | ||
// +build mips | ||
|
||
TEXT ·SyscallWrite(SB), $0-24 | ||
MOVW $4004, R2 // #define SYS_write 4004 | ||
MOVW fd+0(FP), R4 | ||
MOVW write_buf+4(FP), R5 | ||
MOVW nbytes+16(FP), R6 | ||
SYSCALL | ||
MOVW R2, ret+0(FP) | ||
RET | ||
|
||
TEXT ·SyscallHintLen(SB), $0-4 | ||
MOVW $0xF0, R2 // #define SYS_hint_len 0xF0 | ||
SYSCALL | ||
MOVW R2, ret+0(FP) | ||
RET | ||
|
||
TEXT ·SyscallHintRead(SB), $0-16 | ||
MOVW $0xF1, R2 // #define SYS_hint_read 0xF1 | ||
MOVW ptr+0(FP), R4 | ||
MOVW len+12(FP), R5 | ||
SYSCALL | ||
RET |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.