neoneo-go/pkg/rpc/response/result/contract_state.go
Anna Shaleva 4911837949 rpc: fix wrong script marshalling in getcontractstate RPC server
problem: `script` field of result.ContractState is marshalled as []byte

solution: add marshaller for result.ContractState
2020-03-24 14:55:20 +03:00

124 lines
3.7 KiB
Go

package result
import (
"encoding/hex"
"encoding/json"
"github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
"github.com/nspcc-dev/neo-go/pkg/util"
)
// ContractState wrapper used for the representation of
// state.Contract on the RPC Server.
type ContractState struct {
Version byte `json:"version"`
ScriptHash util.Uint160 `json:"hash"`
Script []byte `json:"script"`
ParamList []smartcontract.ParamType `json:"parameters"`
ReturnType smartcontract.ParamType `json:"returntype"`
Name string `json:"name"`
CodeVersion string `json:"code_version"`
Author string `json:"author"`
Email string `json:"email"`
Description string `json:"description"`
Properties Properties `json:"properties"`
}
// Properties response wrapper.
type Properties struct {
HasStorage bool `json:"storage"`
HasDynamicInvoke bool `json:"dynamic_invoke"`
IsPayable bool `json:"is_payable"`
}
// contractState is an auxilliary struct for proper Script marshaling.
type contractState struct {
Version byte `json:"version"`
ScriptHash util.Uint160 `json:"hash"`
Script string `json:"script"`
ParamList []smartcontract.ParamType `json:"parameters"`
ReturnType smartcontract.ParamType `json:"returntype"`
Name string `json:"name"`
CodeVersion string `json:"code_version"`
Author string `json:"author"`
Email string `json:"email"`
Description string `json:"description"`
Properties Properties `json:"properties"`
}
// NewContractState creates a new Contract wrapper.
func NewContractState(c *state.Contract) ContractState {
properties := Properties{
HasStorage: c.HasStorage(),
HasDynamicInvoke: c.HasDynamicInvoke(),
IsPayable: c.IsPayable(),
}
return ContractState{
Version: 0,
ScriptHash: c.ScriptHash(),
Script: c.Script,
ParamList: c.ParamList,
ReturnType: c.ReturnType,
Properties: properties,
Name: c.Name,
CodeVersion: c.CodeVersion,
Author: c.Author,
Email: c.Email,
Description: c.Description,
}
}
// MarshalJSON implements json.Marshaler interface.
func (c ContractState) MarshalJSON() ([]byte, error) {
s := &contractState{
Version: c.Version,
ScriptHash: c.ScriptHash,
Script: hex.EncodeToString(c.Script),
ParamList: c.ParamList,
ReturnType: c.ReturnType,
Name: c.Name,
CodeVersion: c.CodeVersion,
Author: c.Author,
Email: c.Email,
Description: c.Description,
Properties: Properties{
HasStorage: c.Properties.HasStorage,
HasDynamicInvoke: c.Properties.HasDynamicInvoke,
IsPayable: c.Properties.IsPayable,
},
}
return json.Marshal(s)
}
// UnmarshalJSON implements json.Unmarshaler interface.
func (c *ContractState) UnmarshalJSON(data []byte) error {
s := new(contractState)
if err := json.Unmarshal(data, s); err != nil {
return err
}
script, err := hex.DecodeString(s.Script)
if err != nil {
return err
}
c.Version = s.Version
c.ScriptHash = s.ScriptHash
c.Script = script
c.ParamList = s.ParamList
c.ReturnType = s.ReturnType
c.Name = s.Name
c.CodeVersion = s.CodeVersion
c.Author = s.Author
c.Email = s.Email
c.Description = s.Description
c.Properties = Properties{
HasStorage: s.Properties.HasStorage,
HasDynamicInvoke: s.Properties.HasDynamicInvoke,
IsPayable: s.Properties.IsPayable,
}
return nil
}