Skip to content

Commit

Permalink
Merge pull request #84 from athenavm/refactor/dont-use-global-map-for…
Browse files Browse the repository at this point in the history
…-hostcontext
  • Loading branch information
poszu authored Aug 13, 2024
2 parents 27b5ec6 + 87d566c commit 99d40c4
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 84 deletions.
126 changes: 51 additions & 75 deletions ffi/athcon/bindings/go/athcon.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,37 +10,13 @@ package athcon
#include <stdlib.h> // for 'free'
extern const struct athcon_host_interface athcon_go_host;
static struct athcon_result execute_wrapper(struct athcon_vm* vm,
uintptr_t context_index, enum athcon_revision rev,
enum athcon_call_kind kind, int32_t depth, int64_t gas,
const athcon_address* recipient, const athcon_address* sender,
const uint8_t* input_data, size_t input_size, const athcon_uint256be* value,
const uint8_t* code, size_t code_size)
{
struct athcon_message msg = {
kind,
depth,
gas,
*recipient,
*sender,
input_data,
input_size,
*value,
0, // code
0, // code_size
};
struct athcon_host_context* context = (struct athcon_host_context*)context_index;
return athcon_execute(vm, &athcon_go_host, context, rev, &msg, code, code_size);
}
*/
import "C"
import (
"fmt"
"path/filepath"
"runtime/cgo"
"strings"
"sync"
"unsafe"

"github.com/ebitengine/purego"
Expand Down Expand Up @@ -186,21 +162,56 @@ type Result struct {
GasRefund int64
}

func (vm *VM) Execute(ctx HostContext, rev Revision,
kind CallKind, depth int, gas int64,
recipient Address, sender Address, input []byte, value Bytes32,
code []byte) (res Result, err error) {

ctxId := addHostContext(ctx)
// FIXME: Clarify passing by pointer vs passing by value.
athconRecipient := athconAddress(recipient)
athconSender := athconAddress(sender)
athconValue := athconBytes32(value)
result := C.execute_wrapper(vm.handle, C.uintptr_t(ctxId), uint32(rev),
C.enum_athcon_call_kind(kind), C.int32_t(depth), C.int64_t(gas),
&athconRecipient, &athconSender, bytesPtr(input), C.size_t(len(input)), &athconValue,
bytesPtr(code), C.size_t(len(code)))
removeHostContext(ctxId)
func (vm *VM) Execute(
ctx HostContext,
rev Revision,
kind CallKind,
depth int,
gas int64,
recipient, sender Address,
input []byte,
value Bytes32,
code []byte,
) (res Result, err error) {
if len(code) == 0 {
return res, fmt.Errorf("code is empty")
}
msg := C.struct_athcon_message{
kind: C.enum_athcon_call_kind(kind),
depth: C.int32_t(depth),
gas: C.int64_t(gas),
recipient: athconAddress(recipient),
sender: athconAddress(sender),
value: athconBytes32(value),
}
if len(input) > 0 {
// Allocate memory for input data in C.
// Otherwise, the Go garbage collector may move the data around and
// invalidate the pointer passed to the C code.
// Without this, the CGO complains `cgo argument has Go pointer to unpinned Go pointer`.
cInputData := C.malloc(C.size_t(len(input)))
if cInputData == nil {
return res, fmt.Errorf("failed to allocate memory for input data")
}
defer C.free(cInputData)

cSlice := unsafe.Slice((*byte)(cInputData), len(input))
copy(cSlice, input)
msg.input_data = (*C.uchar)(unsafe.Pointer(&cSlice[0]))
msg.input_size = C.size_t(len(input))
}

ctxHandle := cgo.NewHandle(ctx)
result := C.athcon_execute(
vm.handle,
&C.athcon_go_host,
(*C.struct_athcon_host_context)(unsafe.Pointer(uintptr(ctxHandle))),
uint32(rev),
&msg,
(*C.uint8_t)(unsafe.Pointer(&code[0])),
C.size_t(len(code)),
)
ctxHandle.Delete()

res.Output = C.GoBytes(unsafe.Pointer(result.output_data), C.int(result.output_size))
res.GasLeft = int64(result.gas_left)
Expand All @@ -215,34 +226,6 @@ func (vm *VM) Execute(ctx HostContext, rev Revision,
return res, err
}

var (
hostContextCounter uintptr
hostContextMap = map[uintptr]HostContext{}
hostContextMapMu sync.Mutex
)

func addHostContext(ctx HostContext) uintptr {
hostContextMapMu.Lock()
id := hostContextCounter
hostContextCounter++
hostContextMap[id] = ctx
hostContextMapMu.Unlock()
return id
}

func removeHostContext(id uintptr) {
hostContextMapMu.Lock()
delete(hostContextMap, id)
hostContextMapMu.Unlock()
}

func getHostContext(idx uintptr) HostContext {
hostContextMapMu.Lock()
ctx := hostContextMap[idx]
hostContextMapMu.Unlock()
return ctx
}

func athconBytes32(in Bytes32) C.athcon_bytes32 {
out := C.athcon_bytes32{}
for i := 0; i < len(in); i++ {
Expand All @@ -258,10 +241,3 @@ func athconAddress(address Address) C.athcon_address {
}
return r
}

func bytesPtr(bytes []byte) *C.uint8_t {
if len(bytes) == 0 {
return nil
}
return (*C.uint8_t)(unsafe.Pointer(&bytes[0]))
}
20 changes: 11 additions & 9 deletions ffi/athcon/bindings/go/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ package athcon
#include <athcon/helpers.h>
*/
import "C"
import "unsafe"
import (
"runtime/cgo"
"unsafe"
)

type CallKind int

Expand Down Expand Up @@ -76,32 +79,31 @@ type HostContext interface {

//export accountExists
func accountExists(pCtx unsafe.Pointer, pAddr *C.athcon_address) C.bool {
ctx := getHostContext(uintptr(pCtx))
ctx := cgo.Handle(pCtx).Value().(HostContext)
return C.bool(ctx.AccountExists(goAddress(*pAddr)))
}

//export getStorage
func getStorage(pCtx unsafe.Pointer, pAddr *C.struct_athcon_address, pKey *C.athcon_bytes32) C.athcon_bytes32 {
ctx := getHostContext(uintptr(pCtx))
ctx := cgo.Handle(pCtx).Value().(HostContext)
return athconBytes32(ctx.GetStorage(goAddress(*pAddr), goHash(*pKey)))
}

//export setStorage
func setStorage(pCtx unsafe.Pointer, pAddr *C.athcon_address, pKey *C.athcon_bytes32, pVal *C.athcon_bytes32) C.enum_athcon_storage_status {
ctx := getHostContext(uintptr(pCtx))
ctx := cgo.Handle(pCtx).Value().(HostContext)
return C.enum_athcon_storage_status(ctx.SetStorage(goAddress(*pAddr), goHash(*pKey), goHash(*pVal)))
}

//export getBalance
func getBalance(pCtx unsafe.Pointer, pAddr *C.athcon_address) C.athcon_uint256be {
ctx := getHostContext(uintptr(pCtx))
ctx := cgo.Handle(pCtx).Value().(HostContext)
return athconBytes32(ctx.GetBalance(goAddress(*pAddr)))
}

//export getTxContext
func getTxContext(pCtx unsafe.Pointer) C.struct_athcon_tx_context {
ctx := getHostContext(uintptr(pCtx))

ctx := cgo.Handle(pCtx).Value().(HostContext)
txContext := ctx.GetTxContext()

return C.struct_athcon_tx_context{
Expand All @@ -116,13 +118,13 @@ func getTxContext(pCtx unsafe.Pointer) C.struct_athcon_tx_context {

//export getBlockHash
func getBlockHash(pCtx unsafe.Pointer, number int64) C.athcon_bytes32 {
ctx := getHostContext(uintptr(pCtx))
ctx := cgo.Handle(pCtx).Value().(HostContext)
return athconBytes32(ctx.GetBlockHash(number))
}

//export call
func call(pCtx unsafe.Pointer, msg *C.struct_athcon_message) C.struct_athcon_result {
ctx := getHostContext(uintptr(pCtx))
ctx := cgo.Handle(pCtx).Value().(HostContext)

kind := CallKind(msg.kind)
output, gasLeft, createAddr, err := ctx.Call(kind, goAddress(msg.recipient), goAddress(msg.sender), goHash(msg.value),
Expand Down

0 comments on commit 99d40c4

Please sign in to comment.