Merge pull request #645 from nspcc-dev/feature/getstorage

rpc: implement getstorage RPC

Closes #343.
This commit is contained in:
Roman Khimov 2020-02-18 12:04:54 +03:00 committed by GitHub
commit 14f557026c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 111 additions and 3 deletions

View file

@ -50,7 +50,7 @@ which would yield the response:
| `getpeers` | Yes |
| `getrawmempool` | No (#175) |
| `getrawtransaction` | Yes |
| `getstorage` | No (#343) |
| `getstorage` | Yes |
| `gettxout` | Yes |
| `getunspents` | Yes |
| `getversion` | Yes |

View file

@ -214,6 +214,18 @@ func _(t *testing.T) {
t.Fatal(err)
}
script = io.NewBufBinWriter()
emit.String(script.BinWriter, "testvalue")
emit.String(script.BinWriter, "testkey")
emit.Int(script.BinWriter, 2)
emit.Opcode(script.BinWriter, opcode.PACK)
emit.String(script.BinWriter, "Put")
emit.AppCall(script.BinWriter, hash.Hash160(avm), false)
tx3 := transaction.NewInvocationTX(script.Bytes(), util.Fixed8FromFloat(100))
b := newBlock(uint32(n+2), newMinerTX(), tx3)
require.NoError(t, bc.AddBlock(b))
outStream, err := os.Create("../rpc/testdata/testblocks.acc")
if err != nil {
t.Fatal(err)

View file

@ -123,6 +123,14 @@ var (
Namespace: "neogo",
},
)
getstorageCalled = prometheus.NewCounter(
prometheus.CounterOpts{
Help: "Number of calls to getstorage rpc endpoint",
Name: "getstorage_called",
Namespace: "neogo",
},
)
)
func init() {
@ -142,5 +150,6 @@ func init() {
gettxoutCalled,
getrawtransactionCalled,
sendrawtransactionCalled,
getstorageCalled,
)
}

View file

@ -207,6 +207,10 @@ Methods:
results = peers
case "getstorage":
getstorageCalled.Inc()
results, resultsErr = s.getStorage(reqParams)
case "validateaddress":
validateaddressCalled.Inc()
param, ok := reqParams.Value(0)
@ -282,6 +286,37 @@ Methods:
s.WriteResponse(req, w, results)
}
func (s *Server) getStorage(ps Params) (interface{}, error) {
param, ok := ps.Value(0)
if !ok {
return nil, errInvalidParams
}
scriptHash, err := param.GetUint160FromHex()
if err != nil {
return nil, errInvalidParams
}
scriptHash = scriptHash.Reverse()
param, ok = ps.Value(1)
if !ok {
return nil, errInvalidParams
}
key, err := param.GetBytesHex()
if err != nil {
return nil, errInvalidParams
}
item := s.chain.GetStorageItem(scriptHash.Reverse(), key)
if item == nil {
return nil, nil
}
return hex.EncodeToString(item.Value), nil
}
func (s *Server) getrawtransaction(reqParams Params) (interface{}, error) {
var resultsErr error
var results interface{}

View file

@ -2,6 +2,7 @@ package rpc
import (
"bytes"
"encoding/hex"
"encoding/json"
"fmt"
"io/ioutil"
@ -75,13 +76,13 @@ var rpcTestCases = map[string][]rpcTestCase{
"getcontractstate": {
{
name: "positive",
params: `["6d1eeca891ee93de2b7a77eb91c26f3b3c04d6cf"]`,
params: `["1a696b32e239dd5eace3f025cac0a193a5746a27"]`,
result: func(e *executor) interface{} { return &GetContractStateResponce{} },
check: func(t *testing.T, e *executor, result interface{}) {
res, ok := result.(*GetContractStateResponce)
require.True(t, ok)
assert.Equal(t, byte(0), res.Result.Version)
assert.Equal(t, util.Uint160{0x6d, 0x1e, 0xec, 0xa8, 0x91, 0xee, 0x93, 0xde, 0x2b, 0x7a, 0x77, 0xeb, 0x91, 0xc2, 0x6f, 0x3b, 0x3c, 0x4, 0xd6, 0xcf}, res.Result.ScriptHash)
assert.Equal(t, util.Uint160{0x1a, 0x69, 0x6b, 0x32, 0xe2, 0x39, 0xdd, 0x5e, 0xac, 0xe3, 0xf0, 0x25, 0xca, 0xc0, 0xa1, 0x93, 0xa5, 0x74, 0x6a, 0x27}, res.Result.ScriptHash)
assert.Equal(t, "0.99", res.Result.CodeVersion)
},
},
@ -101,6 +102,48 @@ var rpcTestCases = map[string][]rpcTestCase{
fail: true,
},
},
"getstorage": {
{
name: "positive",
params: `["1a696b32e239dd5eace3f025cac0a193a5746a27", "746573746b6579"]`,
result: func(e *executor) interface{} { return &StringResultResponse{} },
check: func(t *testing.T, e *executor, result interface{}) {
res, ok := result.(*StringResultResponse)
require.True(t, ok)
assert.Equal(t, hex.EncodeToString([]byte("testvalue")), res.Result)
},
},
{
name: "missing key",
params: `["1a696b32e239dd5eace3f025cac0a193a5746a27", "7465"]`,
result: func(e *executor) interface{} { return &StringResultResponse{} },
check: func(t *testing.T, e *executor, result interface{}) {
res, ok := result.(*StringResultResponse)
require.True(t, ok)
assert.Equal(t, "", res.Result)
},
},
{
name: "no params",
params: `[]`,
fail: true,
},
{
name: "no second parameter",
params: `["1a696b32e239dd5eace3f025cac0a193a5746a27"]`,
fail: true,
},
{
name: "invalid hash",
params: `["notahex"]`,
fail: true,
},
{
name: "invalid key",
params: `["1a696b32e239dd5eace3f025cac0a193a5746a27", "notahex"]`,
fail: true,
},
},
"getassetstate": {
{
name: "positive",

Binary file not shown.

9
pkg/rpc/testdata/test_contract.go vendored Normal file
View file

@ -0,0 +1,9 @@
package testdata
import "github.com/CityOfZion/neo-go/pkg/interop/storage"
func Main(operation string, args []interface{}) interface{} {
ctx := storage.GetContext()
storage.Put(ctx, args[0].([]byte), args[1].([]byte))
return true
}

Binary file not shown.