rpc/core: implement invokescript method, fix #348
Extend Blockchainer with one more method to spawn a VM for test runs and use it to run scripts. Gas consumption is not counted or limited in any way at the moment (see #424).
This commit is contained in:
parent
94776b8a1f
commit
ebc1ba4f38
5 changed files with 54 additions and 0 deletions
|
@ -1111,6 +1111,14 @@ func (bc *Blockchain) spawnVMWithInterops(interopCtx *interopContext) *vm.VM {
|
|||
return vm
|
||||
}
|
||||
|
||||
// GetTestVM returns a VM and a Store setup for a test run of some sort of code.
|
||||
func (bc *Blockchain) GetTestVM() (*vm.VM, storage.Store) {
|
||||
tmpStore := storage.NewMemCachedStore(bc.store)
|
||||
systemInterop := newInteropContext(0x10, bc, tmpStore, nil, nil)
|
||||
vm := bc.spawnVMWithInterops(systemInterop)
|
||||
return vm, tmpStore
|
||||
}
|
||||
|
||||
// verifyHashAgainstScript verifies given hash against the given witness.
|
||||
func (bc *Blockchain) verifyHashAgainstScript(hash util.Uint160, witness *transaction.Witness, checkedHash util.Uint256, interopCtx *interopContext) error {
|
||||
verification := witness.VerificationScript
|
||||
|
|
|
@ -2,8 +2,10 @@ package core
|
|||
|
||||
import (
|
||||
"github.com/CityOfZion/neo-go/config"
|
||||
"github.com/CityOfZion/neo-go/pkg/core/storage"
|
||||
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/CityOfZion/neo-go/pkg/vm"
|
||||
)
|
||||
|
||||
// Blockchainer is an interface that abstract the implementation
|
||||
|
@ -27,6 +29,7 @@ type Blockchainer interface {
|
|||
GetScriptHashesForVerifying(*transaction.Transaction) ([]util.Uint160, error)
|
||||
GetStorageItem(scripthash util.Uint160, key []byte) *StorageItem
|
||||
GetStorageItems(hash util.Uint160) (map[string]*StorageItem, error)
|
||||
GetTestVM() (*vm.VM, storage.Store)
|
||||
GetTransaction(util.Uint256) (*transaction.Transaction, uint32, error)
|
||||
GetUnspentCoinState(util.Uint256) *UnspentCoinState
|
||||
References(t *transaction.Transaction) map[transaction.Input]*transaction.Output
|
||||
|
|
|
@ -9,9 +9,11 @@ import (
|
|||
|
||||
"github.com/CityOfZion/neo-go/config"
|
||||
"github.com/CityOfZion/neo-go/pkg/core"
|
||||
"github.com/CityOfZion/neo-go/pkg/core/storage"
|
||||
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
||||
"github.com/CityOfZion/neo-go/pkg/network/payload"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/CityOfZion/neo-go/pkg/vm"
|
||||
)
|
||||
|
||||
type testChain struct {
|
||||
|
@ -78,6 +80,9 @@ func (chain testChain) GetScriptHashesForVerifying(*transaction.Transaction) ([]
|
|||
func (chain testChain) GetStorageItem(scripthash util.Uint160, key []byte) *core.StorageItem {
|
||||
panic("TODO")
|
||||
}
|
||||
func (chain testChain) GetTestVM() (*vm.VM, storage.Store) {
|
||||
panic("TODO")
|
||||
}
|
||||
func (chain testChain) GetStorageItems(hash util.Uint160) (map[string]*core.StorageItem, error) {
|
||||
panic("TODO")
|
||||
}
|
||||
|
|
|
@ -227,6 +227,9 @@ Methods:
|
|||
case "getrawtransaction":
|
||||
results, resultsErr = s.getrawtransaction(reqParams)
|
||||
|
||||
case "invokescript":
|
||||
results, resultsErr = s.invokescript(reqParams)
|
||||
|
||||
case "sendrawtransaction":
|
||||
results, resultsErr = s.sendrawtransaction(reqParams)
|
||||
|
||||
|
@ -280,6 +283,28 @@ func (s *Server) getrawtransaction(reqParams Params) (interface{}, error) {
|
|||
return results, resultsErr
|
||||
}
|
||||
|
||||
// invokescript implements the `invokescript` RPC call.
|
||||
func (s *Server) invokescript(reqParams Params) (interface{}, error) {
|
||||
hexScript, err := reqParams.ValueWithType(0, "string")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
script, err := hex.DecodeString(hexScript.StringVal)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
vm, _ := s.chain.GetTestVM()
|
||||
vm.LoadScript(script)
|
||||
_ = vm.Run()
|
||||
result := &wrappers.InvokeResult{
|
||||
State: vm.State(),
|
||||
GasConsumed: "0.1",
|
||||
Script: hexScript.StringVal,
|
||||
Stack: vm.Estack(),
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (s *Server) sendrawtransaction(reqParams Params) (interface{}, error) {
|
||||
var resultsErr error
|
||||
var results interface{}
|
||||
|
|
13
pkg/rpc/wrappers/invoke_result.go
Normal file
13
pkg/rpc/wrappers/invoke_result.go
Normal file
|
@ -0,0 +1,13 @@
|
|||
package wrappers
|
||||
|
||||
import (
|
||||
"github.com/CityOfZion/neo-go/pkg/vm"
|
||||
)
|
||||
|
||||
// InvokeResult is used as a wrapper to represent an invokation result.
|
||||
type InvokeResult struct {
|
||||
State string `json:"state"`
|
||||
GasConsumed string `json:"gas_consumed"`
|
||||
Script string `json:"script"`
|
||||
Stack *vm.Stack
|
||||
}
|
Loading…
Reference in a new issue