forked from TrueCloudLab/neoneo-go
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/hash"
|
||||||
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
||||||
"github.com/CityOfZion/neo-go/pkg/rpc"
|
"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/smartcontract"
|
||||||
"github.com/CityOfZion/neo-go/pkg/util"
|
"github.com/CityOfZion/neo-go/pkg/util"
|
||||||
"github.com/CityOfZion/neo-go/pkg/vm"
|
"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.
|
// TODO: Fix the missing neo-go.yml file with the `init` command when the package manager is in place.
|
||||||
if !ctx.Bool("skip-details") {
|
if !ctx.Bool("skip-details") {
|
||||||
details := parseContractDetails()
|
details := parseContractDetails()
|
||||||
details.ReturnType = rpc.ByteArray
|
details.ReturnType = request.ByteArray
|
||||||
details.Parameters = make([]rpc.StackParamType, 2)
|
details.Parameters = make([]request.StackParamType, 2)
|
||||||
details.Parameters[0] = rpc.String
|
details.Parameters[0] = request.String
|
||||||
details.Parameters[1] = rpc.Array
|
details.Parameters[1] = request.Array
|
||||||
|
|
||||||
project := &ProjectConfig{Contract: details}
|
project := &ProjectConfig{Contract: details}
|
||||||
b, err := yaml.Marshal(project)
|
b, err := yaml.Marshal(project)
|
||||||
|
@ -362,7 +364,7 @@ func invokeInternal(ctx *cli.Context, withMethod bool, signAndPush bool) error {
|
||||||
operation string
|
operation string
|
||||||
params = make([]smartcontract.Parameter, 0)
|
params = make([]smartcontract.Parameter, 0)
|
||||||
paramsStart = 1
|
paramsStart = 1
|
||||||
resp *rpc.InvokeScriptResponse
|
resp *response.InvokeScript
|
||||||
wif *keys.WIF
|
wif *keys.WIF
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ import (
|
||||||
"github.com/CityOfZion/neo-go/pkg/core/state"
|
"github.com/CityOfZion/neo-go/pkg/core/state"
|
||||||
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
||||||
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
"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/CityOfZion/neo-go/pkg/util"
|
||||||
"github.com/pkg/errors"
|
"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 (
|
var (
|
||||||
r = request{
|
r = request.Raw{
|
||||||
JSONRPC: c.version,
|
JSONRPC: c.version,
|
||||||
Method: method,
|
Method: method,
|
||||||
Params: p.values,
|
RawParams: p.Values,
|
||||||
ID: 1,
|
ID: 1,
|
||||||
}
|
}
|
||||||
buf = new(bytes.Buffer)
|
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 (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
@ -29,12 +29,13 @@ type (
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// These are parameter types accepted by RPC server.
|
||||||
const (
|
const (
|
||||||
defaultT paramType = iota
|
defaultT paramType = iota
|
||||||
stringT
|
StringT
|
||||||
numberT
|
NumberT
|
||||||
arrayT
|
ArrayT
|
||||||
funcParamT
|
FuncParamT
|
||||||
)
|
)
|
||||||
|
|
||||||
func (p Param) String() string {
|
func (p Param) String() string {
|
||||||
|
@ -123,7 +124,7 @@ func (p Param) GetBytesHex() ([]byte, error) {
|
||||||
func (p *Param) UnmarshalJSON(data []byte) error {
|
func (p *Param) UnmarshalJSON(data []byte) error {
|
||||||
var s string
|
var s string
|
||||||
if err := json.Unmarshal(data, &s); err == nil {
|
if err := json.Unmarshal(data, &s); err == nil {
|
||||||
p.Type = stringT
|
p.Type = StringT
|
||||||
p.Value = s
|
p.Value = s
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -131,7 +132,7 @@ func (p *Param) UnmarshalJSON(data []byte) error {
|
||||||
|
|
||||||
var num float64
|
var num float64
|
||||||
if err := json.Unmarshal(data, &num); err == nil {
|
if err := json.Unmarshal(data, &num); err == nil {
|
||||||
p.Type = numberT
|
p.Type = NumberT
|
||||||
p.Value = int(num)
|
p.Value = int(num)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -142,7 +143,7 @@ func (p *Param) UnmarshalJSON(data []byte) error {
|
||||||
jd.DisallowUnknownFields()
|
jd.DisallowUnknownFields()
|
||||||
var fp FuncParam
|
var fp FuncParam
|
||||||
if err := jd.Decode(&fp); err == nil {
|
if err := jd.Decode(&fp); err == nil {
|
||||||
p.Type = funcParamT
|
p.Type = FuncParamT
|
||||||
p.Value = fp
|
p.Value = fp
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -150,7 +151,7 @@ func (p *Param) UnmarshalJSON(data []byte) error {
|
||||||
|
|
||||||
var ps []Param
|
var ps []Param
|
||||||
if err := json.Unmarshal(data, &ps); err == nil {
|
if err := json.Unmarshal(data, &ps); err == nil {
|
||||||
p.Type = arrayT
|
p.Type = ArrayT
|
||||||
p.Value = ps
|
p.Value = ps
|
||||||
|
|
||||||
return nil
|
return nil
|
|
@ -1,4 +1,4 @@
|
||||||
package rpc
|
package request
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
@ -15,35 +15,35 @@ func TestParam_UnmarshalJSON(t *testing.T) {
|
||||||
msg := `["str1", 123, ["str2", 3], [{"type": "String", "value": "jajaja"}]]`
|
msg := `["str1", 123, ["str2", 3], [{"type": "String", "value": "jajaja"}]]`
|
||||||
expected := Params{
|
expected := Params{
|
||||||
{
|
{
|
||||||
Type: stringT,
|
Type: StringT,
|
||||||
Value: "str1",
|
Value: "str1",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Type: numberT,
|
Type: NumberT,
|
||||||
Value: 123,
|
Value: 123,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Type: arrayT,
|
Type: ArrayT,
|
||||||
Value: []Param{
|
Value: []Param{
|
||||||
{
|
{
|
||||||
Type: stringT,
|
Type: StringT,
|
||||||
Value: "str2",
|
Value: "str2",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Type: numberT,
|
Type: NumberT,
|
||||||
Value: 3,
|
Value: 3,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Type: arrayT,
|
Type: ArrayT,
|
||||||
Value: []Param{
|
Value: []Param{
|
||||||
{
|
{
|
||||||
Type: funcParamT,
|
Type: FuncParamT,
|
||||||
Value: FuncParam{
|
Value: FuncParam{
|
||||||
Type: String,
|
Type: String,
|
||||||
Value: Param{
|
Value: Param{
|
||||||
Type: stringT,
|
Type: StringT,
|
||||||
Value: "jajaja",
|
Value: "jajaja",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -61,34 +61,34 @@ func TestParam_UnmarshalJSON(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParamGetString(t *testing.T) {
|
func TestParamGetString(t *testing.T) {
|
||||||
p := Param{stringT, "jajaja"}
|
p := Param{StringT, "jajaja"}
|
||||||
str, err := p.GetString()
|
str, err := p.GetString()
|
||||||
assert.Equal(t, "jajaja", str)
|
assert.Equal(t, "jajaja", str)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
p = Param{stringT, int(100500)}
|
p = Param{StringT, int(100500)}
|
||||||
_, err = p.GetString()
|
_, err = p.GetString()
|
||||||
require.NotNil(t, err)
|
require.NotNil(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParamGetInt(t *testing.T) {
|
func TestParamGetInt(t *testing.T) {
|
||||||
p := Param{numberT, int(100500)}
|
p := Param{NumberT, int(100500)}
|
||||||
i, err := p.GetInt()
|
i, err := p.GetInt()
|
||||||
assert.Equal(t, 100500, i)
|
assert.Equal(t, 100500, i)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
p = Param{numberT, "jajaja"}
|
p = Param{NumberT, "jajaja"}
|
||||||
_, err = p.GetInt()
|
_, err = p.GetInt()
|
||||||
require.NotNil(t, err)
|
require.NotNil(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParamGetArray(t *testing.T) {
|
func TestParamGetArray(t *testing.T) {
|
||||||
p := Param{arrayT, []Param{{numberT, 42}}}
|
p := Param{ArrayT, []Param{{NumberT, 42}}}
|
||||||
a, err := p.GetArray()
|
a, err := p.GetArray()
|
||||||
assert.Equal(t, []Param{{numberT, 42}}, a)
|
assert.Equal(t, []Param{{NumberT, 42}}, a)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
p = Param{arrayT, 42}
|
p = Param{ArrayT, 42}
|
||||||
_, err = p.GetArray()
|
_, err = p.GetArray()
|
||||||
require.NotNil(t, err)
|
require.NotNil(t, err)
|
||||||
}
|
}
|
||||||
|
@ -96,16 +96,16 @@ func TestParamGetArray(t *testing.T) {
|
||||||
func TestParamGetUint256(t *testing.T) {
|
func TestParamGetUint256(t *testing.T) {
|
||||||
gas := "602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7"
|
gas := "602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7"
|
||||||
u256, _ := util.Uint256DecodeStringLE(gas)
|
u256, _ := util.Uint256DecodeStringLE(gas)
|
||||||
p := Param{stringT, gas}
|
p := Param{StringT, gas}
|
||||||
u, err := p.GetUint256()
|
u, err := p.GetUint256()
|
||||||
assert.Equal(t, u256, u)
|
assert.Equal(t, u256, u)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
p = Param{stringT, 42}
|
p = Param{StringT, 42}
|
||||||
_, err = p.GetUint256()
|
_, err = p.GetUint256()
|
||||||
require.NotNil(t, err)
|
require.NotNil(t, err)
|
||||||
|
|
||||||
p = Param{stringT, "qq2c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7"}
|
p = Param{StringT, "qq2c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7"}
|
||||||
_, err = p.GetUint256()
|
_, err = p.GetUint256()
|
||||||
require.NotNil(t, err)
|
require.NotNil(t, err)
|
||||||
}
|
}
|
||||||
|
@ -113,16 +113,16 @@ func TestParamGetUint256(t *testing.T) {
|
||||||
func TestParamGetUint160FromHex(t *testing.T) {
|
func TestParamGetUint160FromHex(t *testing.T) {
|
||||||
in := "50befd26fdf6e4d957c11e078b24ebce6291456f"
|
in := "50befd26fdf6e4d957c11e078b24ebce6291456f"
|
||||||
u160, _ := util.Uint160DecodeStringLE(in)
|
u160, _ := util.Uint160DecodeStringLE(in)
|
||||||
p := Param{stringT, in}
|
p := Param{StringT, in}
|
||||||
u, err := p.GetUint160FromHex()
|
u, err := p.GetUint160FromHex()
|
||||||
assert.Equal(t, u160, u)
|
assert.Equal(t, u160, u)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
p = Param{stringT, 42}
|
p = Param{StringT, 42}
|
||||||
_, err = p.GetUint160FromHex()
|
_, err = p.GetUint160FromHex()
|
||||||
require.NotNil(t, err)
|
require.NotNil(t, err)
|
||||||
|
|
||||||
p = Param{stringT, "wwbefd26fdf6e4d957c11e078b24ebce6291456f"}
|
p = Param{StringT, "wwbefd26fdf6e4d957c11e078b24ebce6291456f"}
|
||||||
_, err = p.GetUint160FromHex()
|
_, err = p.GetUint160FromHex()
|
||||||
require.NotNil(t, err)
|
require.NotNil(t, err)
|
||||||
}
|
}
|
||||||
|
@ -130,16 +130,16 @@ func TestParamGetUint160FromHex(t *testing.T) {
|
||||||
func TestParamGetUint160FromAddress(t *testing.T) {
|
func TestParamGetUint160FromAddress(t *testing.T) {
|
||||||
in := "AK2nJJpJr6o664CWJKi1QRXjqeic2zRp8y"
|
in := "AK2nJJpJr6o664CWJKi1QRXjqeic2zRp8y"
|
||||||
u160, _ := address.StringToUint160(in)
|
u160, _ := address.StringToUint160(in)
|
||||||
p := Param{stringT, in}
|
p := Param{StringT, in}
|
||||||
u, err := p.GetUint160FromAddress()
|
u, err := p.GetUint160FromAddress()
|
||||||
assert.Equal(t, u160, u)
|
assert.Equal(t, u160, u)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
p = Param{stringT, 42}
|
p = Param{StringT, 42}
|
||||||
_, err = p.GetUint160FromAddress()
|
_, err = p.GetUint160FromAddress()
|
||||||
require.NotNil(t, err)
|
require.NotNil(t, err)
|
||||||
|
|
||||||
p = Param{stringT, "QK2nJJpJr6o664CWJKi1QRXjqeic2zRp8y"}
|
p = Param{StringT, "QK2nJJpJr6o664CWJKi1QRXjqeic2zRp8y"}
|
||||||
_, err = p.GetUint160FromAddress()
|
_, err = p.GetUint160FromAddress()
|
||||||
require.NotNil(t, err)
|
require.NotNil(t, err)
|
||||||
}
|
}
|
||||||
|
@ -148,19 +148,19 @@ func TestParamGetFuncParam(t *testing.T) {
|
||||||
fp := FuncParam{
|
fp := FuncParam{
|
||||||
Type: String,
|
Type: String,
|
||||||
Value: Param{
|
Value: Param{
|
||||||
Type: stringT,
|
Type: StringT,
|
||||||
Value: "jajaja",
|
Value: "jajaja",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
p := Param{
|
p := Param{
|
||||||
Type: funcParamT,
|
Type: FuncParamT,
|
||||||
Value: fp,
|
Value: fp,
|
||||||
}
|
}
|
||||||
newfp, err := p.GetFuncParam()
|
newfp, err := p.GetFuncParam()
|
||||||
assert.Equal(t, fp, newfp)
|
assert.Equal(t, fp, newfp)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
p = Param{funcParamT, 42}
|
p = Param{FuncParamT, 42}
|
||||||
_, err = p.GetFuncParam()
|
_, err = p.GetFuncParam()
|
||||||
require.NotNil(t, err)
|
require.NotNil(t, err)
|
||||||
}
|
}
|
||||||
|
@ -168,16 +168,16 @@ func TestParamGetFuncParam(t *testing.T) {
|
||||||
func TestParamGetBytesHex(t *testing.T) {
|
func TestParamGetBytesHex(t *testing.T) {
|
||||||
in := "602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7"
|
in := "602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7"
|
||||||
inb, _ := hex.DecodeString(in)
|
inb, _ := hex.DecodeString(in)
|
||||||
p := Param{stringT, in}
|
p := Param{StringT, in}
|
||||||
bh, err := p.GetBytesHex()
|
bh, err := p.GetBytesHex()
|
||||||
assert.Equal(t, inb, bh)
|
assert.Equal(t, inb, bh)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
p = Param{stringT, 42}
|
p = Param{StringT, 42}
|
||||||
_, err = p.GetBytesHex()
|
_, err = p.GetBytesHex()
|
||||||
require.NotNil(t, err)
|
require.NotNil(t, err)
|
||||||
|
|
||||||
p = Param{stringT, "qq2c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7"}
|
p = Param{StringT, "qq2c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7"}
|
||||||
_, err = p.GetBytesHex()
|
_, err = p.GetBytesHex()
|
||||||
require.NotNil(t, err)
|
require.NotNil(t, err)
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package rpc
|
package request
|
||||||
|
|
||||||
type (
|
type (
|
||||||
// Params represents the JSON-RPC params.
|
// Params represents the JSON-RPC params.
|
|
@ -1,4 +1,4 @@
|
||||||
package rpc
|
package request
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
|
@ -1,4 +1,4 @@
|
||||||
package rpc
|
package request
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"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 (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -18,10 +18,13 @@ type (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
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{
|
return &Error{
|
||||||
Code: code,
|
Code: code,
|
||||||
HTTPCode: httpCode,
|
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
|
// NewParseError creates a new error with code
|
||||||
// -32700.:%s
|
// -32700.:%s
|
||||||
func NewParseError(data string, cause error) *Error {
|
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
|
// NewInvalidRequestError creates a new error with
|
||||||
// code -32600.
|
// code -32600.
|
||||||
func NewInvalidRequestError(data string, cause error) *Error {
|
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
|
// NewMethodNotFoundError creates a new error with
|
||||||
// code -32601.
|
// code -32601.
|
||||||
func NewMethodNotFoundError(data string, cause error) *Error {
|
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
|
// NewInvalidParamsError creates a new error with
|
||||||
// code -32602.
|
// code -32602.
|
||||||
func NewInvalidParamsError(data string, cause error) *Error {
|
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
|
// NewInternalServerError creates a new error with
|
||||||
// code -32603.
|
// code -32603.
|
||||||
func NewInternalServerError(data string, cause error) *Error {
|
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
|
// NewRPCError creates a new error with
|
||||||
// code -100
|
// code -100
|
||||||
func NewRPCError(message string, data string, cause error) *Error {
|
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.
|
// 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)
|
return fmt.Sprintf("%s (%d) - %s - %s", e.Message, e.Code, e.Data, e.Cause)
|
||||||
}
|
}
|
|
@ -1,15 +1,17 @@
|
||||||
package rpc
|
package response
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
"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/rpc/response/result"
|
||||||
"github.com/CityOfZion/neo-go/pkg/vm"
|
"github.com/CityOfZion/neo-go/pkg/vm"
|
||||||
)
|
)
|
||||||
|
|
||||||
// InvokeScriptResponse stores response for the invoke script call.
|
// InvokeScript stores response for the invoke script call.
|
||||||
type InvokeScriptResponse struct {
|
type InvokeScript struct {
|
||||||
responseHeader
|
HeaderAndError
|
||||||
Error *Error `json:"error,omitempty"`
|
|
||||||
Result *InvokeResult `json:"result,omitempty"`
|
Result *InvokeResult `json:"result,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,19 +21,18 @@ type InvokeResult struct {
|
||||||
State vm.State `json:"state"`
|
State vm.State `json:"state"`
|
||||||
GasConsumed string `json:"gas_consumed"`
|
GasConsumed string `json:"gas_consumed"`
|
||||||
Script string `json:"script"`
|
Script string `json:"script"`
|
||||||
Stack []StackParam
|
Stack []request.StackParam
|
||||||
}
|
}
|
||||||
|
|
||||||
// AccountStateResponse holds the getaccountstate response.
|
// AccountState holds the getaccountstate response.
|
||||||
type AccountStateResponse struct {
|
type AccountState struct {
|
||||||
responseHeader
|
Header
|
||||||
Result *Account `json:"result"`
|
Result *Account `json:"result"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnspentResponse represents server response to the `getunspents` command.
|
// Unspent represents server response to the `getunspents` command.
|
||||||
type UnspentResponse struct {
|
type Unspent struct {
|
||||||
responseHeader
|
HeaderAndError
|
||||||
Error *Error `json:"error,omitempty"`
|
|
||||||
Result *result.Unspents `json:"result,omitempty"`
|
Result *result.Unspents `json:"result,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,68 +52,54 @@ type Balance struct {
|
||||||
Value string `json:"value"`
|
Value string `json:"value"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type params struct {
|
// Header is a generic JSON-RPC 2.0 response header (ID and JSON-RPC version).
|
||||||
values []interface{}
|
type Header struct {
|
||||||
|
ID json.RawMessage `json:"id"`
|
||||||
|
JSONRPC string `json:"jsonrpc"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func newParams(vals ...interface{}) params {
|
// HeaderAndError adds an Error (that can be empty) to the Header, it's used
|
||||||
p := params{}
|
// to construct type-specific responses.
|
||||||
p.values = make([]interface{}, len(vals))
|
type HeaderAndError struct {
|
||||||
for i := 0; i < len(p.values); i++ {
|
Header
|
||||||
p.values[i] = vals[i]
|
Error *Error `json:"error,omitempty"`
|
||||||
}
|
|
||||||
return p
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type request struct {
|
// Raw represents a standard raw JSON-RPC 2.0
|
||||||
JSONRPC string `json:"jsonrpc"`
|
// response: http://www.jsonrpc.org/specification#response_object.
|
||||||
Method string `json:"method"`
|
type Raw struct {
|
||||||
Params []interface{} `json:"params"`
|
HeaderAndError
|
||||||
ID int `json:"id"`
|
Result interface{} `json:"result,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type responseHeader struct {
|
// SendToAddress stores response for the sendtoaddress call.
|
||||||
ID int `json:"id"`
|
type SendToAddress struct {
|
||||||
JSONRPC string `json:"jsonrpc"`
|
HeaderAndError
|
||||||
|
Result *Tx
|
||||||
}
|
}
|
||||||
|
|
||||||
type response struct {
|
// GetTxOut represents result of `gettxout` RPC call.
|
||||||
responseHeader
|
type GetTxOut struct {
|
||||||
Error *Error `json:"error"`
|
HeaderAndError
|
||||||
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
|
|
||||||
Result *result.TransactionOutput
|
Result *result.TransactionOutput
|
||||||
}
|
}
|
||||||
|
|
||||||
// RawTxResponse stores transaction with blockchain metadata to be sent as a response.
|
// GetRawTx represents verbose output of `getrawtransaction` RPC call.
|
||||||
type RawTxResponse struct {
|
type GetRawTx struct {
|
||||||
TxResponse
|
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"`
|
BlockHash string `json:"blockhash"`
|
||||||
Confirmations uint `json:"confirmations"`
|
Confirmations uint `json:"confirmations"`
|
||||||
BlockTime uint `json:"blocktime"`
|
BlockTime uint `json:"blocktime"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// TxResponse stores transaction to be sent as a response.
|
// Tx stores transaction to be sent as a response.
|
||||||
type TxResponse struct {
|
type Tx struct {
|
||||||
TxID string `json:"txid"`
|
TxID string `json:"txid"`
|
||||||
Size int `json:"size"`
|
Size int `json:"size"`
|
||||||
Type string `json:"type"` // todo: convert to TransactionType
|
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"
|
||||||
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
||||||
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
"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/smartcontract"
|
||||||
"github.com/CityOfZion/neo-go/pkg/util"
|
"github.com/CityOfZion/neo-go/pkg/util"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
@ -17,11 +19,11 @@ import (
|
||||||
// missing output wrapper at the moment, thus commented out
|
// missing output wrapper at the moment, thus commented out
|
||||||
// func (c *Client) getBlock(indexOrHash interface{}, verbose bool) (*response, error) {
|
// func (c *Client) getBlock(indexOrHash interface{}, verbose bool) (*response, error) {
|
||||||
// var (
|
// var (
|
||||||
// params = newParams(indexOrHash)
|
// params = request.NewRawParams(indexOrHash)
|
||||||
// resp = &response{}
|
// resp = &response{}
|
||||||
// )
|
// )
|
||||||
// if verbose {
|
// if verbose {
|
||||||
// params = newParams(indexOrHash, 1)
|
// params = request.NewRawParams(indexOrHash, 1)
|
||||||
// }
|
// }
|
||||||
// if err := c.performRequest("getblock", params, resp); err != nil {
|
// if err := c.performRequest("getblock", params, resp); err != nil {
|
||||||
// return nil, err
|
// return nil, err
|
||||||
|
@ -30,10 +32,10 @@ import (
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// GetAccountState returns detailed information about a NEO account.
|
// 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 (
|
var (
|
||||||
params = newParams(address)
|
params = request.NewRawParams(address)
|
||||||
resp = &AccountStateResponse{}
|
resp = &response.AccountState{}
|
||||||
)
|
)
|
||||||
if err := c.performRequest("getaccountstate", params, resp); err != nil {
|
if err := c.performRequest("getaccountstate", params, resp); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -42,10 +44,10 @@ func (c *Client) GetAccountState(address string) (*AccountStateResponse, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUnspents returns UTXOs for the given NEO account.
|
// 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 (
|
var (
|
||||||
params = newParams(address)
|
params = request.NewRawParams(address)
|
||||||
resp = &UnspentResponse{}
|
resp = &response.Unspent{}
|
||||||
)
|
)
|
||||||
if err := c.performRequest("getunspents", params, resp); err != nil {
|
if err := c.performRequest("getunspents", params, resp); err != nil {
|
||||||
return nil, err
|
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.
|
// 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.
|
// 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 (
|
var (
|
||||||
params = newParams(script)
|
params = request.NewRawParams(script)
|
||||||
resp = &InvokeScriptResponse{}
|
resp = &response.InvokeScript{}
|
||||||
)
|
)
|
||||||
if err := c.performRequest("invokescript", params, resp); err != nil {
|
if err := c.performRequest("invokescript", params, resp); err != nil {
|
||||||
return nil, err
|
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
|
// InvokeFunction returns the results after calling the smart contract scripthash
|
||||||
// with the given operation and parameters.
|
// with the given operation and parameters.
|
||||||
// NOTE: this is test invoke and will not affect the blockchain.
|
// 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 (
|
var (
|
||||||
p = newParams(script, operation, params)
|
p = request.NewRawParams(script, operation, params)
|
||||||
resp = &InvokeScriptResponse{}
|
resp = &response.InvokeScript{}
|
||||||
)
|
)
|
||||||
if err := c.performRequest("invokefunction", p, resp); err != nil {
|
if err := c.performRequest("invokefunction", p, resp); err != nil {
|
||||||
return nil, err
|
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
|
// Invoke returns the results after calling the smart contract scripthash
|
||||||
// with the given parameters.
|
// 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 (
|
var (
|
||||||
p = newParams(script, params)
|
p = request.NewRawParams(script, params)
|
||||||
resp = &InvokeScriptResponse{}
|
resp = &response.InvokeScript{}
|
||||||
)
|
)
|
||||||
if err := c.performRequest("invoke", p, resp); err != nil {
|
if err := c.performRequest("invoke", p, resp); err != nil {
|
||||||
return nil, err
|
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
|
// missing output wrapper at the moment, thus commented out
|
||||||
// func (c *Client) getRawTransaction(hash string, verbose bool) (*response, error) {
|
// func (c *Client) getRawTransaction(hash string, verbose bool) (*response, error) {
|
||||||
// var (
|
// var (
|
||||||
// params = newParams(hash, verbose)
|
// params = request.NewRawParams(hash, verbose)
|
||||||
// resp = &response{}
|
// resp = &response{}
|
||||||
// )
|
// )
|
||||||
// if err := c.performRequest("getrawtransaction", params, resp); err != nil {
|
// 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.
|
// The given hex string needs to be signed with a keypair.
|
||||||
// When the result of the response object is true, the TX has successfully
|
// When the result of the response object is true, the TX has successfully
|
||||||
// been broadcasted to the network.
|
// 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 (
|
var (
|
||||||
params = newParams(hex.EncodeToString(rawTX.Bytes()))
|
params = request.NewRawParams(hex.EncodeToString(rawTX.Bytes()))
|
||||||
resp = &response{}
|
resp = &response.Raw{}
|
||||||
)
|
)
|
||||||
if err := c.performRequest("sendrawtransaction", params, resp); err != nil {
|
if err := c.performRequest("sendrawtransaction", params, resp); err != nil {
|
||||||
return nil, err
|
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.
|
// SendToAddress sends an amount of specific asset to a given address.
|
||||||
// This call requires open wallet. (`wif` key in client struct.)
|
// 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.
|
// 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 (
|
var (
|
||||||
err error
|
err error
|
||||||
rawTx *transaction.Transaction
|
rawTx *transaction.Transaction
|
||||||
|
@ -135,23 +137,23 @@ func (c *Client) SendToAddress(asset util.Uint256, address string, amount util.F
|
||||||
wif: c.WIF(),
|
wif: c.WIF(),
|
||||||
balancer: c.Balancer(),
|
balancer: c.Balancer(),
|
||||||
}
|
}
|
||||||
resp *response
|
respRaw *response.Raw
|
||||||
response = &SendToAddressResponse{}
|
resp = &response.SendToAddress{}
|
||||||
)
|
)
|
||||||
|
|
||||||
if rawTx, err = CreateRawContractTransaction(txParams); err != nil {
|
if rawTx, err = CreateRawContractTransaction(txParams); err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to create raw transaction for `sendtoaddress`")
|
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")
|
return nil, errors.Wrap(err, "failed to send raw transaction")
|
||||||
}
|
}
|
||||||
response.Error = resp.Error
|
resp.Error = respRaw.Error
|
||||||
response.ID = resp.ID
|
resp.ID = respRaw.ID
|
||||||
response.JSONRPC = resp.JSONRPC
|
resp.JSONRPC = respRaw.JSONRPC
|
||||||
response.Result = &TxResponse{
|
resp.Result = &response.Tx{
|
||||||
TxID: rawTx.Hash().StringLE(),
|
TxID: rawTx.Hash().StringLE(),
|
||||||
}
|
}
|
||||||
return response, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SignAndPushInvocationTx signs and pushes given script as an invocation
|
// SignAndPushInvocationTx signs and pushes given script as an invocation
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package rpc
|
package rpc
|
||||||
|
|
||||||
|
import "github.com/CityOfZion/neo-go/pkg/rpc/request"
|
||||||
|
|
||||||
// ContractDetails contains contract metadata.
|
// ContractDetails contains contract metadata.
|
||||||
type ContractDetails struct {
|
type ContractDetails struct {
|
||||||
Author string
|
Author string
|
||||||
|
@ -10,6 +12,6 @@ type ContractDetails struct {
|
||||||
HasStorage bool
|
HasStorage bool
|
||||||
HasDynamicInvocation bool
|
HasDynamicInvocation bool
|
||||||
IsPayable bool
|
IsPayable bool
|
||||||
ReturnType StackParamType
|
ReturnType request.StackParamType
|
||||||
Parameters []StackParamType
|
Parameters []request.StackParamType
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package rpc
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -14,6 +15,8 @@ import (
|
||||||
"github.com/CityOfZion/neo-go/pkg/encoding/address"
|
"github.com/CityOfZion/neo-go/pkg/encoding/address"
|
||||||
"github.com/CityOfZion/neo-go/pkg/io"
|
"github.com/CityOfZion/neo-go/pkg/io"
|
||||||
"github.com/CityOfZion/neo-go/pkg/network"
|
"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/rpc/response/result"
|
||||||
"github.com/CityOfZion/neo-go/pkg/util"
|
"github.com/CityOfZion/neo-go/pkg/util"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
@ -71,13 +74,13 @@ func (s *Server) Shutdown() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) requestHandler(w http.ResponseWriter, httpRequest *http.Request) {
|
func (s *Server) requestHandler(w http.ResponseWriter, httpRequest *http.Request) {
|
||||||
req := NewRequest()
|
req := request.NewIn()
|
||||||
|
|
||||||
if httpRequest.Method != "POST" {
|
if httpRequest.Method != "POST" {
|
||||||
s.WriteErrorResponse(
|
s.WriteErrorResponse(
|
||||||
req,
|
req,
|
||||||
w,
|
w,
|
||||||
NewInvalidParamsError(
|
response.NewInvalidParamsError(
|
||||||
fmt.Sprintf("Invalid method '%s', please retry with 'POST'", httpRequest.Method), nil,
|
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)
|
err := req.DecodeData(httpRequest.Body)
|
||||||
if err != nil {
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
reqParams, err := req.Params()
|
reqParams, err := req.Params()
|
||||||
if err != nil {
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
s.methodHandler(w, req, *reqParams)
|
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",
|
s.log.Debug("processing rpc request",
|
||||||
zap.String("method", req.Method),
|
zap.String("method", req.Method),
|
||||||
zap.String("params", fmt.Sprintf("%v", reqParams)))
|
zap.String("params", fmt.Sprintf("%v", reqParams)))
|
||||||
|
@ -121,33 +124,33 @@ Methods:
|
||||||
|
|
||||||
param, ok := reqParams.Value(0)
|
param, ok := reqParams.Value(0)
|
||||||
if !ok {
|
if !ok {
|
||||||
resultsErr = errInvalidParams
|
resultsErr = response.ErrInvalidParams
|
||||||
break Methods
|
break Methods
|
||||||
}
|
}
|
||||||
|
|
||||||
switch param.Type {
|
switch param.Type {
|
||||||
case stringT:
|
case request.StringT:
|
||||||
var err error
|
var err error
|
||||||
hash, err = param.GetUint256()
|
hash, err = param.GetUint256()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resultsErr = errInvalidParams
|
resultsErr = response.ErrInvalidParams
|
||||||
break Methods
|
break Methods
|
||||||
}
|
}
|
||||||
case numberT:
|
case request.NumberT:
|
||||||
num, err := s.blockHeightFromParam(param)
|
num, err := s.blockHeightFromParam(param)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resultsErr = errInvalidParams
|
resultsErr = response.ErrInvalidParams
|
||||||
break Methods
|
break Methods
|
||||||
}
|
}
|
||||||
hash = s.chain.GetHeaderHash(num)
|
hash = s.chain.GetHeaderHash(num)
|
||||||
default:
|
default:
|
||||||
resultsErr = errInvalidParams
|
resultsErr = response.ErrInvalidParams
|
||||||
break Methods
|
break Methods
|
||||||
}
|
}
|
||||||
|
|
||||||
block, err := s.chain.GetBlock(hash)
|
block, err := s.chain.GetBlock(hash)
|
||||||
if err != nil {
|
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
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,14 +168,14 @@ Methods:
|
||||||
|
|
||||||
case "getblockhash":
|
case "getblockhash":
|
||||||
getblockHashCalled.Inc()
|
getblockHashCalled.Inc()
|
||||||
param, ok := reqParams.ValueWithType(0, numberT)
|
param, ok := reqParams.ValueWithType(0, request.NumberT)
|
||||||
if !ok {
|
if !ok {
|
||||||
resultsErr = errInvalidParams
|
resultsErr = response.ErrInvalidParams
|
||||||
break Methods
|
break Methods
|
||||||
}
|
}
|
||||||
num, err := s.blockHeightFromParam(param)
|
num, err := s.blockHeightFromParam(param)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resultsErr = errInvalidParams
|
resultsErr = response.ErrInvalidParams
|
||||||
break Methods
|
break Methods
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,22 +209,22 @@ Methods:
|
||||||
validateaddressCalled.Inc()
|
validateaddressCalled.Inc()
|
||||||
param, ok := reqParams.Value(0)
|
param, ok := reqParams.Value(0)
|
||||||
if !ok {
|
if !ok {
|
||||||
resultsErr = errInvalidParams
|
resultsErr = response.ErrInvalidParams
|
||||||
break Methods
|
break Methods
|
||||||
}
|
}
|
||||||
results = validateAddress(param.Value)
|
results = validateAddress(param.Value)
|
||||||
|
|
||||||
case "getassetstate":
|
case "getassetstate":
|
||||||
getassetstateCalled.Inc()
|
getassetstateCalled.Inc()
|
||||||
param, ok := reqParams.ValueWithType(0, stringT)
|
param, ok := reqParams.ValueWithType(0, request.StringT)
|
||||||
if !ok {
|
if !ok {
|
||||||
resultsErr = errInvalidParams
|
resultsErr = response.ErrInvalidParams
|
||||||
break Methods
|
break Methods
|
||||||
}
|
}
|
||||||
|
|
||||||
paramAssetID, err := param.GetUint256()
|
paramAssetID, err := param.GetUint256()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resultsErr = errInvalidParams
|
resultsErr = response.ErrInvalidParams
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,7 +232,7 @@ Methods:
|
||||||
if as != nil {
|
if as != nil {
|
||||||
results = result.NewAssetState(as)
|
results = result.NewAssetState(as)
|
||||||
} else {
|
} else {
|
||||||
resultsErr = NewRPCError("Unknown asset", "", nil)
|
resultsErr = response.NewRPCError("Unknown asset", "", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
case "getaccountstate":
|
case "getaccountstate":
|
||||||
|
@ -266,7 +269,7 @@ Methods:
|
||||||
results, resultsErr = s.sendrawtransaction(reqParams)
|
results, resultsErr = s.sendrawtransaction(reqParams)
|
||||||
|
|
||||||
default:
|
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 {
|
if resultsErr != nil {
|
||||||
|
@ -277,27 +280,27 @@ Methods:
|
||||||
s.WriteResponse(req, w, results)
|
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)
|
param, ok := ps.Value(0)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errInvalidParams
|
return nil, response.ErrInvalidParams
|
||||||
}
|
}
|
||||||
|
|
||||||
scriptHash, err := param.GetUint160FromHex()
|
scriptHash, err := param.GetUint160FromHex()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errInvalidParams
|
return nil, response.ErrInvalidParams
|
||||||
}
|
}
|
||||||
|
|
||||||
scriptHash = scriptHash.Reverse()
|
scriptHash = scriptHash.Reverse()
|
||||||
|
|
||||||
param, ok = ps.Value(1)
|
param, ok = ps.Value(1)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errInvalidParams
|
return nil, response.ErrInvalidParams
|
||||||
}
|
}
|
||||||
|
|
||||||
key, err := param.GetBytesHex()
|
key, err := param.GetBytesHex()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errInvalidParams
|
return nil, response.ErrInvalidParams
|
||||||
}
|
}
|
||||||
|
|
||||||
item := s.chain.GetStorageItem(scriptHash.Reverse(), key)
|
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
|
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 resultsErr error
|
||||||
var results interface{}
|
var results interface{}
|
||||||
|
|
||||||
if param0, ok := reqParams.Value(0); !ok {
|
if param0, ok := reqParams.Value(0); !ok {
|
||||||
return nil, errInvalidParams
|
return nil, response.ErrInvalidParams
|
||||||
} else if txHash, err := param0.GetUint256(); err != nil {
|
} else if txHash, err := param0.GetUint256(); err != nil {
|
||||||
resultsErr = errInvalidParams
|
resultsErr = response.ErrInvalidParams
|
||||||
} else if tx, height, err := s.chain.GetTransaction(txHash); err != nil {
|
} else if tx, height, err := s.chain.GetTransaction(txHash); err != nil {
|
||||||
err = errors.Wrapf(err, "Invalid transaction hash: %s", txHash)
|
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 {
|
} else if len(reqParams) >= 2 {
|
||||||
_header := s.chain.GetHeaderHash(int(height))
|
_header := s.chain.GetHeaderHash(int(height))
|
||||||
header, err := s.chain.GetHeader(_header)
|
header, err := s.chain.GetHeader(_header)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resultsErr = NewInvalidParamsError(err.Error(), err)
|
resultsErr = response.NewInvalidParamsError(err.Error(), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
param1, _ := reqParams.Value(1)
|
param1, _ := reqParams.Value(1)
|
||||||
|
@ -345,34 +348,34 @@ func (s *Server) getrawtransaction(reqParams Params) (interface{}, error) {
|
||||||
return results, resultsErr
|
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)
|
p, ok := ps.Value(0)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errInvalidParams
|
return nil, response.ErrInvalidParams
|
||||||
}
|
}
|
||||||
|
|
||||||
h, err := p.GetUint256()
|
h, err := p.GetUint256()
|
||||||
if err != nil {
|
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 {
|
if !ok {
|
||||||
return nil, errInvalidParams
|
return nil, response.ErrInvalidParams
|
||||||
}
|
}
|
||||||
|
|
||||||
num, err := p.GetInt()
|
num, err := p.GetInt()
|
||||||
if err != nil || num < 0 {
|
if err != nil || num < 0 {
|
||||||
return nil, errInvalidParams
|
return nil, response.ErrInvalidParams
|
||||||
}
|
}
|
||||||
|
|
||||||
tx, _, err := s.chain.GetTransaction(h)
|
tx, _, err := s.chain.GetTransaction(h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, NewInvalidParamsError(err.Error(), err)
|
return nil, response.NewInvalidParamsError(err.Error(), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if num >= len(tx.Outputs) {
|
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]
|
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).
|
// 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{}
|
var results interface{}
|
||||||
|
|
||||||
param, ok := reqParams.ValueWithType(0, stringT)
|
param, ok := reqParams.ValueWithType(0, request.StringT)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errInvalidParams
|
return nil, response.ErrInvalidParams
|
||||||
} else if scriptHash, err := param.GetUint160FromHex(); err != nil {
|
} else if scriptHash, err := param.GetUint160FromHex(); err != nil {
|
||||||
return nil, errInvalidParams
|
return nil, response.ErrInvalidParams
|
||||||
} else {
|
} else {
|
||||||
cs := s.chain.GetContractState(scriptHash)
|
cs := s.chain.GetContractState(scriptHash)
|
||||||
if cs != nil {
|
if cs != nil {
|
||||||
results = result.NewContractState(cs)
|
results = result.NewContractState(cs)
|
||||||
} else {
|
} else {
|
||||||
return nil, NewRPCError("Unknown contract", "", nil)
|
return nil, response.NewRPCError("Unknown contract", "", nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return results, nil
|
return results, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// getAccountState returns account state either in short or full (unspents included) form.
|
// 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 resultsErr error
|
||||||
var results interface{}
|
var results interface{}
|
||||||
|
|
||||||
param, ok := reqParams.ValueWithType(0, stringT)
|
param, ok := reqParams.ValueWithType(0, request.StringT)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errInvalidParams
|
return nil, response.ErrInvalidParams
|
||||||
} else if scriptHash, err := param.GetUint160FromAddress(); err != nil {
|
} else if scriptHash, err := param.GetUint160FromAddress(); err != nil {
|
||||||
return nil, errInvalidParams
|
return nil, response.ErrInvalidParams
|
||||||
} else {
|
} else {
|
||||||
as := s.chain.GetAccountState(scriptHash)
|
as := s.chain.GetAccountState(scriptHash)
|
||||||
if as == nil {
|
if as == nil {
|
||||||
|
@ -417,7 +420,7 @@ func (s *Server) getAccountState(reqParams Params, unspents bool) (interface{},
|
||||||
if unspents {
|
if unspents {
|
||||||
str, err := param.GetString()
|
str, err := param.GetString()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errInvalidParams
|
return nil, response.ErrInvalidParams
|
||||||
}
|
}
|
||||||
results = result.NewUnspents(as, s.chain, str)
|
results = result.NewUnspents(as, s.chain, str)
|
||||||
} else {
|
} else {
|
||||||
|
@ -428,18 +431,18 @@ func (s *Server) getAccountState(reqParams Params, unspents bool) (interface{},
|
||||||
}
|
}
|
||||||
|
|
||||||
// invoke implements the `invoke` RPC call.
|
// invoke implements the `invoke` RPC call.
|
||||||
func (s *Server) invoke(reqParams Params) (interface{}, error) {
|
func (s *Server) invoke(reqParams request.Params) (interface{}, error) {
|
||||||
scriptHashHex, ok := reqParams.ValueWithType(0, stringT)
|
scriptHashHex, ok := reqParams.ValueWithType(0, request.StringT)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errInvalidParams
|
return nil, response.ErrInvalidParams
|
||||||
}
|
}
|
||||||
scriptHash, err := scriptHashHex.GetUint160FromHex()
|
scriptHash, err := scriptHashHex.GetUint160FromHex()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
sliceP, ok := reqParams.ValueWithType(1, arrayT)
|
sliceP, ok := reqParams.ValueWithType(1, request.ArrayT)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errInvalidParams
|
return nil, response.ErrInvalidParams
|
||||||
}
|
}
|
||||||
slice, err := sliceP.GetArray()
|
slice, err := sliceP.GetArray()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -453,10 +456,10 @@ func (s *Server) invoke(reqParams Params) (interface{}, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// invokescript implements the `invokescript` RPC call.
|
// invokescript implements the `invokescript` RPC call.
|
||||||
func (s *Server) invokeFunction(reqParams Params) (interface{}, error) {
|
func (s *Server) invokeFunction(reqParams request.Params) (interface{}, error) {
|
||||||
scriptHashHex, ok := reqParams.ValueWithType(0, stringT)
|
scriptHashHex, ok := reqParams.ValueWithType(0, request.StringT)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errInvalidParams
|
return nil, response.ErrInvalidParams
|
||||||
}
|
}
|
||||||
scriptHash, err := scriptHashHex.GetUint160FromHex()
|
scriptHash, err := scriptHashHex.GetUint160FromHex()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -470,14 +473,14 @@ func (s *Server) invokeFunction(reqParams Params) (interface{}, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// invokescript implements the `invokescript` RPC call.
|
// 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 {
|
if len(reqParams) < 1 {
|
||||||
return nil, errInvalidParams
|
return nil, response.ErrInvalidParams
|
||||||
}
|
}
|
||||||
|
|
||||||
script, err := reqParams[0].GetBytesHex()
|
script, err := reqParams[0].GetBytesHex()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errInvalidParams
|
return nil, response.ErrInvalidParams
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.runScriptInVM(script), nil
|
return s.runScriptInVM(script), nil
|
||||||
|
@ -499,14 +502,14 @@ func (s *Server) runScriptInVM(script []byte) *result.Invoke {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) sendrawtransaction(reqParams Params) (interface{}, error) {
|
func (s *Server) sendrawtransaction(reqParams request.Params) (interface{}, error) {
|
||||||
var resultsErr error
|
var resultsErr error
|
||||||
var results interface{}
|
var results interface{}
|
||||||
|
|
||||||
if len(reqParams) < 1 {
|
if len(reqParams) < 1 {
|
||||||
return nil, errInvalidParams
|
return nil, response.ErrInvalidParams
|
||||||
} else if byteTx, err := reqParams[0].GetBytesHex(); err != nil {
|
} else if byteTx, err := reqParams[0].GetBytesHex(); err != nil {
|
||||||
return nil, errInvalidParams
|
return nil, response.ErrInvalidParams
|
||||||
} else {
|
} else {
|
||||||
r := io.NewBinReaderFromBuf(byteTx)
|
r := io.NewBinReaderFromBuf(byteTx)
|
||||||
tx := &transaction.Transaction{}
|
tx := &transaction.Transaction{}
|
||||||
|
@ -533,14 +536,14 @@ func (s *Server) sendrawtransaction(reqParams Params) (interface{}, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resultsErr = NewInternalServerError(err.Error(), err)
|
resultsErr = response.NewInternalServerError(err.Error(), err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return results, resultsErr
|
return results, resultsErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) blockHeightFromParam(param *Param) (int, error) {
|
func (s *Server) blockHeightFromParam(param *request.Param) (int, error) {
|
||||||
num, err := param.GetInt()
|
num, err := param.GetInt()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
|
@ -552,6 +555,71 @@ func (s *Server) blockHeightFromParam(param *Param) (int, error) {
|
||||||
return num, nil
|
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
|
// 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
|
// see https://docs.neo.org/en-us/node/cli/2.9.4/api/validateaddress.html
|
||||||
func validateAddress(addr interface{}) result.ValidateAddress {
|
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/core/storage"
|
||||||
"github.com/CityOfZion/neo-go/pkg/io"
|
"github.com/CityOfZion/neo-go/pkg/io"
|
||||||
"github.com/CityOfZion/neo-go/pkg/network"
|
"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/rpc/response/result"
|
||||||
"github.com/CityOfZion/neo-go/pkg/util"
|
"github.com/CityOfZion/neo-go/pkg/util"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
@ -38,11 +39,11 @@ type SendTXResponse struct {
|
||||||
type InvokeFunctionResponse struct {
|
type InvokeFunctionResponse struct {
|
||||||
Jsonrpc string `json:"jsonrpc"`
|
Jsonrpc string `json:"jsonrpc"`
|
||||||
Result struct {
|
Result struct {
|
||||||
Script string `json:"script"`
|
Script string `json:"script"`
|
||||||
State string `json:"state"`
|
State string `json:"state"`
|
||||||
GasConsumed string `json:"gas_consumed"`
|
GasConsumed string `json:"gas_consumed"`
|
||||||
Stack []FuncParam `json:"stack"`
|
Stack []request.FuncParam `json:"stack"`
|
||||||
TX string `json:"tx,omitempty"`
|
TX string `json:"tx,omitempty"`
|
||||||
} `json:"result"`
|
} `json:"result"`
|
||||||
ID int `json:"id"`
|
ID int `json:"id"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ import (
|
||||||
|
|
||||||
"github.com/CityOfZion/neo-go/pkg/core"
|
"github.com/CityOfZion/neo-go/pkg/core"
|
||||||
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
"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/rpc/response/result"
|
||||||
"github.com/CityOfZion/neo-go/pkg/util"
|
"github.com/CityOfZion/neo-go/pkg/util"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
@ -602,7 +603,7 @@ func TestRPC(t *testing.T) {
|
||||||
body := doRPCCall(rpc, handler, t)
|
body := doRPCCall(rpc, handler, t)
|
||||||
checkErrResponse(t, body, false)
|
checkErrResponse(t, body, false)
|
||||||
|
|
||||||
var result GetTxOutResponse
|
var result response.GetTxOut
|
||||||
err := json.Unmarshal(body, &result)
|
err := json.Unmarshal(body, &result)
|
||||||
require.NoErrorf(t, err, "could not parse response: %s", body)
|
require.NoErrorf(t, err, "could not parse response: %s", body)
|
||||||
assert.Equal(t, 0, result.Result.N)
|
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/crypto/keys"
|
||||||
"github.com/CityOfZion/neo-go/pkg/encoding/address"
|
"github.com/CityOfZion/neo-go/pkg/encoding/address"
|
||||||
"github.com/CityOfZion/neo-go/pkg/io"
|
"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/smartcontract"
|
||||||
"github.com/CityOfZion/neo-go/pkg/util"
|
"github.com/CityOfZion/neo-go/pkg/util"
|
||||||
"github.com/CityOfZion/neo-go/pkg/vm/emit"
|
"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
|
// expandArrayIntoScript pushes all FuncParam parameters from the given array
|
||||||
// into the given buffer in reverse order.
|
// 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-- {
|
for j := len(slice) - 1; j >= 0; j-- {
|
||||||
fp, err := slice[j].GetFuncParam()
|
fp, err := slice[j].GetFuncParam()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
switch fp.Type {
|
switch fp.Type {
|
||||||
case ByteArray, Signature:
|
case request.ByteArray, request.Signature:
|
||||||
str, err := fp.Value.GetBytesHex()
|
str, err := fp.Value.GetBytesHex()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
emit.Bytes(script, str)
|
emit.Bytes(script, str)
|
||||||
case String:
|
case request.String:
|
||||||
str, err := fp.Value.GetString()
|
str, err := fp.Value.GetString()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
emit.String(script, str)
|
emit.String(script, str)
|
||||||
case Hash160:
|
case request.Hash160:
|
||||||
hash, err := fp.Value.GetUint160FromHex()
|
hash, err := fp.Value.GetUint160FromHex()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
emit.Bytes(script, hash.BytesBE())
|
emit.Bytes(script, hash.BytesBE())
|
||||||
case Hash256:
|
case request.Hash256:
|
||||||
hash, err := fp.Value.GetUint256()
|
hash, err := fp.Value.GetUint256()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
emit.Bytes(script, hash.BytesBE())
|
emit.Bytes(script, hash.BytesBE())
|
||||||
case PublicKey:
|
case request.PublicKey:
|
||||||
str, err := fp.Value.GetString()
|
str, err := fp.Value.GetString()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -182,13 +183,13 @@ func expandArrayIntoScript(script *io.BinWriter, slice []Param) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
emit.Bytes(script, key.Bytes())
|
emit.Bytes(script, key.Bytes())
|
||||||
case Integer:
|
case request.Integer:
|
||||||
val, err := fp.Value.GetInt()
|
val, err := fp.Value.GetInt()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
emit.Int(script, int64(val))
|
emit.Int(script, int64(val))
|
||||||
case Boolean:
|
case request.Boolean:
|
||||||
str, err := fp.Value.GetString()
|
str, err := fp.Value.GetString()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -210,19 +211,19 @@ func expandArrayIntoScript(script *io.BinWriter, slice []Param) error {
|
||||||
|
|
||||||
// CreateFunctionInvocationScript creates a script to invoke given contract with
|
// CreateFunctionInvocationScript creates a script to invoke given contract with
|
||||||
// given parameters.
|
// given parameters.
|
||||||
func CreateFunctionInvocationScript(contract util.Uint160, params Params) ([]byte, error) {
|
func CreateFunctionInvocationScript(contract util.Uint160, params request.Params) ([]byte, error) {
|
||||||
script := io.NewBufBinWriter()
|
script := io.NewBufBinWriter()
|
||||||
for i := len(params) - 1; i >= 0; i-- {
|
for i := len(params) - 1; i >= 0; i-- {
|
||||||
switch params[i].Type {
|
switch params[i].Type {
|
||||||
case stringT:
|
case request.StringT:
|
||||||
emit.String(script.BinWriter, params[i].String())
|
emit.String(script.BinWriter, params[i].String())
|
||||||
case numberT:
|
case request.NumberT:
|
||||||
num, err := params[i].GetInt()
|
num, err := params[i].GetInt()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
emit.String(script.BinWriter, strconv.Itoa(num))
|
emit.String(script.BinWriter, strconv.Itoa(num))
|
||||||
case arrayT:
|
case request.ArrayT:
|
||||||
slice, err := params[i].GetArray()
|
slice, err := params[i].GetArray()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -244,7 +245,7 @@ func CreateFunctionInvocationScript(contract util.Uint160, params Params) ([]byt
|
||||||
// given parameters. It differs from CreateFunctionInvocationScript in that it
|
// given parameters. It differs from CreateFunctionInvocationScript in that it
|
||||||
// expects one array of FuncParams and expands it onto the stack as independent
|
// expects one array of FuncParams and expands it onto the stack as independent
|
||||||
// elements.
|
// elements.
|
||||||
func CreateInvocationScript(contract util.Uint160, funcParams []Param) ([]byte, error) {
|
func CreateInvocationScript(contract util.Uint160, funcParams []request.Param) ([]byte, error) {
|
||||||
script := io.NewBufBinWriter()
|
script := io.NewBufBinWriter()
|
||||||
err := expandArrayIntoScript(script.BinWriter, funcParams)
|
err := expandArrayIntoScript(script.BinWriter, funcParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -4,56 +4,57 @@ import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/CityOfZion/neo-go/pkg/rpc/request"
|
||||||
"github.com/CityOfZion/neo-go/pkg/util"
|
"github.com/CityOfZion/neo-go/pkg/util"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestInvocationScriptCreationGood(t *testing.T) {
|
func TestInvocationScriptCreationGood(t *testing.T) {
|
||||||
p := Param{stringT, "50befd26fdf6e4d957c11e078b24ebce6291456f"}
|
p := request.Param{Type: request.StringT, Value: "50befd26fdf6e4d957c11e078b24ebce6291456f"}
|
||||||
contract, err := p.GetUint160FromHex()
|
contract, err := p.GetUint160FromHex()
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
var paramScripts = []struct {
|
var paramScripts = []struct {
|
||||||
ps Params
|
ps request.Params
|
||||||
script string
|
script string
|
||||||
}{{
|
}{{
|
||||||
script: "676f459162ceeb248b071ec157d9e4f6fd26fdbe50",
|
script: "676f459162ceeb248b071ec157d9e4f6fd26fdbe50",
|
||||||
}, {
|
}, {
|
||||||
ps: Params{{stringT, "transfer"}},
|
ps: request.Params{{Type: request.StringT, Value: "transfer"}},
|
||||||
script: "087472616e73666572676f459162ceeb248b071ec157d9e4f6fd26fdbe50",
|
script: "087472616e73666572676f459162ceeb248b071ec157d9e4f6fd26fdbe50",
|
||||||
}, {
|
}, {
|
||||||
ps: Params{{numberT, 42}},
|
ps: request.Params{{Type: request.NumberT, Value: 42}},
|
||||||
script: "023432676f459162ceeb248b071ec157d9e4f6fd26fdbe50",
|
script: "023432676f459162ceeb248b071ec157d9e4f6fd26fdbe50",
|
||||||
}, {
|
}, {
|
||||||
ps: Params{{stringT, "a"}, {arrayT, []Param{}}},
|
ps: request.Params{{Type: request.StringT, Value: "a"}, {Type: request.ArrayT, Value: []request.Param{}}},
|
||||||
script: "00c10161676f459162ceeb248b071ec157d9e4f6fd26fdbe50",
|
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",
|
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",
|
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",
|
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",
|
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",
|
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",
|
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",
|
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",
|
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",
|
script: "0051c10161676f459162ceeb248b071ec157d9e4f6fd26fdbe50",
|
||||||
}}
|
}}
|
||||||
for _, ps := range paramScripts {
|
for _, ps := range paramScripts {
|
||||||
|
@ -66,21 +67,21 @@ func TestInvocationScriptCreationGood(t *testing.T) {
|
||||||
func TestInvocationScriptCreationBad(t *testing.T) {
|
func TestInvocationScriptCreationBad(t *testing.T) {
|
||||||
contract := util.Uint160{}
|
contract := util.Uint160{}
|
||||||
|
|
||||||
var testParams = []Params{
|
var testParams = []request.Params{
|
||||||
{{numberT, "qwerty"}},
|
{{Type: request.NumberT, Value: "qwerty"}},
|
||||||
{{arrayT, 42}},
|
{{Type: request.ArrayT, Value: 42}},
|
||||||
{{arrayT, []Param{{numberT, 42}}}},
|
{{Type: request.ArrayT, Value: []request.Param{{Type: request.NumberT, Value: 42}}}},
|
||||||
{{arrayT, []Param{{funcParamT, FuncParam{ByteArray, Param{stringT, "qwerty"}}}}}},
|
{{Type: request.ArrayT, Value: []request.Param{{Type: request.FuncParamT, Value: request.FuncParam{Type: request.ByteArray, Value: request.Param{Type: request.StringT, Value: "qwerty"}}}}}},
|
||||||
{{arrayT, []Param{{funcParamT, FuncParam{Signature, Param{stringT, "qwerty"}}}}}},
|
{{Type: request.ArrayT, Value: []request.Param{{Type: request.FuncParamT, Value: request.FuncParam{Type: request.Signature, Value: request.Param{Type: request.StringT, Value: "qwerty"}}}}}},
|
||||||
{{arrayT, []Param{{funcParamT, FuncParam{String, Param{numberT, 42}}}}}},
|
{{Type: request.ArrayT, Value: []request.Param{{Type: request.FuncParamT, Value: request.FuncParam{Type: request.String, Value: request.Param{Type: request.NumberT, Value: 42}}}}}},
|
||||||
{{arrayT, []Param{{funcParamT, FuncParam{Hash160, Param{stringT, "qwerty"}}}}}},
|
{{Type: request.ArrayT, Value: []request.Param{{Type: request.FuncParamT, Value: request.FuncParam{Type: request.Hash160, Value: request.Param{Type: request.StringT, Value: "qwerty"}}}}}},
|
||||||
{{arrayT, []Param{{funcParamT, FuncParam{Hash256, Param{stringT, "qwerty"}}}}}},
|
{{Type: request.ArrayT, Value: []request.Param{{Type: request.FuncParamT, Value: request.FuncParam{Type: request.Hash256, Value: request.Param{Type: request.StringT, Value: "qwerty"}}}}}},
|
||||||
{{arrayT, []Param{{funcParamT, FuncParam{PublicKey, Param{numberT, 42}}}}}},
|
{{Type: request.ArrayT, Value: []request.Param{{Type: request.FuncParamT, Value: request.FuncParam{Type: request.PublicKey, Value: request.Param{Type: request.NumberT, Value: 42}}}}}},
|
||||||
{{arrayT, []Param{{funcParamT, FuncParam{PublicKey, Param{stringT, "qwerty"}}}}}},
|
{{Type: request.ArrayT, Value: []request.Param{{Type: request.FuncParamT, Value: request.FuncParam{Type: request.PublicKey, Value: request.Param{Type: request.StringT, Value: "qwerty"}}}}}},
|
||||||
{{arrayT, []Param{{funcParamT, FuncParam{Integer, Param{stringT, "qwerty"}}}}}},
|
{{Type: request.ArrayT, Value: []request.Param{{Type: request.FuncParamT, Value: request.FuncParam{Type: request.Integer, Value: request.Param{Type: request.StringT, Value: "qwerty"}}}}}},
|
||||||
{{arrayT, []Param{{funcParamT, FuncParam{Boolean, Param{numberT, 42}}}}}},
|
{{Type: request.ArrayT, Value: []request.Param{{Type: request.FuncParamT, Value: request.FuncParam{Type: request.Boolean, Value: request.Param{Type: request.NumberT, Value: 42}}}}}},
|
||||||
{{arrayT, []Param{{funcParamT, FuncParam{Boolean, Param{stringT, "qwerty"}}}}}},
|
{{Type: request.ArrayT, Value: []request.Param{{Type: request.FuncParamT, Value: request.FuncParam{Type: request.Boolean, Value: request.Param{Type: request.StringT, Value: "qwerty"}}}}}},
|
||||||
{{arrayT, []Param{{funcParamT, FuncParam{Unknown, Param{}}}}}},
|
{{Type: request.ArrayT, Value: []request.Param{{Type: request.FuncParamT, Value: request.FuncParam{Type: request.Unknown, Value: request.Param{}}}}}},
|
||||||
}
|
}
|
||||||
for _, ps := range testParams {
|
for _, ps := range testParams {
|
||||||
_, err := CreateFunctionInvocationScript(contract, ps)
|
_, err := CreateFunctionInvocationScript(contract, ps)
|
||||||
|
|
Loading…
Reference in a new issue