2019-09-18 15:21:16 +00:00
|
|
|
package rpc
|
|
|
|
|
|
|
|
import (
|
|
|
|
"net/http"
|
2019-10-15 09:52:10 +00:00
|
|
|
"os"
|
2019-09-18 15:21:16 +00:00
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/CityOfZion/neo-go/config"
|
|
|
|
"github.com/CityOfZion/neo-go/pkg/core"
|
2020-01-14 12:32:07 +00:00
|
|
|
"github.com/CityOfZion/neo-go/pkg/core/block"
|
2019-09-18 15:21:16 +00:00
|
|
|
"github.com/CityOfZion/neo-go/pkg/core/storage"
|
2019-10-15 09:52:10 +00:00
|
|
|
"github.com/CityOfZion/neo-go/pkg/io"
|
2019-09-18 15:21:16 +00:00
|
|
|
"github.com/CityOfZion/neo-go/pkg/network"
|
2020-01-14 12:02:38 +00:00
|
|
|
"github.com/CityOfZion/neo-go/pkg/rpc/request"
|
2020-01-13 15:20:30 +00:00
|
|
|
"github.com/CityOfZion/neo-go/pkg/rpc/response/result"
|
2020-02-15 17:00:38 +00:00
|
|
|
"github.com/CityOfZion/neo-go/pkg/util"
|
2019-09-18 15:21:16 +00:00
|
|
|
"github.com/stretchr/testify/require"
|
2019-12-30 07:43:05 +00:00
|
|
|
"go.uber.org/zap/zaptest"
|
2019-09-18 15:21:16 +00:00
|
|
|
)
|
|
|
|
|
2019-09-24 15:47:23 +00:00
|
|
|
// ErrorResponse struct represents JSON-RPC error.
|
|
|
|
type ErrorResponse struct {
|
|
|
|
Jsonrpc string `json:"jsonrpc"`
|
|
|
|
Error struct {
|
|
|
|
Code int `json:"code"`
|
|
|
|
Message string `json:"message"`
|
|
|
|
} `json:"error"`
|
|
|
|
ID int `json:"id"`
|
|
|
|
}
|
|
|
|
|
2019-09-18 15:21:16 +00:00
|
|
|
// SendTXResponse struct for testing.
|
|
|
|
type SendTXResponse struct {
|
|
|
|
Jsonrpc string `json:"jsonrpc"`
|
|
|
|
Result bool `json:"result"`
|
|
|
|
ID int `json:"id"`
|
|
|
|
}
|
|
|
|
|
2019-11-26 10:13:17 +00:00
|
|
|
// InvokeFunctionResponse struct for testing.
|
|
|
|
type InvokeFunctionResponse struct {
|
|
|
|
Jsonrpc string `json:"jsonrpc"`
|
|
|
|
Result struct {
|
2020-01-14 12:02:38 +00:00
|
|
|
Script string `json:"script"`
|
|
|
|
State string `json:"state"`
|
|
|
|
GasConsumed string `json:"gas_consumed"`
|
|
|
|
Stack []request.FuncParam `json:"stack"`
|
|
|
|
TX string `json:"tx,omitempty"`
|
2019-11-26 10:13:17 +00:00
|
|
|
} `json:"result"`
|
|
|
|
ID int `json:"id"`
|
|
|
|
}
|
|
|
|
|
2019-09-18 15:21:16 +00:00
|
|
|
// ValidateAddrResponse struct for testing.
|
|
|
|
type ValidateAddrResponse struct {
|
2020-01-13 08:33:04 +00:00
|
|
|
Jsonrpc string `json:"jsonrpc"`
|
|
|
|
Result result.ValidateAddress `json:"result"`
|
|
|
|
ID int `json:"id"`
|
2019-09-18 15:21:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// GetPeersResponse struct for testing.
|
|
|
|
type GetPeersResponse struct {
|
|
|
|
Jsonrpc string `json:"jsonrpc"`
|
|
|
|
Result struct {
|
|
|
|
Unconnected []int `json:"unconnected"`
|
|
|
|
Connected []int `json:"connected"`
|
|
|
|
Bad []int `json:"bad"`
|
|
|
|
} `json:"result"`
|
|
|
|
ID int `json:"id"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetVersionResponse struct for testing.
|
|
|
|
type GetVersionResponse struct {
|
|
|
|
Jsonrpc string `json:"jsonrpc"`
|
|
|
|
Result result.Version `json:"result"`
|
|
|
|
ID int `json:"id"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// IntResultResponse struct for testing.
|
|
|
|
type IntResultResponse struct {
|
|
|
|
Jsonrpc string `json:"jsonrpc"`
|
|
|
|
Result int `json:"result"`
|
|
|
|
ID int `json:"id"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// StringResultResponse struct for testing.
|
|
|
|
type StringResultResponse struct {
|
|
|
|
Jsonrpc string `json:"jsonrpc"`
|
|
|
|
Result string `json:"result"`
|
|
|
|
ID int `json:"id"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetBlockResponse struct for testing.
|
|
|
|
type GetBlockResponse struct {
|
2020-01-13 10:21:44 +00:00
|
|
|
Jsonrpc string `json:"jsonrpc"`
|
|
|
|
Result result.Block `json:"result"`
|
|
|
|
ID int `json:"id"`
|
2019-09-18 15:21:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// GetAssetResponse struct for testing.
|
|
|
|
type GetAssetResponse struct {
|
|
|
|
Jsonrpc string `json:"jsonrpc"`
|
|
|
|
Result struct {
|
|
|
|
AssetID string `json:"assetID"`
|
|
|
|
AssetType int `json:"assetType"`
|
|
|
|
Name string `json:"name"`
|
|
|
|
Amount string `json:"amount"`
|
|
|
|
Available string `json:"available"`
|
|
|
|
Precision int `json:"precision"`
|
|
|
|
Fee int `json:"fee"`
|
|
|
|
Address string `json:"address"`
|
|
|
|
Owner string `json:"owner"`
|
|
|
|
Admin string `json:"admin"`
|
|
|
|
Issuer string `json:"issuer"`
|
|
|
|
Expiration int `json:"expiration"`
|
|
|
|
IsFrozen bool `json:"is_frozen"`
|
|
|
|
} `json:"result"`
|
|
|
|
ID int `json:"id"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetAccountStateResponse struct for testing.
|
|
|
|
type GetAccountStateResponse struct {
|
|
|
|
Jsonrpc string `json:"jsonrpc"`
|
|
|
|
Result struct {
|
|
|
|
Version int `json:"version"`
|
|
|
|
ScriptHash string `json:"script_hash"`
|
|
|
|
Frozen bool `json:"frozen"`
|
|
|
|
Votes []interface{} `json:"votes"`
|
|
|
|
Balances []struct {
|
|
|
|
Asset string `json:"asset"`
|
|
|
|
Value string `json:"value"`
|
|
|
|
} `json:"balances"`
|
|
|
|
} `json:"result"`
|
|
|
|
ID int `json:"id"`
|
2019-11-15 19:04:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// GetUnspents struct for testing.
|
|
|
|
type GetUnspents struct {
|
|
|
|
Jsonrpc string `json:"jsonrpc"`
|
|
|
|
Result struct {
|
|
|
|
Balance []struct {
|
|
|
|
Unspents []struct {
|
|
|
|
TxID string `json:"txid"`
|
|
|
|
Index int `json:"n"`
|
|
|
|
Value string `json:"value"`
|
|
|
|
} `json:"unspent"`
|
|
|
|
AssetHash string `json:"asset_hash"`
|
|
|
|
Asset string `json:"asset"`
|
|
|
|
AssetSymbol string `json:"asset_symbol"`
|
|
|
|
Amount string `json:"amount"`
|
|
|
|
} `json:"balance"`
|
|
|
|
Address string `json:"address"`
|
|
|
|
} `json:"result"`
|
|
|
|
ID int `json:"id"`
|
2019-09-18 15:21:16 +00:00
|
|
|
}
|
|
|
|
|
2020-02-15 17:00:38 +00:00
|
|
|
// GetContractStateResponse struct for testing.
|
|
|
|
type GetContractStateResponce struct {
|
|
|
|
Jsonrpc string `json:"jsonrpc"`
|
|
|
|
Result struct {
|
|
|
|
Version byte `json:"version"`
|
|
|
|
ScriptHash util.Uint160 `json:"hash"`
|
|
|
|
Script []byte `json:"script"`
|
|
|
|
ParamList interface{} `json:"parameters"`
|
|
|
|
ReturnType interface{} `json:"returntype"`
|
|
|
|
Name string `json:"name"`
|
|
|
|
CodeVersion string `json:"code_version"`
|
|
|
|
Author string `json:"author"`
|
|
|
|
Email string `json:"email"`
|
|
|
|
Description string `json:"description"`
|
|
|
|
Properties struct {
|
|
|
|
HasStorage bool `json:"storage"`
|
|
|
|
HasDynamicInvoke bool `json:"dynamic_invoke"`
|
|
|
|
IsPayable bool `json:"is_payable"`
|
|
|
|
} `json:"properties"`
|
|
|
|
} `json:"result"`
|
|
|
|
ID int `json:"id"`
|
|
|
|
}
|
|
|
|
|
2019-11-07 17:47:48 +00:00
|
|
|
func initServerWithInMemoryChain(t *testing.T) (*core.Blockchain, http.HandlerFunc) {
|
2019-10-15 09:52:10 +00:00
|
|
|
var nBlocks uint32
|
|
|
|
|
2019-09-18 15:21:16 +00:00
|
|
|
net := config.ModeUnitTestNet
|
|
|
|
configPath := "../../config"
|
|
|
|
cfg, err := config.Load(configPath, net)
|
|
|
|
require.NoError(t, err, "could not load config")
|
|
|
|
|
|
|
|
memoryStore := storage.NewMemoryStore()
|
2019-12-30 08:44:52 +00:00
|
|
|
logger := zaptest.NewLogger(t)
|
|
|
|
chain, err := core.NewBlockchain(memoryStore, cfg.ProtocolConfiguration, logger)
|
2019-09-18 15:21:16 +00:00
|
|
|
require.NoError(t, err, "could not create chain")
|
|
|
|
|
2019-11-07 17:47:48 +00:00
|
|
|
go chain.Run()
|
2019-10-15 09:52:10 +00:00
|
|
|
|
2020-02-17 12:04:25 +00:00
|
|
|
// File "./testdata/testblocks.acc" was generated by function core._
|
|
|
|
// ("neo-go/pkg/core/helper_test.go").
|
|
|
|
// To generate new "./testdata/testblocks.acc", follow the steps:
|
|
|
|
// 1. Rename the function
|
|
|
|
// 2. Add specific test-case into "neo-go/pkg/core/blockchain_test.go"
|
|
|
|
// 3. Run tests with `$ make test`
|
2020-02-15 17:00:38 +00:00
|
|
|
f, err := os.Open("testdata/testblocks.acc")
|
2019-10-15 09:52:10 +00:00
|
|
|
require.Nil(t, err)
|
|
|
|
br := io.NewBinReaderFromIO(f)
|
2019-12-12 15:52:23 +00:00
|
|
|
nBlocks = br.ReadU32LE()
|
2019-10-15 09:52:10 +00:00
|
|
|
require.Nil(t, br.Err)
|
|
|
|
for i := 0; i < int(nBlocks); i++ {
|
2020-01-14 12:32:07 +00:00
|
|
|
b := &block.Block{}
|
|
|
|
b.DecodeBinary(br)
|
2019-10-15 09:52:10 +00:00
|
|
|
require.Nil(t, br.Err)
|
2020-01-14 12:32:07 +00:00
|
|
|
require.NoError(t, chain.AddBlock(b))
|
2019-10-15 09:52:10 +00:00
|
|
|
}
|
2019-09-18 15:21:16 +00:00
|
|
|
|
|
|
|
serverConfig := network.NewServerConfig(cfg)
|
2020-01-22 08:17:51 +00:00
|
|
|
server, err := network.NewServer(serverConfig, chain, logger)
|
|
|
|
require.NoError(t, err)
|
2019-12-30 08:44:52 +00:00
|
|
|
rpcServer := NewServer(chain, cfg.ApplicationConfiguration.RPC, server, logger)
|
2019-09-18 15:21:16 +00:00
|
|
|
handler := http.HandlerFunc(rpcServer.requestHandler)
|
|
|
|
|
|
|
|
return chain, handler
|
|
|
|
}
|