2018-03-23 20:36:59 +00:00
|
|
|
package rpc
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2019-02-20 17:39:32 +00:00
|
|
|
"encoding/hex"
|
2018-03-23 20:36:59 +00:00
|
|
|
"fmt"
|
|
|
|
"net/http"
|
2019-01-25 11:20:35 +00:00
|
|
|
"strconv"
|
2018-03-23 20:36:59 +00:00
|
|
|
|
2019-11-01 10:23:46 +00:00
|
|
|
"github.com/CityOfZion/neo-go/config"
|
2018-03-23 20:36:59 +00:00
|
|
|
"github.com/CityOfZion/neo-go/pkg/core"
|
Implement rpc server method: sendrawtransaction (#174)
* Added new config attributes: 'SecondsPerBlock','LowPriorityThreshold'
* Added new files:
* Added new method: CompareTo
* Fixed empty Slice case
* Added new methods: LessThan, GreaterThan, Equal, CompareTo
* Added new method: InputIntersection
* Added MaxTransactionSize, GroupOutputByAssetID
* Added ned method: ScriptHash
* Added new method: IsDoubleSpend
* Refactor blockchainer, Added Feer interface, Verify and GetMemPool method
* 1) Added MemPool
2) Added new methods to satisfy the blockchainer interface: IsLowPriority, Verify, GetMemPool
* Added new methods: RelayTxn, RelayDirectly
* Fixed tests
* Implemented RPC server method sendrawtransaction
* Refactor getrawtransaction, sendrawtransaction in separate methods
* Moved 'secondsPerBlock' to config file
* Implemented Kim suggestions:
1) Fixed data race issues
2) refactor Verify method
3) Get rid of unused InputIntersection method due to refactoring Verify method
4) Fixed bug in https://github.com/CityOfZion/neo-go/pull/174#discussion_r264108135
5) minor simplications of the code
* Fixed minor issues related to
1) space
2) getter methods do not need pointer on the receiver
3) error message
4) refactoring CompareTo method in uint256.go
* Fixed small issues
* Use sync.RWMutex instead of sync.Mutex
* Refined (R)Lock/(R)Unlock
* return error instead of bool in Verify methods
2019-03-20 12:30:05 +00:00
|
|
|
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
2019-09-16 09:18:13 +00:00
|
|
|
"github.com/CityOfZion/neo-go/pkg/io"
|
2018-03-23 20:36:59 +00:00
|
|
|
"github.com/CityOfZion/neo-go/pkg/network"
|
|
|
|
"github.com/CityOfZion/neo-go/pkg/rpc/result"
|
2018-03-30 06:15:03 +00:00
|
|
|
"github.com/CityOfZion/neo-go/pkg/rpc/wrappers"
|
2018-03-23 20:36:59 +00:00
|
|
|
"github.com/CityOfZion/neo-go/pkg/util"
|
2019-02-08 08:04:38 +00:00
|
|
|
"github.com/pkg/errors"
|
2019-12-30 08:44:52 +00:00
|
|
|
"go.uber.org/zap"
|
2018-03-23 20:36:59 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type (
|
|
|
|
// Server represents the JSON-RPC 2.0 server.
|
|
|
|
Server struct {
|
|
|
|
*http.Server
|
|
|
|
chain core.Blockchainer
|
2019-11-01 10:23:46 +00:00
|
|
|
config config.RPCConfig
|
2018-03-23 20:36:59 +00:00
|
|
|
coreServer *network.Server
|
2019-12-30 08:44:52 +00:00
|
|
|
log *zap.Logger
|
2018-03-23 20:36:59 +00:00
|
|
|
}
|
|
|
|
)
|
|
|
|
|
2019-11-21 13:42:51 +00:00
|
|
|
var invalidBlockHeightError = func(index int, height int) error {
|
|
|
|
return errors.Errorf("Param at index %d should be greater than or equal to 0 and less then or equal to current block height, got: %d", index, height)
|
|
|
|
}
|
2018-03-25 10:13:47 +00:00
|
|
|
|
2018-03-23 20:36:59 +00:00
|
|
|
// NewServer creates a new Server struct.
|
2019-12-30 08:44:52 +00:00
|
|
|
func NewServer(chain core.Blockchainer, conf config.RPCConfig, coreServer *network.Server, log *zap.Logger) Server {
|
2019-11-01 10:23:46 +00:00
|
|
|
httpServer := &http.Server{
|
|
|
|
Addr: conf.Address + ":" + strconv.FormatUint(uint64(conf.Port), 10),
|
|
|
|
}
|
|
|
|
|
2018-03-23 20:36:59 +00:00
|
|
|
return Server{
|
2019-11-01 10:23:46 +00:00
|
|
|
Server: httpServer,
|
2018-03-23 20:36:59 +00:00
|
|
|
chain: chain,
|
2019-11-01 10:23:46 +00:00
|
|
|
config: conf,
|
2018-03-23 20:36:59 +00:00
|
|
|
coreServer: coreServer,
|
2019-12-30 08:44:52 +00:00
|
|
|
log: log,
|
2018-03-23 20:36:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Start creates a new JSON-RPC server
|
|
|
|
// listening on the configured port.
|
|
|
|
func (s *Server) Start(errChan chan error) {
|
2019-11-01 10:23:46 +00:00
|
|
|
if !s.config.Enabled {
|
2019-12-30 08:44:52 +00:00
|
|
|
s.log.Info("RPC server is not enabled")
|
2019-11-01 10:23:46 +00:00
|
|
|
return
|
|
|
|
}
|
2018-03-23 20:36:59 +00:00
|
|
|
s.Handler = http.HandlerFunc(s.requestHandler)
|
2019-12-30 08:44:52 +00:00
|
|
|
s.log.Info("starting rpc-server", zap.String("endpoint", s.Addr))
|
2018-03-23 20:36:59 +00:00
|
|
|
|
|
|
|
errChan <- s.ListenAndServe()
|
|
|
|
}
|
|
|
|
|
2019-10-22 14:56:03 +00:00
|
|
|
// Shutdown overrides the http.Server Shutdown
|
2018-03-23 20:36:59 +00:00
|
|
|
// method.
|
|
|
|
func (s *Server) Shutdown() error {
|
2019-12-30 08:44:52 +00:00
|
|
|
s.log.Info("shutting down rpc-server", zap.String("endpoint", s.Addr))
|
2018-03-23 20:36:59 +00:00
|
|
|
return s.Server.Shutdown(context.Background())
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Server) requestHandler(w http.ResponseWriter, httpRequest *http.Request) {
|
2019-12-30 10:42:33 +00:00
|
|
|
req := NewRequest()
|
2018-03-23 20:36:59 +00:00
|
|
|
|
|
|
|
if httpRequest.Method != "POST" {
|
2019-12-30 08:44:52 +00:00
|
|
|
s.WriteErrorResponse(
|
|
|
|
req,
|
2018-03-23 20:36:59 +00:00
|
|
|
w,
|
|
|
|
NewInvalidParamsError(
|
|
|
|
fmt.Sprintf("Invalid method '%s', please retry with 'POST'", httpRequest.Method), nil,
|
|
|
|
),
|
|
|
|
)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
err := req.DecodeData(httpRequest.Body)
|
|
|
|
if err != nil {
|
2019-12-30 08:44:52 +00:00
|
|
|
s.WriteErrorResponse(req, w, NewParseError("Problem parsing JSON-RPC request body", err))
|
2018-03-23 20:36:59 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
reqParams, err := req.Params()
|
|
|
|
if err != nil {
|
2019-12-30 08:44:52 +00:00
|
|
|
s.WriteErrorResponse(req, w, NewInvalidParamsError("Problem parsing request parameters", err))
|
2018-03-23 20:36:59 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
s.methodHandler(w, req, *reqParams)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Server) methodHandler(w http.ResponseWriter, req *Request, reqParams Params) {
|
2020-01-13 13:45:36 +00:00
|
|
|
s.log.Debug("processing rpc request",
|
2019-12-30 08:44:52 +00:00
|
|
|
zap.String("method", req.Method),
|
|
|
|
zap.String("params", fmt.Sprintf("%v", reqParams)))
|
2018-03-23 20:36:59 +00:00
|
|
|
|
2019-02-20 16:28:11 +00:00
|
|
|
var (
|
|
|
|
results interface{}
|
|
|
|
resultsErr error
|
|
|
|
)
|
2018-03-23 20:36:59 +00:00
|
|
|
|
2018-03-25 10:13:47 +00:00
|
|
|
Methods:
|
2018-03-23 20:36:59 +00:00
|
|
|
switch req.Method {
|
|
|
|
case "getbestblockhash":
|
2019-10-29 17:51:17 +00:00
|
|
|
getbestblockhashCalled.Inc()
|
2019-11-27 09:23:18 +00:00
|
|
|
results = "0x" + s.chain.CurrentBlockHash().StringLE()
|
2018-03-23 20:36:59 +00:00
|
|
|
|
|
|
|
case "getblock":
|
2019-10-29 17:51:17 +00:00
|
|
|
getbestblockCalled.Inc()
|
2018-03-23 20:36:59 +00:00
|
|
|
var hash util.Uint256
|
|
|
|
|
2019-11-21 13:42:51 +00:00
|
|
|
param, ok := reqParams.Value(0)
|
|
|
|
if !ok {
|
|
|
|
resultsErr = errInvalidParams
|
2019-02-20 16:28:11 +00:00
|
|
|
break Methods
|
2018-03-23 20:36:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
switch param.Type {
|
2019-11-21 13:42:51 +00:00
|
|
|
case stringT:
|
|
|
|
var err error
|
|
|
|
hash, err = param.GetUint256()
|
2018-03-23 20:36:59 +00:00
|
|
|
if err != nil {
|
2019-02-20 16:28:11 +00:00
|
|
|
resultsErr = errInvalidParams
|
|
|
|
break Methods
|
2018-03-23 20:36:59 +00:00
|
|
|
}
|
2019-11-21 13:42:51 +00:00
|
|
|
case numberT:
|
2019-11-26 10:13:17 +00:00
|
|
|
num, err := s.blockHeightFromParam(param)
|
|
|
|
if err != nil {
|
2019-02-20 16:28:11 +00:00
|
|
|
resultsErr = errInvalidParams
|
2018-03-25 10:13:47 +00:00
|
|
|
break Methods
|
|
|
|
}
|
2019-11-26 10:13:17 +00:00
|
|
|
hash = s.chain.GetHeaderHash(num)
|
2019-11-26 10:31:11 +00:00
|
|
|
default:
|
2019-02-20 16:28:11 +00:00
|
|
|
resultsErr = errInvalidParams
|
|
|
|
break Methods
|
2018-03-23 20:36:59 +00:00
|
|
|
}
|
|
|
|
|
2018-03-30 06:15:03 +00:00
|
|
|
block, err := s.chain.GetBlock(hash)
|
2018-03-23 20:36:59 +00:00
|
|
|
if err != nil {
|
|
|
|
resultsErr = NewInternalServerError(fmt.Sprintf("Problem locating block with hash: %s", hash), err)
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
2019-12-24 20:01:16 +00:00
|
|
|
if len(reqParams) == 2 && reqParams[1].Value == 1 {
|
|
|
|
results = wrappers.NewBlock(block, s.chain)
|
|
|
|
} else {
|
|
|
|
writer := io.NewBufBinWriter()
|
|
|
|
block.EncodeBinary(writer.BinWriter)
|
|
|
|
results = hex.EncodeToString(writer.Bytes())
|
|
|
|
}
|
|
|
|
|
2018-03-23 20:36:59 +00:00
|
|
|
case "getblockcount":
|
2019-10-29 17:51:17 +00:00
|
|
|
getblockcountCalled.Inc()
|
2019-11-01 17:13:00 +00:00
|
|
|
results = s.chain.BlockHeight() + 1
|
2018-03-23 20:36:59 +00:00
|
|
|
|
|
|
|
case "getblockhash":
|
2019-10-29 17:51:17 +00:00
|
|
|
getblockHashCalled.Inc()
|
2019-11-21 13:42:51 +00:00
|
|
|
param, ok := reqParams.ValueWithType(0, numberT)
|
|
|
|
if !ok {
|
|
|
|
resultsErr = errInvalidParams
|
2019-02-20 16:28:11 +00:00
|
|
|
break Methods
|
2019-11-26 10:13:17 +00:00
|
|
|
}
|
|
|
|
num, err := s.blockHeightFromParam(param)
|
|
|
|
if err != nil {
|
|
|
|
resultsErr = errInvalidParams
|
2019-02-20 16:28:11 +00:00
|
|
|
break Methods
|
2018-03-23 20:36:59 +00:00
|
|
|
}
|
|
|
|
|
2019-11-26 10:13:17 +00:00
|
|
|
results = s.chain.GetHeaderHash(num)
|
2019-02-20 16:28:11 +00:00
|
|
|
|
2018-03-23 20:36:59 +00:00
|
|
|
case "getconnectioncount":
|
2019-10-29 17:51:17 +00:00
|
|
|
getconnectioncountCalled.Inc()
|
2018-03-23 20:36:59 +00:00
|
|
|
results = s.coreServer.PeerCount()
|
|
|
|
|
|
|
|
case "getversion":
|
2019-10-29 17:51:17 +00:00
|
|
|
getversionCalled.Inc()
|
2018-03-23 20:36:59 +00:00
|
|
|
results = result.Version{
|
2019-11-05 12:22:07 +00:00
|
|
|
Port: s.coreServer.Port,
|
2018-03-23 20:36:59 +00:00
|
|
|
Nonce: s.coreServer.ID(),
|
|
|
|
UserAgent: s.coreServer.UserAgent,
|
|
|
|
}
|
|
|
|
|
|
|
|
case "getpeers":
|
2019-10-29 17:51:17 +00:00
|
|
|
getpeersCalled.Inc()
|
2018-03-23 20:36:59 +00:00
|
|
|
peers := result.NewPeers()
|
|
|
|
for _, addr := range s.coreServer.UnconnectedPeers() {
|
|
|
|
peers.AddPeer("unconnected", addr)
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, addr := range s.coreServer.BadPeers() {
|
|
|
|
peers.AddPeer("bad", addr)
|
|
|
|
}
|
|
|
|
|
|
|
|
for addr := range s.coreServer.Peers() {
|
2019-11-06 07:55:21 +00:00
|
|
|
peers.AddPeer("connected", addr.PeerAddr().String())
|
2018-03-23 20:36:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
results = peers
|
|
|
|
|
2019-02-13 18:18:47 +00:00
|
|
|
case "validateaddress":
|
2019-10-29 17:51:17 +00:00
|
|
|
validateaddressCalled.Inc()
|
2019-11-21 13:42:51 +00:00
|
|
|
param, ok := reqParams.Value(0)
|
|
|
|
if !ok {
|
|
|
|
resultsErr = errInvalidParams
|
2019-02-20 16:28:11 +00:00
|
|
|
break Methods
|
2019-02-13 18:18:47 +00:00
|
|
|
}
|
2019-11-21 13:42:51 +00:00
|
|
|
results = wrappers.ValidateAddress(param.Value)
|
2019-02-13 18:18:47 +00:00
|
|
|
|
2018-11-26 21:12:33 +00:00
|
|
|
case "getassetstate":
|
2019-10-29 17:51:17 +00:00
|
|
|
getassetstateCalled.Inc()
|
2019-11-21 13:42:51 +00:00
|
|
|
param, ok := reqParams.ValueWithType(0, stringT)
|
|
|
|
if !ok {
|
|
|
|
resultsErr = errInvalidParams
|
2019-02-20 16:28:11 +00:00
|
|
|
break Methods
|
2018-11-26 21:12:33 +00:00
|
|
|
}
|
|
|
|
|
2019-11-21 13:42:51 +00:00
|
|
|
paramAssetID, err := param.GetUint256()
|
2019-02-08 08:04:38 +00:00
|
|
|
if err != nil {
|
2019-02-20 16:28:11 +00:00
|
|
|
resultsErr = errInvalidParams
|
2018-11-26 21:12:33 +00:00
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
as := s.chain.GetAssetState(paramAssetID)
|
|
|
|
if as != nil {
|
|
|
|
results = wrappers.NewAssetState(as)
|
|
|
|
} else {
|
|
|
|
results = "Invalid assetid"
|
|
|
|
}
|
|
|
|
|
2019-02-08 08:04:38 +00:00
|
|
|
case "getaccountstate":
|
2019-10-29 17:51:17 +00:00
|
|
|
getaccountstateCalled.Inc()
|
2019-11-15 19:04:10 +00:00
|
|
|
results, resultsErr = s.getAccountState(reqParams, false)
|
|
|
|
|
2019-02-20 17:39:32 +00:00
|
|
|
case "getrawtransaction":
|
2019-10-29 17:51:17 +00:00
|
|
|
getrawtransactionCalled.Inc()
|
Implement rpc server method: sendrawtransaction (#174)
* Added new config attributes: 'SecondsPerBlock','LowPriorityThreshold'
* Added new files:
* Added new method: CompareTo
* Fixed empty Slice case
* Added new methods: LessThan, GreaterThan, Equal, CompareTo
* Added new method: InputIntersection
* Added MaxTransactionSize, GroupOutputByAssetID
* Added ned method: ScriptHash
* Added new method: IsDoubleSpend
* Refactor blockchainer, Added Feer interface, Verify and GetMemPool method
* 1) Added MemPool
2) Added new methods to satisfy the blockchainer interface: IsLowPriority, Verify, GetMemPool
* Added new methods: RelayTxn, RelayDirectly
* Fixed tests
* Implemented RPC server method sendrawtransaction
* Refactor getrawtransaction, sendrawtransaction in separate methods
* Moved 'secondsPerBlock' to config file
* Implemented Kim suggestions:
1) Fixed data race issues
2) refactor Verify method
3) Get rid of unused InputIntersection method due to refactoring Verify method
4) Fixed bug in https://github.com/CityOfZion/neo-go/pull/174#discussion_r264108135
5) minor simplications of the code
* Fixed minor issues related to
1) space
2) getter methods do not need pointer on the receiver
3) error message
4) refactoring CompareTo method in uint256.go
* Fixed small issues
* Use sync.RWMutex instead of sync.Mutex
* Refined (R)Lock/(R)Unlock
* return error instead of bool in Verify methods
2019-03-20 12:30:05 +00:00
|
|
|
results, resultsErr = s.getrawtransaction(reqParams)
|
2019-02-20 17:39:32 +00:00
|
|
|
|
2019-11-15 19:04:10 +00:00
|
|
|
case "getunspents":
|
|
|
|
getunspentsCalled.Inc()
|
|
|
|
results, resultsErr = s.getAccountState(reqParams, true)
|
|
|
|
|
2019-11-28 16:08:31 +00:00
|
|
|
case "invoke":
|
|
|
|
results, resultsErr = s.invoke(reqParams)
|
|
|
|
|
2019-11-26 10:13:17 +00:00
|
|
|
case "invokefunction":
|
|
|
|
results, resultsErr = s.invokeFunction(reqParams)
|
|
|
|
|
2019-10-29 15:31:39 +00:00
|
|
|
case "invokescript":
|
|
|
|
results, resultsErr = s.invokescript(reqParams)
|
|
|
|
|
Implement rpc server method: sendrawtransaction (#174)
* Added new config attributes: 'SecondsPerBlock','LowPriorityThreshold'
* Added new files:
* Added new method: CompareTo
* Fixed empty Slice case
* Added new methods: LessThan, GreaterThan, Equal, CompareTo
* Added new method: InputIntersection
* Added MaxTransactionSize, GroupOutputByAssetID
* Added ned method: ScriptHash
* Added new method: IsDoubleSpend
* Refactor blockchainer, Added Feer interface, Verify and GetMemPool method
* 1) Added MemPool
2) Added new methods to satisfy the blockchainer interface: IsLowPriority, Verify, GetMemPool
* Added new methods: RelayTxn, RelayDirectly
* Fixed tests
* Implemented RPC server method sendrawtransaction
* Refactor getrawtransaction, sendrawtransaction in separate methods
* Moved 'secondsPerBlock' to config file
* Implemented Kim suggestions:
1) Fixed data race issues
2) refactor Verify method
3) Get rid of unused InputIntersection method due to refactoring Verify method
4) Fixed bug in https://github.com/CityOfZion/neo-go/pull/174#discussion_r264108135
5) minor simplications of the code
* Fixed minor issues related to
1) space
2) getter methods do not need pointer on the receiver
3) error message
4) refactoring CompareTo method in uint256.go
* Fixed small issues
* Use sync.RWMutex instead of sync.Mutex
* Refined (R)Lock/(R)Unlock
* return error instead of bool in Verify methods
2019-03-20 12:30:05 +00:00
|
|
|
case "sendrawtransaction":
|
2019-10-29 17:51:17 +00:00
|
|
|
sendrawtransactionCalled.Inc()
|
Implement rpc server method: sendrawtransaction (#174)
* Added new config attributes: 'SecondsPerBlock','LowPriorityThreshold'
* Added new files:
* Added new method: CompareTo
* Fixed empty Slice case
* Added new methods: LessThan, GreaterThan, Equal, CompareTo
* Added new method: InputIntersection
* Added MaxTransactionSize, GroupOutputByAssetID
* Added ned method: ScriptHash
* Added new method: IsDoubleSpend
* Refactor blockchainer, Added Feer interface, Verify and GetMemPool method
* 1) Added MemPool
2) Added new methods to satisfy the blockchainer interface: IsLowPriority, Verify, GetMemPool
* Added new methods: RelayTxn, RelayDirectly
* Fixed tests
* Implemented RPC server method sendrawtransaction
* Refactor getrawtransaction, sendrawtransaction in separate methods
* Moved 'secondsPerBlock' to config file
* Implemented Kim suggestions:
1) Fixed data race issues
2) refactor Verify method
3) Get rid of unused InputIntersection method due to refactoring Verify method
4) Fixed bug in https://github.com/CityOfZion/neo-go/pull/174#discussion_r264108135
5) minor simplications of the code
* Fixed minor issues related to
1) space
2) getter methods do not need pointer on the receiver
3) error message
4) refactoring CompareTo method in uint256.go
* Fixed small issues
* Use sync.RWMutex instead of sync.Mutex
* Refined (R)Lock/(R)Unlock
* return error instead of bool in Verify methods
2019-03-20 12:30:05 +00:00
|
|
|
results, resultsErr = s.sendrawtransaction(reqParams)
|
2019-02-08 08:04:38 +00:00
|
|
|
|
2018-03-23 20:36:59 +00:00
|
|
|
default:
|
|
|
|
resultsErr = NewMethodNotFoundError(fmt.Sprintf("Method '%s' not supported", req.Method), nil)
|
|
|
|
}
|
|
|
|
|
|
|
|
if resultsErr != nil {
|
2019-12-30 08:44:52 +00:00
|
|
|
s.WriteErrorResponse(req, w, resultsErr)
|
2018-03-25 10:13:47 +00:00
|
|
|
return
|
2018-03-23 20:36:59 +00:00
|
|
|
}
|
|
|
|
|
2019-12-30 08:44:52 +00:00
|
|
|
s.WriteResponse(req, w, results)
|
2018-03-25 10:13:47 +00:00
|
|
|
}
|
|
|
|
|
Implement rpc server method: sendrawtransaction (#174)
* Added new config attributes: 'SecondsPerBlock','LowPriorityThreshold'
* Added new files:
* Added new method: CompareTo
* Fixed empty Slice case
* Added new methods: LessThan, GreaterThan, Equal, CompareTo
* Added new method: InputIntersection
* Added MaxTransactionSize, GroupOutputByAssetID
* Added ned method: ScriptHash
* Added new method: IsDoubleSpend
* Refactor blockchainer, Added Feer interface, Verify and GetMemPool method
* 1) Added MemPool
2) Added new methods to satisfy the blockchainer interface: IsLowPriority, Verify, GetMemPool
* Added new methods: RelayTxn, RelayDirectly
* Fixed tests
* Implemented RPC server method sendrawtransaction
* Refactor getrawtransaction, sendrawtransaction in separate methods
* Moved 'secondsPerBlock' to config file
* Implemented Kim suggestions:
1) Fixed data race issues
2) refactor Verify method
3) Get rid of unused InputIntersection method due to refactoring Verify method
4) Fixed bug in https://github.com/CityOfZion/neo-go/pull/174#discussion_r264108135
5) minor simplications of the code
* Fixed minor issues related to
1) space
2) getter methods do not need pointer on the receiver
3) error message
4) refactoring CompareTo method in uint256.go
* Fixed small issues
* Use sync.RWMutex instead of sync.Mutex
* Refined (R)Lock/(R)Unlock
* return error instead of bool in Verify methods
2019-03-20 12:30:05 +00:00
|
|
|
func (s *Server) getrawtransaction(reqParams Params) (interface{}, error) {
|
|
|
|
var resultsErr error
|
|
|
|
var results interface{}
|
|
|
|
|
2019-11-21 13:42:51 +00:00
|
|
|
if param0, ok := reqParams.Value(0); !ok {
|
|
|
|
return nil, errInvalidParams
|
|
|
|
} else if txHash, err := param0.GetUint256(); err != nil {
|
Implement rpc server method: sendrawtransaction (#174)
* Added new config attributes: 'SecondsPerBlock','LowPriorityThreshold'
* Added new files:
* Added new method: CompareTo
* Fixed empty Slice case
* Added new methods: LessThan, GreaterThan, Equal, CompareTo
* Added new method: InputIntersection
* Added MaxTransactionSize, GroupOutputByAssetID
* Added ned method: ScriptHash
* Added new method: IsDoubleSpend
* Refactor blockchainer, Added Feer interface, Verify and GetMemPool method
* 1) Added MemPool
2) Added new methods to satisfy the blockchainer interface: IsLowPriority, Verify, GetMemPool
* Added new methods: RelayTxn, RelayDirectly
* Fixed tests
* Implemented RPC server method sendrawtransaction
* Refactor getrawtransaction, sendrawtransaction in separate methods
* Moved 'secondsPerBlock' to config file
* Implemented Kim suggestions:
1) Fixed data race issues
2) refactor Verify method
3) Get rid of unused InputIntersection method due to refactoring Verify method
4) Fixed bug in https://github.com/CityOfZion/neo-go/pull/174#discussion_r264108135
5) minor simplications of the code
* Fixed minor issues related to
1) space
2) getter methods do not need pointer on the receiver
3) error message
4) refactoring CompareTo method in uint256.go
* Fixed small issues
* Use sync.RWMutex instead of sync.Mutex
* Refined (R)Lock/(R)Unlock
* return error instead of bool in Verify methods
2019-03-20 12:30:05 +00:00
|
|
|
resultsErr = errInvalidParams
|
|
|
|
} else if tx, height, err := s.chain.GetTransaction(txHash); err != nil {
|
|
|
|
err = errors.Wrapf(err, "Invalid transaction hash: %s", txHash)
|
2019-11-21 13:42:51 +00:00
|
|
|
return nil, NewInvalidParamsError(err.Error(), err)
|
Implement rpc server method: sendrawtransaction (#174)
* Added new config attributes: 'SecondsPerBlock','LowPriorityThreshold'
* Added new files:
* Added new method: CompareTo
* Fixed empty Slice case
* Added new methods: LessThan, GreaterThan, Equal, CompareTo
* Added new method: InputIntersection
* Added MaxTransactionSize, GroupOutputByAssetID
* Added ned method: ScriptHash
* Added new method: IsDoubleSpend
* Refactor blockchainer, Added Feer interface, Verify and GetMemPool method
* 1) Added MemPool
2) Added new methods to satisfy the blockchainer interface: IsLowPriority, Verify, GetMemPool
* Added new methods: RelayTxn, RelayDirectly
* Fixed tests
* Implemented RPC server method sendrawtransaction
* Refactor getrawtransaction, sendrawtransaction in separate methods
* Moved 'secondsPerBlock' to config file
* Implemented Kim suggestions:
1) Fixed data race issues
2) refactor Verify method
3) Get rid of unused InputIntersection method due to refactoring Verify method
4) Fixed bug in https://github.com/CityOfZion/neo-go/pull/174#discussion_r264108135
5) minor simplications of the code
* Fixed minor issues related to
1) space
2) getter methods do not need pointer on the receiver
3) error message
4) refactoring CompareTo method in uint256.go
* Fixed small issues
* Use sync.RWMutex instead of sync.Mutex
* Refined (R)Lock/(R)Unlock
* return error instead of bool in Verify methods
2019-03-20 12:30:05 +00:00
|
|
|
} else if len(reqParams) >= 2 {
|
|
|
|
_header := s.chain.GetHeaderHash(int(height))
|
|
|
|
header, err := s.chain.GetHeader(_header)
|
|
|
|
if err != nil {
|
|
|
|
resultsErr = NewInvalidParamsError(err.Error(), err)
|
|
|
|
}
|
|
|
|
|
2019-11-21 13:42:51 +00:00
|
|
|
param1, _ := reqParams.Value(1)
|
|
|
|
switch v := param1.Value.(type) {
|
Implement rpc server method: sendrawtransaction (#174)
* Added new config attributes: 'SecondsPerBlock','LowPriorityThreshold'
* Added new files:
* Added new method: CompareTo
* Fixed empty Slice case
* Added new methods: LessThan, GreaterThan, Equal, CompareTo
* Added new method: InputIntersection
* Added MaxTransactionSize, GroupOutputByAssetID
* Added ned method: ScriptHash
* Added new method: IsDoubleSpend
* Refactor blockchainer, Added Feer interface, Verify and GetMemPool method
* 1) Added MemPool
2) Added new methods to satisfy the blockchainer interface: IsLowPriority, Verify, GetMemPool
* Added new methods: RelayTxn, RelayDirectly
* Fixed tests
* Implemented RPC server method sendrawtransaction
* Refactor getrawtransaction, sendrawtransaction in separate methods
* Moved 'secondsPerBlock' to config file
* Implemented Kim suggestions:
1) Fixed data race issues
2) refactor Verify method
3) Get rid of unused InputIntersection method due to refactoring Verify method
4) Fixed bug in https://github.com/CityOfZion/neo-go/pull/174#discussion_r264108135
5) minor simplications of the code
* Fixed minor issues related to
1) space
2) getter methods do not need pointer on the receiver
3) error message
4) refactoring CompareTo method in uint256.go
* Fixed small issues
* Use sync.RWMutex instead of sync.Mutex
* Refined (R)Lock/(R)Unlock
* return error instead of bool in Verify methods
2019-03-20 12:30:05 +00:00
|
|
|
|
|
|
|
case int, float64, bool, string:
|
|
|
|
if v == 0 || v == "0" || v == 0.0 || v == false || v == "false" {
|
|
|
|
results = hex.EncodeToString(tx.Bytes())
|
|
|
|
} else {
|
|
|
|
results = wrappers.NewTransactionOutputRaw(tx, header, s.chain)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
results = wrappers.NewTransactionOutputRaw(tx, header, s.chain)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
results = hex.EncodeToString(tx.Bytes())
|
|
|
|
}
|
|
|
|
|
|
|
|
return results, resultsErr
|
|
|
|
}
|
|
|
|
|
2019-11-15 19:04:10 +00:00
|
|
|
// getAccountState returns account state either in short or full (unspents included) form.
|
|
|
|
func (s *Server) getAccountState(reqParams Params, unspents bool) (interface{}, error) {
|
|
|
|
var resultsErr error
|
|
|
|
var results interface{}
|
|
|
|
|
2019-11-21 13:42:51 +00:00
|
|
|
param, ok := reqParams.ValueWithType(0, stringT)
|
|
|
|
if !ok {
|
|
|
|
return nil, errInvalidParams
|
2019-11-26 10:13:17 +00:00
|
|
|
} else if scriptHash, err := param.GetUint160FromAddress(); err != nil {
|
2019-11-21 13:42:51 +00:00
|
|
|
return nil, errInvalidParams
|
2019-11-15 19:04:10 +00:00
|
|
|
} else if as := s.chain.GetAccountState(scriptHash); as != nil {
|
|
|
|
if unspents {
|
2019-11-26 10:13:17 +00:00
|
|
|
str, err := param.GetString()
|
|
|
|
if err != nil {
|
|
|
|
return nil, errInvalidParams
|
|
|
|
}
|
|
|
|
results = wrappers.NewUnspents(as, s.chain, str)
|
2019-11-15 19:04:10 +00:00
|
|
|
} else {
|
|
|
|
results = wrappers.NewAccountState(as)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
results = "Invalid public account address"
|
|
|
|
}
|
|
|
|
return results, resultsErr
|
|
|
|
}
|
|
|
|
|
2019-11-28 16:08:31 +00:00
|
|
|
// invoke implements the `invoke` RPC call.
|
|
|
|
func (s *Server) invoke(reqParams Params) (interface{}, error) {
|
|
|
|
scriptHashHex, ok := reqParams.ValueWithType(0, stringT)
|
|
|
|
if !ok {
|
|
|
|
return nil, errInvalidParams
|
|
|
|
}
|
|
|
|
scriptHash, err := scriptHashHex.GetUint160FromHex()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
sliceP, ok := reqParams.ValueWithType(1, arrayT)
|
|
|
|
if !ok {
|
|
|
|
return nil, errInvalidParams
|
|
|
|
}
|
|
|
|
slice, err := sliceP.GetArray()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
script, err := CreateInvocationScript(scriptHash, slice)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2019-11-28 16:12:23 +00:00
|
|
|
return s.runScriptInVM(script), nil
|
2019-11-28 16:08:31 +00:00
|
|
|
}
|
|
|
|
|
2019-11-26 10:13:17 +00:00
|
|
|
// invokescript implements the `invokescript` RPC call.
|
|
|
|
func (s *Server) invokeFunction(reqParams Params) (interface{}, error) {
|
|
|
|
scriptHashHex, ok := reqParams.ValueWithType(0, stringT)
|
|
|
|
if !ok {
|
|
|
|
return nil, errInvalidParams
|
|
|
|
}
|
|
|
|
scriptHash, err := scriptHashHex.GetUint160FromHex()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
script, err := CreateFunctionInvocationScript(scriptHash, reqParams[1:])
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2019-11-28 16:12:23 +00:00
|
|
|
return s.runScriptInVM(script), nil
|
2019-11-26 10:13:17 +00:00
|
|
|
}
|
|
|
|
|
2019-10-29 15:31:39 +00:00
|
|
|
// invokescript implements the `invokescript` RPC call.
|
|
|
|
func (s *Server) invokescript(reqParams Params) (interface{}, error) {
|
2019-11-21 14:42:02 +00:00
|
|
|
if len(reqParams) < 1 {
|
2019-11-21 13:42:51 +00:00
|
|
|
return nil, errInvalidParams
|
2019-10-29 15:31:39 +00:00
|
|
|
}
|
2019-11-21 14:42:02 +00:00
|
|
|
|
|
|
|
script, err := reqParams[0].GetBytesHex()
|
2019-10-29 15:31:39 +00:00
|
|
|
if err != nil {
|
2019-11-21 14:42:02 +00:00
|
|
|
return nil, errInvalidParams
|
2019-10-29 15:31:39 +00:00
|
|
|
}
|
2019-11-21 14:42:02 +00:00
|
|
|
|
2019-11-28 16:12:23 +00:00
|
|
|
return s.runScriptInVM(script), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// runScriptInVM runs given script in a new test VM and returns the invocation
|
|
|
|
// result.
|
|
|
|
func (s *Server) runScriptInVM(script []byte) *wrappers.InvokeResult {
|
2019-10-29 15:31:39 +00:00
|
|
|
vm, _ := s.chain.GetTestVM()
|
2020-01-21 12:42:56 +00:00
|
|
|
vm.SetGasLimit(s.config.MaxGasInvoke)
|
2019-10-29 15:31:39 +00:00
|
|
|
vm.LoadScript(script)
|
|
|
|
_ = vm.Run()
|
|
|
|
result := &wrappers.InvokeResult{
|
|
|
|
State: vm.State(),
|
2020-01-21 12:37:47 +00:00
|
|
|
GasConsumed: vm.GasConsumed().String(),
|
2019-11-28 16:12:23 +00:00
|
|
|
Script: hex.EncodeToString(script),
|
2019-10-29 15:31:39 +00:00
|
|
|
Stack: vm.Estack(),
|
|
|
|
}
|
2019-11-28 16:12:23 +00:00
|
|
|
return result
|
2019-10-29 15:31:39 +00:00
|
|
|
}
|
|
|
|
|
Implement rpc server method: sendrawtransaction (#174)
* Added new config attributes: 'SecondsPerBlock','LowPriorityThreshold'
* Added new files:
* Added new method: CompareTo
* Fixed empty Slice case
* Added new methods: LessThan, GreaterThan, Equal, CompareTo
* Added new method: InputIntersection
* Added MaxTransactionSize, GroupOutputByAssetID
* Added ned method: ScriptHash
* Added new method: IsDoubleSpend
* Refactor blockchainer, Added Feer interface, Verify and GetMemPool method
* 1) Added MemPool
2) Added new methods to satisfy the blockchainer interface: IsLowPriority, Verify, GetMemPool
* Added new methods: RelayTxn, RelayDirectly
* Fixed tests
* Implemented RPC server method sendrawtransaction
* Refactor getrawtransaction, sendrawtransaction in separate methods
* Moved 'secondsPerBlock' to config file
* Implemented Kim suggestions:
1) Fixed data race issues
2) refactor Verify method
3) Get rid of unused InputIntersection method due to refactoring Verify method
4) Fixed bug in https://github.com/CityOfZion/neo-go/pull/174#discussion_r264108135
5) minor simplications of the code
* Fixed minor issues related to
1) space
2) getter methods do not need pointer on the receiver
3) error message
4) refactoring CompareTo method in uint256.go
* Fixed small issues
* Use sync.RWMutex instead of sync.Mutex
* Refined (R)Lock/(R)Unlock
* return error instead of bool in Verify methods
2019-03-20 12:30:05 +00:00
|
|
|
func (s *Server) sendrawtransaction(reqParams Params) (interface{}, error) {
|
|
|
|
var resultsErr error
|
|
|
|
var results interface{}
|
|
|
|
|
2019-11-21 14:42:02 +00:00
|
|
|
if len(reqParams) < 1 {
|
|
|
|
return nil, errInvalidParams
|
|
|
|
} else if byteTx, err := reqParams[0].GetBytesHex(); err != nil {
|
|
|
|
return nil, errInvalidParams
|
Implement rpc server method: sendrawtransaction (#174)
* Added new config attributes: 'SecondsPerBlock','LowPriorityThreshold'
* Added new files:
* Added new method: CompareTo
* Fixed empty Slice case
* Added new methods: LessThan, GreaterThan, Equal, CompareTo
* Added new method: InputIntersection
* Added MaxTransactionSize, GroupOutputByAssetID
* Added ned method: ScriptHash
* Added new method: IsDoubleSpend
* Refactor blockchainer, Added Feer interface, Verify and GetMemPool method
* 1) Added MemPool
2) Added new methods to satisfy the blockchainer interface: IsLowPriority, Verify, GetMemPool
* Added new methods: RelayTxn, RelayDirectly
* Fixed tests
* Implemented RPC server method sendrawtransaction
* Refactor getrawtransaction, sendrawtransaction in separate methods
* Moved 'secondsPerBlock' to config file
* Implemented Kim suggestions:
1) Fixed data race issues
2) refactor Verify method
3) Get rid of unused InputIntersection method due to refactoring Verify method
4) Fixed bug in https://github.com/CityOfZion/neo-go/pull/174#discussion_r264108135
5) minor simplications of the code
* Fixed minor issues related to
1) space
2) getter methods do not need pointer on the receiver
3) error message
4) refactoring CompareTo method in uint256.go
* Fixed small issues
* Use sync.RWMutex instead of sync.Mutex
* Refined (R)Lock/(R)Unlock
* return error instead of bool in Verify methods
2019-03-20 12:30:05 +00:00
|
|
|
} else {
|
2019-09-16 09:18:13 +00:00
|
|
|
r := io.NewBinReaderFromBuf(byteTx)
|
Implement rpc server method: sendrawtransaction (#174)
* Added new config attributes: 'SecondsPerBlock','LowPriorityThreshold'
* Added new files:
* Added new method: CompareTo
* Fixed empty Slice case
* Added new methods: LessThan, GreaterThan, Equal, CompareTo
* Added new method: InputIntersection
* Added MaxTransactionSize, GroupOutputByAssetID
* Added ned method: ScriptHash
* Added new method: IsDoubleSpend
* Refactor blockchainer, Added Feer interface, Verify and GetMemPool method
* 1) Added MemPool
2) Added new methods to satisfy the blockchainer interface: IsLowPriority, Verify, GetMemPool
* Added new methods: RelayTxn, RelayDirectly
* Fixed tests
* Implemented RPC server method sendrawtransaction
* Refactor getrawtransaction, sendrawtransaction in separate methods
* Moved 'secondsPerBlock' to config file
* Implemented Kim suggestions:
1) Fixed data race issues
2) refactor Verify method
3) Get rid of unused InputIntersection method due to refactoring Verify method
4) Fixed bug in https://github.com/CityOfZion/neo-go/pull/174#discussion_r264108135
5) minor simplications of the code
* Fixed minor issues related to
1) space
2) getter methods do not need pointer on the receiver
3) error message
4) refactoring CompareTo method in uint256.go
* Fixed small issues
* Use sync.RWMutex instead of sync.Mutex
* Refined (R)Lock/(R)Unlock
* return error instead of bool in Verify methods
2019-03-20 12:30:05 +00:00
|
|
|
tx := &transaction.Transaction{}
|
2019-09-16 16:31:49 +00:00
|
|
|
tx.DecodeBinary(r)
|
|
|
|
if r.Err != nil {
|
|
|
|
err = errors.Wrap(r.Err, "transaction DecodeBinary failed")
|
|
|
|
} else {
|
|
|
|
relayReason := s.coreServer.RelayTxn(tx)
|
|
|
|
switch relayReason {
|
|
|
|
case network.RelaySucceed:
|
|
|
|
results = true
|
|
|
|
case network.RelayAlreadyExists:
|
|
|
|
err = errors.New("block or transaction already exists and cannot be sent repeatedly")
|
|
|
|
case network.RelayOutOfMemory:
|
|
|
|
err = errors.New("the memory pool is full and no more transactions can be sent")
|
|
|
|
case network.RelayUnableToVerify:
|
|
|
|
err = errors.New("the block cannot be validated")
|
|
|
|
case network.RelayInvalid:
|
|
|
|
err = errors.New("block or transaction validation failed")
|
|
|
|
case network.RelayPolicyFail:
|
|
|
|
err = errors.New("one of the Policy filters failed")
|
|
|
|
default:
|
|
|
|
err = errors.New("unknown error")
|
|
|
|
}
|
Implement rpc server method: sendrawtransaction (#174)
* Added new config attributes: 'SecondsPerBlock','LowPriorityThreshold'
* Added new files:
* Added new method: CompareTo
* Fixed empty Slice case
* Added new methods: LessThan, GreaterThan, Equal, CompareTo
* Added new method: InputIntersection
* Added MaxTransactionSize, GroupOutputByAssetID
* Added ned method: ScriptHash
* Added new method: IsDoubleSpend
* Refactor blockchainer, Added Feer interface, Verify and GetMemPool method
* 1) Added MemPool
2) Added new methods to satisfy the blockchainer interface: IsLowPriority, Verify, GetMemPool
* Added new methods: RelayTxn, RelayDirectly
* Fixed tests
* Implemented RPC server method sendrawtransaction
* Refactor getrawtransaction, sendrawtransaction in separate methods
* Moved 'secondsPerBlock' to config file
* Implemented Kim suggestions:
1) Fixed data race issues
2) refactor Verify method
3) Get rid of unused InputIntersection method due to refactoring Verify method
4) Fixed bug in https://github.com/CityOfZion/neo-go/pull/174#discussion_r264108135
5) minor simplications of the code
* Fixed minor issues related to
1) space
2) getter methods do not need pointer on the receiver
3) error message
4) refactoring CompareTo method in uint256.go
* Fixed small issues
* Use sync.RWMutex instead of sync.Mutex
* Refined (R)Lock/(R)Unlock
* return error instead of bool in Verify methods
2019-03-20 12:30:05 +00:00
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
resultsErr = NewInternalServerError(err.Error(), err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return results, resultsErr
|
|
|
|
}
|
|
|
|
|
2019-11-26 10:13:17 +00:00
|
|
|
func (s Server) blockHeightFromParam(param *Param) (int, error) {
|
|
|
|
num, err := param.GetInt()
|
|
|
|
if err != nil {
|
|
|
|
return 0, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if num < 0 || num > int(s.chain.BlockHeight()) {
|
|
|
|
return 0, invalidBlockHeightError(0, num)
|
|
|
|
}
|
|
|
|
return num, nil
|
2018-03-23 20:36:59 +00:00
|
|
|
}
|