github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/services/rpcsrv/server.go (about) 1 package rpcsrv 2 3 import ( 4 "bytes" 5 "context" 6 "crypto/elliptic" 7 "encoding/binary" 8 "encoding/hex" 9 "encoding/json" 10 "errors" 11 "fmt" 12 "math" 13 "math/big" 14 "net" 15 "net/http" 16 "strconv" 17 "strings" 18 "sync" 19 "sync/atomic" 20 "time" 21 22 "github.com/google/uuid" 23 "github.com/gorilla/websocket" 24 "github.com/nspcc-dev/neo-go/pkg/config" 25 "github.com/nspcc-dev/neo-go/pkg/config/limits" 26 "github.com/nspcc-dev/neo-go/pkg/config/netmode" 27 "github.com/nspcc-dev/neo-go/pkg/core" 28 "github.com/nspcc-dev/neo-go/pkg/core/block" 29 "github.com/nspcc-dev/neo-go/pkg/core/interop" 30 "github.com/nspcc-dev/neo-go/pkg/core/interop/iterator" 31 "github.com/nspcc-dev/neo-go/pkg/core/mempool" 32 "github.com/nspcc-dev/neo-go/pkg/core/mempoolevent" 33 "github.com/nspcc-dev/neo-go/pkg/core/mpt" 34 "github.com/nspcc-dev/neo-go/pkg/core/native" 35 "github.com/nspcc-dev/neo-go/pkg/core/state" 36 "github.com/nspcc-dev/neo-go/pkg/core/storage" 37 "github.com/nspcc-dev/neo-go/pkg/core/transaction" 38 "github.com/nspcc-dev/neo-go/pkg/crypto/hash" 39 "github.com/nspcc-dev/neo-go/pkg/crypto/keys" 40 "github.com/nspcc-dev/neo-go/pkg/encoding/address" 41 "github.com/nspcc-dev/neo-go/pkg/io" 42 "github.com/nspcc-dev/neo-go/pkg/neorpc" 43 "github.com/nspcc-dev/neo-go/pkg/neorpc/result" 44 "github.com/nspcc-dev/neo-go/pkg/neorpc/rpcevent" 45 "github.com/nspcc-dev/neo-go/pkg/network" 46 "github.com/nspcc-dev/neo-go/pkg/network/payload" 47 "github.com/nspcc-dev/neo-go/pkg/services/oracle/broadcaster" 48 "github.com/nspcc-dev/neo-go/pkg/services/rpcsrv/params" 49 "github.com/nspcc-dev/neo-go/pkg/smartcontract" 50 "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" 51 "github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest" 52 "github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest/standard" 53 "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger" 54 "github.com/nspcc-dev/neo-go/pkg/util" 55 "github.com/nspcc-dev/neo-go/pkg/vm" 56 "github.com/nspcc-dev/neo-go/pkg/vm/emit" 57 "github.com/nspcc-dev/neo-go/pkg/vm/opcode" 58 "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" 59 "go.uber.org/zap" 60 ) 61 62 type ( 63 // Ledger abstracts away the Blockchain as used by the RPC server. 64 Ledger interface { 65 AddBlock(block *block.Block) error 66 BlockHeight() uint32 67 CalculateAttributesFee(tx *transaction.Transaction) int64 68 CalculateClaimable(h util.Uint160, endHeight uint32) (*big.Int, error) 69 CurrentBlockHash() util.Uint256 70 FeePerByte() int64 71 ForEachNEP11Transfer(acc util.Uint160, newestTimestamp uint64, f func(*state.NEP11Transfer) (bool, error)) error 72 ForEachNEP17Transfer(acc util.Uint160, newestTimestamp uint64, f func(*state.NEP17Transfer) (bool, error)) error 73 GetAppExecResults(util.Uint256, trigger.Type) ([]state.AppExecResult, error) 74 GetBaseExecFee() int64 75 GetBlock(hash util.Uint256) (*block.Block, error) 76 GetCommittee() (keys.PublicKeys, error) 77 GetConfig() config.Blockchain 78 GetContractScriptHash(id int32) (util.Uint160, error) 79 GetContractState(hash util.Uint160) *state.Contract 80 GetEnrollments() ([]state.Validator, error) 81 GetGoverningTokenBalance(acc util.Uint160) (*big.Int, uint32) 82 GetHeader(hash util.Uint256) (*block.Header, error) 83 GetHeaderHash(uint32) util.Uint256 84 GetMaxVerificationGAS() int64 85 GetMemPool() *mempool.Pool 86 GetNEP11Contracts() []util.Uint160 87 GetNEP17Contracts() []util.Uint160 88 GetNativeContractScriptHash(string) (util.Uint160, error) 89 GetNatives() []state.Contract 90 GetNextBlockValidators() ([]*keys.PublicKey, error) 91 GetNotaryContractScriptHash() util.Uint160 92 GetStateModule() core.StateRoot 93 GetStorageItem(id int32, key []byte) state.StorageItem 94 GetTestHistoricVM(t trigger.Type, tx *transaction.Transaction, nextBlockHeight uint32) (*interop.Context, error) 95 GetTestVM(t trigger.Type, tx *transaction.Transaction, b *block.Block) (*interop.Context, error) 96 GetTokenLastUpdated(acc util.Uint160) (map[int32]uint32, error) 97 GetTransaction(util.Uint256) (*transaction.Transaction, uint32, error) 98 HeaderHeight() uint32 99 InitVerificationContext(ic *interop.Context, hash util.Uint160, witness *transaction.Witness) error 100 P2PSigExtensionsEnabled() bool 101 SubscribeForBlocks(ch chan *block.Block) 102 SubscribeForHeadersOfAddedBlocks(ch chan *block.Header) 103 SubscribeForExecutions(ch chan *state.AppExecResult) 104 SubscribeForNotifications(ch chan *state.ContainedNotificationEvent) 105 SubscribeForTransactions(ch chan *transaction.Transaction) 106 UnsubscribeFromBlocks(ch chan *block.Block) 107 UnsubscribeFromHeadersOfAddedBlocks(ch chan *block.Header) 108 UnsubscribeFromExecutions(ch chan *state.AppExecResult) 109 UnsubscribeFromNotifications(ch chan *state.ContainedNotificationEvent) 110 UnsubscribeFromTransactions(ch chan *transaction.Transaction) 111 VerifyTx(*transaction.Transaction) error 112 VerifyWitness(util.Uint160, hash.Hashable, *transaction.Witness, int64) (int64, error) 113 mempool.Feer // fee interface 114 ContractStorageSeeker 115 } 116 117 // ContractStorageSeeker is the interface `findstorage*` handlers need to be able to 118 // seek over contract storage. Prefix is trimmed in the resulting pair's key. 119 ContractStorageSeeker interface { 120 SeekStorage(id int32, prefix []byte, cont func(k, v []byte) bool) 121 } 122 123 // OracleHandler is the interface oracle service needs to provide for the Server. 124 OracleHandler interface { 125 AddResponse(pub *keys.PublicKey, reqID uint64, txSig []byte) 126 } 127 128 // Server represents the JSON-RPC 2.0 server. 129 Server struct { 130 http []*http.Server 131 https []*http.Server 132 133 chain Ledger 134 config config.RPC 135 // wsReadLimit represents web-socket message limit for a receiving side. 136 wsReadLimit int64 137 upgrader websocket.Upgrader 138 network netmode.Magic 139 stateRootEnabled bool 140 coreServer *network.Server 141 oracle *atomic.Value 142 log *zap.Logger 143 shutdown chan struct{} 144 started atomic.Bool 145 errChan chan<- error 146 147 sessionsLock sync.Mutex 148 sessions map[string]*session 149 150 subsLock sync.RWMutex 151 subscribers map[*subscriber]bool 152 153 subsCounterLock sync.RWMutex 154 blockSubs int 155 blockHeaderSubs int 156 executionSubs int 157 notificationSubs int 158 transactionSubs int 159 notaryRequestSubs int 160 161 blockCh chan *block.Block 162 blockHeaderCh chan *block.Header 163 executionCh chan *state.AppExecResult 164 notificationCh chan *state.ContainedNotificationEvent 165 transactionCh chan *transaction.Transaction 166 notaryRequestCh chan mempoolevent.Event 167 subEventsToExitCh chan struct{} 168 } 169 170 // session holds a set of iterators got after invoke* call with corresponding 171 // finalizer and session expiration timer. 172 session struct { 173 // iteratorsLock protects iteratorIdentifiers of the current session. 174 iteratorsLock sync.Mutex 175 // iteratorIdentifiers stores the set of Iterator stackitems got either from original invocation 176 // or from historic MPT-based invocation. In the second case, iteratorIdentifiers are supposed 177 // to be filled during the first `traverseiterator` call using corresponding params. 178 iteratorIdentifiers []*iteratorIdentifier 179 timer *time.Timer 180 finalize func() 181 } 182 // iteratorIdentifier represents Iterator on the server side, holding iterator ID and Iterator stackitem. 183 iteratorIdentifier struct { 184 ID string 185 // Item represents Iterator stackitem. 186 Item stackitem.Item 187 } 188 ) 189 190 const ( 191 // Disconnection timeout. 192 wsPongLimit = 60 * time.Second 193 194 // Ping period for connection liveness check. 195 wsPingPeriod = wsPongLimit / 2 196 197 // Write deadline. 198 wsWriteLimit = wsPingPeriod / 2 199 200 // Default maximum number of websocket clients per Server. 201 defaultMaxWebSocketClients = 64 202 203 // Maximum number of elements for get*transfers requests. 204 maxTransfersLimit = 1000 205 206 // defaultSessionPoolSize is the number of concurrently running iterator sessions. 207 defaultSessionPoolSize = 20 208 ) 209 210 var rpcHandlers = map[string]func(*Server, params.Params) (any, *neorpc.Error){ 211 "calculatenetworkfee": (*Server).calculateNetworkFee, 212 "findstates": (*Server).findStates, 213 "findstorage": (*Server).findStorage, 214 "findstoragehistoric": (*Server).findStorageHistoric, 215 "getapplicationlog": (*Server).getApplicationLog, 216 "getbestblockhash": (*Server).getBestBlockHash, 217 "getblock": (*Server).getBlock, 218 "getblockcount": (*Server).getBlockCount, 219 "getblockhash": (*Server).getBlockHash, 220 "getblockheader": (*Server).getBlockHeader, 221 "getblockheadercount": (*Server).getBlockHeaderCount, 222 "getblocksysfee": (*Server).getBlockSysFee, 223 "getcandidates": (*Server).getCandidates, 224 "getcommittee": (*Server).getCommittee, 225 "getconnectioncount": (*Server).getConnectionCount, 226 "getcontractstate": (*Server).getContractState, 227 "getnativecontracts": (*Server).getNativeContracts, 228 "getnep11balances": (*Server).getNEP11Balances, 229 "getnep11properties": (*Server).getNEP11Properties, 230 "getnep11transfers": (*Server).getNEP11Transfers, 231 "getnep17balances": (*Server).getNEP17Balances, 232 "getnep17transfers": (*Server).getNEP17Transfers, 233 "getpeers": (*Server).getPeers, 234 "getproof": (*Server).getProof, 235 "getrawmempool": (*Server).getRawMempool, 236 "getrawnotarypool": (*Server).getRawNotaryPool, 237 "getrawnotarytransaction": (*Server).getRawNotaryTransaction, 238 "getrawtransaction": (*Server).getrawtransaction, 239 "getstate": (*Server).getState, 240 "getstateheight": (*Server).getStateHeight, 241 "getstateroot": (*Server).getStateRoot, 242 "getstorage": (*Server).getStorage, 243 "getstoragehistoric": (*Server).getStorageHistoric, 244 "gettransactionheight": (*Server).getTransactionHeight, 245 "getunclaimedgas": (*Server).getUnclaimedGas, 246 "getnextblockvalidators": (*Server).getNextBlockValidators, 247 "getversion": (*Server).getVersion, 248 "invokefunction": (*Server).invokeFunction, 249 "invokefunctionhistoric": (*Server).invokeFunctionHistoric, 250 "invokescript": (*Server).invokescript, 251 "invokescripthistoric": (*Server).invokescripthistoric, 252 "invokecontractverify": (*Server).invokeContractVerify, 253 "invokecontractverifyhistoric": (*Server).invokeContractVerifyHistoric, 254 "sendrawtransaction": (*Server).sendrawtransaction, 255 "submitblock": (*Server).submitBlock, 256 "submitnotaryrequest": (*Server).submitNotaryRequest, 257 "submitoracleresponse": (*Server).submitOracleResponse, 258 "terminatesession": (*Server).terminateSession, 259 "traverseiterator": (*Server).traverseIterator, 260 "validateaddress": (*Server).validateAddress, 261 "verifyproof": (*Server).verifyProof, 262 } 263 264 var rpcWsHandlers = map[string]func(*Server, params.Params, *subscriber) (any, *neorpc.Error){ 265 "subscribe": (*Server).subscribe, 266 "unsubscribe": (*Server).unsubscribe, 267 } 268 269 // New creates a new Server struct. Pay attention that orc is expected to be either 270 // untyped nil or non-nil structure implementing OracleHandler interface. 271 func New(chain Ledger, conf config.RPC, coreServer *network.Server, 272 orc OracleHandler, log *zap.Logger, errChan chan<- error) Server { 273 protoCfg := chain.GetConfig().ProtocolConfiguration 274 if conf.SessionEnabled { 275 if conf.SessionExpirationTime <= 0 { 276 conf.SessionExpirationTime = int(protoCfg.TimePerBlock / time.Second) 277 log.Info("SessionExpirationTime is not set or wrong, setting default value", zap.Int("SessionExpirationTime", conf.SessionExpirationTime)) 278 } 279 if conf.SessionPoolSize <= 0 { 280 conf.SessionPoolSize = defaultSessionPoolSize 281 log.Info("SessionPoolSize is not set or wrong, setting default value", zap.Int("SessionPoolSize", defaultSessionPoolSize)) 282 } 283 } 284 if conf.MaxIteratorResultItems <= 0 { 285 conf.MaxIteratorResultItems = config.DefaultMaxIteratorResultItems 286 log.Info("MaxIteratorResultItems is not set or wrong, setting default value", zap.Int("MaxIteratorResultItems", config.DefaultMaxIteratorResultItems)) 287 } 288 if conf.MaxFindResultItems <= 0 { 289 conf.MaxFindResultItems = config.DefaultMaxFindResultItems 290 log.Info("MaxFindResultItems is not set or wrong, setting default value", zap.Int("MaxFindResultItems", config.DefaultMaxFindResultItems)) 291 } 292 if conf.MaxFindStorageResultItems <= 0 { 293 conf.MaxFindStorageResultItems = config.DefaultMaxFindStorageResultItems 294 log.Info("MaxFindStorageResultItems is not set or wrong, setting default value", zap.Int("MaxFindStorageResultItems", config.DefaultMaxFindStorageResultItems)) 295 } 296 if conf.MaxNEP11Tokens <= 0 { 297 conf.MaxNEP11Tokens = config.DefaultMaxNEP11Tokens 298 log.Info("MaxNEP11Tokens is not set or wrong, setting default value", zap.Int("MaxNEP11Tokens", config.DefaultMaxNEP11Tokens)) 299 } 300 if conf.MaxRequestBodyBytes <= 0 { 301 conf.MaxRequestBodyBytes = config.DefaultMaxRequestBodyBytes 302 log.Info("MaxRequestBodyBytes is not set or wong, setting default value", zap.Int("MaxRequestBodyBytes", config.DefaultMaxRequestBodyBytes)) 303 } 304 if conf.MaxRequestHeaderBytes <= 0 { 305 conf.MaxRequestHeaderBytes = config.DefaultMaxRequestHeaderBytes 306 log.Info("MaxRequestHeaderBytes is not set or wong, setting default value", zap.Int("MaxRequestHeaderBytes", config.DefaultMaxRequestHeaderBytes)) 307 } 308 if conf.MaxWebSocketClients == 0 { 309 conf.MaxWebSocketClients = defaultMaxWebSocketClients 310 log.Info("MaxWebSocketClients is not set or wrong, setting default value", zap.Int("MaxWebSocketClients", defaultMaxWebSocketClients)) 311 } 312 var oracleWrapped = new(atomic.Value) 313 if orc != nil { 314 oracleWrapped.Store(orc) 315 } 316 var wsOriginChecker func(*http.Request) bool 317 if conf.EnableCORSWorkaround { 318 wsOriginChecker = func(_ *http.Request) bool { return true } 319 } 320 321 addrs := conf.Addresses 322 httpServers := make([]*http.Server, len(addrs)) 323 for i, addr := range addrs { 324 httpServers[i] = &http.Server{ 325 Addr: addr, 326 MaxHeaderBytes: conf.MaxRequestHeaderBytes, 327 } 328 } 329 330 var tlsServers []*http.Server 331 if cfg := conf.TLSConfig; cfg.Enabled { 332 addrs := cfg.Addresses 333 tlsServers = make([]*http.Server, len(addrs)) 334 for i, addr := range addrs { 335 tlsServers[i] = &http.Server{ 336 Addr: addr, 337 MaxHeaderBytes: conf.MaxRequestHeaderBytes, 338 } 339 } 340 } 341 342 return Server{ 343 http: httpServers, 344 https: tlsServers, 345 346 chain: chain, 347 config: conf, 348 wsReadLimit: int64(protoCfg.MaxBlockSize*4)/3 + 1024, // Enough for Base64-encoded content of `submitblock` and `submitp2pnotaryrequest`. 349 upgrader: websocket.Upgrader{CheckOrigin: wsOriginChecker}, 350 network: protoCfg.Magic, 351 stateRootEnabled: protoCfg.StateRootInHeader, 352 coreServer: coreServer, 353 log: log, 354 oracle: oracleWrapped, 355 shutdown: make(chan struct{}), 356 errChan: errChan, 357 358 sessions: make(map[string]*session), 359 360 subscribers: make(map[*subscriber]bool), 361 // These are NOT buffered to preserve original order of events. 362 blockCh: make(chan *block.Block), 363 executionCh: make(chan *state.AppExecResult), 364 notificationCh: make(chan *state.ContainedNotificationEvent), 365 transactionCh: make(chan *transaction.Transaction), 366 notaryRequestCh: make(chan mempoolevent.Event), 367 blockHeaderCh: make(chan *block.Header), 368 subEventsToExitCh: make(chan struct{}), 369 } 370 } 371 372 // Name returns service name. 373 func (s *Server) Name() string { 374 return "rpc" 375 } 376 377 // Start creates a new JSON-RPC server listening on the configured port. It creates 378 // goroutines needed internally and it returns its errors via errChan passed to New(). 379 // The Server only starts once, subsequent calls to Start are no-op. 380 func (s *Server) Start() { 381 if !s.config.Enabled { 382 s.log.Info("RPC server is not enabled") 383 return 384 } 385 if !s.started.CompareAndSwap(false, true) { 386 s.log.Info("RPC server already started") 387 return 388 } 389 390 go s.handleSubEvents() 391 392 for _, srv := range s.http { 393 srv.Handler = http.HandlerFunc(s.handleHTTPRequest) 394 s.log.Info("starting rpc-server", zap.String("endpoint", srv.Addr)) 395 396 ln, err := net.Listen("tcp", srv.Addr) 397 if err != nil { 398 s.errChan <- fmt.Errorf("failed to listen on %s: %w", srv.Addr, err) 399 return 400 } 401 srv.Addr = ln.Addr().String() // set Addr to the actual address 402 go func(server *http.Server) { 403 err = server.Serve(ln) 404 if !errors.Is(err, http.ErrServerClosed) { 405 s.log.Error("failed to start RPC server", zap.Error(err)) 406 s.errChan <- err 407 } 408 }(srv) 409 } 410 411 if cfg := s.config.TLSConfig; cfg.Enabled { 412 for _, srv := range s.https { 413 srv.Handler = http.HandlerFunc(s.handleHTTPRequest) 414 s.log.Info("starting rpc-server (https)", zap.String("endpoint", srv.Addr)) 415 416 ln, err := net.Listen("tcp", srv.Addr) 417 if err != nil { 418 s.errChan <- err 419 return 420 } 421 srv.Addr = ln.Addr().String() 422 423 go func(srv *http.Server) { 424 err = srv.ServeTLS(ln, cfg.CertFile, cfg.KeyFile) 425 if !errors.Is(err, http.ErrServerClosed) { 426 s.log.Error("failed to start TLS RPC server", 427 zap.String("endpoint", srv.Addr), zap.Error(err)) 428 s.errChan <- err 429 } 430 }(srv) 431 } 432 } 433 } 434 435 // Shutdown stops the RPC server if it's running. It can only be called once, 436 // subsequent calls to Shutdown on the same instance are no-op. The instance 437 // that was stopped can not be started again by calling Start (use a new 438 // instance if needed). 439 func (s *Server) Shutdown() { 440 if !s.started.CompareAndSwap(true, false) { 441 return 442 } 443 // Signal to websocket writer routines and handleSubEvents. 444 close(s.shutdown) 445 446 if s.config.TLSConfig.Enabled { 447 for _, srv := range s.https { 448 s.log.Info("shutting down RPC server (https)", zap.String("endpoint", srv.Addr)) 449 err := srv.Shutdown(context.Background()) 450 if err != nil { 451 s.log.Warn("error during RPC (https) server shutdown", 452 zap.String("endpoint", srv.Addr), zap.Error(err)) 453 } 454 } 455 } 456 457 for _, srv := range s.http { 458 s.log.Info("shutting down RPC server", zap.String("endpoint", srv.Addr)) 459 err := srv.Shutdown(context.Background()) 460 if err != nil { 461 s.log.Warn("error during RPC (http) server shutdown", 462 zap.String("endpoint", srv.Addr), zap.Error(err)) 463 } 464 } 465 466 // Perform sessions finalisation. 467 if s.config.SessionEnabled { 468 s.sessionsLock.Lock() 469 for _, session := range s.sessions { 470 // Concurrent iterator traversal may still be in process, thus need to protect iteratorIdentifiers access. 471 session.iteratorsLock.Lock() 472 session.finalize() 473 if !session.timer.Stop() { 474 <-session.timer.C 475 } 476 session.iteratorsLock.Unlock() 477 } 478 s.sessions = nil 479 s.sessionsLock.Unlock() 480 } 481 482 // Wait for handleSubEvents to finish. 483 <-s.subEventsToExitCh 484 _ = s.log.Sync() 485 } 486 487 // SetOracleHandler allows to update oracle handler used by the Server. 488 func (s *Server) SetOracleHandler(orc OracleHandler) { 489 s.oracle.Store(orc) 490 } 491 492 func (s *Server) handleHTTPRequest(w http.ResponseWriter, httpRequest *http.Request) { 493 // Restrict request body before further processing. 494 httpRequest.Body = http.MaxBytesReader(w, httpRequest.Body, int64(s.config.MaxRequestBodyBytes)) 495 req := params.NewRequest() 496 497 if httpRequest.URL.Path == "/ws" && httpRequest.Method == "GET" { 498 // Technically there is a race between this check and 499 // s.subscribers modification 20 lines below, but it's tiny 500 // and not really critical to bother with it. Some additional 501 // clients may sneak in, no big deal. 502 s.subsLock.RLock() 503 numOfSubs := len(s.subscribers) 504 s.subsLock.RUnlock() 505 if numOfSubs >= s.config.MaxWebSocketClients { 506 s.writeHTTPErrorResponse( 507 params.NewIn(), 508 w, 509 neorpc.NewInternalServerError("websocket users limit reached"), 510 ) 511 return 512 } 513 ws, err := s.upgrader.Upgrade(w, httpRequest, nil) 514 if err != nil { 515 s.log.Info("websocket connection upgrade failed", zap.Error(err)) 516 return 517 } 518 resChan := make(chan abstractResult) // response.abstract or response.abstractBatch 519 subChan := make(chan intEvent, notificationBufSize) 520 subscr := &subscriber{writer: subChan} 521 s.subsLock.Lock() 522 s.subscribers[subscr] = true 523 s.subsLock.Unlock() 524 go s.handleWsWrites(ws, resChan, subChan) 525 s.handleWsReads(ws, resChan, subscr) 526 return 527 } 528 529 if httpRequest.Method == "OPTIONS" && s.config.EnableCORSWorkaround { // Preflight CORS. 530 setCORSOriginHeaders(w.Header()) 531 w.Header().Set("Access-Control-Allow-Methods", "GET, POST") // GET for websockets. 532 w.Header().Set("Access-Control-Max-Age", "21600") // 6 hours. 533 return 534 } 535 536 if httpRequest.Method != "POST" { 537 s.writeHTTPErrorResponse( 538 params.NewIn(), 539 w, 540 neorpc.NewInvalidParamsError(fmt.Sprintf("invalid method '%s', please retry with 'POST'", httpRequest.Method)), 541 ) 542 return 543 } 544 545 err := req.DecodeData(httpRequest.Body) 546 if err != nil { 547 s.writeHTTPErrorResponse(params.NewIn(), w, neorpc.NewParseError(err.Error())) 548 return 549 } 550 551 resp := s.handleRequest(req, nil) 552 s.writeHTTPServerResponse(req, w, resp) 553 } 554 555 // RegisterLocal performs local client registration. 556 func (s *Server) RegisterLocal(ctx context.Context, events chan<- neorpc.Notification) func(*neorpc.Request) (*neorpc.Response, error) { 557 subChan := make(chan intEvent, notificationBufSize) 558 subscr := &subscriber{writer: subChan} 559 s.subsLock.Lock() 560 s.subscribers[subscr] = true 561 s.subsLock.Unlock() 562 go s.handleLocalNotifications(ctx, events, subChan, subscr) 563 return func(req *neorpc.Request) (*neorpc.Response, error) { 564 return s.handleInternal(req, subscr) 565 } 566 } 567 568 func (s *Server) handleRequest(req *params.Request, sub *subscriber) abstractResult { 569 if req.In != nil { 570 req.In.Method = escapeForLog(req.In.Method) // No valid method name will be changed by it. 571 return s.handleIn(req.In, sub) 572 } 573 resp := make(abstractBatch, len(req.Batch)) 574 for i, in := range req.Batch { 575 in.Method = escapeForLog(in.Method) // No valid method name will be changed by it. 576 resp[i] = s.handleIn(&in, sub) 577 } 578 return resp 579 } 580 581 // handleInternal is an experimental interface to handle client requests directly. 582 func (s *Server) handleInternal(req *neorpc.Request, sub *subscriber) (*neorpc.Response, error) { 583 var ( 584 res any 585 rpcRes = &neorpc.Response{ 586 HeaderAndError: neorpc.HeaderAndError{ 587 Header: neorpc.Header{ 588 JSONRPC: req.JSONRPC, 589 ID: json.RawMessage(strconv.FormatUint(req.ID, 10)), 590 }, 591 }, 592 } 593 ) 594 reqParams, err := params.FromAny(req.Params) 595 if err != nil { 596 return nil, err 597 } 598 599 s.log.Debug("processing local rpc request", 600 zap.String("method", req.Method), 601 zap.Stringer("params", reqParams)) 602 603 start := time.Now() 604 defer func() { addReqTimeMetric(req.Method, time.Since(start)) }() 605 606 rpcRes.Error = neorpc.NewMethodNotFoundError(fmt.Sprintf("method %q not supported", req.Method)) 607 handler, ok := rpcHandlers[req.Method] 608 if ok { 609 res, rpcRes.Error = handler(s, reqParams) 610 } else if sub != nil { 611 handler, ok := rpcWsHandlers[req.Method] 612 if ok { 613 res, rpcRes.Error = handler(s, reqParams, sub) 614 } 615 } 616 if res != nil { 617 b, err := json.Marshal(res) 618 if err != nil { 619 return nil, fmt.Errorf("response can't be JSONized: %w", err) 620 } 621 rpcRes.Result = json.RawMessage(b) 622 } 623 return rpcRes, nil 624 } 625 626 func (s *Server) handleIn(req *params.In, sub *subscriber) abstract { 627 var res any 628 var resErr *neorpc.Error 629 if req.JSONRPC != neorpc.JSONRPCVersion { 630 return s.packResponse(req, nil, neorpc.NewInvalidParamsError(fmt.Sprintf("problem parsing JSON: invalid version, expected 2.0 got '%s'", req.JSONRPC))) 631 } 632 633 reqParams := params.Params(req.RawParams) 634 635 s.log.Debug("processing rpc request", 636 zap.String("method", req.Method), 637 zap.Stringer("params", reqParams)) 638 639 start := time.Now() 640 defer func() { addReqTimeMetric(req.Method, time.Since(start)) }() 641 642 resErr = neorpc.NewMethodNotFoundError(fmt.Sprintf("method %q not supported", req.Method)) 643 handler, ok := rpcHandlers[req.Method] 644 if ok { 645 res, resErr = handler(s, reqParams) 646 } else if sub != nil { 647 handler, ok := rpcWsHandlers[req.Method] 648 if ok { 649 res, resErr = handler(s, reqParams, sub) 650 } 651 } 652 return s.packResponse(req, res, resErr) 653 } 654 655 func (s *Server) handleLocalNotifications(ctx context.Context, events chan<- neorpc.Notification, subChan <-chan intEvent, subscr *subscriber) { 656 eventloop: 657 for { 658 select { 659 case <-s.shutdown: 660 break eventloop 661 case <-ctx.Done(): 662 break eventloop 663 case ev := <-subChan: 664 events <- *ev.ntf // Make a copy. 665 } 666 } 667 close(events) 668 s.dropSubscriber(subscr) 669 drainloop: 670 for { 671 select { 672 case <-subChan: 673 default: 674 break drainloop 675 } 676 } 677 } 678 679 func (s *Server) handleWsWrites(ws *websocket.Conn, resChan <-chan abstractResult, subChan <-chan intEvent) { 680 pingTicker := time.NewTicker(wsPingPeriod) 681 eventloop: 682 for { 683 select { 684 case <-s.shutdown: 685 break eventloop 686 case event, ok := <-subChan: 687 if !ok { 688 break eventloop 689 } 690 if err := ws.SetWriteDeadline(time.Now().Add(wsWriteLimit)); err != nil { 691 break eventloop 692 } 693 if err := ws.WritePreparedMessage(event.msg); err != nil { 694 break eventloop 695 } 696 case res, ok := <-resChan: 697 if !ok { 698 break eventloop 699 } 700 if err := ws.SetWriteDeadline(time.Now().Add(wsWriteLimit)); err != nil { 701 break eventloop 702 } 703 if err := ws.WriteJSON(res); err != nil { 704 break eventloop 705 } 706 case <-pingTicker.C: 707 if err := ws.SetWriteDeadline(time.Now().Add(wsWriteLimit)); err != nil { 708 break eventloop 709 } 710 if err := ws.WriteMessage(websocket.PingMessage, []byte{}); err != nil { 711 break eventloop 712 } 713 } 714 } 715 ws.Close() 716 pingTicker.Stop() 717 // Drain notification channel as there might be some goroutines blocked 718 // on it. 719 drainloop: 720 for { 721 select { 722 case _, ok := <-subChan: 723 if !ok { 724 break drainloop 725 } 726 default: 727 break drainloop 728 } 729 } 730 } 731 732 func (s *Server) handleWsReads(ws *websocket.Conn, resChan chan<- abstractResult, subscr *subscriber) { 733 ws.SetReadLimit(s.wsReadLimit) 734 err := ws.SetReadDeadline(time.Now().Add(wsPongLimit)) 735 ws.SetPongHandler(func(string) error { return ws.SetReadDeadline(time.Now().Add(wsPongLimit)) }) 736 requestloop: 737 for err == nil { 738 req := params.NewRequest() 739 err := ws.ReadJSON(req) 740 if err != nil { 741 break 742 } 743 res := s.handleRequest(req, subscr) 744 res.RunForErrors(func(jsonErr *neorpc.Error) { 745 s.logRequestError(req, jsonErr) 746 }) 747 select { 748 case <-s.shutdown: 749 break requestloop 750 case resChan <- res: 751 } 752 } 753 s.dropSubscriber(subscr) 754 close(resChan) 755 ws.Close() 756 } 757 758 func (s *Server) dropSubscriber(subscr *subscriber) { 759 s.subsLock.Lock() 760 delete(s.subscribers, subscr) 761 s.subsLock.Unlock() 762 s.subsCounterLock.Lock() 763 for _, e := range subscr.feeds { 764 if e.event != neorpc.InvalidEventID { 765 s.unsubscribeFromChannel(e.event) 766 } 767 } 768 s.subsCounterLock.Unlock() 769 } 770 771 func (s *Server) getBestBlockHash(_ params.Params) (any, *neorpc.Error) { 772 return "0x" + s.chain.CurrentBlockHash().StringLE(), nil 773 } 774 775 func (s *Server) getBlockCount(_ params.Params) (any, *neorpc.Error) { 776 return s.chain.BlockHeight() + 1, nil 777 } 778 779 func (s *Server) getBlockHeaderCount(_ params.Params) (any, *neorpc.Error) { 780 return s.chain.HeaderHeight() + 1, nil 781 } 782 783 func (s *Server) getConnectionCount(_ params.Params) (any, *neorpc.Error) { 784 return s.coreServer.PeerCount(), nil 785 } 786 787 func (s *Server) blockHashFromParam(param *params.Param) (util.Uint256, *neorpc.Error) { 788 var ( 789 hash util.Uint256 790 err error 791 ) 792 if param == nil { 793 return hash, neorpc.ErrInvalidParams 794 } 795 796 if hash, err = param.GetUint256(); err != nil { 797 num, respErr := s.blockHeightFromParam(param) 798 if respErr != nil { 799 return hash, respErr 800 } 801 hash = s.chain.GetHeaderHash(num) 802 } 803 return hash, nil 804 } 805 806 func (s *Server) fillBlockMetadata(obj io.Serializable, h *block.Header) result.BlockMetadata { 807 res := result.BlockMetadata{ 808 Size: io.GetVarSize(obj), // obj can be a Block or a Header. 809 Confirmations: s.chain.BlockHeight() - h.Index + 1, 810 } 811 812 hash := s.chain.GetHeaderHash(h.Index + 1) 813 if !hash.Equals(util.Uint256{}) { 814 res.NextBlockHash = &hash 815 } 816 return res 817 } 818 819 func (s *Server) getBlock(reqParams params.Params) (any, *neorpc.Error) { 820 param := reqParams.Value(0) 821 hash, respErr := s.blockHashFromParam(param) 822 if respErr != nil { 823 return nil, respErr 824 } 825 826 block, err := s.chain.GetBlock(hash) 827 if err != nil { 828 return nil, neorpc.WrapErrorWithData(neorpc.ErrUnknownBlock, err.Error()) 829 } 830 831 if v, _ := reqParams.Value(1).GetBoolean(); v { 832 res := result.Block{ 833 Block: *block, 834 BlockMetadata: s.fillBlockMetadata(block, &block.Header), 835 } 836 return res, nil 837 } 838 writer := io.NewBufBinWriter() 839 block.EncodeBinary(writer.BinWriter) 840 return writer.Bytes(), nil 841 } 842 843 func (s *Server) getBlockHash(reqParams params.Params) (any, *neorpc.Error) { 844 num, err := s.blockHeightFromParam(reqParams.Value(0)) 845 if err != nil { 846 return nil, err 847 } 848 849 return s.chain.GetHeaderHash(num), nil 850 } 851 852 func (s *Server) getVersion(_ params.Params) (any, *neorpc.Error) { 853 port, err := s.coreServer.Port(nil) // any port will suite 854 if err != nil { 855 return nil, neorpc.NewInternalServerError(fmt.Sprintf("cannot fetch tcp port: %s", err)) 856 } 857 858 cfg := s.chain.GetConfig() 859 hfs := make(map[config.Hardfork]uint32, len(cfg.Hardforks)) 860 for _, cfgHf := range config.Hardforks { 861 height, ok := cfg.Hardforks[cfgHf.String()] 862 if !ok { 863 continue 864 } 865 hfs[cfgHf] = height 866 } 867 return &result.Version{ 868 TCPPort: port, 869 Nonce: s.coreServer.ID(), 870 UserAgent: s.coreServer.UserAgent, 871 RPC: result.RPC{ 872 MaxIteratorResultItems: s.config.MaxIteratorResultItems, 873 SessionEnabled: s.config.SessionEnabled, 874 }, 875 Protocol: result.Protocol{ 876 AddressVersion: address.NEO3Prefix, 877 Network: cfg.Magic, 878 MillisecondsPerBlock: int(cfg.TimePerBlock / time.Millisecond), 879 MaxTraceableBlocks: cfg.MaxTraceableBlocks, 880 MaxValidUntilBlockIncrement: cfg.MaxValidUntilBlockIncrement, 881 MaxTransactionsPerBlock: cfg.MaxTransactionsPerBlock, 882 MemoryPoolMaxTransactions: cfg.MemPoolSize, 883 ValidatorsCount: byte(cfg.GetNumOfCNs(s.chain.BlockHeight())), 884 InitialGasDistribution: cfg.InitialGASSupply, 885 Hardforks: hfs, 886 887 CommitteeHistory: cfg.CommitteeHistory, 888 P2PSigExtensions: cfg.P2PSigExtensions, 889 StateRootInHeader: cfg.StateRootInHeader, 890 ValidatorsHistory: cfg.ValidatorsHistory, 891 }, 892 }, nil 893 } 894 895 func (s *Server) getPeers(_ params.Params) (any, *neorpc.Error) { 896 peers := result.NewGetPeers() 897 peers.AddUnconnected(s.coreServer.UnconnectedPeers()) 898 peers.AddConnected(s.coreServer.ConnectedPeers()) 899 peers.AddBad(s.coreServer.BadPeers()) 900 return peers, nil 901 } 902 903 func (s *Server) getRawMempool(reqParams params.Params) (any, *neorpc.Error) { 904 verbose, _ := reqParams.Value(0).GetBoolean() 905 mp := s.chain.GetMemPool() 906 hashList := make([]util.Uint256, 0) 907 for _, item := range mp.GetVerifiedTransactions() { 908 hashList = append(hashList, item.Hash()) 909 } 910 if !verbose { 911 return hashList, nil 912 } 913 return result.RawMempool{ 914 Height: s.chain.BlockHeight(), 915 Verified: hashList, 916 Unverified: []util.Uint256{}, // avoid `null` result 917 }, nil 918 } 919 920 func (s *Server) validateAddress(reqParams params.Params) (any, *neorpc.Error) { 921 param, err := reqParams.Value(0).GetString() 922 if err != nil { 923 return nil, neorpc.ErrInvalidParams 924 } 925 926 return result.ValidateAddress{ 927 Address: reqParams.Value(0), 928 IsValid: validateAddress(param), 929 }, nil 930 } 931 932 // calculateNetworkFee calculates network fee for the transaction. 933 func (s *Server) calculateNetworkFee(reqParams params.Params) (any, *neorpc.Error) { 934 if len(reqParams) < 1 { 935 return 0, neorpc.ErrInvalidParams 936 } 937 byteTx, err := reqParams[0].GetBytesBase64() 938 if err != nil { 939 return 0, neorpc.WrapErrorWithData(neorpc.ErrInvalidParams, err.Error()) 940 } 941 tx, err := transaction.NewTransactionFromBytes(byteTx) 942 if err != nil { 943 return 0, neorpc.WrapErrorWithData(neorpc.ErrInvalidParams, err.Error()) 944 } 945 hashablePart, err := tx.EncodeHashableFields() 946 if err != nil { 947 return 0, neorpc.WrapErrorWithData(neorpc.ErrInvalidParams, fmt.Sprintf("failed to compute tx size: %s", err)) 948 } 949 size := len(hashablePart) + io.GetVarSize(len(tx.Signers)) 950 var ( 951 netFee int64 952 // Verification GAS cost can't exceed this policy. 953 gasLimit = s.chain.GetMaxVerificationGAS() 954 ) 955 if gasLimit > int64(s.config.MaxGasInvoke) { 956 // But we honor instance configuration as well. 957 gasLimit = int64(s.config.MaxGasInvoke) 958 } 959 for i, signer := range tx.Signers { 960 w := tx.Scripts[i] 961 if len(w.InvocationScript) == 0 { // No invocation provided, try to infer one. 962 var paramz []manifest.Parameter 963 if len(w.VerificationScript) == 0 { // Contract-based verification 964 cs := s.chain.GetContractState(signer.Account) 965 if cs == nil { 966 return 0, neorpc.WrapErrorWithData(neorpc.ErrInvalidVerificationFunction, fmt.Sprintf("signer %d has no verification script and no deployed contract", i)) 967 } 968 md := cs.Manifest.ABI.GetMethod(manifest.MethodVerify, -1) 969 if md == nil || md.ReturnType != smartcontract.BoolType { 970 return 0, neorpc.WrapErrorWithData(neorpc.ErrInvalidVerificationFunction, fmt.Sprintf("signer %d has no verify method in deployed contract", i)) 971 } 972 paramz = md.Parameters // Might as well have none params and it's OK. 973 } else { // Regular signature verification. 974 if vm.IsSignatureContract(w.VerificationScript) { 975 paramz = []manifest.Parameter{{Type: smartcontract.SignatureType}} 976 } else if nSigs, _, ok := vm.ParseMultiSigContract(w.VerificationScript); ok { 977 paramz = make([]manifest.Parameter, nSigs) 978 for j := 0; j < nSigs; j++ { 979 paramz[j] = manifest.Parameter{Type: smartcontract.SignatureType} 980 } 981 } 982 } 983 inv := io.NewBufBinWriter() 984 for _, p := range paramz { 985 p.Type.EncodeDefaultValue(inv.BinWriter) 986 } 987 if inv.Err != nil { 988 return nil, neorpc.NewInternalServerError(fmt.Sprintf("failed to create dummy invocation script (signer %d): %s", i, inv.Err.Error())) 989 } 990 w.InvocationScript = inv.Bytes() 991 } 992 gasConsumed, err := s.chain.VerifyWitness(signer.Account, tx, &w, gasLimit) 993 if err != nil && !errors.Is(err, core.ErrInvalidSignature) { 994 return nil, neorpc.WrapErrorWithData(neorpc.ErrInvalidSignature, err.Error()) 995 } 996 gasLimit -= gasConsumed 997 netFee += gasConsumed 998 size += io.GetVarSize(w.VerificationScript) + io.GetVarSize(w.InvocationScript) 999 } 1000 netFee += int64(size)*s.chain.FeePerByte() + s.chain.CalculateAttributesFee(tx) 1001 return result.NetworkFee{Value: netFee}, nil 1002 } 1003 1004 // getApplicationLog returns the contract log based on the specified txid or blockid. 1005 func (s *Server) getApplicationLog(reqParams params.Params) (any, *neorpc.Error) { 1006 hash, err := reqParams.Value(0).GetUint256() 1007 if err != nil { 1008 return nil, neorpc.ErrInvalidParams 1009 } 1010 1011 trig := trigger.All 1012 if len(reqParams) > 1 { 1013 trigString, err := reqParams.Value(1).GetString() 1014 if err != nil { 1015 return nil, neorpc.ErrInvalidParams 1016 } 1017 trig, err = trigger.FromString(trigString) 1018 if err != nil { 1019 return nil, neorpc.ErrInvalidParams 1020 } 1021 } 1022 1023 appExecResults, err := s.chain.GetAppExecResults(hash, trigger.All) 1024 if err != nil { 1025 return nil, neorpc.WrapErrorWithData(neorpc.ErrUnknownScriptContainer, fmt.Sprintf("failed to locate application log: %s", err)) 1026 } 1027 return result.NewApplicationLog(hash, appExecResults, trig), nil 1028 } 1029 1030 func (s *Server) getNEP11Tokens(h util.Uint160, acc util.Uint160, bw *io.BufBinWriter) ([]stackitem.Item, string, int, error) { 1031 items, finalize, err := s.invokeReadOnlyMulti(bw, h, []string{"tokensOf", "symbol", "decimals"}, [][]any{{acc}, nil, nil}) 1032 if err != nil { 1033 return nil, "", 0, err 1034 } 1035 defer finalize() 1036 if (items[0].Type() != stackitem.InteropT) || !iterator.IsIterator(items[0]) { 1037 return nil, "", 0, fmt.Errorf("invalid `tokensOf` result type %s", items[0].String()) 1038 } 1039 vals := iterator.Values(items[0], s.config.MaxNEP11Tokens) 1040 sym, err := stackitem.ToString(items[1]) 1041 if err != nil { 1042 return nil, "", 0, fmt.Errorf("`symbol` return value error: %w", err) 1043 } 1044 dec, err := items[2].TryInteger() 1045 if err != nil { 1046 return nil, "", 0, fmt.Errorf("`decimals` return value error: %w", err) 1047 } 1048 if !dec.IsInt64() || dec.Sign() == -1 || dec.Int64() > math.MaxInt32 { 1049 return nil, "", 0, errors.New("`decimals` returned a bad integer") 1050 } 1051 return vals, sym, int(dec.Int64()), nil 1052 } 1053 1054 func (s *Server) getNEP11Balances(ps params.Params) (any, *neorpc.Error) { 1055 u, err := ps.Value(0).GetUint160FromAddressOrHex() 1056 if err != nil { 1057 return nil, neorpc.ErrInvalidParams 1058 } 1059 1060 bs := &result.NEP11Balances{ 1061 Address: address.Uint160ToString(u), 1062 Balances: []result.NEP11AssetBalance{}, 1063 } 1064 lastUpdated, err := s.chain.GetTokenLastUpdated(u) 1065 if err != nil { 1066 return nil, neorpc.NewInternalServerError(fmt.Sprintf("Failed to get NEP-11 last updated block: %s", err.Error())) 1067 } 1068 var count int 1069 stateSyncPoint := lastUpdated[math.MinInt32] 1070 bw := io.NewBufBinWriter() 1071 contract_loop: 1072 for _, h := range s.chain.GetNEP11Contracts() { 1073 toks, sym, dec, err := s.getNEP11Tokens(h, u, bw) 1074 if err != nil { 1075 continue 1076 } 1077 if len(toks) == 0 { 1078 continue 1079 } 1080 cs := s.chain.GetContractState(h) 1081 if cs == nil { 1082 continue 1083 } 1084 isDivisible := (standard.ComplyABI(&cs.Manifest, standard.Nep11Divisible) == nil) 1085 lub, ok := lastUpdated[cs.ID] 1086 if !ok { 1087 cfg := s.chain.GetConfig() 1088 if !cfg.P2PStateExchangeExtensions && cfg.Ledger.RemoveUntraceableBlocks { 1089 return nil, neorpc.NewInternalServerError(fmt.Sprintf("failed to get LastUpdatedBlock for balance of %s token: internal database inconsistency", cs.Hash.StringLE())) 1090 } 1091 lub = stateSyncPoint 1092 } 1093 bs.Balances = append(bs.Balances, result.NEP11AssetBalance{ 1094 Asset: h, 1095 Decimals: dec, 1096 Name: cs.Manifest.Name, 1097 Symbol: sym, 1098 Tokens: make([]result.NEP11TokenBalance, 0, len(toks)), 1099 }) 1100 curAsset := &bs.Balances[len(bs.Balances)-1] 1101 for i := range toks { 1102 id, err := toks[i].TryBytes() 1103 if err != nil || len(id) > limits.MaxStorageKeyLen { 1104 continue 1105 } 1106 var amount = "1" 1107 if isDivisible { 1108 balance, err := s.getNEP11DTokenBalance(h, u, id, bw) 1109 if err != nil { 1110 continue 1111 } 1112 if balance.Sign() == 0 { 1113 continue 1114 } 1115 amount = balance.String() 1116 } 1117 count++ 1118 curAsset.Tokens = append(curAsset.Tokens, result.NEP11TokenBalance{ 1119 ID: hex.EncodeToString(id), 1120 Amount: amount, 1121 LastUpdated: lub, 1122 }) 1123 if count >= s.config.MaxNEP11Tokens { 1124 break contract_loop 1125 } 1126 } 1127 } 1128 return bs, nil 1129 } 1130 1131 func (s *Server) invokeNEP11Properties(h util.Uint160, id []byte, bw *io.BufBinWriter) ([]stackitem.MapElement, error) { 1132 item, finalize, err := s.invokeReadOnly(bw, h, "properties", id) 1133 if err != nil { 1134 return nil, err 1135 } 1136 defer finalize() 1137 if item.Type() != stackitem.MapT { 1138 return nil, fmt.Errorf("invalid `properties` result type %s", item.String()) 1139 } 1140 return item.Value().([]stackitem.MapElement), nil 1141 } 1142 1143 func (s *Server) getNEP11Properties(ps params.Params) (any, *neorpc.Error) { 1144 asset, err := ps.Value(0).GetUint160FromAddressOrHex() 1145 if err != nil { 1146 return nil, neorpc.ErrInvalidParams 1147 } 1148 token, err := ps.Value(1).GetBytesHex() 1149 if err != nil { 1150 return nil, neorpc.ErrInvalidParams 1151 } 1152 props, err := s.invokeNEP11Properties(asset, token, nil) 1153 if err != nil { 1154 return nil, neorpc.WrapErrorWithData(neorpc.ErrExecutionFailed, fmt.Sprintf("Failed to get NEP-11 properties: %s", err.Error())) 1155 } 1156 res := make(map[string]any) 1157 for _, kv := range props { 1158 key, err := kv.Key.TryBytes() 1159 if err != nil { 1160 continue 1161 } 1162 var val any 1163 if result.KnownNEP11Properties[string(key)] || kv.Value.Type() != stackitem.AnyT { 1164 v, err := kv.Value.TryBytes() 1165 if err != nil { 1166 continue 1167 } 1168 if result.KnownNEP11Properties[string(key)] { 1169 val = string(v) 1170 } else { 1171 val = v 1172 } 1173 } 1174 res[string(key)] = val 1175 } 1176 return res, nil 1177 } 1178 1179 func (s *Server) getNEP17Balances(ps params.Params) (any, *neorpc.Error) { 1180 u, err := ps.Value(0).GetUint160FromAddressOrHex() 1181 if err != nil { 1182 return nil, neorpc.ErrInvalidParams 1183 } 1184 1185 bs := &result.NEP17Balances{ 1186 Address: address.Uint160ToString(u), 1187 Balances: []result.NEP17Balance{}, 1188 } 1189 lastUpdated, err := s.chain.GetTokenLastUpdated(u) 1190 if err != nil { 1191 return nil, neorpc.NewInternalServerError(fmt.Sprintf("Failed to get NEP-17 last updated block: %s", err.Error())) 1192 } 1193 stateSyncPoint := lastUpdated[math.MinInt32] 1194 bw := io.NewBufBinWriter() 1195 for _, h := range s.chain.GetNEP17Contracts() { 1196 balance, sym, dec, err := s.getNEP17TokenBalance(h, u, bw) 1197 if err != nil { 1198 continue 1199 } 1200 if balance.Sign() == 0 { 1201 continue 1202 } 1203 cs := s.chain.GetContractState(h) 1204 if cs == nil { 1205 continue 1206 } 1207 lub, ok := lastUpdated[cs.ID] 1208 if !ok { 1209 cfg := s.chain.GetConfig() 1210 if !cfg.P2PStateExchangeExtensions && cfg.Ledger.RemoveUntraceableBlocks { 1211 return nil, neorpc.NewInternalServerError(fmt.Sprintf("failed to get LastUpdatedBlock for balance of %s token: internal database inconsistency", cs.Hash.StringLE())) 1212 } 1213 lub = stateSyncPoint 1214 } 1215 bs.Balances = append(bs.Balances, result.NEP17Balance{ 1216 Asset: h, 1217 Amount: balance.String(), 1218 Decimals: dec, 1219 LastUpdated: lub, 1220 Name: cs.Manifest.Name, 1221 Symbol: sym, 1222 }) 1223 } 1224 return bs, nil 1225 } 1226 1227 func (s *Server) invokeReadOnly(bw *io.BufBinWriter, h util.Uint160, method string, params ...any) (stackitem.Item, func(), error) { 1228 r, f, err := s.invokeReadOnlyMulti(bw, h, []string{method}, [][]any{params}) 1229 if err != nil { 1230 return nil, nil, err 1231 } 1232 return r[0], f, nil 1233 } 1234 1235 func (s *Server) invokeReadOnlyMulti(bw *io.BufBinWriter, h util.Uint160, methods []string, params [][]any) ([]stackitem.Item, func(), error) { 1236 if bw == nil { 1237 bw = io.NewBufBinWriter() 1238 } else { 1239 bw.Reset() 1240 } 1241 if len(methods) != len(params) { 1242 return nil, nil, fmt.Errorf("asymmetric parameters") 1243 } 1244 for i := range methods { 1245 emit.AppCall(bw.BinWriter, h, methods[i], callflag.ReadStates|callflag.AllowCall, params[i]...) 1246 if bw.Err != nil { 1247 return nil, nil, fmt.Errorf("failed to create `%s` invocation script: %w", methods[i], bw.Err) 1248 } 1249 } 1250 script := bw.Bytes() 1251 tx := &transaction.Transaction{Script: script} 1252 ic, err := s.chain.GetTestVM(trigger.Application, tx, nil) 1253 if err != nil { 1254 return nil, nil, fmt.Errorf("faile to prepare test VM: %w", err) 1255 } 1256 ic.VM.GasLimit = core.HeaderVerificationGasLimit 1257 ic.VM.LoadScriptWithFlags(script, callflag.All) 1258 err = ic.VM.Run() 1259 if err != nil { 1260 ic.Finalize() 1261 return nil, nil, fmt.Errorf("failed to run %d methods of %s: %w", len(methods), h.StringLE(), err) 1262 } 1263 estack := ic.VM.Estack() 1264 if estack.Len() != len(methods) { 1265 ic.Finalize() 1266 return nil, nil, fmt.Errorf("invalid return values count: expected %d, got %d", len(methods), estack.Len()) 1267 } 1268 return estack.ToArray(), ic.Finalize, nil 1269 } 1270 1271 func (s *Server) getNEP17TokenBalance(h util.Uint160, acc util.Uint160, bw *io.BufBinWriter) (*big.Int, string, int, error) { 1272 items, finalize, err := s.invokeReadOnlyMulti(bw, h, []string{"balanceOf", "symbol", "decimals"}, [][]any{{acc}, nil, nil}) 1273 if err != nil { 1274 return nil, "", 0, err 1275 } 1276 finalize() 1277 res, err := items[0].TryInteger() 1278 if err != nil { 1279 return nil, "", 0, fmt.Errorf("unexpected `balanceOf` result type: %w", err) 1280 } 1281 sym, err := stackitem.ToString(items[1]) 1282 if err != nil { 1283 return nil, "", 0, fmt.Errorf("`symbol` return value error: %w", err) 1284 } 1285 dec, err := items[2].TryInteger() 1286 if err != nil { 1287 return nil, "", 0, fmt.Errorf("`decimals` return value error: %w", err) 1288 } 1289 if !dec.IsInt64() || dec.Sign() == -1 || dec.Int64() > math.MaxInt32 { 1290 return nil, "", 0, errors.New("`decimals` returned a bad integer") 1291 } 1292 return res, sym, int(dec.Int64()), nil 1293 } 1294 1295 func (s *Server) getNEP11DTokenBalance(h util.Uint160, acc util.Uint160, id []byte, bw *io.BufBinWriter) (*big.Int, error) { 1296 item, finalize, err := s.invokeReadOnly(bw, h, "balanceOf", acc, id) 1297 if err != nil { 1298 return nil, err 1299 } 1300 finalize() 1301 res, err := item.TryInteger() 1302 if err != nil { 1303 return nil, fmt.Errorf("unexpected `balanceOf` result type: %w", err) 1304 } 1305 return res, nil 1306 } 1307 1308 func getTimestampsAndLimit(ps params.Params, index int) (uint64, uint64, int, int, error) { 1309 var start, end uint64 1310 var limit, page int 1311 1312 limit = maxTransfersLimit 1313 pStart, pEnd, pLimit, pPage := ps.Value(index), ps.Value(index+1), ps.Value(index+2), ps.Value(index+3) 1314 if pPage != nil { 1315 p, err := pPage.GetInt() 1316 if err != nil { 1317 return 0, 0, 0, 0, err 1318 } 1319 if p < 0 { 1320 return 0, 0, 0, 0, errors.New("can't use negative page") 1321 } 1322 page = p 1323 } 1324 if pLimit != nil { 1325 l, err := pLimit.GetInt() 1326 if err != nil { 1327 return 0, 0, 0, 0, err 1328 } 1329 if l <= 0 { 1330 return 0, 0, 0, 0, errors.New("can't use negative or zero limit") 1331 } 1332 if l > maxTransfersLimit { 1333 return 0, 0, 0, 0, errors.New("too big limit requested") 1334 } 1335 limit = l 1336 } 1337 if pEnd != nil { 1338 val, err := pEnd.GetInt() 1339 if err != nil { 1340 return 0, 0, 0, 0, err 1341 } 1342 end = uint64(val) 1343 } else { 1344 end = uint64(time.Now().Unix() * 1000) 1345 } 1346 if pStart != nil { 1347 val, err := pStart.GetInt() 1348 if err != nil { 1349 return 0, 0, 0, 0, err 1350 } 1351 start = uint64(val) 1352 } else { 1353 start = uint64(time.Now().Add(-time.Hour*24*7).Unix() * 1000) 1354 } 1355 return start, end, limit, page, nil 1356 } 1357 1358 func (s *Server) getNEP11Transfers(ps params.Params) (any, *neorpc.Error) { 1359 return s.getTokenTransfers(ps, true) 1360 } 1361 1362 func (s *Server) getNEP17Transfers(ps params.Params) (any, *neorpc.Error) { 1363 return s.getTokenTransfers(ps, false) 1364 } 1365 1366 func (s *Server) getTokenTransfers(ps params.Params, isNEP11 bool) (any, *neorpc.Error) { 1367 u, err := ps.Value(0).GetUint160FromAddressOrHex() 1368 if err != nil { 1369 return nil, neorpc.ErrInvalidParams 1370 } 1371 1372 start, end, limit, page, err := getTimestampsAndLimit(ps, 1) 1373 if err != nil { 1374 return nil, neorpc.NewInvalidParamsError(fmt.Sprintf("malformed timestamps/limit: %s", err)) 1375 } 1376 1377 bs := &tokenTransfers{ 1378 Address: address.Uint160ToString(u), 1379 Received: []any{}, 1380 Sent: []any{}, 1381 } 1382 cache := make(map[int32]util.Uint160) 1383 var resCount, frameCount int 1384 // handleTransfer returns items to be added into the received and sent arrays 1385 // along with a continue flag and error. 1386 var handleTransfer = func(tr *state.NEP17Transfer) (*result.NEP17Transfer, *result.NEP17Transfer, bool, error) { 1387 var received, sent *result.NEP17Transfer 1388 1389 // Iterating from the newest to the oldest, not yet reached required 1390 // time frame, continue looping. 1391 if tr.Timestamp > end { 1392 return nil, nil, true, nil 1393 } 1394 // Iterating from the newest to the oldest, moved past required 1395 // time frame, stop looping. 1396 if tr.Timestamp < start { 1397 return nil, nil, false, nil 1398 } 1399 frameCount++ 1400 // Using limits, not yet reached required page. 1401 if limit != 0 && page*limit >= frameCount { 1402 return nil, nil, true, nil 1403 } 1404 1405 h, err := s.getHash(tr.Asset, cache) 1406 if err != nil { 1407 return nil, nil, false, err 1408 } 1409 1410 transfer := result.NEP17Transfer{ 1411 Timestamp: tr.Timestamp, 1412 Asset: h, 1413 Index: tr.Block, 1414 TxHash: tr.Tx, 1415 } 1416 if !tr.Counterparty.Equals(util.Uint160{}) { 1417 transfer.Address = address.Uint160ToString(tr.Counterparty) 1418 } 1419 if tr.Amount.Sign() > 0 { // token was received 1420 transfer.Amount = tr.Amount.String() 1421 received = &result.NEP17Transfer{} 1422 *received = transfer // Make a copy, transfer is to be modified below. 1423 } else { 1424 transfer.Amount = new(big.Int).Neg(tr.Amount).String() 1425 sent = &result.NEP17Transfer{} 1426 *sent = transfer 1427 } 1428 1429 resCount++ 1430 // Check limits for continue flag. 1431 return received, sent, !(limit != 0 && resCount >= limit), nil 1432 } 1433 if !isNEP11 { 1434 err = s.chain.ForEachNEP17Transfer(u, end, func(tr *state.NEP17Transfer) (bool, error) { 1435 r, s, res, err := handleTransfer(tr) 1436 if err == nil { 1437 if r != nil { 1438 bs.Received = append(bs.Received, r) 1439 } 1440 if s != nil { 1441 bs.Sent = append(bs.Sent, s) 1442 } 1443 } 1444 return res, err 1445 }) 1446 } else { 1447 err = s.chain.ForEachNEP11Transfer(u, end, func(tr *state.NEP11Transfer) (bool, error) { 1448 r, s, res, err := handleTransfer(&tr.NEP17Transfer) 1449 if err == nil { 1450 id := hex.EncodeToString(tr.ID) 1451 if r != nil { 1452 bs.Received = append(bs.Received, nep17TransferToNEP11(r, id)) 1453 } 1454 if s != nil { 1455 bs.Sent = append(bs.Sent, nep17TransferToNEP11(s, id)) 1456 } 1457 } 1458 return res, err 1459 }) 1460 } 1461 if err != nil { 1462 return nil, neorpc.NewInternalServerError(fmt.Sprintf("invalid transfer log: %s", err)) 1463 } 1464 return bs, nil 1465 } 1466 1467 // getHash returns the hash of the contract by its ID using cache. 1468 func (s *Server) getHash(contractID int32, cache map[int32]util.Uint160) (util.Uint160, error) { 1469 if d, ok := cache[contractID]; ok { 1470 return d, nil 1471 } 1472 h, err := s.chain.GetContractScriptHash(contractID) 1473 if err != nil { 1474 return util.Uint160{}, err 1475 } 1476 cache[contractID] = h 1477 return h, nil 1478 } 1479 1480 func (s *Server) contractIDFromParam(param *params.Param, root ...util.Uint256) (int32, *neorpc.Error) { 1481 var result int32 1482 if param == nil { 1483 return 0, neorpc.ErrInvalidParams 1484 } 1485 if scriptHash, err := param.GetUint160FromHex(); err == nil { 1486 if len(root) == 0 { 1487 cs := s.chain.GetContractState(scriptHash) 1488 if cs == nil { 1489 return 0, neorpc.ErrUnknownContract 1490 } 1491 result = cs.ID 1492 } else { 1493 cs, respErr := s.getHistoricalContractState(root[0], scriptHash) 1494 if respErr != nil { 1495 return 0, respErr 1496 } 1497 result = cs.ID 1498 } 1499 } else { 1500 id, err := param.GetInt() 1501 if err != nil { 1502 return 0, neorpc.ErrInvalidParams 1503 } 1504 if err := checkInt32(id); err != nil { 1505 return 0, neorpc.WrapErrorWithData(neorpc.ErrInvalidParams, err.Error()) 1506 } 1507 result = int32(id) 1508 } 1509 return result, nil 1510 } 1511 1512 // getContractScriptHashFromParam returns the contract script hash by hex contract hash, address, id or native contract name. 1513 func (s *Server) contractScriptHashFromParam(param *params.Param) (util.Uint160, *neorpc.Error) { 1514 var result util.Uint160 1515 if param == nil { 1516 return result, neorpc.ErrInvalidParams 1517 } 1518 nameOrHashOrIndex, err := param.GetString() 1519 if err != nil { 1520 return result, neorpc.ErrInvalidParams 1521 } 1522 result, err = param.GetUint160FromAddressOrHex() 1523 if err == nil { 1524 return result, nil 1525 } 1526 result, err = s.chain.GetNativeContractScriptHash(nameOrHashOrIndex) 1527 if err == nil { 1528 return result, nil 1529 } 1530 id, err := strconv.Atoi(nameOrHashOrIndex) 1531 if err != nil { 1532 return result, neorpc.NewInvalidParamsError(fmt.Sprintf("Invalid contract identifier (name/hash/index is expected) : %s", err.Error())) 1533 } 1534 if err := checkInt32(id); err != nil { 1535 return result, neorpc.WrapErrorWithData(neorpc.ErrInvalidParams, err.Error()) 1536 } 1537 result, err = s.chain.GetContractScriptHash(int32(id)) 1538 if err != nil { 1539 return result, neorpc.ErrUnknownContract 1540 } 1541 return result, nil 1542 } 1543 1544 func makeStorageKey(id int32, key []byte) []byte { 1545 skey := make([]byte, 4+len(key)) 1546 binary.LittleEndian.PutUint32(skey, uint32(id)) 1547 copy(skey[4:], key) 1548 return skey 1549 } 1550 1551 var errKeepOnlyLatestState = errors.New("'KeepOnlyLatestState' setting is enabled") 1552 1553 func (s *Server) getProof(ps params.Params) (any, *neorpc.Error) { 1554 if s.chain.GetConfig().Ledger.KeepOnlyLatestState { 1555 return nil, neorpc.WrapErrorWithData(neorpc.ErrUnsupportedState, fmt.Sprintf("'getproof' is not supported: %s", errKeepOnlyLatestState)) 1556 } 1557 root, err := ps.Value(0).GetUint256() 1558 if err != nil { 1559 return nil, neorpc.ErrInvalidParams 1560 } 1561 sc, err := ps.Value(1).GetUint160FromHex() 1562 if err != nil { 1563 return nil, neorpc.ErrInvalidParams 1564 } 1565 key, err := ps.Value(2).GetBytesBase64() 1566 if err != nil { 1567 return nil, neorpc.ErrInvalidParams 1568 } 1569 cs, respErr := s.getHistoricalContractState(root, sc) 1570 if respErr != nil { 1571 return nil, respErr 1572 } 1573 skey := makeStorageKey(cs.ID, key) 1574 proof, err := s.chain.GetStateModule().GetStateProof(root, skey) 1575 if err != nil { 1576 if errors.Is(err, mpt.ErrNotFound) { 1577 return nil, neorpc.ErrUnknownStorageItem 1578 } 1579 return nil, neorpc.NewInternalServerError(fmt.Sprintf("failed to get proof: %s", err)) 1580 } 1581 return &result.ProofWithKey{ 1582 Key: skey, 1583 Proof: proof, 1584 }, nil 1585 } 1586 1587 func (s *Server) verifyProof(ps params.Params) (any, *neorpc.Error) { 1588 if s.chain.GetConfig().Ledger.KeepOnlyLatestState { 1589 return nil, neorpc.WrapErrorWithData(neorpc.ErrUnsupportedState, fmt.Sprintf("'verifyproof' is not supported: %s", errKeepOnlyLatestState)) 1590 } 1591 root, err := ps.Value(0).GetUint256() 1592 if err != nil { 1593 return nil, neorpc.ErrInvalidParams 1594 } 1595 proofStr, err := ps.Value(1).GetString() 1596 if err != nil { 1597 return nil, neorpc.ErrInvalidParams 1598 } 1599 var p result.ProofWithKey 1600 if err := p.FromString(proofStr); err != nil { 1601 return nil, neorpc.ErrInvalidParams 1602 } 1603 vp := new(result.VerifyProof) 1604 val, ok := mpt.VerifyProof(root, p.Key, p.Proof) 1605 if !ok { 1606 return nil, neorpc.ErrInvalidProof 1607 } 1608 vp.Value = val 1609 return vp, nil 1610 } 1611 1612 func (s *Server) getState(ps params.Params) (any, *neorpc.Error) { 1613 root, respErr := s.getStateRootFromParam(ps.Value(0)) 1614 if respErr != nil { 1615 return nil, respErr 1616 } 1617 csHash, err := ps.Value(1).GetUint160FromHex() 1618 if err != nil { 1619 return nil, neorpc.WrapErrorWithData(neorpc.ErrInvalidParams, "invalid contract hash") 1620 } 1621 key, err := ps.Value(2).GetBytesBase64() 1622 if err != nil { 1623 return nil, neorpc.WrapErrorWithData(neorpc.ErrInvalidParams, "invalid key") 1624 } 1625 cs, respErr := s.getHistoricalContractState(root, csHash) 1626 if respErr != nil { 1627 return nil, respErr 1628 } 1629 sKey := makeStorageKey(cs.ID, key) 1630 res, err := s.chain.GetStateModule().GetState(root, sKey) 1631 if err != nil { 1632 if errors.Is(err, mpt.ErrNotFound) { 1633 return nil, neorpc.WrapErrorWithData(neorpc.ErrInvalidParams, fmt.Sprintf("invalid key: %s", err.Error())) 1634 } 1635 return nil, neorpc.NewInternalServerError(fmt.Sprintf("Failed to get historical item state: %s", err.Error())) 1636 } 1637 return res, nil 1638 } 1639 1640 func (s *Server) findStates(ps params.Params) (any, *neorpc.Error) { 1641 root, respErr := s.getStateRootFromParam(ps.Value(0)) 1642 if respErr != nil { 1643 return nil, respErr 1644 } 1645 csHash, err := ps.Value(1).GetUint160FromHex() 1646 if err != nil { 1647 return nil, neorpc.WrapErrorWithData(neorpc.ErrInvalidParams, fmt.Sprintf("invalid contract hash: %s", err)) 1648 } 1649 prefix, err := ps.Value(2).GetBytesBase64() 1650 if err != nil { 1651 return nil, neorpc.WrapErrorWithData(neorpc.ErrInvalidParams, fmt.Sprintf("invalid prefix: %s", err)) 1652 } 1653 var ( 1654 key []byte 1655 count = s.config.MaxFindResultItems 1656 ) 1657 if len(ps) > 3 { 1658 key, err = ps.Value(3).GetBytesBase64() 1659 if err != nil { 1660 return nil, neorpc.WrapErrorWithData(neorpc.ErrInvalidParams, fmt.Sprintf("invalid key: %s", err)) 1661 } 1662 if len(key) > 0 { 1663 if !bytes.HasPrefix(key, prefix) { 1664 return nil, neorpc.WrapErrorWithData(neorpc.ErrInvalidParams, "key doesn't match prefix") 1665 } 1666 key = key[len(prefix):] 1667 } else { 1668 // empty ("") key shouldn't exclude item matching prefix from the result 1669 key = nil 1670 } 1671 } 1672 if len(ps) > 4 { 1673 count, err = ps.Value(4).GetInt() 1674 if err != nil { 1675 return nil, neorpc.WrapErrorWithData(neorpc.ErrInvalidParams, fmt.Sprintf("invalid count: %s", err)) 1676 } 1677 if count > s.config.MaxFindResultItems { 1678 count = s.config.MaxFindResultItems 1679 } 1680 } 1681 cs, respErr := s.getHistoricalContractState(root, csHash) 1682 if respErr != nil { 1683 return nil, respErr 1684 } 1685 pKey := makeStorageKey(cs.ID, prefix) 1686 kvs, err := s.chain.GetStateModule().FindStates(root, pKey, key, count+1) // +1 to define result truncation 1687 if err != nil && !errors.Is(err, mpt.ErrNotFound) { 1688 return nil, neorpc.NewInternalServerError(fmt.Sprintf("failed to find state items: %s", err)) 1689 } 1690 res := result.FindStates{} 1691 if len(kvs) == count+1 { 1692 res.Truncated = true 1693 kvs = kvs[:len(kvs)-1] 1694 } 1695 if len(kvs) > 0 { 1696 proof, err := s.chain.GetStateModule().GetStateProof(root, kvs[0].Key) 1697 if err != nil { 1698 return nil, neorpc.NewInternalServerError(fmt.Sprintf("failed to get first proof: %s", err)) 1699 } 1700 res.FirstProof = &result.ProofWithKey{ 1701 Key: kvs[0].Key, 1702 Proof: proof, 1703 } 1704 } 1705 if len(kvs) > 1 { 1706 proof, err := s.chain.GetStateModule().GetStateProof(root, kvs[len(kvs)-1].Key) 1707 if err != nil { 1708 return nil, neorpc.NewInternalServerError(fmt.Sprintf("failed to get last proof: %s", err)) 1709 } 1710 res.LastProof = &result.ProofWithKey{ 1711 Key: kvs[len(kvs)-1].Key, 1712 Proof: proof, 1713 } 1714 } 1715 res.Results = make([]result.KeyValue, len(kvs)) 1716 for i, kv := range kvs { 1717 res.Results[i] = result.KeyValue{ 1718 Key: kv.Key[4:], // cut contract ID as it is done in C# 1719 Value: kv.Value, 1720 } 1721 } 1722 return res, nil 1723 } 1724 1725 // getStateRootFromParam retrieves state root hash from the provided parameter 1726 // (only util.Uint256 serialized representation is allowed) and checks whether 1727 // MPT states are supported for the old stateroot. 1728 func (s *Server) getStateRootFromParam(p *params.Param) (util.Uint256, *neorpc.Error) { 1729 root, err := p.GetUint256() 1730 if err != nil { 1731 return util.Uint256{}, neorpc.WrapErrorWithData(neorpc.ErrInvalidParams, "invalid stateroot") 1732 } 1733 if s.chain.GetConfig().Ledger.KeepOnlyLatestState { 1734 curr, err := s.chain.GetStateModule().GetStateRoot(s.chain.BlockHeight()) 1735 if err != nil { 1736 return util.Uint256{}, neorpc.NewInternalServerError(fmt.Sprintf("failed to get current stateroot: %s", err)) 1737 } 1738 if !curr.Root.Equals(root) { 1739 return util.Uint256{}, neorpc.WrapErrorWithData(neorpc.ErrUnsupportedState, fmt.Sprintf("state-based methods are not supported for old states: %s", errKeepOnlyLatestState)) 1740 } 1741 } 1742 return root, nil 1743 } 1744 1745 func (s *Server) findStorage(reqParams params.Params) (any, *neorpc.Error) { 1746 id, prefix, start, take, respErr := s.getFindStorageParams(reqParams) 1747 if respErr != nil { 1748 return nil, respErr 1749 } 1750 return s.findStorageInternal(id, prefix, start, take, s.chain) 1751 } 1752 1753 func (s *Server) findStorageInternal(id int32, prefix []byte, start, take int, seeker ContractStorageSeeker) (any, *neorpc.Error) { 1754 var ( 1755 i int 1756 end = start + take 1757 // Result is an empty list if a contract state is not found as it is in C# implementation. 1758 res = &result.FindStorage{Results: make([]result.KeyValue, 0)} 1759 ) 1760 seeker.SeekStorage(id, prefix, func(k, v []byte) bool { 1761 if i < start { 1762 i++ 1763 return true 1764 } 1765 if i < end { 1766 res.Results = append(res.Results, result.KeyValue{ 1767 Key: bytes.Clone(append(prefix, k...)), // Don't strip prefix, as it is done in C#. 1768 Value: v, 1769 }) 1770 i++ 1771 return true 1772 } 1773 res.Truncated = true 1774 return false 1775 }) 1776 res.Next = i 1777 return res, nil 1778 } 1779 1780 func (s *Server) findStorageHistoric(reqParams params.Params) (any, *neorpc.Error) { 1781 root, respErr := s.getStateRootFromParam(reqParams.Value(0)) 1782 if respErr != nil { 1783 return nil, respErr 1784 } 1785 if len(reqParams) < 2 { 1786 return nil, neorpc.ErrInvalidParams 1787 } 1788 id, prefix, start, take, respErr := s.getFindStorageParams(reqParams[1:], root) 1789 if respErr != nil { 1790 return nil, respErr 1791 } 1792 1793 return s.findStorageInternal(id, prefix, start, take, mptStorageSeeker{ 1794 root: root, 1795 module: s.chain.GetStateModule(), 1796 }) 1797 } 1798 1799 // mptStorageSeeker is an auxiliary structure that implements ContractStorageSeeker interface. 1800 type mptStorageSeeker struct { 1801 root util.Uint256 1802 module core.StateRoot 1803 } 1804 1805 func (s mptStorageSeeker) SeekStorage(id int32, prefix []byte, cont func(k, v []byte) bool) { 1806 key := makeStorageKey(id, prefix) 1807 s.module.SeekStates(s.root, key, cont) 1808 } 1809 1810 func (s *Server) getFindStorageParams(reqParams params.Params, root ...util.Uint256) (int32, []byte, int, int, *neorpc.Error) { 1811 if len(reqParams) < 2 { 1812 return 0, nil, 0, 0, neorpc.ErrInvalidParams 1813 } 1814 id, respErr := s.contractIDFromParam(reqParams.Value(0), root...) 1815 if respErr != nil { 1816 return 0, nil, 0, 0, respErr 1817 } 1818 1819 prefix, err := reqParams.Value(1).GetBytesBase64() 1820 if err != nil { 1821 return 0, nil, 0, 0, neorpc.WrapErrorWithData(neorpc.ErrInvalidParams, fmt.Sprintf("invalid prefix: %s", err)) 1822 } 1823 1824 var skip int 1825 if len(reqParams) > 2 { 1826 skip, err = reqParams.Value(2).GetInt() 1827 if err != nil { 1828 return 0, nil, 0, 0, neorpc.WrapErrorWithData(neorpc.ErrInvalidParams, fmt.Sprintf("invalid start: %s", err)) 1829 } 1830 } 1831 return id, prefix, skip, s.config.MaxFindStorageResultItems, nil 1832 } 1833 1834 func (s *Server) getHistoricalContractState(root util.Uint256, csHash util.Uint160) (*state.Contract, *neorpc.Error) { 1835 csKey := makeStorageKey(native.ManagementContractID, native.MakeContractKey(csHash)) 1836 csBytes, err := s.chain.GetStateModule().GetState(root, csKey) 1837 if err != nil { 1838 return nil, neorpc.WrapErrorWithData(neorpc.ErrUnknownContract, fmt.Sprintf("Failed to get historical contract state: %s", err.Error())) 1839 } 1840 contract := new(state.Contract) 1841 err = stackitem.DeserializeConvertible(csBytes, contract) 1842 if err != nil { 1843 return nil, neorpc.NewInternalServerError(fmt.Sprintf("failed to deserialize historical contract state: %s", err)) 1844 } 1845 return contract, nil 1846 } 1847 1848 func (s *Server) getStateHeight(_ params.Params) (any, *neorpc.Error) { 1849 var height = s.chain.BlockHeight() 1850 var stateHeight = s.chain.GetStateModule().CurrentValidatedHeight() 1851 if s.chain.GetConfig().StateRootInHeader { 1852 stateHeight = height - 1 1853 } 1854 return &result.StateHeight{ 1855 Local: height, 1856 Validated: stateHeight, 1857 }, nil 1858 } 1859 1860 func (s *Server) getStateRoot(ps params.Params) (any, *neorpc.Error) { 1861 p := ps.Value(0) 1862 if p == nil { 1863 return nil, neorpc.NewInvalidParamsError("missing stateroot identifier") 1864 } 1865 var rt *state.MPTRoot 1866 var h util.Uint256 1867 height, err := p.GetIntStrict() 1868 if err == nil { 1869 if err := checkUint32(height); err != nil { 1870 return nil, neorpc.WrapErrorWithData(neorpc.ErrInvalidParams, err.Error()) 1871 } 1872 rt, err = s.chain.GetStateModule().GetStateRoot(uint32(height)) 1873 } else if h, err = p.GetUint256(); err == nil { 1874 var hdr *block.Header 1875 hdr, err = s.chain.GetHeader(h) 1876 if err == nil { 1877 rt, err = s.chain.GetStateModule().GetStateRoot(hdr.Index) 1878 } 1879 } 1880 if err != nil { 1881 return nil, neorpc.ErrUnknownStateRoot 1882 } 1883 return rt, nil 1884 } 1885 1886 func (s *Server) getStorage(ps params.Params) (any, *neorpc.Error) { 1887 id, rErr := s.contractIDFromParam(ps.Value(0)) 1888 if rErr != nil { 1889 return nil, rErr 1890 } 1891 1892 key, err := ps.Value(1).GetBytesBase64() 1893 if err != nil { 1894 return nil, neorpc.ErrInvalidParams 1895 } 1896 1897 item := s.chain.GetStorageItem(id, key) 1898 if item == nil { 1899 return "", neorpc.ErrUnknownStorageItem 1900 } 1901 1902 return []byte(item), nil 1903 } 1904 1905 func (s *Server) getStorageHistoric(ps params.Params) (any, *neorpc.Error) { 1906 root, respErr := s.getStateRootFromParam(ps.Value(0)) 1907 if respErr != nil { 1908 return nil, respErr 1909 } 1910 if len(ps) < 2 { 1911 return nil, neorpc.ErrInvalidParams 1912 } 1913 1914 id, rErr := s.contractIDFromParam(ps.Value(1), root) 1915 if rErr != nil { 1916 return nil, rErr 1917 } 1918 key, err := ps.Value(2).GetBytesBase64() 1919 if err != nil { 1920 return nil, neorpc.ErrInvalidParams 1921 } 1922 pKey := makeStorageKey(id, key) 1923 1924 v, err := s.chain.GetStateModule().GetState(root, pKey) 1925 if err != nil && !errors.Is(err, mpt.ErrNotFound) { 1926 return nil, neorpc.NewInternalServerError(fmt.Sprintf("failed to get state item: %s", err)) 1927 } 1928 if v == nil { 1929 return "", neorpc.ErrUnknownStorageItem 1930 } 1931 1932 return v, nil 1933 } 1934 1935 func (s *Server) getrawtransaction(reqParams params.Params) (any, *neorpc.Error) { 1936 txHash, err := reqParams.Value(0).GetUint256() 1937 if err != nil { 1938 return nil, neorpc.ErrInvalidParams 1939 } 1940 tx, height, err := s.chain.GetTransaction(txHash) 1941 if err != nil { 1942 return nil, neorpc.ErrUnknownTransaction 1943 } 1944 if v, _ := reqParams.Value(1).GetBoolean(); v { 1945 res := result.TransactionOutputRaw{ 1946 Transaction: *tx, 1947 } 1948 if height == math.MaxUint32 { // Mempooled transaction. 1949 return res, nil 1950 } 1951 _header := s.chain.GetHeaderHash(height) 1952 header, err := s.chain.GetHeader(_header) 1953 if err != nil { 1954 return nil, neorpc.NewInternalServerError(fmt.Sprintf("Failed to get header for the transaction: %s", err.Error())) 1955 } 1956 aers, err := s.chain.GetAppExecResults(txHash, trigger.Application) 1957 if err != nil { 1958 return nil, neorpc.NewInternalServerError(fmt.Sprintf("Failed to get application log for the transaction: %s", err.Error())) 1959 } 1960 if len(aers) == 0 { 1961 return nil, neorpc.NewInternalServerError("Inconsistent application log: application log for the transaction is empty") 1962 } 1963 res.TransactionMetadata = result.TransactionMetadata{ 1964 Blockhash: header.Hash(), 1965 Confirmations: int(s.chain.BlockHeight() - header.Index + 1), 1966 Timestamp: header.Timestamp, 1967 VMState: aers[0].VMState.String(), 1968 } 1969 return res, nil 1970 } 1971 return tx.Bytes(), nil 1972 } 1973 1974 func (s *Server) getTransactionHeight(ps params.Params) (any, *neorpc.Error) { 1975 h, err := ps.Value(0).GetUint256() 1976 if err != nil { 1977 return nil, neorpc.ErrInvalidParams 1978 } 1979 1980 _, height, err := s.chain.GetTransaction(h) 1981 if err != nil || height == math.MaxUint32 { 1982 return nil, neorpc.ErrUnknownTransaction 1983 } 1984 1985 return height, nil 1986 } 1987 1988 // getContractState returns contract state (contract information, according to the contract script hash, 1989 // contract id or native contract name). 1990 func (s *Server) getContractState(reqParams params.Params) (any, *neorpc.Error) { 1991 scriptHash, err := s.contractScriptHashFromParam(reqParams.Value(0)) 1992 if err != nil { 1993 return nil, err 1994 } 1995 cs := s.chain.GetContractState(scriptHash) 1996 if cs == nil { 1997 return nil, neorpc.ErrUnknownContract 1998 } 1999 return cs, nil 2000 } 2001 2002 func (s *Server) getNativeContracts(_ params.Params) (any, *neorpc.Error) { 2003 return s.chain.GetNatives(), nil 2004 } 2005 2006 // getBlockSysFee returns the system fees of the block, based on the specified index. 2007 func (s *Server) getBlockSysFee(reqParams params.Params) (any, *neorpc.Error) { 2008 num, err := s.blockHeightFromParam(reqParams.Value(0)) 2009 if err != nil { 2010 return 0, neorpc.WrapErrorWithData(err, fmt.Sprintf("invalid block height: %s", err.Data)) 2011 } 2012 2013 headerHash := s.chain.GetHeaderHash(num) 2014 block, errBlock := s.chain.GetBlock(headerHash) 2015 if errBlock != nil { 2016 return 0, neorpc.ErrUnknownBlock 2017 } 2018 2019 var blockSysFee int64 2020 for _, tx := range block.Transactions { 2021 blockSysFee += tx.SystemFee 2022 } 2023 2024 return blockSysFee, nil 2025 } 2026 2027 // getBlockHeader returns the corresponding block header information according to the specified script hash. 2028 func (s *Server) getBlockHeader(reqParams params.Params) (any, *neorpc.Error) { 2029 param := reqParams.Value(0) 2030 hash, respErr := s.blockHashFromParam(param) 2031 if respErr != nil { 2032 return nil, respErr 2033 } 2034 2035 verbose, _ := reqParams.Value(1).GetBoolean() 2036 h, err := s.chain.GetHeader(hash) 2037 if err != nil { 2038 return nil, neorpc.ErrUnknownBlock 2039 } 2040 2041 if verbose { 2042 res := result.Header{ 2043 Header: *h, 2044 BlockMetadata: s.fillBlockMetadata(h, h), 2045 } 2046 return res, nil 2047 } 2048 2049 buf := io.NewBufBinWriter() 2050 h.EncodeBinary(buf.BinWriter) 2051 if buf.Err != nil { 2052 return nil, neorpc.NewInternalServerError(fmt.Sprintf("encoding error: %s", buf.Err)) 2053 } 2054 return buf.Bytes(), nil 2055 } 2056 2057 // getUnclaimedGas returns unclaimed GAS amount of the specified address. 2058 func (s *Server) getUnclaimedGas(ps params.Params) (any, *neorpc.Error) { 2059 u, err := ps.Value(0).GetUint160FromAddressOrHex() 2060 if err != nil { 2061 return nil, neorpc.ErrInvalidParams 2062 } 2063 2064 neo, _ := s.chain.GetGoverningTokenBalance(u) 2065 if neo.Sign() == 0 { 2066 return result.UnclaimedGas{ 2067 Address: u, 2068 }, nil 2069 } 2070 gas, err := s.chain.CalculateClaimable(u, s.chain.BlockHeight()+1) // +1 as in C#, for the next block. 2071 if err != nil { 2072 return nil, neorpc.NewInternalServerError(fmt.Sprintf("Can't calculate claimable: %s", err.Error())) 2073 } 2074 return result.UnclaimedGas{ 2075 Address: u, 2076 Unclaimed: *gas, 2077 }, nil 2078 } 2079 2080 // getCandidates returns the current list of candidates with their active/inactive voting status. 2081 func (s *Server) getCandidates(_ params.Params) (any, *neorpc.Error) { 2082 var validators keys.PublicKeys 2083 2084 validators, err := s.chain.GetNextBlockValidators() 2085 if err != nil { 2086 return nil, neorpc.NewInternalServerError(fmt.Sprintf("Can't get next block validators: %s", err.Error())) 2087 } 2088 enrollments, err := s.chain.GetEnrollments() 2089 if err != nil { 2090 return nil, neorpc.NewInternalServerError(fmt.Sprintf("Can't get enrollments: %s", err.Error())) 2091 } 2092 var res = make([]result.Candidate, 0) 2093 for _, v := range enrollments { 2094 res = append(res, result.Candidate{ 2095 PublicKey: *v.Key, 2096 Votes: v.Votes.Int64(), 2097 Active: validators.Contains(v.Key), 2098 }) 2099 } 2100 return res, nil 2101 } 2102 2103 // getNextBlockValidators returns validators for the next block with voting status. 2104 func (s *Server) getNextBlockValidators(_ params.Params) (any, *neorpc.Error) { 2105 var validators keys.PublicKeys 2106 2107 validators, err := s.chain.GetNextBlockValidators() 2108 if err != nil { 2109 return nil, neorpc.NewInternalServerError(fmt.Sprintf("Can't get next block validators: %s", err.Error())) 2110 } 2111 enrollments, err := s.chain.GetEnrollments() 2112 if err != nil { 2113 return nil, neorpc.NewInternalServerError(fmt.Sprintf("Can't get enrollments: %s", err.Error())) 2114 } 2115 var res = make([]result.Validator, 0) 2116 for _, v := range enrollments { 2117 if !validators.Contains(v.Key) { 2118 continue 2119 } 2120 res = append(res, result.Validator{ 2121 PublicKey: *v.Key, 2122 Votes: v.Votes.Int64(), 2123 }) 2124 } 2125 return res, nil 2126 } 2127 2128 // getCommittee returns the current list of NEO committee members. 2129 func (s *Server) getCommittee(_ params.Params) (any, *neorpc.Error) { 2130 keys, err := s.chain.GetCommittee() 2131 if err != nil { 2132 return nil, neorpc.NewInternalServerError(fmt.Sprintf("can't get committee members: %s", err)) 2133 } 2134 return keys, nil 2135 } 2136 2137 // invokeFunction implements the `invokeFunction` RPC call. 2138 func (s *Server) invokeFunction(reqParams params.Params) (any, *neorpc.Error) { 2139 tx, verbose, respErr := s.getInvokeFunctionParams(reqParams) 2140 if respErr != nil { 2141 return nil, respErr 2142 } 2143 return s.runScriptInVM(trigger.Application, tx.Script, util.Uint160{}, tx, nil, verbose) 2144 } 2145 2146 // invokeFunctionHistoric implements the `invokeFunctionHistoric` RPC call. 2147 func (s *Server) invokeFunctionHistoric(reqParams params.Params) (any, *neorpc.Error) { 2148 nextH, respErr := s.getHistoricParams(reqParams) 2149 if respErr != nil { 2150 return nil, respErr 2151 } 2152 if len(reqParams) < 2 { 2153 return nil, neorpc.ErrInvalidParams 2154 } 2155 tx, verbose, respErr := s.getInvokeFunctionParams(reqParams[1:]) 2156 if respErr != nil { 2157 return nil, respErr 2158 } 2159 return s.runScriptInVM(trigger.Application, tx.Script, util.Uint160{}, tx, &nextH, verbose) 2160 } 2161 2162 func (s *Server) getInvokeFunctionParams(reqParams params.Params) (*transaction.Transaction, bool, *neorpc.Error) { 2163 if len(reqParams) < 2 { 2164 return nil, false, neorpc.ErrInvalidParams 2165 } 2166 scriptHash, responseErr := s.contractScriptHashFromParam(reqParams.Value(0)) 2167 if responseErr != nil { 2168 return nil, false, responseErr 2169 } 2170 method, err := reqParams[1].GetString() 2171 if err != nil { 2172 return nil, false, neorpc.ErrInvalidParams 2173 } 2174 var invparams *params.Param 2175 if len(reqParams) > 2 { 2176 invparams = &reqParams[2] 2177 } 2178 tx := &transaction.Transaction{} 2179 if len(reqParams) > 3 { 2180 signers, _, err := reqParams[3].GetSignersWithWitnesses() 2181 if err != nil { 2182 return nil, false, neorpc.ErrInvalidParams 2183 } 2184 tx.Signers = signers 2185 } 2186 var verbose bool 2187 if len(reqParams) > 4 { 2188 verbose, err = reqParams[4].GetBoolean() 2189 if err != nil { 2190 return nil, false, neorpc.ErrInvalidParams 2191 } 2192 } 2193 if len(tx.Signers) == 0 { 2194 tx.Signers = []transaction.Signer{{Account: util.Uint160{}, Scopes: transaction.None}} 2195 } 2196 script, err := params.CreateFunctionInvocationScript(scriptHash, method, invparams) 2197 if err != nil { 2198 return nil, false, neorpc.WrapErrorWithData(neorpc.ErrInvalidParams, fmt.Sprintf("can't create invocation script: %s", err)) 2199 } 2200 tx.Script = script 2201 return tx, verbose, nil 2202 } 2203 2204 // invokescript implements the `invokescript` RPC call. 2205 func (s *Server) invokescript(reqParams params.Params) (any, *neorpc.Error) { 2206 tx, verbose, respErr := s.getInvokeScriptParams(reqParams) 2207 if respErr != nil { 2208 return nil, respErr 2209 } 2210 return s.runScriptInVM(trigger.Application, tx.Script, util.Uint160{}, tx, nil, verbose) 2211 } 2212 2213 // invokescripthistoric implements the `invokescripthistoric` RPC call. 2214 func (s *Server) invokescripthistoric(reqParams params.Params) (any, *neorpc.Error) { 2215 nextH, respErr := s.getHistoricParams(reqParams) 2216 if respErr != nil { 2217 return nil, respErr 2218 } 2219 if len(reqParams) < 2 { 2220 return nil, neorpc.ErrInvalidParams 2221 } 2222 tx, verbose, respErr := s.getInvokeScriptParams(reqParams[1:]) 2223 if respErr != nil { 2224 return nil, respErr 2225 } 2226 return s.runScriptInVM(trigger.Application, tx.Script, util.Uint160{}, tx, &nextH, verbose) 2227 } 2228 2229 func (s *Server) getInvokeScriptParams(reqParams params.Params) (*transaction.Transaction, bool, *neorpc.Error) { 2230 script, err := reqParams.Value(0).GetBytesBase64() 2231 if err != nil { 2232 return nil, false, neorpc.ErrInvalidParams 2233 } 2234 2235 tx := &transaction.Transaction{} 2236 if len(reqParams) > 1 { 2237 signers, witnesses, err := reqParams[1].GetSignersWithWitnesses() 2238 if err != nil { 2239 return nil, false, neorpc.WrapErrorWithData(neorpc.ErrInvalidParams, err.Error()) 2240 } 2241 tx.Signers = signers 2242 tx.Scripts = witnesses 2243 } 2244 var verbose bool 2245 if len(reqParams) > 2 { 2246 verbose, err = reqParams[2].GetBoolean() 2247 if err != nil { 2248 return nil, false, neorpc.WrapErrorWithData(neorpc.ErrInvalidParams, err.Error()) 2249 } 2250 } 2251 if len(tx.Signers) == 0 { 2252 tx.Signers = []transaction.Signer{{Account: util.Uint160{}, Scopes: transaction.None}} 2253 } 2254 tx.Script = script 2255 return tx, verbose, nil 2256 } 2257 2258 // invokeContractVerify implements the `invokecontractverify` RPC call. 2259 func (s *Server) invokeContractVerify(reqParams params.Params) (any, *neorpc.Error) { 2260 scriptHash, tx, invocationScript, respErr := s.getInvokeContractVerifyParams(reqParams) 2261 if respErr != nil { 2262 return nil, respErr 2263 } 2264 return s.runScriptInVM(trigger.Verification, invocationScript, scriptHash, tx, nil, false) 2265 } 2266 2267 // invokeContractVerifyHistoric implements the `invokecontractverifyhistoric` RPC call. 2268 func (s *Server) invokeContractVerifyHistoric(reqParams params.Params) (any, *neorpc.Error) { 2269 nextH, respErr := s.getHistoricParams(reqParams) 2270 if respErr != nil { 2271 return nil, respErr 2272 } 2273 if len(reqParams) < 2 { 2274 return nil, neorpc.ErrInvalidParams 2275 } 2276 scriptHash, tx, invocationScript, respErr := s.getInvokeContractVerifyParams(reqParams[1:]) 2277 if respErr != nil { 2278 return nil, respErr 2279 } 2280 return s.runScriptInVM(trigger.Verification, invocationScript, scriptHash, tx, &nextH, false) 2281 } 2282 2283 func (s *Server) getInvokeContractVerifyParams(reqParams params.Params) (util.Uint160, *transaction.Transaction, []byte, *neorpc.Error) { 2284 scriptHash, responseErr := s.contractScriptHashFromParam(reqParams.Value(0)) 2285 if responseErr != nil { 2286 return util.Uint160{}, nil, nil, responseErr 2287 } 2288 2289 bw := io.NewBufBinWriter() 2290 if len(reqParams) > 1 { 2291 args, err := reqParams[1].GetArray() // second `invokecontractverify` parameter is an array of arguments for `verify` method 2292 if err != nil { 2293 return util.Uint160{}, nil, nil, neorpc.WrapErrorWithData(neorpc.ErrInvalidParams, err.Error()) 2294 } 2295 if len(args) > 0 { 2296 err := params.ExpandArrayIntoScript(bw.BinWriter, args) 2297 if err != nil { 2298 return util.Uint160{}, nil, nil, neorpc.NewInternalServerError(fmt.Sprintf("can't create witness invocation script: %s", err)) 2299 } 2300 } 2301 } 2302 invocationScript := bw.Bytes() 2303 2304 tx := &transaction.Transaction{Script: []byte{byte(opcode.RET)}} // need something in script 2305 if len(reqParams) > 2 { 2306 signers, witnesses, err := reqParams[2].GetSignersWithWitnesses() 2307 if err != nil { 2308 return util.Uint160{}, nil, nil, neorpc.ErrInvalidParams 2309 } 2310 tx.Signers = signers 2311 tx.Scripts = witnesses 2312 } else { // fill the only known signer - the contract with `verify` method 2313 tx.Signers = []transaction.Signer{{Account: scriptHash}} 2314 tx.Scripts = []transaction.Witness{{InvocationScript: invocationScript, VerificationScript: []byte{}}} 2315 } 2316 return scriptHash, tx, invocationScript, nil 2317 } 2318 2319 // getHistoricParams checks that historic calls are supported and returns index of 2320 // a fake next block to perform the historic call. It also checks that 2321 // specified stateroot is stored at the specified height for further request 2322 // handling consistency. 2323 func (s *Server) getHistoricParams(reqParams params.Params) (uint32, *neorpc.Error) { 2324 if s.chain.GetConfig().Ledger.KeepOnlyLatestState { 2325 return 0, neorpc.WrapErrorWithData(neorpc.ErrUnsupportedState, fmt.Sprintf("only latest state is supported: %s", errKeepOnlyLatestState)) 2326 } 2327 if len(reqParams) < 1 { 2328 return 0, neorpc.ErrInvalidParams 2329 } 2330 height, respErr := s.blockHeightFromParam(reqParams.Value(0)) 2331 if respErr != nil { 2332 hash, err := reqParams.Value(0).GetUint256() 2333 if err != nil { 2334 return 0, neorpc.NewInvalidParamsError(fmt.Sprintf("invalid block hash or index or stateroot hash: %s", err)) 2335 } 2336 b, err := s.chain.GetBlock(hash) 2337 if err != nil { 2338 stateH, err := s.chain.GetStateModule().GetLatestStateHeight(hash) 2339 if err != nil { 2340 return 0, neorpc.NewInvalidParamsError(fmt.Sprintf("unknown block or stateroot: %s", err)) 2341 } 2342 height = stateH 2343 } else { 2344 height = b.Index 2345 } 2346 } 2347 return height + 1, nil 2348 } 2349 2350 func (s *Server) prepareInvocationContext(t trigger.Type, script []byte, contractScriptHash util.Uint160, tx *transaction.Transaction, nextH *uint32, verbose bool) (*interop.Context, *neorpc.Error) { 2351 var ( 2352 err error 2353 ic *interop.Context 2354 ) 2355 if nextH == nil { 2356 ic, err = s.chain.GetTestVM(t, tx, nil) 2357 if err != nil { 2358 return nil, neorpc.NewInternalServerError(fmt.Sprintf("failed to create test VM: %s", err)) 2359 } 2360 } else { 2361 ic, err = s.chain.GetTestHistoricVM(t, tx, *nextH) 2362 if err != nil { 2363 return nil, neorpc.NewInternalServerError(fmt.Sprintf("failed to create historic VM: %s", err)) 2364 } 2365 } 2366 if verbose { 2367 ic.VM.EnableInvocationTree() 2368 } 2369 ic.VM.GasLimit = int64(s.config.MaxGasInvoke) 2370 if t == trigger.Verification { 2371 // We need this special case because witnesses verification is not the simple System.Contract.Call, 2372 // and we need to define exactly the amount of gas consumed for a contract witness verification. 2373 gasPolicy := s.chain.GetMaxVerificationGAS() 2374 if ic.VM.GasLimit > gasPolicy { 2375 ic.VM.GasLimit = gasPolicy 2376 } 2377 2378 err = s.chain.InitVerificationContext(ic, contractScriptHash, &transaction.Witness{InvocationScript: script, VerificationScript: []byte{}}) 2379 if err != nil { 2380 switch { 2381 case errors.Is(err, core.ErrUnknownVerificationContract): 2382 return nil, neorpc.WrapErrorWithData(neorpc.ErrUnknownContract, err.Error()) 2383 case errors.Is(err, core.ErrInvalidVerificationContract): 2384 return nil, neorpc.WrapErrorWithData(neorpc.ErrInvalidVerificationFunction, err.Error()) 2385 default: 2386 return nil, neorpc.NewInternalServerError(fmt.Sprintf("can't prepare verification VM: %s", err)) 2387 } 2388 } 2389 } else { 2390 ic.VM.LoadScriptWithFlags(script, callflag.All) 2391 } 2392 return ic, nil 2393 } 2394 2395 // runScriptInVM runs the given script in a new test VM and returns the invocation 2396 // result. The script is either a simple script in case of `application` trigger, 2397 // witness invocation script in case of `verification` trigger (it pushes `verify` 2398 // arguments on stack before verification). In case of contract verification 2399 // contractScriptHash should be specified. 2400 func (s *Server) runScriptInVM(t trigger.Type, script []byte, contractScriptHash util.Uint160, tx *transaction.Transaction, nextH *uint32, verbose bool) (*result.Invoke, *neorpc.Error) { 2401 ic, respErr := s.prepareInvocationContext(t, script, contractScriptHash, tx, nextH, verbose) 2402 if respErr != nil { 2403 return nil, respErr 2404 } 2405 err := ic.VM.Run() 2406 var faultException string 2407 if err != nil { 2408 faultException = err.Error() 2409 } 2410 items := ic.VM.Estack().ToArray() 2411 sess := s.postProcessExecStack(items) 2412 var id uuid.UUID 2413 2414 if sess != nil { 2415 // nextH == nil only when we're not using MPT-backed storage, therefore 2416 // the second attempt won't stop here. 2417 if s.config.SessionBackedByMPT && nextH == nil { 2418 ic.Finalize() 2419 // Rerun with MPT-backed storage. 2420 return s.runScriptInVM(t, script, contractScriptHash, tx, &ic.Block.Index, verbose) 2421 } 2422 id = uuid.New() 2423 sessionID := id.String() 2424 sess.finalize = ic.Finalize 2425 sess.timer = time.AfterFunc(time.Second*time.Duration(s.config.SessionExpirationTime), func() { 2426 s.sessionsLock.Lock() 2427 defer s.sessionsLock.Unlock() 2428 if len(s.sessions) == 0 { 2429 return 2430 } 2431 sess, ok := s.sessions[sessionID] 2432 if !ok { 2433 return 2434 } 2435 sess.iteratorsLock.Lock() 2436 sess.finalize() 2437 delete(s.sessions, sessionID) 2438 sess.iteratorsLock.Unlock() 2439 }) 2440 s.sessionsLock.Lock() 2441 if len(s.sessions) >= s.config.SessionPoolSize { 2442 ic.Finalize() 2443 s.sessionsLock.Unlock() 2444 return nil, neorpc.NewInternalServerError("max session capacity reached") 2445 } 2446 s.sessions[sessionID] = sess 2447 s.sessionsLock.Unlock() 2448 } else { 2449 ic.Finalize() 2450 } 2451 var diag *result.InvokeDiag 2452 tree := ic.VM.GetInvocationTree() 2453 if tree != nil { 2454 diag = &result.InvokeDiag{ 2455 Invocations: tree.Calls, 2456 Changes: storage.BatchToOperations(ic.DAO.GetBatch()), 2457 } 2458 } 2459 notifications := ic.Notifications 2460 if notifications == nil { 2461 notifications = make([]state.NotificationEvent, 0) 2462 } 2463 res := &result.Invoke{ 2464 State: ic.VM.State().String(), 2465 GasConsumed: ic.VM.GasConsumed(), 2466 Script: script, 2467 Stack: items, 2468 FaultException: faultException, 2469 Notifications: notifications, 2470 Diagnostics: diag, 2471 Session: id, 2472 } 2473 2474 return res, nil 2475 } 2476 2477 // postProcessExecStack changes iterator interop items according to the server configuration. 2478 // It does modifications in-place, but it returns a session if any iterator was registered. 2479 func (s *Server) postProcessExecStack(stack []stackitem.Item) *session { 2480 var sess session 2481 2482 for i, v := range stack { 2483 var id uuid.UUID 2484 2485 stack[i], id = s.registerOrDumpIterator(v) 2486 if id != (uuid.UUID{}) { 2487 sess.iteratorIdentifiers = append(sess.iteratorIdentifiers, &iteratorIdentifier{ 2488 ID: id.String(), 2489 Item: v, 2490 }) 2491 } 2492 } 2493 if len(sess.iteratorIdentifiers) != 0 { 2494 return &sess 2495 } 2496 return nil 2497 } 2498 2499 // registerOrDumpIterator changes iterator interop stack items into result.Iterator 2500 // interop stack items and returns a uuid for it if sessions are enabled. All the other stack 2501 // items are not changed. 2502 func (s *Server) registerOrDumpIterator(item stackitem.Item) (stackitem.Item, uuid.UUID) { 2503 var iterID uuid.UUID 2504 2505 if (item.Type() != stackitem.InteropT) || !iterator.IsIterator(item) { 2506 return item, iterID 2507 } 2508 var resIterator result.Iterator 2509 2510 if s.config.SessionEnabled { 2511 iterID = uuid.New() 2512 resIterator.ID = &iterID 2513 } else { 2514 resIterator.Values, resIterator.Truncated = iterator.ValuesTruncated(item, s.config.MaxIteratorResultItems) 2515 } 2516 return stackitem.NewInterop(resIterator), iterID 2517 } 2518 2519 func (s *Server) traverseIterator(reqParams params.Params) (any, *neorpc.Error) { 2520 if !s.config.SessionEnabled { 2521 return nil, neorpc.ErrSessionsDisabled 2522 } 2523 sID, err := reqParams.Value(0).GetUUID() 2524 if err != nil { 2525 return nil, neorpc.NewInvalidParamsError(fmt.Sprintf("invalid session ID: %s", err)) 2526 } 2527 iID, err := reqParams.Value(1).GetUUID() 2528 if err != nil { 2529 return nil, neorpc.NewInvalidParamsError(fmt.Sprintf("invalid iterator ID: %s", err)) 2530 } 2531 count, err := reqParams.Value(2).GetInt() 2532 if err != nil { 2533 return nil, neorpc.NewInvalidParamsError(fmt.Sprintf("invalid iterator items count: %s", err)) 2534 } 2535 if err := checkInt32(count); err != nil { 2536 return nil, neorpc.NewInvalidParamsError("invalid iterator items count: not an int32") 2537 } 2538 if count > s.config.MaxIteratorResultItems { 2539 return nil, neorpc.NewInvalidParamsError(fmt.Sprintf("iterator items count (%d) is out of range (%d at max)", count, s.config.MaxIteratorResultItems)) 2540 } 2541 2542 s.sessionsLock.Lock() 2543 session, ok := s.sessions[sID.String()] 2544 if !ok { 2545 s.sessionsLock.Unlock() 2546 return nil, neorpc.ErrUnknownSession 2547 } 2548 session.iteratorsLock.Lock() 2549 // Perform `till` update only after session.iteratorsLock is taken in order to have more 2550 // precise session lifetime. 2551 session.timer.Reset(time.Second * time.Duration(s.config.SessionExpirationTime)) 2552 s.sessionsLock.Unlock() 2553 2554 var ( 2555 iIDStr = iID.String() 2556 iVals []stackitem.Item 2557 found bool 2558 ) 2559 for _, it := range session.iteratorIdentifiers { 2560 if iIDStr == it.ID { 2561 iVals = iterator.Values(it.Item, count) 2562 found = true 2563 break 2564 } 2565 } 2566 session.iteratorsLock.Unlock() 2567 if !found { 2568 return nil, neorpc.ErrUnknownIterator 2569 } 2570 2571 result := make([]json.RawMessage, len(iVals)) 2572 for j := range iVals { 2573 result[j], err = stackitem.ToJSONWithTypes(iVals[j]) 2574 if err != nil { 2575 return nil, neorpc.NewInternalServerError(fmt.Sprintf("failed to marshal iterator value: %s", err)) 2576 } 2577 } 2578 return result, nil 2579 } 2580 2581 func (s *Server) terminateSession(reqParams params.Params) (any, *neorpc.Error) { 2582 if !s.config.SessionEnabled { 2583 return nil, neorpc.ErrSessionsDisabled 2584 } 2585 sID, err := reqParams.Value(0).GetUUID() 2586 if err != nil { 2587 return nil, neorpc.NewInvalidParamsError(fmt.Sprintf("invalid session ID: %s", err)) 2588 } 2589 strSID := sID.String() 2590 s.sessionsLock.Lock() 2591 defer s.sessionsLock.Unlock() 2592 session, ok := s.sessions[strSID] 2593 if !ok { 2594 return nil, neorpc.ErrUnknownSession 2595 } 2596 // Iterators access Seek channel under the hood; finalizer closes this channel, thus, 2597 // we need to perform finalisation under iteratorsLock. 2598 session.iteratorsLock.Lock() 2599 session.finalize() 2600 if !session.timer.Stop() { 2601 <-session.timer.C 2602 } 2603 delete(s.sessions, strSID) 2604 session.iteratorsLock.Unlock() 2605 return ok, nil 2606 } 2607 2608 // submitBlock broadcasts a raw block over the Neo network. 2609 func (s *Server) submitBlock(reqParams params.Params) (any, *neorpc.Error) { 2610 blockBytes, err := reqParams.Value(0).GetBytesBase64() 2611 if err != nil { 2612 return nil, neorpc.NewInvalidParamsError(fmt.Sprintf("missing parameter or not a base64: %s", err)) 2613 } 2614 b := block.New(s.stateRootEnabled) 2615 r := io.NewBinReaderFromBuf(blockBytes) 2616 b.DecodeBinary(r) 2617 if r.Err != nil { 2618 return nil, neorpc.NewInvalidParamsError(fmt.Sprintf("can't decode block: %s", r.Err)) 2619 } 2620 return getRelayResult(s.chain.AddBlock(b), b.Hash()) 2621 } 2622 2623 // submitNotaryRequest broadcasts P2PNotaryRequest over the Neo network. 2624 func (s *Server) submitNotaryRequest(ps params.Params) (any, *neorpc.Error) { 2625 if !s.chain.P2PSigExtensionsEnabled() { 2626 return nil, neorpc.NewInternalServerError("P2PSignatureExtensions are disabled") 2627 } 2628 2629 bytePayload, err := ps.Value(0).GetBytesBase64() 2630 if err != nil { 2631 return nil, neorpc.NewInvalidParamsError(fmt.Sprintf("not a base64: %s", err)) 2632 } 2633 r, err := payload.NewP2PNotaryRequestFromBytes(bytePayload) 2634 if err != nil { 2635 return nil, neorpc.NewInvalidParamsError(fmt.Sprintf("can't decode notary payload: %s", err)) 2636 } 2637 return getRelayResult(s.coreServer.RelayP2PNotaryRequest(r), r.FallbackTransaction.Hash()) 2638 } 2639 2640 // getRelayResult returns successful relay result or an error. 2641 func getRelayResult(err error, hash util.Uint256) (any, *neorpc.Error) { 2642 switch { 2643 case err == nil: 2644 return result.RelayResult{ 2645 Hash: hash, 2646 }, nil 2647 case errors.Is(err, core.ErrTxExpired): 2648 return nil, neorpc.WrapErrorWithData(neorpc.ErrExpiredTransaction, err.Error()) 2649 case errors.Is(err, core.ErrAlreadyExists) || errors.Is(err, core.ErrInvalidBlockIndex): 2650 return nil, neorpc.WrapErrorWithData(neorpc.ErrAlreadyExists, err.Error()) 2651 case errors.Is(err, core.ErrAlreadyInPool): 2652 return nil, neorpc.WrapErrorWithData(neorpc.ErrAlreadyInPool, err.Error()) 2653 case errors.Is(err, core.ErrOOM): 2654 return nil, neorpc.WrapErrorWithData(neorpc.ErrMempoolCapReached, err.Error()) 2655 case errors.Is(err, core.ErrPolicy): 2656 return nil, neorpc.WrapErrorWithData(neorpc.ErrPolicyFailed, err.Error()) 2657 case errors.Is(err, core.ErrInvalidScript): 2658 return nil, neorpc.WrapErrorWithData(neorpc.ErrInvalidScript, err.Error()) 2659 case errors.Is(err, core.ErrTxTooBig): 2660 return nil, neorpc.WrapErrorWithData(neorpc.ErrInvalidSize, err.Error()) 2661 case errors.Is(err, core.ErrTxSmallNetworkFee): 2662 return nil, neorpc.WrapErrorWithData(neorpc.ErrInsufficientNetworkFee, err.Error()) 2663 case errors.Is(err, core.ErrInvalidAttribute): 2664 return nil, neorpc.WrapErrorWithData(neorpc.ErrInvalidAttribute, err.Error()) 2665 case errors.Is(err, core.ErrInsufficientFunds), errors.Is(err, core.ErrMemPoolConflict): 2666 return nil, neorpc.WrapErrorWithData(neorpc.ErrInsufficientFunds, err.Error()) 2667 case errors.Is(err, core.ErrInvalidSignature): 2668 return nil, neorpc.WrapErrorWithData(neorpc.ErrInvalidSignature, err.Error()) 2669 default: 2670 return nil, neorpc.WrapErrorWithData(neorpc.ErrVerificationFailed, err.Error()) 2671 } 2672 } 2673 2674 func (s *Server) submitOracleResponse(ps params.Params) (any, *neorpc.Error) { 2675 oraclePtr := s.oracle.Load() 2676 if oraclePtr == nil { 2677 return nil, neorpc.ErrOracleDisabled 2678 } 2679 oracle := oraclePtr.(OracleHandler) 2680 var pub *keys.PublicKey 2681 pubBytes, err := ps.Value(0).GetBytesBase64() 2682 if err == nil { 2683 pub, err = keys.NewPublicKeyFromBytes(pubBytes, elliptic.P256()) 2684 } 2685 if err != nil { 2686 return nil, neorpc.NewInvalidParamsError(fmt.Sprintf("public key is missing: %s", err)) 2687 } 2688 reqID, err := ps.Value(1).GetInt() 2689 if err != nil { 2690 return nil, neorpc.NewInvalidParamsError(fmt.Sprintf("request ID is missing: %s", err)) 2691 } 2692 txSig, err := ps.Value(2).GetBytesBase64() 2693 if err != nil { 2694 return nil, neorpc.WrapErrorWithData(neorpc.ErrInvalidParams, fmt.Sprintf("tx signature is missing: %s", err)) 2695 } 2696 msgSig, err := ps.Value(3).GetBytesBase64() 2697 if err != nil { 2698 return nil, neorpc.WrapErrorWithData(neorpc.ErrInvalidParams, fmt.Sprintf("msg signature is missing: %s", err)) 2699 } 2700 data := broadcaster.GetMessage(pubBytes, uint64(reqID), txSig) 2701 if !pub.Verify(msgSig, hash.Sha256(data).BytesBE()) { 2702 return nil, neorpc.ErrInvalidSignature 2703 } 2704 oracle.AddResponse(pub, uint64(reqID), txSig) 2705 return json.RawMessage([]byte("{}")), nil 2706 } 2707 2708 func (s *Server) sendrawtransaction(reqParams params.Params) (any, *neorpc.Error) { 2709 if len(reqParams) < 1 { 2710 return nil, neorpc.NewInvalidParamsError("not enough parameters") 2711 } 2712 byteTx, err := reqParams[0].GetBytesBase64() 2713 if err != nil { 2714 return nil, neorpc.NewInvalidParamsError(fmt.Sprintf("not a base64: %s", err)) 2715 } 2716 tx, err := transaction.NewTransactionFromBytes(byteTx) 2717 if err != nil { 2718 return nil, neorpc.NewInvalidParamsError(fmt.Sprintf("can't decode transaction: %s", err)) 2719 } 2720 return getRelayResult(s.coreServer.RelayTxn(tx), tx.Hash()) 2721 } 2722 2723 // subscribe handles subscription requests from websocket clients. 2724 func (s *Server) subscribe(reqParams params.Params, sub *subscriber) (any, *neorpc.Error) { 2725 streamName, err := reqParams.Value(0).GetString() 2726 if err != nil { 2727 return nil, neorpc.ErrInvalidParams 2728 } 2729 event, err := neorpc.GetEventIDFromString(streamName) 2730 if err != nil || event == neorpc.MissedEventID { 2731 return nil, neorpc.ErrInvalidParams 2732 } 2733 if event == neorpc.NotaryRequestEventID && !s.chain.P2PSigExtensionsEnabled() { 2734 return nil, neorpc.WrapErrorWithData(neorpc.ErrInvalidParams, "P2PSigExtensions are disabled") 2735 } 2736 // Optional filter. 2737 var filter neorpc.SubscriptionFilter 2738 if p := reqParams.Value(1); p != nil { 2739 param := *p 2740 jd := json.NewDecoder(bytes.NewReader(param.RawMessage)) 2741 jd.DisallowUnknownFields() 2742 switch event { 2743 case neorpc.BlockEventID, neorpc.HeaderOfAddedBlockEventID: 2744 flt := new(neorpc.BlockFilter) 2745 err = jd.Decode(flt) 2746 filter = *flt 2747 case neorpc.TransactionEventID: 2748 flt := new(neorpc.TxFilter) 2749 err = jd.Decode(flt) 2750 filter = *flt 2751 case neorpc.NotaryRequestEventID: 2752 flt := new(neorpc.NotaryRequestFilter) 2753 err = jd.Decode(flt) 2754 filter = *flt 2755 case neorpc.NotificationEventID: 2756 flt := new(neorpc.NotificationFilter) 2757 err = jd.Decode(flt) 2758 filter = *flt 2759 case neorpc.ExecutionEventID: 2760 flt := new(neorpc.ExecutionFilter) 2761 err = jd.Decode(flt) 2762 filter = *flt 2763 } 2764 if err != nil { 2765 return nil, neorpc.WrapErrorWithData(neorpc.ErrInvalidParams, err.Error()) 2766 } 2767 } 2768 if filter != nil { 2769 err = filter.IsValid() 2770 if err != nil { 2771 return nil, neorpc.WrapErrorWithData(neorpc.ErrInvalidParams, err.Error()) 2772 } 2773 } 2774 2775 s.subsLock.Lock() 2776 var id int 2777 for ; id < len(sub.feeds); id++ { 2778 if sub.feeds[id].event == neorpc.InvalidEventID { 2779 break 2780 } 2781 } 2782 if id == len(sub.feeds) { 2783 s.subsLock.Unlock() 2784 return nil, neorpc.NewInternalServerError("maximum number of subscriptions is reached") 2785 } 2786 sub.feeds[id].event = event 2787 sub.feeds[id].filter = filter 2788 s.subsLock.Unlock() 2789 2790 s.subsCounterLock.Lock() 2791 select { 2792 case <-s.shutdown: 2793 s.subsCounterLock.Unlock() 2794 return nil, neorpc.NewInternalServerError("server is shutting down") 2795 default: 2796 } 2797 s.subscribeToChannel(event) 2798 s.subsCounterLock.Unlock() 2799 return strconv.FormatInt(int64(id), 10), nil 2800 } 2801 2802 // subscribeToChannel subscribes RPC server to appropriate chain events if 2803 // it's not yet subscribed for them. It's supposed to be called with s.subsCounterLock 2804 // taken by the caller. 2805 func (s *Server) subscribeToChannel(event neorpc.EventID) { 2806 switch event { 2807 case neorpc.BlockEventID: 2808 if s.blockSubs == 0 { 2809 s.chain.SubscribeForBlocks(s.blockCh) 2810 } 2811 s.blockSubs++ 2812 case neorpc.TransactionEventID: 2813 if s.transactionSubs == 0 { 2814 s.chain.SubscribeForTransactions(s.transactionCh) 2815 } 2816 s.transactionSubs++ 2817 case neorpc.NotificationEventID: 2818 if s.notificationSubs == 0 { 2819 s.chain.SubscribeForNotifications(s.notificationCh) 2820 } 2821 s.notificationSubs++ 2822 case neorpc.ExecutionEventID: 2823 if s.executionSubs == 0 { 2824 s.chain.SubscribeForExecutions(s.executionCh) 2825 } 2826 s.executionSubs++ 2827 case neorpc.NotaryRequestEventID: 2828 if s.notaryRequestSubs == 0 { 2829 s.coreServer.SubscribeForNotaryRequests(s.notaryRequestCh) 2830 } 2831 s.notaryRequestSubs++ 2832 case neorpc.HeaderOfAddedBlockEventID: 2833 if s.blockHeaderSubs == 0 { 2834 s.chain.SubscribeForHeadersOfAddedBlocks(s.blockHeaderCh) 2835 } 2836 s.blockHeaderSubs++ 2837 } 2838 } 2839 2840 // unsubscribe handles unsubscription requests from websocket clients. 2841 func (s *Server) unsubscribe(reqParams params.Params, sub *subscriber) (any, *neorpc.Error) { 2842 id, err := reqParams.Value(0).GetInt() 2843 if err != nil || id < 0 { 2844 return nil, neorpc.ErrInvalidParams 2845 } 2846 s.subsLock.Lock() 2847 if len(sub.feeds) <= id || sub.feeds[id].event == neorpc.InvalidEventID { 2848 s.subsLock.Unlock() 2849 return nil, neorpc.ErrInvalidParams 2850 } 2851 event := sub.feeds[id].event 2852 sub.feeds[id].event = neorpc.InvalidEventID 2853 sub.feeds[id].filter = nil 2854 s.subsLock.Unlock() 2855 2856 s.subsCounterLock.Lock() 2857 s.unsubscribeFromChannel(event) 2858 s.subsCounterLock.Unlock() 2859 return true, nil 2860 } 2861 2862 // unsubscribeFromChannel unsubscribes RPC server from appropriate chain events 2863 // if there are no other subscribers for it. It must be called with s.subsConutersLock 2864 // holding by the caller. 2865 func (s *Server) unsubscribeFromChannel(event neorpc.EventID) { 2866 switch event { 2867 case neorpc.BlockEventID: 2868 s.blockSubs-- 2869 if s.blockSubs == 0 { 2870 s.chain.UnsubscribeFromBlocks(s.blockCh) 2871 } 2872 case neorpc.TransactionEventID: 2873 s.transactionSubs-- 2874 if s.transactionSubs == 0 { 2875 s.chain.UnsubscribeFromTransactions(s.transactionCh) 2876 } 2877 case neorpc.NotificationEventID: 2878 s.notificationSubs-- 2879 if s.notificationSubs == 0 { 2880 s.chain.UnsubscribeFromNotifications(s.notificationCh) 2881 } 2882 case neorpc.ExecutionEventID: 2883 s.executionSubs-- 2884 if s.executionSubs == 0 { 2885 s.chain.UnsubscribeFromExecutions(s.executionCh) 2886 } 2887 case neorpc.NotaryRequestEventID: 2888 s.notaryRequestSubs-- 2889 if s.notaryRequestSubs == 0 { 2890 s.coreServer.UnsubscribeFromNotaryRequests(s.notaryRequestCh) 2891 } 2892 case neorpc.HeaderOfAddedBlockEventID: 2893 s.blockHeaderSubs-- 2894 if s.blockHeaderSubs == 0 { 2895 s.chain.UnsubscribeFromHeadersOfAddedBlocks(s.blockHeaderCh) 2896 } 2897 } 2898 } 2899 2900 // handleSubEvents processes Server subscriptions until Shutdown. Upon 2901 // completion signals to subEventCh channel. 2902 func (s *Server) handleSubEvents() { 2903 var overflowEvent = neorpc.Notification{ 2904 JSONRPC: neorpc.JSONRPCVersion, 2905 Event: neorpc.MissedEventID, 2906 Payload: make([]any, 0), 2907 } 2908 b, err := json.Marshal(overflowEvent) 2909 if err != nil { 2910 s.log.Error("fatal: failed to marshal overflow event", zap.Error(err)) 2911 return 2912 } 2913 overflowMsg, err := websocket.NewPreparedMessage(websocket.TextMessage, b) 2914 if err != nil { 2915 s.log.Error("fatal: failed to prepare overflow message", zap.Error(err)) 2916 return 2917 } 2918 chloop: 2919 for { 2920 var resp = neorpc.Notification{ 2921 JSONRPC: neorpc.JSONRPCVersion, 2922 Payload: make([]any, 1), 2923 } 2924 var msg *websocket.PreparedMessage 2925 select { 2926 case <-s.shutdown: 2927 break chloop 2928 case b := <-s.blockCh: 2929 resp.Event = neorpc.BlockEventID 2930 resp.Payload[0] = b 2931 case execution := <-s.executionCh: 2932 resp.Event = neorpc.ExecutionEventID 2933 resp.Payload[0] = execution 2934 case notification := <-s.notificationCh: 2935 resp.Event = neorpc.NotificationEventID 2936 resp.Payload[0] = notification 2937 case tx := <-s.transactionCh: 2938 resp.Event = neorpc.TransactionEventID 2939 resp.Payload[0] = tx 2940 case e := <-s.notaryRequestCh: 2941 resp.Event = neorpc.NotaryRequestEventID 2942 resp.Payload[0] = &result.NotaryRequestEvent{ 2943 Type: e.Type, 2944 NotaryRequest: e.Data.(*payload.P2PNotaryRequest), 2945 } 2946 case header := <-s.blockHeaderCh: 2947 resp.Event = neorpc.HeaderOfAddedBlockEventID 2948 resp.Payload[0] = header 2949 } 2950 s.subsLock.RLock() 2951 subloop: 2952 for sub := range s.subscribers { 2953 if sub.overflown.Load() { 2954 continue 2955 } 2956 for i := range sub.feeds { 2957 if rpcevent.Matches(sub.feeds[i], &resp) { 2958 if msg == nil { 2959 b, err = json.Marshal(resp) 2960 if err != nil { 2961 s.log.Error("failed to marshal notification", 2962 zap.Error(err), 2963 zap.Stringer("type", resp.Event)) 2964 break subloop 2965 } 2966 msg, err = websocket.NewPreparedMessage(websocket.TextMessage, b) 2967 if err != nil { 2968 s.log.Error("failed to prepare notification message", 2969 zap.Error(err), 2970 zap.Stringer("type", resp.Event)) 2971 break subloop 2972 } 2973 } 2974 select { 2975 case sub.writer <- intEvent{msg, &resp}: 2976 default: 2977 sub.overflown.Store(true) 2978 // MissedEvent is to be delivered eventually. 2979 go func(sub *subscriber) { 2980 sub.writer <- intEvent{overflowMsg, &overflowEvent} 2981 sub.overflown.Store(false) 2982 }(sub) 2983 } 2984 // The message is sent only once per subscriber. 2985 break 2986 } 2987 } 2988 } 2989 s.subsLock.RUnlock() 2990 } 2991 // It's important to do it with subsCounterLock held because no subscription routine 2992 // should be running concurrently to this one. And even if one is to run 2993 // after unlock, it'll see closed s.shutdown and won't subscribe. 2994 s.subsCounterLock.Lock() 2995 // There might be no subscription in reality, but it's not a problem as 2996 // core.Blockchain allows unsubscribing non-subscribed channels. 2997 s.chain.UnsubscribeFromBlocks(s.blockCh) 2998 s.chain.UnsubscribeFromTransactions(s.transactionCh) 2999 s.chain.UnsubscribeFromNotifications(s.notificationCh) 3000 s.chain.UnsubscribeFromExecutions(s.executionCh) 3001 s.chain.UnsubscribeFromHeadersOfAddedBlocks(s.blockHeaderCh) 3002 if s.chain.P2PSigExtensionsEnabled() { 3003 s.coreServer.UnsubscribeFromNotaryRequests(s.notaryRequestCh) 3004 } 3005 s.subsCounterLock.Unlock() 3006 drainloop: 3007 for { 3008 select { 3009 case <-s.blockCh: 3010 case <-s.executionCh: 3011 case <-s.notificationCh: 3012 case <-s.transactionCh: 3013 case <-s.notaryRequestCh: 3014 case <-s.blockHeaderCh: 3015 default: 3016 break drainloop 3017 } 3018 } 3019 // It's not required closing these, but since they're drained already 3020 // this is safe. 3021 close(s.blockCh) 3022 close(s.transactionCh) 3023 close(s.notificationCh) 3024 close(s.executionCh) 3025 close(s.notaryRequestCh) 3026 close(s.blockHeaderCh) 3027 // notify Shutdown routine 3028 close(s.subEventsToExitCh) 3029 } 3030 3031 func (s *Server) blockHeightFromParam(param *params.Param) (uint32, *neorpc.Error) { 3032 num, err := param.GetInt() 3033 if err != nil { 3034 return 0, neorpc.ErrInvalidParams 3035 } 3036 3037 if num < 0 || int64(num) > int64(s.chain.BlockHeight()) { 3038 return 0, neorpc.WrapErrorWithData(neorpc.ErrUnknownHeight, fmt.Sprintf("param at index %d should be greater than or equal to 0 and less than or equal to current block height, got: %d", 0, num)) 3039 } 3040 return uint32(num), nil 3041 } 3042 3043 func (s *Server) packResponse(r *params.In, result any, respErr *neorpc.Error) abstract { 3044 resp := abstract{ 3045 Header: neorpc.Header{ 3046 JSONRPC: r.JSONRPC, 3047 ID: r.RawID, 3048 }, 3049 } 3050 if respErr != nil { 3051 resp.Error = respErr 3052 } else { 3053 resp.Result = result 3054 } 3055 return resp 3056 } 3057 3058 // logRequestError is a request error logger. 3059 func (s *Server) logRequestError(r *params.Request, jsonErr *neorpc.Error) { 3060 logFields := []zap.Field{ 3061 zap.Int64("code", jsonErr.Code), 3062 } 3063 if len(jsonErr.Data) != 0 { 3064 logFields = append(logFields, zap.String("cause", jsonErr.Data)) 3065 } 3066 3067 if r.In != nil { 3068 logFields = append(logFields, zap.String("method", r.In.Method)) 3069 params := params.Params(r.In.RawParams) 3070 logFields = append(logFields, zap.Any("params", params)) 3071 } 3072 3073 logText := "Error encountered with rpc request" 3074 switch jsonErr.Code { 3075 case neorpc.InternalServerErrorCode: 3076 s.log.Error(logText, logFields...) 3077 default: 3078 s.log.Info(logText, logFields...) 3079 } 3080 } 3081 3082 // writeHTTPErrorResponse writes an error response to the ResponseWriter. 3083 func (s *Server) writeHTTPErrorResponse(r *params.In, w http.ResponseWriter, jsonErr *neorpc.Error) { 3084 resp := s.packResponse(r, nil, jsonErr) 3085 s.writeHTTPServerResponse(¶ms.Request{In: r}, w, resp) 3086 } 3087 3088 func setCORSOriginHeaders(h http.Header) { 3089 h.Set("Access-Control-Allow-Origin", "*") 3090 h.Set("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With") 3091 } 3092 3093 func (s *Server) writeHTTPServerResponse(r *params.Request, w http.ResponseWriter, resp abstractResult) { 3094 // Errors can happen in many places and we can only catch ALL of them here. 3095 resp.RunForErrors(func(jsonErr *neorpc.Error) { 3096 s.logRequestError(r, jsonErr) 3097 }) 3098 w.Header().Set("Content-Type", "application/json; charset=utf-8") 3099 if s.config.EnableCORSWorkaround { 3100 setCORSOriginHeaders(w.Header()) 3101 } 3102 if r.In != nil { 3103 resp := resp.(abstract) 3104 if resp.Error != nil { 3105 w.WriteHeader(getHTTPCodeForError(resp.Error)) 3106 } 3107 } 3108 3109 encoder := json.NewEncoder(w) 3110 err := encoder.Encode(resp) 3111 3112 if err != nil { 3113 switch { 3114 case r.In != nil: 3115 s.log.Error("Error encountered while encoding response", 3116 zap.String("err", err.Error()), 3117 zap.String("method", r.In.Method)) 3118 case r.Batch != nil: 3119 s.log.Error("Error encountered while encoding batch response", 3120 zap.String("err", err.Error())) 3121 } 3122 } 3123 } 3124 3125 // validateAddress verifies that the address is a correct Neo address 3126 // see https://docs.neo.org/en-us/node/cli/2.9.4/api/validateaddress.html 3127 func validateAddress(addr any) bool { 3128 if addr, ok := addr.(string); ok { 3129 _, err := address.StringToUint160(addr) 3130 return err == nil 3131 } 3132 return false 3133 } 3134 3135 func escapeForLog(in string) string { 3136 return strings.Map(func(c rune) rune { 3137 if !strconv.IsGraphic(c) { 3138 return -1 3139 } 3140 return c 3141 }, in) 3142 } 3143 3144 // Addresses returns the list of addresses RPC server is listening to in the form of 3145 // address:port. 3146 func (s *Server) Addresses() []string { 3147 res := make([]string, len(s.http)) 3148 for i, srv := range s.http { 3149 res[i] = srv.Addr 3150 } 3151 return res 3152 } 3153 3154 func (s *Server) getRawNotaryPool(_ params.Params) (any, *neorpc.Error) { 3155 if !s.chain.P2PSigExtensionsEnabled() { 3156 return nil, neorpc.NewInternalServerError("P2PSignatureExtensions are disabled") 3157 } 3158 nrp := s.coreServer.GetNotaryPool() 3159 res := &result.RawNotaryPool{Hashes: make(map[util.Uint256][]util.Uint256)} 3160 nrp.IterateVerifiedTransactions(func(tx *transaction.Transaction, data any) bool { 3161 if data != nil { 3162 d := data.(*payload.P2PNotaryRequest) 3163 mainHash := d.MainTransaction.Hash() 3164 fallbackHash := d.FallbackTransaction.Hash() 3165 res.Hashes[mainHash] = append(res.Hashes[mainHash], fallbackHash) 3166 } 3167 return true 3168 }) 3169 return res, nil 3170 } 3171 3172 func (s *Server) getRawNotaryTransaction(reqParams params.Params) (any, *neorpc.Error) { 3173 if !s.chain.P2PSigExtensionsEnabled() { 3174 return nil, neorpc.NewInternalServerError("P2PSignatureExtensions are disabled") 3175 } 3176 3177 txHash, err := reqParams.Value(0).GetUint256() 3178 if err != nil { 3179 return nil, neorpc.ErrInvalidParams 3180 } 3181 nrp := s.coreServer.GetNotaryPool() 3182 // Try to find fallback transaction. 3183 tx, ok := nrp.TryGetValue(txHash) 3184 if !ok { 3185 // Try to find main transaction. 3186 nrp.IterateVerifiedTransactions(func(t *transaction.Transaction, data any) bool { 3187 if data != nil && data.(*payload.P2PNotaryRequest).MainTransaction.Hash().Equals(txHash) { 3188 tx = data.(*payload.P2PNotaryRequest).MainTransaction 3189 return false 3190 } 3191 return true 3192 }) 3193 // The transaction was not found. 3194 if tx == nil { 3195 return nil, neorpc.ErrUnknownTransaction 3196 } 3197 } 3198 3199 if v, _ := reqParams.Value(1).GetBoolean(); v { 3200 return tx, nil 3201 } 3202 return tx.Bytes(), nil 3203 }