Skip to content

Commit

Permalink
add wasm smart contract call (DNAProject#10)
Browse files Browse the repository at this point in the history
add wasm smart contract call
  • Loading branch information
JasonZhouPW authored and laizy committed Mar 30, 2018
1 parent c8e9c26 commit 23dd5b8
Show file tree
Hide file tree
Showing 10 changed files with 302 additions and 141 deletions.
20 changes: 15 additions & 5 deletions smartcontract/service/wasm/state_machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ package wasm
import (
"bytes"
"errors"
"fmt"
"io/ioutil"
"fmt"

"github.com/ontio/ontology/common"
"github.com/ontio/ontology/core/states"
Expand All @@ -33,6 +33,7 @@ import (
"github.com/ontio/ontology/vm/wasmvm/exec"
"github.com/ontio/ontology/vm/wasmvm/util"
"github.com/ontio/ontology/vm/wasmvm/wasm"

)

type WasmStateMachine struct {
Expand Down Expand Up @@ -111,19 +112,17 @@ func (s *WasmStateMachine) getstore(engine *exec.ExecutionEngine) (bool, error)
if err != nil {
return false, err
}

k, err := serializeStorageKey(vm.CodeHash, key)
if err != nil {
return false, err
}

item, err := s.CloneCache.Get(scommon.ST_STORAGE, k)
if err != nil {
return false, err
}

// idx = int64.max value if item is nil
//todo need more test about the nil case
idx, err := vm.SetPointerMemory(item)
idx, err := vm.SetPointerMemory(item.(*states.StorageItem).Value)
if err != nil {
return false, err
}
Expand Down Expand Up @@ -161,6 +160,17 @@ func (s *WasmStateMachine) deletestore(engine *exec.ExecutionEngine) (bool, erro
return true, nil
}

func (s *WasmStateMachine) GetContractCodeFromAddress(address common.Address) ([]byte, error) {

dcode, err := s.ldgerStore.GetContractState(address)
if err != nil {
return nil, err
}

return dcode.Code.Code, nil

}

//call other contract
func callContract(engine *exec.ExecutionEngine) (bool, error) {
vm := engine.GetVM()
Expand Down
44 changes: 39 additions & 5 deletions smartcontract/service/wasm/state_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@
package wasm

import (
"errors"

"github.com/ontio/ontology/common"
"github.com/ontio/ontology/common/log"
"github.com/ontio/ontology/core/store"
"github.com/ontio/ontology/core/types"
"github.com/ontio/ontology/errors"
"github.com/ontio/ontology/smartcontract/event"
trigger "github.com/ontio/ontology/smartcontract/types"
"github.com/ontio/ontology/vm/wasmvm/exec"
Expand All @@ -41,7 +43,8 @@ func NewWasmStateReader(ldgerStore store.LedgerStore, trigger trigger.TriggerTyp
trigger: trigger,
}

i.Register("GetBlockHeight", i.getblockheight)
i.Register("GetBlockHeight", i.Getblockheight)
i.Register("RuntimeNotify", i.RuntimeNotify)

return i
}
Expand All @@ -59,7 +62,7 @@ func (i *WasmStateReader) Invoke(methodName string, engine *exec.ExecutionEngine
if v, ok := i.serviceMap[methodName]; ok {
return v(engine)
}
return true, errors.New("Not supported method:" + methodName)
return true, errors.NewErr("Not supported method:" + methodName)
}

func (i *WasmStateReader) MergeMap(mMap map[string]func(*exec.ExecutionEngine) (bool, error)) bool {
Expand All @@ -83,7 +86,7 @@ func (i *WasmStateReader) Exists(name string) bool {

//============================block apis here============================/

func (i *WasmStateReader) getblockheight(engine *exec.ExecutionEngine) (bool, error) {
func (i *WasmStateReader) Getblockheight(engine *exec.ExecutionEngine) (bool, error) {
vm := engine.GetVM()

h := i.ldgerStore.GetCurrentBlockHeight()
Expand All @@ -93,3 +96,34 @@ func (i *WasmStateReader) getblockheight(engine *exec.ExecutionEngine) (bool, er
}
return true, nil
}

func (i *WasmStateReader) RuntimeNotify(engine *exec.ExecutionEngine) (bool, error) {
vm := engine.GetVM()
envCall := vm.GetEnvCall()
params := envCall.GetParams()

if len(params) != 1 {
return false, errors.NewErr("[RuntimeNotify] get Parameter count error!")
}

returnStr, err := vm.GetPointerMemory(params[0])
if err != nil {
return false, err
}

tran, ok := engine.CodeContainer.(*types.Transaction)
if !ok {
log.Error("[RuntimeNotify] Container not transaction!")
return false, errors.NewErr("[RuntimeNotify] Container not transaction!")
}

hash := engine.GetVM().CodeHash

txid := tran.Hash()

i.Notifications = append(i.Notifications, &event.NotifyEventInfo{TxHash: txid, CodeHash: hash, States: []interface{}{common.ToHexString([]byte(returnStr))}})
vm.RestoreCtx()

return true, nil

}
39 changes: 34 additions & 5 deletions smartcontract/smartcontract.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,14 @@
package smartcontract

import (
"bytes"
"encoding/binary"

"github.com/ontio/ontology/common"
"github.com/ontio/ontology/core/store"
scommon "github.com/ontio/ontology/core/store/common"
ctypes "github.com/ontio/ontology/core/types"
"github.com/ontio/ontology/errors"
"github.com/ontio/ontology/smartcontract/context"
"github.com/ontio/ontology/smartcontract/event"
"github.com/ontio/ontology/smartcontract/service/native"
Expand Down Expand Up @@ -115,19 +119,44 @@ func (sc *SmartContract) Execute() error {
stateMachine.CloneCache.Commit()
sc.Notifications = append(sc.Notifications, stateMachine.Notifications...)
case vmtypes.WASMVM:
//todo refactor following code to match Neovm
stateMachine := wasm.NewWasmStateMachine(sc.Config.Store, sc.Config.DBCache, stypes.Application, sc.Config.Time)

engine := exec.NewExecutionEngine(
sc.Config.Tx,
new(util.ECDsaCrypto),
sc.Config.Table,
stateMachine,
"product",
)
//todo how to get the input
input := []byte{}
engine.Call(ctx.ContractAddress, ctx.Code.Code, input)
//fmt.Println(engine)

tmpcodes := bytes.Split(ctx.Code.Code, []byte(exec.PARAM_SPLITER))
if len(tmpcodes) != 3 {
return errors.NewErr("Wasm paramter count error")
}
contractCode := tmpcodes[0]

addr, err := common.AddressParseFromBytes(contractCode)
if err != nil {
return errors.NewErr("get contract address error")
}

dpcode, err := stateMachine.GetContractCodeFromAddress(addr)
if err != nil {
return errors.NewErr("get contract error")
}

input := ctx.Code.Code[len(contractCode)+1:]
res, err := engine.Call(ctx.ContractAddress, dpcode, input)
if err != nil {
return err
}

//todo how to deal with the result???
_, err = engine.GetVM().GetPointerMemory(uint64(binary.LittleEndian.Uint32(res)))
if err != nil {
return err
}

stateMachine.CloneCache.Commit()
sc.Notifications = append(sc.Notifications, stateMachine.Notifications...)
}
Expand Down
1 change: 0 additions & 1 deletion vm/wasmvm/exec/contract_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import (
"io/ioutil"
"testing"

"github.com/ontio/ontology/common"
"github.com/ontio/ontology/common/serialization"
"github.com/ontio/ontology/common"
)
Expand Down
2 changes: 1 addition & 1 deletion vm/wasmvm/exec/env_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -551,7 +551,7 @@ func jsonMashal(engine *ExecutionEngine) (bool, error) {
if err != nil {
return false, err
}
ret.Pval = string(tmp)
ret.Pval = util.TrimBuffToString(tmp)

case "int_array":
tmp, err := engine.vm.GetPointerMemory(val)
Expand Down
7 changes: 2 additions & 5 deletions vm/wasmvm/exec/excution_engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func NewExecutionEngine(container interfaces.CodeContainer, crypto interfaces.Cr
engine := &ExecutionEngine{
crypto: crypto,
table: table,
codeContainer: container,
CodeContainer: container,
service: NewInteropService(),
version: ver,
}
Expand All @@ -92,7 +92,7 @@ type ExecutionEngine struct {
crypto interfaces.Crypto
table interfaces.CodeTable
service *InteropService
codeContainer interfaces.CodeContainer
CodeContainer interfaces.CodeContainer
vm *VM
//todo ,move to contract info later
version string //for test different contracts
Expand Down Expand Up @@ -315,7 +315,6 @@ func (e *ExecutionEngine) Call(caller common.Address, code, input []byte) (retur
}()

if e.version != "test" {

methodName := CONTRACT_METHOD_NAME //fix to "invoke"

tmparr := bytes.Split(input, []byte(PARAM_SPLITER))
Expand All @@ -331,7 +330,6 @@ func (e *ExecutionEngine) Call(caller common.Address, code, input []byte) (retur
if err != nil {
return nil, errors.New("[Call]Verify wasm failed!" + err.Error())
}

//3. verify the module
//already verified in step 2

Expand Down Expand Up @@ -368,7 +366,6 @@ func (e *ExecutionEngine) Call(caller common.Address, code, input []byte) (retur

//get function type
ftype := m.Types.Entries[int(fidx)]

//method ,param bytes
params := make([]uint64, 2)

Expand Down
Binary file modified vm/wasmvm/exec/test_data2/contract.wasm
Binary file not shown.
Loading

0 comments on commit 23dd5b8

Please sign in to comment.