rpc: separate out request and response structures
Mostly as is, no real effort done yet to optimize them, so there are still a lot of duplicates there, but at least we sort them out into different smaller packages.
This commit is contained in:
parent
69e1ad512f
commit
f330f2f40b
18 changed files with 422 additions and 396 deletions
|
@ -15,6 +15,8 @@ import (
|
|||
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
|
||||
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
||||
"github.com/CityOfZion/neo-go/pkg/rpc"
|
||||
"github.com/CityOfZion/neo-go/pkg/rpc/request"
|
||||
"github.com/CityOfZion/neo-go/pkg/rpc/response"
|
||||
"github.com/CityOfZion/neo-go/pkg/smartcontract"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/CityOfZion/neo-go/pkg/vm"
|
||||
|
@ -294,10 +296,10 @@ func initSmartContract(ctx *cli.Context) error {
|
|||
// TODO: Fix the missing neo-go.yml file with the `init` command when the package manager is in place.
|
||||
if !ctx.Bool("skip-details") {
|
||||
details := parseContractDetails()
|
||||
details.ReturnType = rpc.ByteArray
|
||||
details.Parameters = make([]rpc.StackParamType, 2)
|
||||
details.Parameters[0] = rpc.String
|
||||
details.Parameters[1] = rpc.Array
|
||||
details.ReturnType = request.ByteArray
|
||||
details.Parameters = make([]request.StackParamType, 2)
|
||||
details.Parameters[0] = request.String
|
||||
details.Parameters[1] = request.Array
|
||||
|
||||
project := &ProjectConfig{Contract: details}
|
||||
b, err := yaml.Marshal(project)
|
||||
|
@ -362,7 +364,7 @@ func invokeInternal(ctx *cli.Context, withMethod bool, signAndPush bool) error {
|
|||
operation string
|
||||
params = make([]smartcontract.Parameter, 0)
|
||||
paramsStart = 1
|
||||
resp *rpc.InvokeScriptResponse
|
||||
resp *response.InvokeScript
|
||||
wif *keys.WIF
|
||||
)
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ import (
|
|||
"github.com/CityOfZion/neo-go/pkg/core/state"
|
||||
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
||||
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
||||
"github.com/CityOfZion/neo-go/pkg/rpc/request"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
@ -177,13 +178,13 @@ func (c *Client) CalculateInputs(address string, asset util.Uint256, cost util.F
|
|||
|
||||
}
|
||||
|
||||
func (c *Client) performRequest(method string, p params, v interface{}) error {
|
||||
func (c *Client) performRequest(method string, p request.RawParams, v interface{}) error {
|
||||
var (
|
||||
r = request{
|
||||
JSONRPC: c.version,
|
||||
Method: method,
|
||||
Params: p.values,
|
||||
ID: 1,
|
||||
r = request.Raw{
|
||||
JSONRPC: c.version,
|
||||
Method: method,
|
||||
RawParams: p.Values,
|
||||
ID: 1,
|
||||
}
|
||||
buf = new(bytes.Buffer)
|
||||
)
|
||||
|
|
|
@ -1,128 +0,0 @@
|
|||
package rpc
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
const (
|
||||
jsonRPCVersion = "2.0"
|
||||
)
|
||||
|
||||
type (
|
||||
// Request represents a standard JSON-RPC 2.0
|
||||
// request: http://www.jsonrpc.org/specification#request_object.
|
||||
Request struct {
|
||||
JSONRPC string `json:"jsonrpc"`
|
||||
Method string `json:"method"`
|
||||
RawParams json.RawMessage `json:"params,omitempty"`
|
||||
RawID json.RawMessage `json:"id,omitempty"`
|
||||
}
|
||||
|
||||
// Response represents a standard JSON-RPC 2.0
|
||||
// response: http://www.jsonrpc.org/specification#response_object.
|
||||
Response struct {
|
||||
JSONRPC string `json:"jsonrpc"`
|
||||
Result interface{} `json:"result,omitempty"`
|
||||
Error *Error `json:"error,omitempty"`
|
||||
ID json.RawMessage `json:"id,omitempty"`
|
||||
}
|
||||
)
|
||||
|
||||
// NewRequest creates a new Request struct.
|
||||
func NewRequest() *Request {
|
||||
return &Request{
|
||||
JSONRPC: jsonRPCVersion,
|
||||
}
|
||||
}
|
||||
|
||||
// DecodeData decodes the given reader into the the request
|
||||
// struct.
|
||||
func (r *Request) DecodeData(data io.ReadCloser) error {
|
||||
defer data.Close()
|
||||
|
||||
err := json.NewDecoder(data).Decode(r)
|
||||
if err != nil {
|
||||
return errors.Errorf("error parsing JSON payload: %s", err)
|
||||
}
|
||||
|
||||
if r.JSONRPC != jsonRPCVersion {
|
||||
return errors.Errorf("invalid version, expected 2.0 got: '%s'", r.JSONRPC)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Params takes a slice of any type and attempts to bind
|
||||
// the params to it.
|
||||
func (r *Request) Params() (*Params, error) {
|
||||
params := Params{}
|
||||
|
||||
err := json.Unmarshal(r.RawParams, ¶ms)
|
||||
if err != nil {
|
||||
return nil, errors.Errorf("error parsing params field in payload: %s", err)
|
||||
}
|
||||
|
||||
return ¶ms, nil
|
||||
}
|
||||
|
||||
// WriteErrorResponse writes an error response to the ResponseWriter.
|
||||
func (s *Server) WriteErrorResponse(r *Request, w http.ResponseWriter, err error) {
|
||||
jsonErr, ok := err.(*Error)
|
||||
if !ok {
|
||||
jsonErr = NewInternalServerError("Internal server error", err)
|
||||
}
|
||||
|
||||
response := Response{
|
||||
JSONRPC: r.JSONRPC,
|
||||
Error: jsonErr,
|
||||
ID: r.RawID,
|
||||
}
|
||||
|
||||
logFields := []zap.Field{
|
||||
zap.Error(jsonErr.Cause),
|
||||
zap.String("method", r.Method),
|
||||
}
|
||||
|
||||
params, err := r.Params()
|
||||
if err == nil {
|
||||
logFields = append(logFields, zap.Any("params", params))
|
||||
}
|
||||
|
||||
s.log.Error("Error encountered with rpc request", logFields...)
|
||||
|
||||
w.WriteHeader(jsonErr.HTTPCode)
|
||||
s.writeServerResponse(r, w, response)
|
||||
}
|
||||
|
||||
// WriteResponse encodes the response and writes it to the ResponseWriter.
|
||||
func (s *Server) WriteResponse(r *Request, w http.ResponseWriter, result interface{}) {
|
||||
response := Response{
|
||||
JSONRPC: r.JSONRPC,
|
||||
Result: result,
|
||||
ID: r.RawID,
|
||||
}
|
||||
|
||||
s.writeServerResponse(r, w, response)
|
||||
}
|
||||
|
||||
func (s *Server) writeServerResponse(r *Request, w http.ResponseWriter, response Response) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
if s.config.EnableCORSWorkaround {
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With")
|
||||
}
|
||||
|
||||
encoder := json.NewEncoder(w)
|
||||
err := encoder.Encode(response)
|
||||
|
||||
if err != nil {
|
||||
s.log.Error("Error encountered while encoding response",
|
||||
zap.String("err", err.Error()),
|
||||
zap.String("method", r.Method))
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package rpc
|
||||
package request
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
@ -29,12 +29,13 @@ type (
|
|||
}
|
||||
)
|
||||
|
||||
// These are parameter types accepted by RPC server.
|
||||
const (
|
||||
defaultT paramType = iota
|
||||
stringT
|
||||
numberT
|
||||
arrayT
|
||||
funcParamT
|
||||
StringT
|
||||
NumberT
|
||||
ArrayT
|
||||
FuncParamT
|
||||
)
|
||||
|
||||
func (p Param) String() string {
|
||||
|
@ -123,7 +124,7 @@ func (p Param) GetBytesHex() ([]byte, error) {
|
|||
func (p *Param) UnmarshalJSON(data []byte) error {
|
||||
var s string
|
||||
if err := json.Unmarshal(data, &s); err == nil {
|
||||
p.Type = stringT
|
||||
p.Type = StringT
|
||||
p.Value = s
|
||||
|
||||
return nil
|
||||
|
@ -131,7 +132,7 @@ func (p *Param) UnmarshalJSON(data []byte) error {
|
|||
|
||||
var num float64
|
||||
if err := json.Unmarshal(data, &num); err == nil {
|
||||
p.Type = numberT
|
||||
p.Type = NumberT
|
||||
p.Value = int(num)
|
||||
|
||||
return nil
|
||||
|
@ -142,7 +143,7 @@ func (p *Param) UnmarshalJSON(data []byte) error {
|
|||
jd.DisallowUnknownFields()
|
||||
var fp FuncParam
|
||||
if err := jd.Decode(&fp); err == nil {
|
||||
p.Type = funcParamT
|
||||
p.Type = FuncParamT
|
||||
p.Value = fp
|
||||
|
||||
return nil
|
||||
|
@ -150,7 +151,7 @@ func (p *Param) UnmarshalJSON(data []byte) error {
|
|||
|
||||
var ps []Param
|
||||
if err := json.Unmarshal(data, &ps); err == nil {
|
||||
p.Type = arrayT
|
||||
p.Type = ArrayT
|
||||
p.Value = ps
|
||||
|
||||
return nil
|
|
@ -1,4 +1,4 @@
|
|||
package rpc
|
||||
package request
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
|
@ -15,35 +15,35 @@ func TestParam_UnmarshalJSON(t *testing.T) {
|
|||
msg := `["str1", 123, ["str2", 3], [{"type": "String", "value": "jajaja"}]]`
|
||||
expected := Params{
|
||||
{
|
||||
Type: stringT,
|
||||
Type: StringT,
|
||||
Value: "str1",
|
||||
},
|
||||
{
|
||||
Type: numberT,
|
||||
Type: NumberT,
|
||||
Value: 123,
|
||||
},
|
||||
{
|
||||
Type: arrayT,
|
||||
Type: ArrayT,
|
||||
Value: []Param{
|
||||
{
|
||||
Type: stringT,
|
||||
Type: StringT,
|
||||
Value: "str2",
|
||||
},
|
||||
{
|
||||
Type: numberT,
|
||||
Type: NumberT,
|
||||
Value: 3,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: arrayT,
|
||||
Type: ArrayT,
|
||||
Value: []Param{
|
||||
{
|
||||
Type: funcParamT,
|
||||
Type: FuncParamT,
|
||||
Value: FuncParam{
|
||||
Type: String,
|
||||
Value: Param{
|
||||
Type: stringT,
|
||||
Type: StringT,
|
||||
Value: "jajaja",
|
||||
},
|
||||
},
|
||||
|
@ -61,34 +61,34 @@ func TestParam_UnmarshalJSON(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestParamGetString(t *testing.T) {
|
||||
p := Param{stringT, "jajaja"}
|
||||
p := Param{StringT, "jajaja"}
|
||||
str, err := p.GetString()
|
||||
assert.Equal(t, "jajaja", str)
|
||||
require.Nil(t, err)
|
||||
|
||||
p = Param{stringT, int(100500)}
|
||||
p = Param{StringT, int(100500)}
|
||||
_, err = p.GetString()
|
||||
require.NotNil(t, err)
|
||||
}
|
||||
|
||||
func TestParamGetInt(t *testing.T) {
|
||||
p := Param{numberT, int(100500)}
|
||||
p := Param{NumberT, int(100500)}
|
||||
i, err := p.GetInt()
|
||||
assert.Equal(t, 100500, i)
|
||||
require.Nil(t, err)
|
||||
|
||||
p = Param{numberT, "jajaja"}
|
||||
p = Param{NumberT, "jajaja"}
|
||||
_, err = p.GetInt()
|
||||
require.NotNil(t, err)
|
||||
}
|
||||
|
||||
func TestParamGetArray(t *testing.T) {
|
||||
p := Param{arrayT, []Param{{numberT, 42}}}
|
||||
p := Param{ArrayT, []Param{{NumberT, 42}}}
|
||||
a, err := p.GetArray()
|
||||
assert.Equal(t, []Param{{numberT, 42}}, a)
|
||||
assert.Equal(t, []Param{{NumberT, 42}}, a)
|
||||
require.Nil(t, err)
|
||||
|
||||
p = Param{arrayT, 42}
|
||||
p = Param{ArrayT, 42}
|
||||
_, err = p.GetArray()
|
||||
require.NotNil(t, err)
|
||||
}
|
||||
|
@ -96,16 +96,16 @@ func TestParamGetArray(t *testing.T) {
|
|||
func TestParamGetUint256(t *testing.T) {
|
||||
gas := "602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7"
|
||||
u256, _ := util.Uint256DecodeStringLE(gas)
|
||||
p := Param{stringT, gas}
|
||||
p := Param{StringT, gas}
|
||||
u, err := p.GetUint256()
|
||||
assert.Equal(t, u256, u)
|
||||
require.Nil(t, err)
|
||||
|
||||
p = Param{stringT, 42}
|
||||
p = Param{StringT, 42}
|
||||
_, err = p.GetUint256()
|
||||
require.NotNil(t, err)
|
||||
|
||||
p = Param{stringT, "qq2c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7"}
|
||||
p = Param{StringT, "qq2c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7"}
|
||||
_, err = p.GetUint256()
|
||||
require.NotNil(t, err)
|
||||
}
|
||||
|
@ -113,16 +113,16 @@ func TestParamGetUint256(t *testing.T) {
|
|||
func TestParamGetUint160FromHex(t *testing.T) {
|
||||
in := "50befd26fdf6e4d957c11e078b24ebce6291456f"
|
||||
u160, _ := util.Uint160DecodeStringLE(in)
|
||||
p := Param{stringT, in}
|
||||
p := Param{StringT, in}
|
||||
u, err := p.GetUint160FromHex()
|
||||
assert.Equal(t, u160, u)
|
||||
require.Nil(t, err)
|
||||
|
||||
p = Param{stringT, 42}
|
||||
p = Param{StringT, 42}
|
||||
_, err = p.GetUint160FromHex()
|
||||
require.NotNil(t, err)
|
||||
|
||||
p = Param{stringT, "wwbefd26fdf6e4d957c11e078b24ebce6291456f"}
|
||||
p = Param{StringT, "wwbefd26fdf6e4d957c11e078b24ebce6291456f"}
|
||||
_, err = p.GetUint160FromHex()
|
||||
require.NotNil(t, err)
|
||||
}
|
||||
|
@ -130,16 +130,16 @@ func TestParamGetUint160FromHex(t *testing.T) {
|
|||
func TestParamGetUint160FromAddress(t *testing.T) {
|
||||
in := "AK2nJJpJr6o664CWJKi1QRXjqeic2zRp8y"
|
||||
u160, _ := address.StringToUint160(in)
|
||||
p := Param{stringT, in}
|
||||
p := Param{StringT, in}
|
||||
u, err := p.GetUint160FromAddress()
|
||||
assert.Equal(t, u160, u)
|
||||
require.Nil(t, err)
|
||||
|
||||
p = Param{stringT, 42}
|
||||
p = Param{StringT, 42}
|
||||
_, err = p.GetUint160FromAddress()
|
||||
require.NotNil(t, err)
|
||||
|
||||
p = Param{stringT, "QK2nJJpJr6o664CWJKi1QRXjqeic2zRp8y"}
|
||||
p = Param{StringT, "QK2nJJpJr6o664CWJKi1QRXjqeic2zRp8y"}
|
||||
_, err = p.GetUint160FromAddress()
|
||||
require.NotNil(t, err)
|
||||
}
|
||||
|
@ -148,19 +148,19 @@ func TestParamGetFuncParam(t *testing.T) {
|
|||
fp := FuncParam{
|
||||
Type: String,
|
||||
Value: Param{
|
||||
Type: stringT,
|
||||
Type: StringT,
|
||||
Value: "jajaja",
|
||||
},
|
||||
}
|
||||
p := Param{
|
||||
Type: funcParamT,
|
||||
Type: FuncParamT,
|
||||
Value: fp,
|
||||
}
|
||||
newfp, err := p.GetFuncParam()
|
||||
assert.Equal(t, fp, newfp)
|
||||
require.Nil(t, err)
|
||||
|
||||
p = Param{funcParamT, 42}
|
||||
p = Param{FuncParamT, 42}
|
||||
_, err = p.GetFuncParam()
|
||||
require.NotNil(t, err)
|
||||
}
|
||||
|
@ -168,16 +168,16 @@ func TestParamGetFuncParam(t *testing.T) {
|
|||
func TestParamGetBytesHex(t *testing.T) {
|
||||
in := "602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7"
|
||||
inb, _ := hex.DecodeString(in)
|
||||
p := Param{stringT, in}
|
||||
p := Param{StringT, in}
|
||||
bh, err := p.GetBytesHex()
|
||||
assert.Equal(t, inb, bh)
|
||||
require.Nil(t, err)
|
||||
|
||||
p = Param{stringT, 42}
|
||||
p = Param{StringT, 42}
|
||||
_, err = p.GetBytesHex()
|
||||
require.NotNil(t, err)
|
||||
|
||||
p = Param{stringT, "qq2c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7"}
|
||||
p = Param{StringT, "qq2c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7"}
|
||||
_, err = p.GetBytesHex()
|
||||
require.NotNil(t, err)
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package rpc
|
||||
package request
|
||||
|
||||
type (
|
||||
// Params represents the JSON-RPC params.
|
|
@ -1,4 +1,4 @@
|
|||
package rpc
|
||||
package request
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
|
@ -1,4 +1,4 @@
|
|||
package rpc
|
||||
package request
|
||||
|
||||
import (
|
||||
"encoding/json"
|
84
pkg/rpc/request/types.go
Normal file
84
pkg/rpc/request/types.go
Normal file
|
@ -0,0 +1,84 @@
|
|||
package request
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
// JSONRPCVersion is the only JSON-RPC protocol version supported.
|
||||
JSONRPCVersion = "2.0"
|
||||
)
|
||||
|
||||
// RawParams is just a slice of abstract values, used to represent parameters
|
||||
// passed from client to server.
|
||||
type RawParams struct {
|
||||
Values []interface{}
|
||||
}
|
||||
|
||||
// NewRawParams creates RawParams from its parameters.
|
||||
func NewRawParams(vals ...interface{}) RawParams {
|
||||
p := RawParams{}
|
||||
p.Values = make([]interface{}, len(vals))
|
||||
for i := 0; i < len(p.Values); i++ {
|
||||
p.Values[i] = vals[i]
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// Raw represents JSON-RPC request.
|
||||
type Raw struct {
|
||||
JSONRPC string `json:"jsonrpc"`
|
||||
Method string `json:"method"`
|
||||
RawParams []interface{} `json:"params"`
|
||||
ID int `json:"id"`
|
||||
}
|
||||
|
||||
// In represents a standard JSON-RPC 2.0
|
||||
// request: http://www.jsonrpc.org/specification#request_object. It's used in
|
||||
// server to represent incoming queries.
|
||||
type In struct {
|
||||
JSONRPC string `json:"jsonrpc"`
|
||||
Method string `json:"method"`
|
||||
RawParams json.RawMessage `json:"params,omitempty"`
|
||||
RawID json.RawMessage `json:"id,omitempty"`
|
||||
}
|
||||
|
||||
// NewIn creates a new Request struct.
|
||||
func NewIn() *In {
|
||||
return &In{
|
||||
JSONRPC: JSONRPCVersion,
|
||||
}
|
||||
}
|
||||
|
||||
// DecodeData decodes the given reader into the the request
|
||||
// struct.
|
||||
func (r *In) DecodeData(data io.ReadCloser) error {
|
||||
defer data.Close()
|
||||
|
||||
err := json.NewDecoder(data).Decode(r)
|
||||
if err != nil {
|
||||
return errors.Errorf("error parsing JSON payload: %s", err)
|
||||
}
|
||||
|
||||
if r.JSONRPC != JSONRPCVersion {
|
||||
return errors.Errorf("invalid version, expected 2.0 got: '%s'", r.JSONRPC)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Params takes a slice of any type and attempts to bind
|
||||
// the params to it.
|
||||
func (r *In) Params() (*Params, error) {
|
||||
params := Params{}
|
||||
|
||||
err := json.Unmarshal(r.RawParams, ¶ms)
|
||||
if err != nil {
|
||||
return nil, errors.Errorf("error parsing params field in payload: %s", err)
|
||||
}
|
||||
|
||||
return ¶ms, nil
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package rpc
|
||||
package response
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
@ -18,10 +18,13 @@ type (
|
|||
)
|
||||
|
||||
var (
|
||||
errInvalidParams = NewInvalidParamsError("", nil)
|
||||
// ErrInvalidParams represents a generic 'invalid parameters' error.
|
||||
ErrInvalidParams = NewInvalidParamsError("", nil)
|
||||
)
|
||||
|
||||
func newError(code int64, httpCode int, message string, data string, cause error) *Error {
|
||||
// NewError is an Error constructor that takes Error contents from its
|
||||
// parameters.
|
||||
func NewError(code int64, httpCode int, message string, data string, cause error) *Error {
|
||||
return &Error{
|
||||
Code: code,
|
||||
HTTPCode: httpCode,
|
||||
|
@ -35,40 +38,40 @@ func newError(code int64, httpCode int, message string, data string, cause error
|
|||
// NewParseError creates a new error with code
|
||||
// -32700.:%s
|
||||
func NewParseError(data string, cause error) *Error {
|
||||
return newError(-32700, http.StatusBadRequest, "Parse Error", data, cause)
|
||||
return NewError(-32700, http.StatusBadRequest, "Parse Error", data, cause)
|
||||
}
|
||||
|
||||
// NewInvalidRequestError creates a new error with
|
||||
// code -32600.
|
||||
func NewInvalidRequestError(data string, cause error) *Error {
|
||||
return newError(-32600, http.StatusUnprocessableEntity, "Invalid Request", data, cause)
|
||||
return NewError(-32600, http.StatusUnprocessableEntity, "Invalid Request", data, cause)
|
||||
}
|
||||
|
||||
// NewMethodNotFoundError creates a new error with
|
||||
// code -32601.
|
||||
func NewMethodNotFoundError(data string, cause error) *Error {
|
||||
return newError(-32601, http.StatusMethodNotAllowed, "Method not found", data, cause)
|
||||
return NewError(-32601, http.StatusMethodNotAllowed, "Method not found", data, cause)
|
||||
}
|
||||
|
||||
// NewInvalidParamsError creates a new error with
|
||||
// code -32602.
|
||||
func NewInvalidParamsError(data string, cause error) *Error {
|
||||
return newError(-32602, http.StatusUnprocessableEntity, "Invalid Params", data, cause)
|
||||
return NewError(-32602, http.StatusUnprocessableEntity, "Invalid Params", data, cause)
|
||||
}
|
||||
|
||||
// NewInternalServerError creates a new error with
|
||||
// code -32603.
|
||||
func NewInternalServerError(data string, cause error) *Error {
|
||||
return newError(-32603, http.StatusInternalServerError, "Internal error", data, cause)
|
||||
return NewError(-32603, http.StatusInternalServerError, "Internal error", data, cause)
|
||||
}
|
||||
|
||||
// NewRPCError creates a new error with
|
||||
// code -100
|
||||
func NewRPCError(message string, data string, cause error) *Error {
|
||||
return newError(-100, http.StatusUnprocessableEntity, message, data, cause)
|
||||
return NewError(-100, http.StatusUnprocessableEntity, message, data, cause)
|
||||
}
|
||||
|
||||
// Error implements the error interface.
|
||||
func (e Error) Error() string {
|
||||
func (e *Error) Error() string {
|
||||
return fmt.Sprintf("%s (%d) - %s - %s", e.Message, e.Code, e.Data, e.Cause)
|
||||
}
|
|
@ -1,15 +1,17 @@
|
|||
package rpc
|
||||
package response
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
||||
"github.com/CityOfZion/neo-go/pkg/rpc/request"
|
||||
"github.com/CityOfZion/neo-go/pkg/rpc/response/result"
|
||||
"github.com/CityOfZion/neo-go/pkg/vm"
|
||||
)
|
||||
|
||||
// InvokeScriptResponse stores response for the invoke script call.
|
||||
type InvokeScriptResponse struct {
|
||||
responseHeader
|
||||
Error *Error `json:"error,omitempty"`
|
||||
// InvokeScript stores response for the invoke script call.
|
||||
type InvokeScript struct {
|
||||
HeaderAndError
|
||||
Result *InvokeResult `json:"result,omitempty"`
|
||||
}
|
||||
|
||||
|
@ -19,19 +21,18 @@ type InvokeResult struct {
|
|||
State vm.State `json:"state"`
|
||||
GasConsumed string `json:"gas_consumed"`
|
||||
Script string `json:"script"`
|
||||
Stack []StackParam
|
||||
Stack []request.StackParam
|
||||
}
|
||||
|
||||
// AccountStateResponse holds the getaccountstate response.
|
||||
type AccountStateResponse struct {
|
||||
responseHeader
|
||||
// AccountState holds the getaccountstate response.
|
||||
type AccountState struct {
|
||||
Header
|
||||
Result *Account `json:"result"`
|
||||
}
|
||||
|
||||
// UnspentResponse represents server response to the `getunspents` command.
|
||||
type UnspentResponse struct {
|
||||
responseHeader
|
||||
Error *Error `json:"error,omitempty"`
|
||||
// Unspent represents server response to the `getunspents` command.
|
||||
type Unspent struct {
|
||||
HeaderAndError
|
||||
Result *result.Unspents `json:"result,omitempty"`
|
||||
}
|
||||
|
||||
|
@ -51,68 +52,54 @@ type Balance struct {
|
|||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
type params struct {
|
||||
values []interface{}
|
||||
// Header is a generic JSON-RPC 2.0 response header (ID and JSON-RPC version).
|
||||
type Header struct {
|
||||
ID json.RawMessage `json:"id"`
|
||||
JSONRPC string `json:"jsonrpc"`
|
||||
}
|
||||
|
||||
func newParams(vals ...interface{}) params {
|
||||
p := params{}
|
||||
p.values = make([]interface{}, len(vals))
|
||||
for i := 0; i < len(p.values); i++ {
|
||||
p.values[i] = vals[i]
|
||||
}
|
||||
return p
|
||||
// HeaderAndError adds an Error (that can be empty) to the Header, it's used
|
||||
// to construct type-specific responses.
|
||||
type HeaderAndError struct {
|
||||
Header
|
||||
Error *Error `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
type request struct {
|
||||
JSONRPC string `json:"jsonrpc"`
|
||||
Method string `json:"method"`
|
||||
Params []interface{} `json:"params"`
|
||||
ID int `json:"id"`
|
||||
// Raw represents a standard raw JSON-RPC 2.0
|
||||
// response: http://www.jsonrpc.org/specification#response_object.
|
||||
type Raw struct {
|
||||
HeaderAndError
|
||||
Result interface{} `json:"result,omitempty"`
|
||||
}
|
||||
|
||||
type responseHeader struct {
|
||||
ID int `json:"id"`
|
||||
JSONRPC string `json:"jsonrpc"`
|
||||
// SendToAddress stores response for the sendtoaddress call.
|
||||
type SendToAddress struct {
|
||||
HeaderAndError
|
||||
Result *Tx
|
||||
}
|
||||
|
||||
type response struct {
|
||||
responseHeader
|
||||
Error *Error `json:"error"`
|
||||
Result interface{} `json:"result"`
|
||||
}
|
||||
|
||||
// SendToAddressResponse stores response for the sendtoaddress call.
|
||||
type SendToAddressResponse struct {
|
||||
responseHeader
|
||||
Error *Error `json:"error"`
|
||||
Result *TxResponse
|
||||
}
|
||||
|
||||
// GetRawTxResponse represents verbose output of `getrawtransaction` RPC call.
|
||||
type GetRawTxResponse struct {
|
||||
responseHeader
|
||||
Error *Error `json:"error"`
|
||||
Result *RawTxResponse `json:"result"`
|
||||
}
|
||||
|
||||
// GetTxOutResponse represents result of `gettxout` RPC call.
|
||||
type GetTxOutResponse struct {
|
||||
responseHeader
|
||||
Error *Error
|
||||
// GetTxOut represents result of `gettxout` RPC call.
|
||||
type GetTxOut struct {
|
||||
HeaderAndError
|
||||
Result *result.TransactionOutput
|
||||
}
|
||||
|
||||
// RawTxResponse stores transaction with blockchain metadata to be sent as a response.
|
||||
type RawTxResponse struct {
|
||||
TxResponse
|
||||
// GetRawTx represents verbose output of `getrawtransaction` RPC call.
|
||||
type GetRawTx struct {
|
||||
HeaderAndError
|
||||
Result *RawTx `json:"result"`
|
||||
}
|
||||
|
||||
// RawTx stores transaction with blockchain metadata to be sent as a response.
|
||||
type RawTx struct {
|
||||
Tx
|
||||
BlockHash string `json:"blockhash"`
|
||||
Confirmations uint `json:"confirmations"`
|
||||
BlockTime uint `json:"blocktime"`
|
||||
}
|
||||
|
||||
// TxResponse stores transaction to be sent as a response.
|
||||
type TxResponse struct {
|
||||
// Tx stores transaction to be sent as a response.
|
||||
type Tx struct {
|
||||
TxID string `json:"txid"`
|
||||
Size int `json:"size"`
|
||||
Type string `json:"type"` // todo: convert to TransactionType
|
|
@ -7,6 +7,8 @@ import (
|
|||
"github.com/CityOfZion/neo-go/pkg/core"
|
||||
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
||||
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
||||
"github.com/CityOfZion/neo-go/pkg/rpc/request"
|
||||
"github.com/CityOfZion/neo-go/pkg/rpc/response"
|
||||
"github.com/CityOfZion/neo-go/pkg/smartcontract"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/pkg/errors"
|
||||
|
@ -17,11 +19,11 @@ import (
|
|||
// missing output wrapper at the moment, thus commented out
|
||||
// func (c *Client) getBlock(indexOrHash interface{}, verbose bool) (*response, error) {
|
||||
// var (
|
||||
// params = newParams(indexOrHash)
|
||||
// params = request.NewRawParams(indexOrHash)
|
||||
// resp = &response{}
|
||||
// )
|
||||
// if verbose {
|
||||
// params = newParams(indexOrHash, 1)
|
||||
// params = request.NewRawParams(indexOrHash, 1)
|
||||
// }
|
||||
// if err := c.performRequest("getblock", params, resp); err != nil {
|
||||
// return nil, err
|
||||
|
@ -30,10 +32,10 @@ import (
|
|||
// }
|
||||
|
||||
// GetAccountState returns detailed information about a NEO account.
|
||||
func (c *Client) GetAccountState(address string) (*AccountStateResponse, error) {
|
||||
func (c *Client) GetAccountState(address string) (*response.AccountState, error) {
|
||||
var (
|
||||
params = newParams(address)
|
||||
resp = &AccountStateResponse{}
|
||||
params = request.NewRawParams(address)
|
||||
resp = &response.AccountState{}
|
||||
)
|
||||
if err := c.performRequest("getaccountstate", params, resp); err != nil {
|
||||
return nil, err
|
||||
|
@ -42,10 +44,10 @@ func (c *Client) GetAccountState(address string) (*AccountStateResponse, error)
|
|||
}
|
||||
|
||||
// GetUnspents returns UTXOs for the given NEO account.
|
||||
func (c *Client) GetUnspents(address string) (*UnspentResponse, error) {
|
||||
func (c *Client) GetUnspents(address string) (*response.Unspent, error) {
|
||||
var (
|
||||
params = newParams(address)
|
||||
resp = &UnspentResponse{}
|
||||
params = request.NewRawParams(address)
|
||||
resp = &response.Unspent{}
|
||||
)
|
||||
if err := c.performRequest("getunspents", params, resp); err != nil {
|
||||
return nil, err
|
||||
|
@ -55,10 +57,10 @@ func (c *Client) GetUnspents(address string) (*UnspentResponse, error) {
|
|||
|
||||
// InvokeScript returns the result of the given script after running it true the VM.
|
||||
// NOTE: This is a test invoke and will not affect the blockchain.
|
||||
func (c *Client) InvokeScript(script string) (*InvokeScriptResponse, error) {
|
||||
func (c *Client) InvokeScript(script string) (*response.InvokeScript, error) {
|
||||
var (
|
||||
params = newParams(script)
|
||||
resp = &InvokeScriptResponse{}
|
||||
params = request.NewRawParams(script)
|
||||
resp = &response.InvokeScript{}
|
||||
)
|
||||
if err := c.performRequest("invokescript", params, resp); err != nil {
|
||||
return nil, err
|
||||
|
@ -69,10 +71,10 @@ func (c *Client) InvokeScript(script string) (*InvokeScriptResponse, error) {
|
|||
// InvokeFunction returns the results after calling the smart contract scripthash
|
||||
// with the given operation and parameters.
|
||||
// NOTE: this is test invoke and will not affect the blockchain.
|
||||
func (c *Client) InvokeFunction(script, operation string, params []smartcontract.Parameter) (*InvokeScriptResponse, error) {
|
||||
func (c *Client) InvokeFunction(script, operation string, params []smartcontract.Parameter) (*response.InvokeScript, error) {
|
||||
var (
|
||||
p = newParams(script, operation, params)
|
||||
resp = &InvokeScriptResponse{}
|
||||
p = request.NewRawParams(script, operation, params)
|
||||
resp = &response.InvokeScript{}
|
||||
)
|
||||
if err := c.performRequest("invokefunction", p, resp); err != nil {
|
||||
return nil, err
|
||||
|
@ -82,10 +84,10 @@ func (c *Client) InvokeFunction(script, operation string, params []smartcontract
|
|||
|
||||
// Invoke returns the results after calling the smart contract scripthash
|
||||
// with the given parameters.
|
||||
func (c *Client) Invoke(script string, params []smartcontract.Parameter) (*InvokeScriptResponse, error) {
|
||||
func (c *Client) Invoke(script string, params []smartcontract.Parameter) (*response.InvokeScript, error) {
|
||||
var (
|
||||
p = newParams(script, params)
|
||||
resp = &InvokeScriptResponse{}
|
||||
p = request.NewRawParams(script, params)
|
||||
resp = &response.InvokeScript{}
|
||||
)
|
||||
if err := c.performRequest("invoke", p, resp); err != nil {
|
||||
return nil, err
|
||||
|
@ -97,7 +99,7 @@ func (c *Client) Invoke(script string, params []smartcontract.Parameter) (*Invok
|
|||
// missing output wrapper at the moment, thus commented out
|
||||
// func (c *Client) getRawTransaction(hash string, verbose bool) (*response, error) {
|
||||
// var (
|
||||
// params = newParams(hash, verbose)
|
||||
// params = request.NewRawParams(hash, verbose)
|
||||
// resp = &response{}
|
||||
// )
|
||||
// if err := c.performRequest("getrawtransaction", params, resp); err != nil {
|
||||
|
@ -110,10 +112,10 @@ func (c *Client) Invoke(script string, params []smartcontract.Parameter) (*Invok
|
|||
// The given hex string needs to be signed with a keypair.
|
||||
// When the result of the response object is true, the TX has successfully
|
||||
// been broadcasted to the network.
|
||||
func (c *Client) sendRawTransaction(rawTX *transaction.Transaction) (*response, error) {
|
||||
func (c *Client) sendRawTransaction(rawTX *transaction.Transaction) (*response.Raw, error) {
|
||||
var (
|
||||
params = newParams(hex.EncodeToString(rawTX.Bytes()))
|
||||
resp = &response{}
|
||||
params = request.NewRawParams(hex.EncodeToString(rawTX.Bytes()))
|
||||
resp = &response.Raw{}
|
||||
)
|
||||
if err := c.performRequest("sendrawtransaction", params, resp); err != nil {
|
||||
return nil, err
|
||||
|
@ -124,7 +126,7 @@ func (c *Client) sendRawTransaction(rawTX *transaction.Transaction) (*response,
|
|||
// SendToAddress sends an amount of specific asset to a given address.
|
||||
// This call requires open wallet. (`wif` key in client struct.)
|
||||
// If response.Result is `true` then transaction was formed correctly and was written in blockchain.
|
||||
func (c *Client) SendToAddress(asset util.Uint256, address string, amount util.Fixed8) (*SendToAddressResponse, error) {
|
||||
func (c *Client) SendToAddress(asset util.Uint256, address string, amount util.Fixed8) (*response.SendToAddress, error) {
|
||||
var (
|
||||
err error
|
||||
rawTx *transaction.Transaction
|
||||
|
@ -135,23 +137,23 @@ func (c *Client) SendToAddress(asset util.Uint256, address string, amount util.F
|
|||
wif: c.WIF(),
|
||||
balancer: c.Balancer(),
|
||||
}
|
||||
resp *response
|
||||
response = &SendToAddressResponse{}
|
||||
respRaw *response.Raw
|
||||
resp = &response.SendToAddress{}
|
||||
)
|
||||
|
||||
if rawTx, err = CreateRawContractTransaction(txParams); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to create raw transaction for `sendtoaddress`")
|
||||
}
|
||||
if resp, err = c.sendRawTransaction(rawTx); err != nil {
|
||||
if respRaw, err = c.sendRawTransaction(rawTx); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to send raw transaction")
|
||||
}
|
||||
response.Error = resp.Error
|
||||
response.ID = resp.ID
|
||||
response.JSONRPC = resp.JSONRPC
|
||||
response.Result = &TxResponse{
|
||||
resp.Error = respRaw.Error
|
||||
resp.ID = respRaw.ID
|
||||
resp.JSONRPC = respRaw.JSONRPC
|
||||
resp.Result = &response.Tx{
|
||||
TxID: rawTx.Hash().StringLE(),
|
||||
}
|
||||
return response, nil
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// SignAndPushInvocationTx signs and pushes given script as an invocation
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package rpc
|
||||
|
||||
import "github.com/CityOfZion/neo-go/pkg/rpc/request"
|
||||
|
||||
// ContractDetails contains contract metadata.
|
||||
type ContractDetails struct {
|
||||
Author string
|
||||
|
@ -10,6 +12,6 @@ type ContractDetails struct {
|
|||
HasStorage bool
|
||||
HasDynamicInvocation bool
|
||||
IsPayable bool
|
||||
ReturnType StackParamType
|
||||
Parameters []StackParamType
|
||||
ReturnType request.StackParamType
|
||||
Parameters []request.StackParamType
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package rpc
|
|||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
@ -14,6 +15,8 @@ import (
|
|||
"github.com/CityOfZion/neo-go/pkg/encoding/address"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/CityOfZion/neo-go/pkg/network"
|
||||
"github.com/CityOfZion/neo-go/pkg/rpc/request"
|
||||
"github.com/CityOfZion/neo-go/pkg/rpc/response"
|
||||
"github.com/CityOfZion/neo-go/pkg/rpc/response/result"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/pkg/errors"
|
||||
|
@ -71,13 +74,13 @@ func (s *Server) Shutdown() error {
|
|||
}
|
||||
|
||||
func (s *Server) requestHandler(w http.ResponseWriter, httpRequest *http.Request) {
|
||||
req := NewRequest()
|
||||
req := request.NewIn()
|
||||
|
||||
if httpRequest.Method != "POST" {
|
||||
s.WriteErrorResponse(
|
||||
req,
|
||||
w,
|
||||
NewInvalidParamsError(
|
||||
response.NewInvalidParamsError(
|
||||
fmt.Sprintf("Invalid method '%s', please retry with 'POST'", httpRequest.Method), nil,
|
||||
),
|
||||
)
|
||||
|
@ -86,20 +89,20 @@ func (s *Server) requestHandler(w http.ResponseWriter, httpRequest *http.Request
|
|||
|
||||
err := req.DecodeData(httpRequest.Body)
|
||||
if err != nil {
|
||||
s.WriteErrorResponse(req, w, NewParseError("Problem parsing JSON-RPC request body", err))
|
||||
s.WriteErrorResponse(req, w, response.NewParseError("Problem parsing JSON-RPC request body", err))
|
||||
return
|
||||
}
|
||||
|
||||
reqParams, err := req.Params()
|
||||
if err != nil {
|
||||
s.WriteErrorResponse(req, w, NewInvalidParamsError("Problem parsing request parameters", err))
|
||||
s.WriteErrorResponse(req, w, response.NewInvalidParamsError("Problem parsing request parameters", err))
|
||||
return
|
||||
}
|
||||
|
||||
s.methodHandler(w, req, *reqParams)
|
||||
}
|
||||
|
||||
func (s *Server) methodHandler(w http.ResponseWriter, req *Request, reqParams Params) {
|
||||
func (s *Server) methodHandler(w http.ResponseWriter, req *request.In, reqParams request.Params) {
|
||||
s.log.Debug("processing rpc request",
|
||||
zap.String("method", req.Method),
|
||||
zap.String("params", fmt.Sprintf("%v", reqParams)))
|
||||
|
@ -121,33 +124,33 @@ Methods:
|
|||
|
||||
param, ok := reqParams.Value(0)
|
||||
if !ok {
|
||||
resultsErr = errInvalidParams
|
||||
resultsErr = response.ErrInvalidParams
|
||||
break Methods
|
||||
}
|
||||
|
||||
switch param.Type {
|
||||
case stringT:
|
||||
case request.StringT:
|
||||
var err error
|
||||
hash, err = param.GetUint256()
|
||||
if err != nil {
|
||||
resultsErr = errInvalidParams
|
||||
resultsErr = response.ErrInvalidParams
|
||||
break Methods
|
||||
}
|
||||
case numberT:
|
||||
case request.NumberT:
|
||||
num, err := s.blockHeightFromParam(param)
|
||||
if err != nil {
|
||||
resultsErr = errInvalidParams
|
||||
resultsErr = response.ErrInvalidParams
|
||||
break Methods
|
||||
}
|
||||
hash = s.chain.GetHeaderHash(num)
|
||||
default:
|
||||
resultsErr = errInvalidParams
|
||||
resultsErr = response.ErrInvalidParams
|
||||
break Methods
|
||||
}
|
||||
|
||||
block, err := s.chain.GetBlock(hash)
|
||||
if err != nil {
|
||||
resultsErr = NewInternalServerError(fmt.Sprintf("Problem locating block with hash: %s", hash), err)
|
||||
resultsErr = response.NewInternalServerError(fmt.Sprintf("Problem locating block with hash: %s", hash), err)
|
||||
break
|
||||
}
|
||||
|
||||
|
@ -165,14 +168,14 @@ Methods:
|
|||
|
||||
case "getblockhash":
|
||||
getblockHashCalled.Inc()
|
||||
param, ok := reqParams.ValueWithType(0, numberT)
|
||||
param, ok := reqParams.ValueWithType(0, request.NumberT)
|
||||
if !ok {
|
||||
resultsErr = errInvalidParams
|
||||
resultsErr = response.ErrInvalidParams
|
||||
break Methods
|
||||
}
|
||||
num, err := s.blockHeightFromParam(param)
|
||||
if err != nil {
|
||||
resultsErr = errInvalidParams
|
||||
resultsErr = response.ErrInvalidParams
|
||||
break Methods
|
||||
}
|
||||
|
||||
|
@ -206,22 +209,22 @@ Methods:
|
|||
validateaddressCalled.Inc()
|
||||
param, ok := reqParams.Value(0)
|
||||
if !ok {
|
||||
resultsErr = errInvalidParams
|
||||
resultsErr = response.ErrInvalidParams
|
||||
break Methods
|
||||
}
|
||||
results = validateAddress(param.Value)
|
||||
|
||||
case "getassetstate":
|
||||
getassetstateCalled.Inc()
|
||||
param, ok := reqParams.ValueWithType(0, stringT)
|
||||
param, ok := reqParams.ValueWithType(0, request.StringT)
|
||||
if !ok {
|
||||
resultsErr = errInvalidParams
|
||||
resultsErr = response.ErrInvalidParams
|
||||
break Methods
|
||||
}
|
||||
|
||||
paramAssetID, err := param.GetUint256()
|
||||
if err != nil {
|
||||
resultsErr = errInvalidParams
|
||||
resultsErr = response.ErrInvalidParams
|
||||
break
|
||||
}
|
||||
|
||||
|
@ -229,7 +232,7 @@ Methods:
|
|||
if as != nil {
|
||||
results = result.NewAssetState(as)
|
||||
} else {
|
||||
resultsErr = NewRPCError("Unknown asset", "", nil)
|
||||
resultsErr = response.NewRPCError("Unknown asset", "", nil)
|
||||
}
|
||||
|
||||
case "getaccountstate":
|
||||
|
@ -266,7 +269,7 @@ Methods:
|
|||
results, resultsErr = s.sendrawtransaction(reqParams)
|
||||
|
||||
default:
|
||||
resultsErr = NewMethodNotFoundError(fmt.Sprintf("Method '%s' not supported", req.Method), nil)
|
||||
resultsErr = response.NewMethodNotFoundError(fmt.Sprintf("Method '%s' not supported", req.Method), nil)
|
||||
}
|
||||
|
||||
if resultsErr != nil {
|
||||
|
@ -277,27 +280,27 @@ Methods:
|
|||
s.WriteResponse(req, w, results)
|
||||
}
|
||||
|
||||
func (s *Server) getStorage(ps Params) (interface{}, error) {
|
||||
func (s *Server) getStorage(ps request.Params) (interface{}, error) {
|
||||
param, ok := ps.Value(0)
|
||||
if !ok {
|
||||
return nil, errInvalidParams
|
||||
return nil, response.ErrInvalidParams
|
||||
}
|
||||
|
||||
scriptHash, err := param.GetUint160FromHex()
|
||||
if err != nil {
|
||||
return nil, errInvalidParams
|
||||
return nil, response.ErrInvalidParams
|
||||
}
|
||||
|
||||
scriptHash = scriptHash.Reverse()
|
||||
|
||||
param, ok = ps.Value(1)
|
||||
if !ok {
|
||||
return nil, errInvalidParams
|
||||
return nil, response.ErrInvalidParams
|
||||
}
|
||||
|
||||
key, err := param.GetBytesHex()
|
||||
if err != nil {
|
||||
return nil, errInvalidParams
|
||||
return nil, response.ErrInvalidParams
|
||||
}
|
||||
|
||||
item := s.chain.GetStorageItem(scriptHash.Reverse(), key)
|
||||
|
@ -308,22 +311,22 @@ func (s *Server) getStorage(ps Params) (interface{}, error) {
|
|||
return hex.EncodeToString(item.Value), nil
|
||||
}
|
||||
|
||||
func (s *Server) getrawtransaction(reqParams Params) (interface{}, error) {
|
||||
func (s *Server) getrawtransaction(reqParams request.Params) (interface{}, error) {
|
||||
var resultsErr error
|
||||
var results interface{}
|
||||
|
||||
if param0, ok := reqParams.Value(0); !ok {
|
||||
return nil, errInvalidParams
|
||||
return nil, response.ErrInvalidParams
|
||||
} else if txHash, err := param0.GetUint256(); err != nil {
|
||||
resultsErr = errInvalidParams
|
||||
resultsErr = response.ErrInvalidParams
|
||||
} else if tx, height, err := s.chain.GetTransaction(txHash); err != nil {
|
||||
err = errors.Wrapf(err, "Invalid transaction hash: %s", txHash)
|
||||
return nil, NewRPCError("Unknown transaction", err.Error(), err)
|
||||
return nil, response.NewRPCError("Unknown transaction", err.Error(), err)
|
||||
} else if len(reqParams) >= 2 {
|
||||
_header := s.chain.GetHeaderHash(int(height))
|
||||
header, err := s.chain.GetHeader(_header)
|
||||
if err != nil {
|
||||
resultsErr = NewInvalidParamsError(err.Error(), err)
|
||||
resultsErr = response.NewInvalidParamsError(err.Error(), err)
|
||||
}
|
||||
|
||||
param1, _ := reqParams.Value(1)
|
||||
|
@ -345,34 +348,34 @@ func (s *Server) getrawtransaction(reqParams Params) (interface{}, error) {
|
|||
return results, resultsErr
|
||||
}
|
||||
|
||||
func (s *Server) getTxOut(ps Params) (interface{}, error) {
|
||||
func (s *Server) getTxOut(ps request.Params) (interface{}, error) {
|
||||
p, ok := ps.Value(0)
|
||||
if !ok {
|
||||
return nil, errInvalidParams
|
||||
return nil, response.ErrInvalidParams
|
||||
}
|
||||
|
||||
h, err := p.GetUint256()
|
||||
if err != nil {
|
||||
return nil, errInvalidParams
|
||||
return nil, response.ErrInvalidParams
|
||||
}
|
||||
|
||||
p, ok = ps.ValueWithType(1, numberT)
|
||||
p, ok = ps.ValueWithType(1, request.NumberT)
|
||||
if !ok {
|
||||
return nil, errInvalidParams
|
||||
return nil, response.ErrInvalidParams
|
||||
}
|
||||
|
||||
num, err := p.GetInt()
|
||||
if err != nil || num < 0 {
|
||||
return nil, errInvalidParams
|
||||
return nil, response.ErrInvalidParams
|
||||
}
|
||||
|
||||
tx, _, err := s.chain.GetTransaction(h)
|
||||
if err != nil {
|
||||
return nil, NewInvalidParamsError(err.Error(), err)
|
||||
return nil, response.NewInvalidParamsError(err.Error(), err)
|
||||
}
|
||||
|
||||
if num >= len(tx.Outputs) {
|
||||
return nil, NewInvalidParamsError("invalid index", errors.New("too big index"))
|
||||
return nil, response.NewInvalidParamsError("invalid index", errors.New("too big index"))
|
||||
}
|
||||
|
||||
out := tx.Outputs[num]
|
||||
|
@ -380,35 +383,35 @@ func (s *Server) getTxOut(ps Params) (interface{}, error) {
|
|||
}
|
||||
|
||||
// getContractState returns contract state (contract information, according to the contract script hash).
|
||||
func (s *Server) getContractState(reqParams Params) (interface{}, error) {
|
||||
func (s *Server) getContractState(reqParams request.Params) (interface{}, error) {
|
||||
var results interface{}
|
||||
|
||||
param, ok := reqParams.ValueWithType(0, stringT)
|
||||
param, ok := reqParams.ValueWithType(0, request.StringT)
|
||||
if !ok {
|
||||
return nil, errInvalidParams
|
||||
return nil, response.ErrInvalidParams
|
||||
} else if scriptHash, err := param.GetUint160FromHex(); err != nil {
|
||||
return nil, errInvalidParams
|
||||
return nil, response.ErrInvalidParams
|
||||
} else {
|
||||
cs := s.chain.GetContractState(scriptHash)
|
||||
if cs != nil {
|
||||
results = result.NewContractState(cs)
|
||||
} else {
|
||||
return nil, NewRPCError("Unknown contract", "", nil)
|
||||
return nil, response.NewRPCError("Unknown contract", "", nil)
|
||||
}
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
|
||||
// getAccountState returns account state either in short or full (unspents included) form.
|
||||
func (s *Server) getAccountState(reqParams Params, unspents bool) (interface{}, error) {
|
||||
func (s *Server) getAccountState(reqParams request.Params, unspents bool) (interface{}, error) {
|
||||
var resultsErr error
|
||||
var results interface{}
|
||||
|
||||
param, ok := reqParams.ValueWithType(0, stringT)
|
||||
param, ok := reqParams.ValueWithType(0, request.StringT)
|
||||
if !ok {
|
||||
return nil, errInvalidParams
|
||||
return nil, response.ErrInvalidParams
|
||||
} else if scriptHash, err := param.GetUint160FromAddress(); err != nil {
|
||||
return nil, errInvalidParams
|
||||
return nil, response.ErrInvalidParams
|
||||
} else {
|
||||
as := s.chain.GetAccountState(scriptHash)
|
||||
if as == nil {
|
||||
|
@ -417,7 +420,7 @@ func (s *Server) getAccountState(reqParams Params, unspents bool) (interface{},
|
|||
if unspents {
|
||||
str, err := param.GetString()
|
||||
if err != nil {
|
||||
return nil, errInvalidParams
|
||||
return nil, response.ErrInvalidParams
|
||||
}
|
||||
results = result.NewUnspents(as, s.chain, str)
|
||||
} else {
|
||||
|
@ -428,18 +431,18 @@ func (s *Server) getAccountState(reqParams Params, unspents bool) (interface{},
|
|||
}
|
||||
|
||||
// invoke implements the `invoke` RPC call.
|
||||
func (s *Server) invoke(reqParams Params) (interface{}, error) {
|
||||
scriptHashHex, ok := reqParams.ValueWithType(0, stringT)
|
||||
func (s *Server) invoke(reqParams request.Params) (interface{}, error) {
|
||||
scriptHashHex, ok := reqParams.ValueWithType(0, request.StringT)
|
||||
if !ok {
|
||||
return nil, errInvalidParams
|
||||
return nil, response.ErrInvalidParams
|
||||
}
|
||||
scriptHash, err := scriptHashHex.GetUint160FromHex()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sliceP, ok := reqParams.ValueWithType(1, arrayT)
|
||||
sliceP, ok := reqParams.ValueWithType(1, request.ArrayT)
|
||||
if !ok {
|
||||
return nil, errInvalidParams
|
||||
return nil, response.ErrInvalidParams
|
||||
}
|
||||
slice, err := sliceP.GetArray()
|
||||
if err != nil {
|
||||
|
@ -453,10 +456,10 @@ func (s *Server) invoke(reqParams Params) (interface{}, error) {
|
|||
}
|
||||
|
||||
// invokescript implements the `invokescript` RPC call.
|
||||
func (s *Server) invokeFunction(reqParams Params) (interface{}, error) {
|
||||
scriptHashHex, ok := reqParams.ValueWithType(0, stringT)
|
||||
func (s *Server) invokeFunction(reqParams request.Params) (interface{}, error) {
|
||||
scriptHashHex, ok := reqParams.ValueWithType(0, request.StringT)
|
||||
if !ok {
|
||||
return nil, errInvalidParams
|
||||
return nil, response.ErrInvalidParams
|
||||
}
|
||||
scriptHash, err := scriptHashHex.GetUint160FromHex()
|
||||
if err != nil {
|
||||
|
@ -470,14 +473,14 @@ func (s *Server) invokeFunction(reqParams Params) (interface{}, error) {
|
|||
}
|
||||
|
||||
// invokescript implements the `invokescript` RPC call.
|
||||
func (s *Server) invokescript(reqParams Params) (interface{}, error) {
|
||||
func (s *Server) invokescript(reqParams request.Params) (interface{}, error) {
|
||||
if len(reqParams) < 1 {
|
||||
return nil, errInvalidParams
|
||||
return nil, response.ErrInvalidParams
|
||||
}
|
||||
|
||||
script, err := reqParams[0].GetBytesHex()
|
||||
if err != nil {
|
||||
return nil, errInvalidParams
|
||||
return nil, response.ErrInvalidParams
|
||||
}
|
||||
|
||||
return s.runScriptInVM(script), nil
|
||||
|
@ -499,14 +502,14 @@ func (s *Server) runScriptInVM(script []byte) *result.Invoke {
|
|||
return result
|
||||
}
|
||||
|
||||
func (s *Server) sendrawtransaction(reqParams Params) (interface{}, error) {
|
||||
func (s *Server) sendrawtransaction(reqParams request.Params) (interface{}, error) {
|
||||
var resultsErr error
|
||||
var results interface{}
|
||||
|
||||
if len(reqParams) < 1 {
|
||||
return nil, errInvalidParams
|
||||
return nil, response.ErrInvalidParams
|
||||
} else if byteTx, err := reqParams[0].GetBytesHex(); err != nil {
|
||||
return nil, errInvalidParams
|
||||
return nil, response.ErrInvalidParams
|
||||
} else {
|
||||
r := io.NewBinReaderFromBuf(byteTx)
|
||||
tx := &transaction.Transaction{}
|
||||
|
@ -533,14 +536,14 @@ func (s *Server) sendrawtransaction(reqParams Params) (interface{}, error) {
|
|||
}
|
||||
}
|
||||
if err != nil {
|
||||
resultsErr = NewInternalServerError(err.Error(), err)
|
||||
resultsErr = response.NewInternalServerError(err.Error(), err)
|
||||
}
|
||||
}
|
||||
|
||||
return results, resultsErr
|
||||
}
|
||||
|
||||
func (s *Server) blockHeightFromParam(param *Param) (int, error) {
|
||||
func (s *Server) blockHeightFromParam(param *request.Param) (int, error) {
|
||||
num, err := param.GetInt()
|
||||
if err != nil {
|
||||
return 0, nil
|
||||
|
@ -552,6 +555,71 @@ func (s *Server) blockHeightFromParam(param *Param) (int, error) {
|
|||
return num, nil
|
||||
}
|
||||
|
||||
// WriteErrorResponse writes an error response to the ResponseWriter.
|
||||
func (s *Server) WriteErrorResponse(r *request.In, w http.ResponseWriter, err error) {
|
||||
jsonErr, ok := err.(*response.Error)
|
||||
if !ok {
|
||||
jsonErr = response.NewInternalServerError("Internal server error", err)
|
||||
}
|
||||
|
||||
resp := response.Raw{
|
||||
HeaderAndError: response.HeaderAndError{
|
||||
Header: response.Header{
|
||||
JSONRPC: r.JSONRPC,
|
||||
ID: r.RawID,
|
||||
},
|
||||
Error: jsonErr,
|
||||
},
|
||||
}
|
||||
|
||||
logFields := []zap.Field{
|
||||
zap.Error(jsonErr.Cause),
|
||||
zap.String("method", r.Method),
|
||||
}
|
||||
|
||||
params, err := r.Params()
|
||||
if err == nil {
|
||||
logFields = append(logFields, zap.Any("params", params))
|
||||
}
|
||||
|
||||
s.log.Error("Error encountered with rpc request", logFields...)
|
||||
|
||||
w.WriteHeader(jsonErr.HTTPCode)
|
||||
s.writeServerResponse(r, w, resp)
|
||||
}
|
||||
|
||||
// WriteResponse encodes the response and writes it to the ResponseWriter.
|
||||
func (s *Server) WriteResponse(r *request.In, w http.ResponseWriter, result interface{}) {
|
||||
resp := response.Raw{
|
||||
HeaderAndError: response.HeaderAndError{
|
||||
Header: response.Header{
|
||||
JSONRPC: r.JSONRPC,
|
||||
ID: r.RawID,
|
||||
},
|
||||
},
|
||||
Result: result,
|
||||
}
|
||||
|
||||
s.writeServerResponse(r, w, resp)
|
||||
}
|
||||
|
||||
func (s *Server) writeServerResponse(r *request.In, w http.ResponseWriter, resp response.Raw) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
if s.config.EnableCORSWorkaround {
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With")
|
||||
}
|
||||
|
||||
encoder := json.NewEncoder(w)
|
||||
err := encoder.Encode(resp)
|
||||
|
||||
if err != nil {
|
||||
s.log.Error("Error encountered while encoding response",
|
||||
zap.String("err", err.Error()),
|
||||
zap.String("method", r.Method))
|
||||
}
|
||||
}
|
||||
|
||||
// validateAddress verifies that the address is a correct NEO address
|
||||
// see https://docs.neo.org/en-us/node/cli/2.9.4/api/validateaddress.html
|
||||
func validateAddress(addr interface{}) result.ValidateAddress {
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"github.com/CityOfZion/neo-go/pkg/core/storage"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/CityOfZion/neo-go/pkg/network"
|
||||
"github.com/CityOfZion/neo-go/pkg/rpc/request"
|
||||
"github.com/CityOfZion/neo-go/pkg/rpc/response/result"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -38,11 +39,11 @@ type SendTXResponse struct {
|
|||
type InvokeFunctionResponse struct {
|
||||
Jsonrpc string `json:"jsonrpc"`
|
||||
Result struct {
|
||||
Script string `json:"script"`
|
||||
State string `json:"state"`
|
||||
GasConsumed string `json:"gas_consumed"`
|
||||
Stack []FuncParam `json:"stack"`
|
||||
TX string `json:"tx,omitempty"`
|
||||
Script string `json:"script"`
|
||||
State string `json:"state"`
|
||||
GasConsumed string `json:"gas_consumed"`
|
||||
Stack []request.FuncParam `json:"stack"`
|
||||
TX string `json:"tx,omitempty"`
|
||||
} `json:"result"`
|
||||
ID int `json:"id"`
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import (
|
|||
|
||||
"github.com/CityOfZion/neo-go/pkg/core"
|
||||
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
||||
"github.com/CityOfZion/neo-go/pkg/rpc/response"
|
||||
"github.com/CityOfZion/neo-go/pkg/rpc/response/result"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
@ -602,7 +603,7 @@ func TestRPC(t *testing.T) {
|
|||
body := doRPCCall(rpc, handler, t)
|
||||
checkErrResponse(t, body, false)
|
||||
|
||||
var result GetTxOutResponse
|
||||
var result response.GetTxOut
|
||||
err := json.Unmarshal(body, &result)
|
||||
require.NoErrorf(t, err, "could not parse response: %s", body)
|
||||
assert.Equal(t, 0, result.Result.N)
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
||||
"github.com/CityOfZion/neo-go/pkg/encoding/address"
|
||||
"github.com/CityOfZion/neo-go/pkg/io"
|
||||
"github.com/CityOfZion/neo-go/pkg/rpc/request"
|
||||
"github.com/CityOfZion/neo-go/pkg/smartcontract"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/CityOfZion/neo-go/pkg/vm/emit"
|
||||
|
@ -141,38 +142,38 @@ func CreateDeploymentScript(avm []byte, contract *ContractDetails) ([]byte, erro
|
|||
|
||||
// expandArrayIntoScript pushes all FuncParam parameters from the given array
|
||||
// into the given buffer in reverse order.
|
||||
func expandArrayIntoScript(script *io.BinWriter, slice []Param) error {
|
||||
func expandArrayIntoScript(script *io.BinWriter, slice []request.Param) error {
|
||||
for j := len(slice) - 1; j >= 0; j-- {
|
||||
fp, err := slice[j].GetFuncParam()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch fp.Type {
|
||||
case ByteArray, Signature:
|
||||
case request.ByteArray, request.Signature:
|
||||
str, err := fp.Value.GetBytesHex()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
emit.Bytes(script, str)
|
||||
case String:
|
||||
case request.String:
|
||||
str, err := fp.Value.GetString()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
emit.String(script, str)
|
||||
case Hash160:
|
||||
case request.Hash160:
|
||||
hash, err := fp.Value.GetUint160FromHex()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
emit.Bytes(script, hash.BytesBE())
|
||||
case Hash256:
|
||||
case request.Hash256:
|
||||
hash, err := fp.Value.GetUint256()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
emit.Bytes(script, hash.BytesBE())
|
||||
case PublicKey:
|
||||
case request.PublicKey:
|
||||
str, err := fp.Value.GetString()
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -182,13 +183,13 @@ func expandArrayIntoScript(script *io.BinWriter, slice []Param) error {
|
|||
return err
|
||||
}
|
||||
emit.Bytes(script, key.Bytes())
|
||||
case Integer:
|
||||
case request.Integer:
|
||||
val, err := fp.Value.GetInt()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
emit.Int(script, int64(val))
|
||||
case Boolean:
|
||||
case request.Boolean:
|
||||
str, err := fp.Value.GetString()
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -210,19 +211,19 @@ func expandArrayIntoScript(script *io.BinWriter, slice []Param) error {
|
|||
|
||||
// CreateFunctionInvocationScript creates a script to invoke given contract with
|
||||
// given parameters.
|
||||
func CreateFunctionInvocationScript(contract util.Uint160, params Params) ([]byte, error) {
|
||||
func CreateFunctionInvocationScript(contract util.Uint160, params request.Params) ([]byte, error) {
|
||||
script := io.NewBufBinWriter()
|
||||
for i := len(params) - 1; i >= 0; i-- {
|
||||
switch params[i].Type {
|
||||
case stringT:
|
||||
case request.StringT:
|
||||
emit.String(script.BinWriter, params[i].String())
|
||||
case numberT:
|
||||
case request.NumberT:
|
||||
num, err := params[i].GetInt()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
emit.String(script.BinWriter, strconv.Itoa(num))
|
||||
case arrayT:
|
||||
case request.ArrayT:
|
||||
slice, err := params[i].GetArray()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -244,7 +245,7 @@ func CreateFunctionInvocationScript(contract util.Uint160, params Params) ([]byt
|
|||
// given parameters. It differs from CreateFunctionInvocationScript in that it
|
||||
// expects one array of FuncParams and expands it onto the stack as independent
|
||||
// elements.
|
||||
func CreateInvocationScript(contract util.Uint160, funcParams []Param) ([]byte, error) {
|
||||
func CreateInvocationScript(contract util.Uint160, funcParams []request.Param) ([]byte, error) {
|
||||
script := io.NewBufBinWriter()
|
||||
err := expandArrayIntoScript(script.BinWriter, funcParams)
|
||||
if err != nil {
|
||||
|
|
|
@ -4,56 +4,57 @@ import (
|
|||
"encoding/hex"
|
||||
"testing"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/rpc/request"
|
||||
"github.com/CityOfZion/neo-go/pkg/util"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestInvocationScriptCreationGood(t *testing.T) {
|
||||
p := Param{stringT, "50befd26fdf6e4d957c11e078b24ebce6291456f"}
|
||||
p := request.Param{Type: request.StringT, Value: "50befd26fdf6e4d957c11e078b24ebce6291456f"}
|
||||
contract, err := p.GetUint160FromHex()
|
||||
require.Nil(t, err)
|
||||
|
||||
var paramScripts = []struct {
|
||||
ps Params
|
||||
ps request.Params
|
||||
script string
|
||||
}{{
|
||||
script: "676f459162ceeb248b071ec157d9e4f6fd26fdbe50",
|
||||
}, {
|
||||
ps: Params{{stringT, "transfer"}},
|
||||
ps: request.Params{{Type: request.StringT, Value: "transfer"}},
|
||||
script: "087472616e73666572676f459162ceeb248b071ec157d9e4f6fd26fdbe50",
|
||||
}, {
|
||||
ps: Params{{numberT, 42}},
|
||||
ps: request.Params{{Type: request.NumberT, Value: 42}},
|
||||
script: "023432676f459162ceeb248b071ec157d9e4f6fd26fdbe50",
|
||||
}, {
|
||||
ps: Params{{stringT, "a"}, {arrayT, []Param{}}},
|
||||
ps: request.Params{{Type: request.StringT, Value: "a"}, {Type: request.ArrayT, Value: []request.Param{}}},
|
||||
script: "00c10161676f459162ceeb248b071ec157d9e4f6fd26fdbe50",
|
||||
}, {
|
||||
ps: Params{{stringT, "a"}, {arrayT, []Param{{funcParamT, FuncParam{ByteArray, Param{stringT, "50befd26fdf6e4d957c11e078b24ebce6291456f"}}}}}},
|
||||
ps: request.Params{{Type: request.StringT, Value: "a"}, {Type: request.ArrayT, Value: []request.Param{{Type: request.FuncParamT, Value: request.FuncParam{Type: request.ByteArray, Value: request.Param{Type: request.StringT, Value: "50befd26fdf6e4d957c11e078b24ebce6291456f"}}}}}},
|
||||
script: "1450befd26fdf6e4d957c11e078b24ebce6291456f51c10161676f459162ceeb248b071ec157d9e4f6fd26fdbe50",
|
||||
}, {
|
||||
ps: Params{{stringT, "a"}, {arrayT, []Param{{funcParamT, FuncParam{Signature, Param{stringT, "4edf5005771de04619235d5a4c7a9a11bb78e008541f1da7725f654c33380a3c87e2959a025da706d7255cb3a3fa07ebe9c6559d0d9e6213c68049168eb1056f"}}}}}},
|
||||
ps: request.Params{{Type: request.StringT, Value: "a"}, {Type: request.ArrayT, Value: []request.Param{{Type: request.FuncParamT, Value: request.FuncParam{Type: request.Signature, Value: request.Param{Type: request.StringT, Value: "4edf5005771de04619235d5a4c7a9a11bb78e008541f1da7725f654c33380a3c87e2959a025da706d7255cb3a3fa07ebe9c6559d0d9e6213c68049168eb1056f"}}}}}},
|
||||
script: "404edf5005771de04619235d5a4c7a9a11bb78e008541f1da7725f654c33380a3c87e2959a025da706d7255cb3a3fa07ebe9c6559d0d9e6213c68049168eb1056f51c10161676f459162ceeb248b071ec157d9e4f6fd26fdbe50",
|
||||
}, {
|
||||
ps: Params{{stringT, "a"}, {arrayT, []Param{{funcParamT, FuncParam{String, Param{stringT, "50befd26fdf6e4d957c11e078b24ebce6291456f"}}}}}},
|
||||
ps: request.Params{{Type: request.StringT, Value: "a"}, {Type: request.ArrayT, Value: []request.Param{{Type: request.FuncParamT, Value: request.FuncParam{Type: request.String, Value: request.Param{Type: request.StringT, Value: "50befd26fdf6e4d957c11e078b24ebce6291456f"}}}}}},
|
||||
script: "283530626566643236666466366534643935376331316530373862323465626365363239313435366651c10161676f459162ceeb248b071ec157d9e4f6fd26fdbe50",
|
||||
}, {
|
||||
ps: Params{{stringT, "a"}, {arrayT, []Param{{funcParamT, FuncParam{Hash160, Param{stringT, "50befd26fdf6e4d957c11e078b24ebce6291456f"}}}}}},
|
||||
ps: request.Params{{Type: request.StringT, Value: "a"}, {Type: request.ArrayT, Value: []request.Param{{Type: request.FuncParamT, Value: request.FuncParam{Type: request.Hash160, Value: request.Param{Type: request.StringT, Value: "50befd26fdf6e4d957c11e078b24ebce6291456f"}}}}}},
|
||||
script: "146f459162ceeb248b071ec157d9e4f6fd26fdbe5051c10161676f459162ceeb248b071ec157d9e4f6fd26fdbe50",
|
||||
}, {
|
||||
ps: Params{{stringT, "a"}, {arrayT, []Param{{funcParamT, FuncParam{Hash256, Param{stringT, "602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7"}}}}}},
|
||||
ps: request.Params{{Type: request.StringT, Value: "a"}, {Type: request.ArrayT, Value: []request.Param{{Type: request.FuncParamT, Value: request.FuncParam{Type: request.Hash256, Value: request.Param{Type: request.StringT, Value: "602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7"}}}}}},
|
||||
script: "20e72d286979ee6cb1b7e65dfddfb2e384100b8d148e7758de42e4168b71792c6051c10161676f459162ceeb248b071ec157d9e4f6fd26fdbe50",
|
||||
}, {
|
||||
ps: Params{{stringT, "a"}, {arrayT, []Param{{funcParamT, FuncParam{PublicKey, Param{stringT, "03c089d7122b840a4935234e82e26ae5efd0c2acb627239dc9f207311337b6f2c1"}}}}}},
|
||||
ps: request.Params{{Type: request.StringT, Value: "a"}, {Type: request.ArrayT, Value: []request.Param{{Type: request.FuncParamT, Value: request.FuncParam{Type: request.PublicKey, Value: request.Param{Type: request.StringT, Value: "03c089d7122b840a4935234e82e26ae5efd0c2acb627239dc9f207311337b6f2c1"}}}}}},
|
||||
script: "2103c089d7122b840a4935234e82e26ae5efd0c2acb627239dc9f207311337b6f2c151c10161676f459162ceeb248b071ec157d9e4f6fd26fdbe50",
|
||||
}, {
|
||||
ps: Params{{stringT, "a"}, {arrayT, []Param{{funcParamT, FuncParam{Integer, Param{numberT, 42}}}}}},
|
||||
ps: request.Params{{Type: request.StringT, Value: "a"}, {Type: request.ArrayT, Value: []request.Param{{Type: request.FuncParamT, Value: request.FuncParam{Type: request.Integer, Value: request.Param{Type: request.NumberT, Value: 42}}}}}},
|
||||
script: "012a51c10161676f459162ceeb248b071ec157d9e4f6fd26fdbe50",
|
||||
}, {
|
||||
ps: Params{{stringT, "a"}, {arrayT, []Param{{funcParamT, FuncParam{Boolean, Param{stringT, "true"}}}}}},
|
||||
ps: request.Params{{Type: request.StringT, Value: "a"}, {Type: request.ArrayT, Value: []request.Param{{Type: request.FuncParamT, Value: request.FuncParam{Type: request.Boolean, Value: request.Param{Type: request.StringT, Value: "true"}}}}}},
|
||||
script: "5151c10161676f459162ceeb248b071ec157d9e4f6fd26fdbe50",
|
||||
}, {
|
||||
ps: Params{{stringT, "a"}, {arrayT, []Param{{funcParamT, FuncParam{Boolean, Param{stringT, "false"}}}}}},
|
||||
ps: request.Params{{Type: request.StringT, Value: "a"}, {Type: request.ArrayT, Value: []request.Param{{Type: request.FuncParamT, Value: request.FuncParam{Type: request.Boolean, Value: request.Param{Type: request.StringT, Value: "false"}}}}}},
|
||||
script: "0051c10161676f459162ceeb248b071ec157d9e4f6fd26fdbe50",
|
||||
}}
|
||||
for _, ps := range paramScripts {
|
||||
|
@ -66,21 +67,21 @@ func TestInvocationScriptCreationGood(t *testing.T) {
|
|||
func TestInvocationScriptCreationBad(t *testing.T) {
|
||||
contract := util.Uint160{}
|
||||
|
||||
var testParams = []Params{
|
||||
{{numberT, "qwerty"}},
|
||||
{{arrayT, 42}},
|
||||
{{arrayT, []Param{{numberT, 42}}}},
|
||||
{{arrayT, []Param{{funcParamT, FuncParam{ByteArray, Param{stringT, "qwerty"}}}}}},
|
||||
{{arrayT, []Param{{funcParamT, FuncParam{Signature, Param{stringT, "qwerty"}}}}}},
|
||||
{{arrayT, []Param{{funcParamT, FuncParam{String, Param{numberT, 42}}}}}},
|
||||
{{arrayT, []Param{{funcParamT, FuncParam{Hash160, Param{stringT, "qwerty"}}}}}},
|
||||
{{arrayT, []Param{{funcParamT, FuncParam{Hash256, Param{stringT, "qwerty"}}}}}},
|
||||
{{arrayT, []Param{{funcParamT, FuncParam{PublicKey, Param{numberT, 42}}}}}},
|
||||
{{arrayT, []Param{{funcParamT, FuncParam{PublicKey, Param{stringT, "qwerty"}}}}}},
|
||||
{{arrayT, []Param{{funcParamT, FuncParam{Integer, Param{stringT, "qwerty"}}}}}},
|
||||
{{arrayT, []Param{{funcParamT, FuncParam{Boolean, Param{numberT, 42}}}}}},
|
||||
{{arrayT, []Param{{funcParamT, FuncParam{Boolean, Param{stringT, "qwerty"}}}}}},
|
||||
{{arrayT, []Param{{funcParamT, FuncParam{Unknown, Param{}}}}}},
|
||||
var testParams = []request.Params{
|
||||
{{Type: request.NumberT, Value: "qwerty"}},
|
||||
{{Type: request.ArrayT, Value: 42}},
|
||||
{{Type: request.ArrayT, Value: []request.Param{{Type: request.NumberT, Value: 42}}}},
|
||||
{{Type: request.ArrayT, Value: []request.Param{{Type: request.FuncParamT, Value: request.FuncParam{Type: request.ByteArray, Value: request.Param{Type: request.StringT, Value: "qwerty"}}}}}},
|
||||
{{Type: request.ArrayT, Value: []request.Param{{Type: request.FuncParamT, Value: request.FuncParam{Type: request.Signature, Value: request.Param{Type: request.StringT, Value: "qwerty"}}}}}},
|
||||
{{Type: request.ArrayT, Value: []request.Param{{Type: request.FuncParamT, Value: request.FuncParam{Type: request.String, Value: request.Param{Type: request.NumberT, Value: 42}}}}}},
|
||||
{{Type: request.ArrayT, Value: []request.Param{{Type: request.FuncParamT, Value: request.FuncParam{Type: request.Hash160, Value: request.Param{Type: request.StringT, Value: "qwerty"}}}}}},
|
||||
{{Type: request.ArrayT, Value: []request.Param{{Type: request.FuncParamT, Value: request.FuncParam{Type: request.Hash256, Value: request.Param{Type: request.StringT, Value: "qwerty"}}}}}},
|
||||
{{Type: request.ArrayT, Value: []request.Param{{Type: request.FuncParamT, Value: request.FuncParam{Type: request.PublicKey, Value: request.Param{Type: request.NumberT, Value: 42}}}}}},
|
||||
{{Type: request.ArrayT, Value: []request.Param{{Type: request.FuncParamT, Value: request.FuncParam{Type: request.PublicKey, Value: request.Param{Type: request.StringT, Value: "qwerty"}}}}}},
|
||||
{{Type: request.ArrayT, Value: []request.Param{{Type: request.FuncParamT, Value: request.FuncParam{Type: request.Integer, Value: request.Param{Type: request.StringT, Value: "qwerty"}}}}}},
|
||||
{{Type: request.ArrayT, Value: []request.Param{{Type: request.FuncParamT, Value: request.FuncParam{Type: request.Boolean, Value: request.Param{Type: request.NumberT, Value: 42}}}}}},
|
||||
{{Type: request.ArrayT, Value: []request.Param{{Type: request.FuncParamT, Value: request.FuncParam{Type: request.Boolean, Value: request.Param{Type: request.StringT, Value: "qwerty"}}}}}},
|
||||
{{Type: request.ArrayT, Value: []request.Param{{Type: request.FuncParamT, Value: request.FuncParam{Type: request.Unknown, Value: request.Param{}}}}}},
|
||||
}
|
||||
for _, ps := range testParams {
|
||||
_, err := CreateFunctionInvocationScript(contract, ps)
|
||||
|
|
Loading…
Reference in a new issue