parent
7121686571
commit
15a939b1da
7 changed files with 112 additions and 5 deletions
|
@ -77,6 +77,11 @@ Both methods also don't currently support arrays in function parameters.
|
|||
It's possible to call this method for any address with neo-go, unlike with C#
|
||||
node where it only works for addresses from opened wallet.
|
||||
|
||||
##### `getcontractstate`
|
||||
|
||||
It's possible to get non-native contract state by its ID, unlike with C# node where
|
||||
it only works for native contracts.
|
||||
|
||||
### Unsupported methods
|
||||
|
||||
Methods listed down below are not going to be supported for various reasons
|
||||
|
|
|
@ -1073,6 +1073,15 @@ func (bc *Blockchain) GetContractScriptHash(id int32) (util.Uint160, error) {
|
|||
return bc.dao.GetContractScriptHash(id)
|
||||
}
|
||||
|
||||
// GetNativeContractScriptHash returns native contract script hash by its name.
|
||||
func (bc *Blockchain) GetNativeContractScriptHash(name string) (util.Uint160, error) {
|
||||
c := bc.contracts.ByName(name)
|
||||
if c != nil {
|
||||
return c.Metadata().Hash, nil
|
||||
}
|
||||
return util.Uint160{}, errors.New("Unknown native contract")
|
||||
}
|
||||
|
||||
// GetConfig returns the config stored in the blockchain.
|
||||
func (bc *Blockchain) GetConfig() config.ProtocolConfiguration {
|
||||
return bc.config
|
||||
|
|
|
@ -39,6 +39,7 @@ type Blockchainer interface {
|
|||
HasBlock(util.Uint256) bool
|
||||
HasTransaction(util.Uint256) bool
|
||||
GetAppExecResult(util.Uint256) (*state.AppExecResult, error)
|
||||
GetNativeContractScriptHash(string) (util.Uint160, error)
|
||||
GetNextBlockValidators() ([]*keys.PublicKey, error)
|
||||
GetNEP5Balances(util.Uint160) *state.NEP5Balances
|
||||
GetValidators() ([]*keys.PublicKey, error)
|
||||
|
|
|
@ -2,6 +2,7 @@ package native
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||
|
@ -35,6 +36,17 @@ func (cs *Contracts) ByHash(h util.Uint160) interop.Contract {
|
|||
return nil
|
||||
}
|
||||
|
||||
// ByName returns native contract with the specified name.
|
||||
func (cs *Contracts) ByName(name string) interop.Contract {
|
||||
name = strings.ToLower(name)
|
||||
for _, ctr := range cs.Contracts {
|
||||
if strings.ToLower(ctr.Metadata().Name) == name {
|
||||
return ctr
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewContracts returns new set of native contracts with new GAS, NEO and Policy
|
||||
// contracts.
|
||||
func NewContracts() *Contracts {
|
||||
|
|
|
@ -89,6 +89,9 @@ func (chain testChain) GetContractState(hash util.Uint160) *state.Contract {
|
|||
func (chain testChain) GetContractScriptHash(id int32) (util.Uint160, error) {
|
||||
panic("TODO")
|
||||
}
|
||||
func (chain testChain) GetNativeContractScriptHash(name string) (util.Uint160, error) {
|
||||
panic("TODO")
|
||||
}
|
||||
func (chain testChain) GetHeaderHash(int) util.Uint256 {
|
||||
return util.Uint256{}
|
||||
}
|
||||
|
|
|
@ -765,6 +765,42 @@ func (s *Server) contractIDFromParam(param *request.Param) (int32, *response.Err
|
|||
return result, nil
|
||||
}
|
||||
|
||||
// getContractScriptHashFromParam returns the contract script hash by hex contract hash, address, id or native contract name.
|
||||
func (s *Server) contractScriptHashFromParam(param *request.Param) (util.Uint160, *response.Error) {
|
||||
var result util.Uint160
|
||||
if param == nil {
|
||||
return result, response.ErrInvalidParams
|
||||
}
|
||||
switch param.Type {
|
||||
case request.StringT:
|
||||
var err error
|
||||
result, err = param.GetUint160FromAddressOrHex()
|
||||
if err == nil {
|
||||
return result, nil
|
||||
}
|
||||
name, err := param.GetString()
|
||||
if err != nil {
|
||||
return result, response.ErrInvalidParams
|
||||
}
|
||||
result, err = s.chain.GetNativeContractScriptHash(name)
|
||||
if err != nil {
|
||||
return result, response.NewRPCError("Unknown contract: querying by name is supported for native contracts only", "", nil)
|
||||
}
|
||||
case request.NumberT:
|
||||
id, err := param.GetInt()
|
||||
if err != nil {
|
||||
return result, response.ErrInvalidParams
|
||||
}
|
||||
result, err = s.chain.GetContractScriptHash(int32(id))
|
||||
if err != nil {
|
||||
return result, response.NewRPCError("Unknown contract", "", err)
|
||||
}
|
||||
default:
|
||||
return result, response.ErrInvalidParams
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (s *Server) getStorage(ps request.Params) (interface{}, *response.Error) {
|
||||
id, rErr := s.contractIDFromParam(ps.Value(0))
|
||||
if rErr == response.ErrUnknown {
|
||||
|
@ -828,11 +864,12 @@ func (s *Server) getTransactionHeight(ps request.Params) (interface{}, *response
|
|||
return height, nil
|
||||
}
|
||||
|
||||
// getContractState returns contract state (contract information, according to the contract script hash).
|
||||
// getContractState returns contract state (contract information, according to the contract script hash,
|
||||
// contract id or native contract name).
|
||||
func (s *Server) getContractState(reqParams request.Params) (interface{}, *response.Error) {
|
||||
scriptHash, err := reqParams.ValueWithType(0, request.StringT).GetUint160FromHex()
|
||||
scriptHash, err := s.contractScriptHashFromParam(reqParams.Value(0))
|
||||
if err != nil {
|
||||
return nil, response.ErrInvalidParams
|
||||
return nil, err
|
||||
}
|
||||
cs := s.chain.GetContractState(scriptHash)
|
||||
if cs == nil {
|
||||
|
|
|
@ -96,7 +96,7 @@ var rpcTestCases = map[string][]rpcTestCase{
|
|||
},
|
||||
"getcontractstate": {
|
||||
{
|
||||
name: "positive",
|
||||
name: "positive, by hash",
|
||||
params: fmt.Sprintf(`["%s"]`, testContractHash),
|
||||
result: func(e *executor) interface{} { return &state.Contract{} },
|
||||
check: func(t *testing.T, e *executor, cs interface{}) {
|
||||
|
@ -106,10 +106,50 @@ var rpcTestCases = map[string][]rpcTestCase{
|
|||
},
|
||||
},
|
||||
{
|
||||
name: "negative",
|
||||
name: "positive, by id",
|
||||
params: `[0]`,
|
||||
result: func(e *executor) interface{} { return &state.Contract{} },
|
||||
check: func(t *testing.T, e *executor, cs interface{}) {
|
||||
res, ok := cs.(*state.Contract)
|
||||
require.True(t, ok)
|
||||
assert.Equal(t, int32(0), res.ID)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "positive, native by id",
|
||||
params: `[-3]`,
|
||||
result: func(e *executor) interface{} { return &state.Contract{} },
|
||||
check: func(t *testing.T, e *executor, cs interface{}) {
|
||||
res, ok := cs.(*state.Contract)
|
||||
require.True(t, ok)
|
||||
assert.Equal(t, int32(-3), res.ID)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "positive, native by name",
|
||||
params: `["Policy"]`,
|
||||
result: func(e *executor) interface{} { return &state.Contract{} },
|
||||
check: func(t *testing.T, e *executor, cs interface{}) {
|
||||
res, ok := cs.(*state.Contract)
|
||||
require.True(t, ok)
|
||||
assert.Equal(t, int32(-3), res.ID)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "negative, bad hash",
|
||||
params: `["6d1eeca891ee93de2b7a77eb91c26f3b3c04d6c3"]`,
|
||||
fail: true,
|
||||
},
|
||||
{
|
||||
name: "negative, bad ID",
|
||||
params: `[-8]`,
|
||||
fail: true,
|
||||
},
|
||||
{
|
||||
name: "negative, bad native name",
|
||||
params: `["unknown_native"]`,
|
||||
fail: true,
|
||||
},
|
||||
{
|
||||
name: "no params",
|
||||
params: `[]`,
|
||||
|
|
Loading…
Reference in a new issue