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(&params.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  }