feat: add wasm ledger

(cherry picked from commit 157965014c)
This commit is contained in:
liweixia 2021-03-24 15:01:20 +08:00 committed by zhourong
parent b10b7dab28
commit f4a9218fd3
3 changed files with 133 additions and 1 deletions

View File

@ -20,6 +20,7 @@ import (
"github.com/meshplus/bitxhub/pkg/vm"
"github.com/meshplus/bitxhub/pkg/vm/boltvm"
"github.com/meshplus/bitxhub/pkg/vm/wasm"
"github.com/meshplus/bitxhub/pkg/vm/wasm/vmledger"
"github.com/sirupsen/logrus"
)
@ -298,7 +299,7 @@ func (exec *BlockExecutor) applyTransaction(i int, tx *pb.Transaction, opt *agen
instance = boltvm.New(ctx, exec.validationEngine, exec.getContracts(opt))
case pb.TransactionData_XVM:
ctx := vm.NewContext(tx, uint64(i), data, exec.ledger, exec.logger)
imports, err := wasm.EmptyImports()
imports, err := vmledger.New()
if err != nil {
return nil, err
}

View File

@ -0,0 +1,18 @@
package vmledger
import (
"github.com/wasmerio/go-ext-wasm/wasmer"
)
type Imports struct {
imports *wasmer.Imports
}
func New() (*wasmer.Imports, error) {
imports := &Imports{
imports: wasmer.NewImports(),
}
imports.importLedger()
return imports.imports, nil
}

View File

@ -0,0 +1,113 @@
package vmledger
// #include <stdlib.h>
//
// extern long long unsigned int get_balance(void *context);
// extern void set_balance(void *context, long long unsigned int value);
// extern int32_t get_state(void *context, long long key_ptr);
// extern void set_state(void *context, long long key_ptr, long long value_ptr);
// extern void add_state(void *context, long long key_ptr, long long value_ptr);
import "C"
import (
"unsafe"
"github.com/meshplus/bitxhub/internal/ledger"
"github.com/wasmerio/go-ext-wasm/wasmer"
)
//export get_balance
func get_balance(context unsafe.Pointer) uint64 {
ctx := wasmer.IntoInstanceContext(context)
ctxMap := ctx.Data().(map[string]interface{})
account := ctxMap["account"].(*ledger.Account)
return account.GetBalance()
}
//export set_balance
func set_balance(context unsafe.Pointer, value uint64) {
ctx := wasmer.IntoInstanceContext(context)
ctxMap := ctx.Data().(map[string]interface{})
account := ctxMap["account"].(*ledger.Account)
account.SetBalance(value)
}
//export get_state
func get_state(context unsafe.Pointer, key_ptr int64) int32 {
ctx := wasmer.IntoInstanceContext(context)
ctxMap := ctx.Data().(map[string]interface{})
data := ctxMap["argmap"].(map[int]int)
alloc := ctxMap["alloc"].(func(...interface{}) (wasmer.Value, error))
account := ctxMap["account"].(*ledger.Account)
memory := ctx.Memory()
key := memory.Data()[key_ptr : key_ptr+int64(data[int(key_ptr)])]
ok, value := account.GetState(key)
if !ok {
return -1
}
lengthOfBytes := len(value)
allocResult, err := alloc(lengthOfBytes)
if err != nil {
return -1
}
inputPointer := allocResult.ToI32()
mem := memory.Data()[inputPointer:]
var i int
for i = 0; i < lengthOfBytes; i++ {
mem[i] = value[i]
}
mem[i] = 0
data[int(inputPointer)] = len(value)
return inputPointer
}
//export set_state
func set_state(context unsafe.Pointer, key_ptr int64, value_ptr int64) {
ctx := wasmer.IntoInstanceContext(context)
ctxMap := ctx.Data().(map[string]interface{})
data := ctxMap["argmap"].(map[int]int)
account := ctxMap["account"].(*ledger.Account)
memory := ctx.Memory()
key := memory.Data()[key_ptr : key_ptr+int64(data[int(key_ptr)])]
value := memory.Data()[value_ptr : value_ptr+int64(data[int(value_ptr)])]
account.SetState(key, value)
}
//export add_state
func add_state(context unsafe.Pointer, key_ptr int64, value_ptr int64) {
ctx := wasmer.IntoInstanceContext(context)
ctxMap := ctx.Data().(map[string]interface{})
data := ctxMap["argmap"].(map[int]int)
account := ctxMap["account"].(*ledger.Account)
memory := ctx.Memory()
key := memory.Data()[key_ptr : key_ptr+int64(data[int(key_ptr)])]
value := memory.Data()[value_ptr : value_ptr+int64(data[int(value_ptr)])]
account.AddState(key, value)
}
func (im *Imports) importLedger() {
var err error
im.imports, err = im.imports.Append("get_balance", get_balance, C.get_balance)
if err != nil {
return
}
im.imports, err = im.imports.Append("set_balance", set_balance, C.set_balance)
if err != nil {
return
}
im.imports, err = im.imports.Append("get_state", get_state, C.get_state)
if err != nil {
return
}
im.imports, err = im.imports.Append("set_state", set_state, C.set_state)
if err != nil {
return
}
im.imports, err = im.imports.Append("add_state", add_state, C.add_state)
if err != nil {
return
}
}