Merge pull request #3063 from tatiana-nspcc/rpcsrv-errors
RPC: add error codes and response errors
This commit is contained in:
commit
5c6a111d00
10 changed files with 1172 additions and 621 deletions
|
@ -139,3 +139,11 @@ hidden under `version` label and `server_id` contains network server ID hidden
|
||||||
under `server_id` label.
|
under `server_id` label.
|
||||||
|
|
||||||
Removal of `serv_node_version` is scheduled for Sep-Oct 2023 (~0.105.0 release).
|
Removal of `serv_node_version` is scheduled for Sep-Oct 2023 (~0.105.0 release).
|
||||||
|
|
||||||
|
## RPC error codes returned by old versions and C#-nodes
|
||||||
|
|
||||||
|
NeoGo retains certain deprecated error codes: `neorpc.ErrCompatGeneric`,
|
||||||
|
`neorpc.ErrCompatNoOpenedWallet`. They returned by nodes not compliant with the
|
||||||
|
neo-project/proposals#156 (NeoGo pre-0.102.0 and all known C# versions).
|
||||||
|
|
||||||
|
Removal of the deprecated RPC error codes is planned once all nodes adopt the new error standard.
|
|
@ -423,7 +423,7 @@ func mkP2PNotary(config config.P2PNotary, chain *core.Blockchain, serv *network.
|
||||||
}
|
}
|
||||||
n, err := notary.NewNotary(cfg, serv.Net, serv.GetNotaryPool(), func(tx *transaction.Transaction) error {
|
n, err := notary.NewNotary(cfg, serv.Net, serv.GetNotaryPool(), func(tx *transaction.Transaction) error {
|
||||||
err := serv.RelayTxn(tx)
|
err := serv.RelayTxn(tx)
|
||||||
if err != nil && !errors.Is(err, core.ErrAlreadyExists) {
|
if err != nil && !errors.Is(err, core.ErrAlreadyExists) && !errors.Is(err, core.ErrAlreadyInPool) {
|
||||||
return fmt.Errorf("can't relay completed notary transaction: hash %s, error: %w", tx.Hash().StringLE(), err)
|
return fmt.Errorf("can't relay completed notary transaction: hash %s, error: %w", tx.Hash().StringLE(), err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
17
docs/rpc.md
17
docs/rpc.md
|
@ -98,6 +98,13 @@ following data types:
|
||||||
|
|
||||||
Any call that takes any of these types for input in JSON format is affected.
|
Any call that takes any of these types for input in JSON format is affected.
|
||||||
|
|
||||||
|
##### Response error codes
|
||||||
|
|
||||||
|
NeoGo currently uses a different set of error codes in comparison to C# implementation, see
|
||||||
|
[proposal](https://github.com/neo-project/proposals/pull/156).
|
||||||
|
NeoGo retains certain deprecated error codes, which will be removed once
|
||||||
|
all nodes adopt the new error standard.
|
||||||
|
|
||||||
##### `calculatenetworkfee`
|
##### `calculatenetworkfee`
|
||||||
|
|
||||||
NeoGo tries to cover more cases with its calculatenetworkfee implementation,
|
NeoGo tries to cover more cases with its calculatenetworkfee implementation,
|
||||||
|
@ -189,6 +196,16 @@ enabled in the server's protocol configuration.
|
||||||
##### `getnep11transfers` and `getnep17transfers`
|
##### `getnep11transfers` and `getnep17transfers`
|
||||||
`transfernotifyindex` is not tracked by NeoGo, thus this field is always zero.
|
`transfernotifyindex` is not tracked by NeoGo, thus this field is always zero.
|
||||||
|
|
||||||
|
##### `traverseiterator` and `terminatesession`
|
||||||
|
|
||||||
|
NeoGo returns an error when it is unable to find a session or iterator, unlike
|
||||||
|
the error-free C# response that provides a default result.
|
||||||
|
|
||||||
|
##### `verifyProof`
|
||||||
|
|
||||||
|
NeoGo can generate an error in response to an invalid proof, unlike
|
||||||
|
the error-free C# implementation.
|
||||||
|
|
||||||
### Unsupported methods
|
### Unsupported methods
|
||||||
|
|
||||||
Methods listed below are not going to be supported for various reasons
|
Methods listed below are not going to be supported for various reasons
|
||||||
|
|
|
@ -88,10 +88,12 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// ErrAlreadyExists is returned when trying to add some already existing
|
// ErrAlreadyExists is returned when trying to add some transaction
|
||||||
// transaction into the pool (not specifying whether it exists in the
|
// that already exists on chain.
|
||||||
// chain or mempool).
|
ErrAlreadyExists = errors.New("already exists in blockchain")
|
||||||
ErrAlreadyExists = errors.New("already exists")
|
// ErrAlreadyInPool is returned when trying to add some already existing
|
||||||
|
// transaction into the mempool.
|
||||||
|
ErrAlreadyInPool = errors.New("already exists in mempool")
|
||||||
// ErrOOM is returned when adding transaction to the memory pool because
|
// ErrOOM is returned when adding transaction to the memory pool because
|
||||||
// it reached its full capacity.
|
// it reached its full capacity.
|
||||||
ErrOOM = errors.New("no space left in the memory pool")
|
ErrOOM = errors.New("no space left in the memory pool")
|
||||||
|
@ -2480,7 +2482,7 @@ func (bc *Blockchain) verifyAndPoolTx(t *transaction.Transaction, pool *mempool.
|
||||||
if err := bc.dao.HasTransaction(t.Hash(), t.Signers); err != nil {
|
if err := bc.dao.HasTransaction(t.Hash(), t.Signers); err != nil {
|
||||||
switch {
|
switch {
|
||||||
case errors.Is(err, dao.ErrAlreadyExists):
|
case errors.Is(err, dao.ErrAlreadyExists):
|
||||||
return fmt.Errorf("blockchain: %w", ErrAlreadyExists)
|
return ErrAlreadyExists
|
||||||
case errors.Is(err, dao.ErrHasConflicts):
|
case errors.Is(err, dao.ErrHasConflicts):
|
||||||
return fmt.Errorf("blockchain: %w", ErrHasConflicts)
|
return fmt.Errorf("blockchain: %w", ErrHasConflicts)
|
||||||
default:
|
default:
|
||||||
|
@ -2500,7 +2502,7 @@ func (bc *Blockchain) verifyAndPoolTx(t *transaction.Transaction, pool *mempool.
|
||||||
case errors.Is(err, mempool.ErrConflict):
|
case errors.Is(err, mempool.ErrConflict):
|
||||||
return ErrMemPoolConflict
|
return ErrMemPoolConflict
|
||||||
case errors.Is(err, mempool.ErrDup):
|
case errors.Is(err, mempool.ErrDup):
|
||||||
return fmt.Errorf("mempool: %w", ErrAlreadyExists)
|
return ErrAlreadyInPool
|
||||||
case errors.Is(err, mempool.ErrInsufficientFunds):
|
case errors.Is(err, mempool.ErrInsufficientFunds):
|
||||||
return ErrInsufficientFunds
|
return ErrInsufficientFunds
|
||||||
case errors.Is(err, mempool.ErrOOM):
|
case errors.Is(err, mempool.ErrOOM):
|
||||||
|
@ -2767,11 +2769,11 @@ var (
|
||||||
ErrWitnessHashMismatch = errors.New("witness hash mismatch")
|
ErrWitnessHashMismatch = errors.New("witness hash mismatch")
|
||||||
ErrNativeContractWitness = errors.New("native contract witness must have empty verification script")
|
ErrNativeContractWitness = errors.New("native contract witness must have empty verification script")
|
||||||
ErrVerificationFailed = errors.New("signature check failed")
|
ErrVerificationFailed = errors.New("signature check failed")
|
||||||
ErrInvalidInvocation = errors.New("invalid invocation script")
|
ErrInvalidInvocationScript = errors.New("invalid invocation script")
|
||||||
ErrInvalidSignature = fmt.Errorf("%w: invalid signature", ErrVerificationFailed)
|
ErrInvalidSignature = fmt.Errorf("%w: invalid signature", ErrVerificationFailed)
|
||||||
ErrInvalidVerification = errors.New("invalid verification script")
|
ErrInvalidVerificationScript = errors.New("invalid verification script")
|
||||||
ErrUnknownVerificationContract = errors.New("unknown verification contract")
|
ErrUnknownVerificationContract = errors.New("unknown verification contract")
|
||||||
ErrInvalidVerificationContract = errors.New("verification contract is missing `verify` method")
|
ErrInvalidVerificationContract = errors.New("verification contract is missing `verify` method or `verify` method has unexpected return value")
|
||||||
)
|
)
|
||||||
|
|
||||||
// InitVerificationContext initializes context for witness check.
|
// InitVerificationContext initializes context for witness check.
|
||||||
|
@ -2785,7 +2787,7 @@ func (bc *Blockchain) InitVerificationContext(ic *interop.Context, hash util.Uin
|
||||||
}
|
}
|
||||||
err := vm.IsScriptCorrect(witness.VerificationScript, nil)
|
err := vm.IsScriptCorrect(witness.VerificationScript, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("%w: %v", ErrInvalidVerification, err) //nolint:errorlint // errorlint: non-wrapping format verb for fmt.Errorf. Use `%w` to format errors
|
return fmt.Errorf("%w: %v", ErrInvalidVerificationScript, err) //nolint:errorlint // errorlint: non-wrapping format verb for fmt.Errorf. Use `%w` to format errors
|
||||||
}
|
}
|
||||||
ic.VM.LoadScriptWithHash(witness.VerificationScript, hash, callflag.ReadOnly)
|
ic.VM.LoadScriptWithHash(witness.VerificationScript, hash, callflag.ReadOnly)
|
||||||
} else {
|
} else {
|
||||||
|
@ -2810,7 +2812,7 @@ func (bc *Blockchain) InitVerificationContext(ic *interop.Context, hash util.Uin
|
||||||
if len(witness.InvocationScript) != 0 {
|
if len(witness.InvocationScript) != 0 {
|
||||||
err := vm.IsScriptCorrect(witness.InvocationScript, nil)
|
err := vm.IsScriptCorrect(witness.InvocationScript, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("%w: %v", ErrInvalidInvocation, err) //nolint:errorlint // errorlint: non-wrapping format verb for fmt.Errorf. Use `%w` to format errors
|
return fmt.Errorf("%w: %v", ErrInvalidInvocationScript, err) //nolint:errorlint // errorlint: non-wrapping format verb for fmt.Errorf. Use `%w` to format errors
|
||||||
}
|
}
|
||||||
ic.VM.LoadScript(witness.InvocationScript)
|
ic.VM.LoadScript(witness.InvocationScript)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1293,7 +1293,7 @@ func TestBlockchain_VerifyTx(t *testing.T) {
|
||||||
InvocationScript: []byte{},
|
InvocationScript: []byte{},
|
||||||
VerificationScript: verif,
|
VerificationScript: verif,
|
||||||
})
|
})
|
||||||
checkErr(t, core.ErrInvalidVerification, tx)
|
checkErr(t, core.ErrInvalidVerificationScript, tx)
|
||||||
})
|
})
|
||||||
t.Run("InvalidInvocationScript", func(t *testing.T) {
|
t.Run("InvalidInvocationScript", func(t *testing.T) {
|
||||||
tx := newTestTx(t, h, testScript)
|
tx := newTestTx(t, h, testScript)
|
||||||
|
@ -1308,7 +1308,7 @@ func TestBlockchain_VerifyTx(t *testing.T) {
|
||||||
InvocationScript: []byte{byte(opcode.JMP), 3, 0xff},
|
InvocationScript: []byte{byte(opcode.JMP), 3, 0xff},
|
||||||
VerificationScript: verif,
|
VerificationScript: verif,
|
||||||
})
|
})
|
||||||
checkErr(t, core.ErrInvalidInvocation, tx)
|
checkErr(t, core.ErrInvalidInvocationScript, tx)
|
||||||
})
|
})
|
||||||
t.Run("Conflict", func(t *testing.T) {
|
t.Run("Conflict", func(t *testing.T) {
|
||||||
balance := bc.GetUtilityTokenBalance(h).Int64()
|
balance := bc.GetUtilityTokenBalance(h).Int64()
|
||||||
|
@ -1358,7 +1358,7 @@ func TestBlockchain_VerifyTx(t *testing.T) {
|
||||||
require.NoError(t, bc.PoolTx(tx))
|
require.NoError(t, bc.PoolTx(tx))
|
||||||
|
|
||||||
err := bc.PoolTx(tx)
|
err := bc.PoolTx(tx)
|
||||||
require.ErrorIs(t, err, core.ErrAlreadyExists)
|
require.ErrorIs(t, err, core.ErrAlreadyInPool)
|
||||||
})
|
})
|
||||||
t.Run("MemPoolOOM", func(t *testing.T) {
|
t.Run("MemPoolOOM", func(t *testing.T) {
|
||||||
mp := mempool.New(1, 0, false, nil)
|
mp := mempool.New(1, 0, false, nil)
|
||||||
|
|
|
@ -27,36 +27,247 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
// RPC error codes defined by the Neo JSON-RPC specification extension.
|
// RPC error codes defined by the Neo JSON-RPC specification extension.
|
||||||
|
// Codes for missing items.
|
||||||
const (
|
const (
|
||||||
// RPCErrorCode is returned on RPC request processing error.
|
// ErrUnknownBlockCode is returned from a call that accepts as a parameter or searches for a header or a block
|
||||||
RPCErrorCode = -100
|
// as a part of its job can't find it.
|
||||||
|
ErrUnknownBlockCode = -101
|
||||||
|
// ErrUnknownContractCode is returned from a call that accepts as a parameter or searches for a contract
|
||||||
|
// as a part of its job can't find it.
|
||||||
|
ErrUnknownContractCode = -102
|
||||||
|
// ErrUnknownTransactionCode is returned from a call that accepts as a parameter or searches for a transaction
|
||||||
|
// as a part of its job can't find it.
|
||||||
|
ErrUnknownTransactionCode = -103
|
||||||
|
// ErrUnknownStorageItemCode is returned from a call that looks for an item in the contract storage
|
||||||
|
// as part of its job can't find it.
|
||||||
|
ErrUnknownStorageItemCode = -104
|
||||||
|
// ErrUnknownScriptContainerCode is returned from a call that accepts as a parameter or searches for a script
|
||||||
|
// container (a block or transaction) as a part of its job can't find it
|
||||||
|
// (this error generalizes -101 and -103 in cases where it's needed).
|
||||||
|
ErrUnknownScriptContainerCode = -105
|
||||||
|
// ErrUnknownStateRootCode is returned from a call that accepts as a parameter or searches for a state root
|
||||||
|
// as a part of its job can't find it.
|
||||||
|
ErrUnknownStateRootCode = -106
|
||||||
|
// ErrUnknownSessionCode is returned from a call that accepts as a parameter or searches for an iterator session
|
||||||
|
// as a part of its job can't find it.
|
||||||
|
ErrUnknownSessionCode = -107
|
||||||
|
// ErrUnknownIteratorCode is returned from a call that accepts as a parameter or searches for a session iterator
|
||||||
|
// as a part of its job can't find it.
|
||||||
|
ErrUnknownIteratorCode = -108
|
||||||
|
// ErrUnknownHeightCode is returned if block or header height passed as parameter or calculated during call
|
||||||
|
// execution is not correct (out of the range known to the node).
|
||||||
|
ErrUnknownHeightCode = -109
|
||||||
|
)
|
||||||
|
|
||||||
|
// Codes for calls that use a wallet (-300...-304) can be returned by the C# RPC server only,
|
||||||
|
// see the https://github.com/nspcc-dev/neo-go/blob/master/docs/rpc.md#unsupported-methods.
|
||||||
|
const (
|
||||||
|
// ErrInsufficientFundsWalletCode is returned if transaction that sends some assets can't be created
|
||||||
|
// because it fails. Can be returned only by the C# RPC server.
|
||||||
|
ErrInsufficientFundsWalletCode = -300
|
||||||
|
// ErrWalletFeeLimitCode is returned if transaction requires more network fee to be paid
|
||||||
|
// than is allowed by settings. Can be returned only by the C# RPC server.
|
||||||
|
ErrWalletFeeLimitCode = -301
|
||||||
|
// ErrNoOpenedWalletCode is returned if server doesn't have any opened wallet to operate with.
|
||||||
|
// Can be returned only by the C# RPC server.
|
||||||
|
ErrNoOpenedWalletCode = -302
|
||||||
|
// ErrWalletNotFoundCode is returned if specified (or configured) wallet file path is invalid.
|
||||||
|
// Can be returned only by the C# RPC server.
|
||||||
|
ErrWalletNotFoundCode = -303
|
||||||
|
// ErrWalletNotSupportedCode is returned if specified (or configured) file can't be opened as a wallet.
|
||||||
|
// Can be returned only by the C# RPC server.
|
||||||
|
ErrWalletNotSupportedCode = -304
|
||||||
|
)
|
||||||
|
|
||||||
|
// Inventory verification or verification script errors.
|
||||||
|
const (
|
||||||
|
// ErrVerificationFailedCode is returned on anything that can't be expressed by other codes.
|
||||||
|
// It is an unclassified inventory verification error.
|
||||||
|
ErrVerificationFailedCode = -500
|
||||||
|
// ErrAlreadyExistsCode is returned if block or transaction is already accepted and processed on chain.
|
||||||
|
ErrAlreadyExistsCode = -501
|
||||||
|
// ErrMempoolCapReachedCode is returned if no more transactions can be accepted into the memory pool
|
||||||
|
// (unless they have a priority) as its full capacity is reached.
|
||||||
|
ErrMempoolCapReachedCode = -502
|
||||||
|
// ErrAlreadyInPoolCode is returned if transaction is already pooled, but not yet accepted into a block.
|
||||||
|
ErrAlreadyInPoolCode = -503
|
||||||
|
// ErrInsufficientNetworkFeeCode is returned if transaction has incorrect (too small per Policy setting)
|
||||||
|
// network fee value.
|
||||||
|
ErrInsufficientNetworkFeeCode = -504
|
||||||
|
// ErrPolicyFailedCode is returned from a call denied by the Policy contract (one of signers is blocked) or
|
||||||
|
// if one of the Policy filters failed.
|
||||||
|
ErrPolicyFailedCode = -505
|
||||||
|
// ErrInvalidScriptCode is returned if transaction contains incorrect executable script.
|
||||||
|
ErrInvalidScriptCode = -506
|
||||||
|
// ErrInvalidAttributeCode is returned if transaction contains an invalid attribute.
|
||||||
|
ErrInvalidAttributeCode = -507
|
||||||
|
// ErrInvalidSignatureCode is returned if one of the verification scripts failed.
|
||||||
|
ErrInvalidSignatureCode = -508
|
||||||
|
// ErrInvalidSizeCode is returned if transaction or its script is too big.
|
||||||
|
ErrInvalidSizeCode = -509
|
||||||
|
// ErrExpiredTransactionCode is returned if transaction's ValidUntilBlock value is already in the past.
|
||||||
|
ErrExpiredTransactionCode = -510
|
||||||
|
// ErrInsufficientFundsCode is returned if sender doesn't have enough GAS to pay for all currently pooled transactions.
|
||||||
|
ErrInsufficientFundsCode = -511
|
||||||
|
// ErrInvalidVerificationFunctionCode is returned if contract doesn't have a verify method or
|
||||||
|
// this method doesn't return proper value.
|
||||||
|
ErrInvalidVerificationFunctionCode = -512
|
||||||
|
)
|
||||||
|
|
||||||
|
// Errors related to node configuration and various services.
|
||||||
|
const (
|
||||||
|
// ErrSessionsDisabledCode is returned if iterator session support is not enabled on the server.
|
||||||
|
ErrSessionsDisabledCode = -601
|
||||||
|
// ErrOracleDisabledCode is returned if Oracle service is not enabled in the configuration (service is not running).
|
||||||
|
ErrOracleDisabledCode = -602
|
||||||
|
// ErrOracleRequestFinishedCode is returned if Oracle request submitted is already completely processed.
|
||||||
|
// Can be returned only by the C# RPC server.
|
||||||
|
ErrOracleRequestFinishedCode = -603
|
||||||
|
// ErrOracleRequestNotFoundCode is returned if Oracle request submitted is not known to this node.
|
||||||
|
// Can be returned only by the C# RPC server.
|
||||||
|
ErrOracleRequestNotFoundCode = -604
|
||||||
|
// ErrOracleNotDesignatedNodeCode is returned if Oracle service is enabled, but this node is not designated
|
||||||
|
// to provide this functionality. Can be returned only by the C# RPC server.
|
||||||
|
ErrOracleNotDesignatedNodeCode = -605
|
||||||
|
// ErrUnsupportedStateCode is returned if this node can't answer requests for old state because it's configured
|
||||||
|
// to keep only the latest one.
|
||||||
|
ErrUnsupportedStateCode = -606
|
||||||
|
// ErrInvalidProofCode is returned if state proof verification failed.
|
||||||
|
ErrInvalidProofCode = -607
|
||||||
|
// ErrExecutionFailedCode is returned from a call made a VM execution, but it has failed.
|
||||||
|
ErrExecutionFailedCode = -608
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// ErrInvalidParams represents a generic 'invalid parameters' error.
|
// ErrCompatGeneric is an error returned by nodes not compliant with the neo-project/proposals#156
|
||||||
ErrInvalidParams = NewInvalidParamsError("invalid params")
|
// (NeoGo pre-0.102.0 and all known C# versions).
|
||||||
// ErrUnknownBlock is returned if requested block is not found.
|
// It can be returned for any call and doesn't have any specific meaning.
|
||||||
ErrUnknownBlock = NewError(RPCErrorCode, "Unknown block", "")
|
//
|
||||||
// ErrUnknownTransaction is returned if requested transaction is not found.
|
// Deprecated: to be removed after all nodes adopt new error standard.
|
||||||
ErrUnknownTransaction = NewError(RPCErrorCode, "Unknown transaction", "")
|
ErrCompatGeneric = NewErrorWithCode(-100, "RPC error")
|
||||||
// ErrUnknownHeader is returned when requested header is not found.
|
|
||||||
ErrUnknownHeader = NewError(RPCErrorCode, "Unknown header", "")
|
// ErrCompatNoOpenedWallet is an error code returned by nodes not compliant with the neo-project/proposals#156
|
||||||
// ErrUnknownScriptContainer is returned when requested block or transaction is not found.
|
// (all known C# versions, NeoGo never used this code). It can be returned for wallet-related operations.
|
||||||
ErrUnknownScriptContainer = NewError(RPCErrorCode, "Unknown script container", "")
|
//
|
||||||
// ErrUnknownStateRoot is returned when requested state root is not found.
|
// Deprecated: to be removed after all nodes adopt new error standard.
|
||||||
ErrUnknownStateRoot = NewError(RPCErrorCode, "Unknown state root", "")
|
ErrCompatNoOpenedWallet = NewErrorWithCode(-400, "No opened wallet")
|
||||||
// ErrAlreadyExists represents SubmitError with code -501.
|
)
|
||||||
ErrAlreadyExists = NewSubmitError(-501, "Block or transaction already exists and cannot be sent repeatedly.")
|
|
||||||
// ErrOutOfMemory represents SubmitError with code -502.
|
var (
|
||||||
ErrOutOfMemory = NewSubmitError(-502, "The memory pool is full and no more transactions can be sent.")
|
// ErrInvalidParams represents a generic "Invalid params" error.
|
||||||
// ErrUnableToVerify represents SubmitError with code -503.
|
ErrInvalidParams = NewInvalidParamsError("Invalid params")
|
||||||
ErrUnableToVerify = NewSubmitError(-503, "The block cannot be validated.")
|
|
||||||
// ErrValidationFailed represents SubmitError with code -504.
|
// ErrUnknownBlock represents an error with code [ErrUnknownBlockCode].
|
||||||
ErrValidationFailed = NewSubmitError(-504, "Block or transaction validation failed.")
|
// Call that accepts as a parameter or searches for a header or a block as a part of its job can't find it.
|
||||||
// ErrPolicyFail represents SubmitError with code -505.
|
ErrUnknownBlock = NewErrorWithCode(ErrUnknownBlockCode, "Unknown block")
|
||||||
ErrPolicyFail = NewSubmitError(-505, "One of the Policy filters failed.")
|
// ErrUnknownContract represents an error with code [ErrUnknownContractCode].
|
||||||
// ErrUnknown represents SubmitError with code -500.
|
// Call that accepts as a parameter or searches for a contract as a part of its job can't find it.
|
||||||
ErrUnknown = NewSubmitError(-500, "Unknown error.")
|
ErrUnknownContract = NewErrorWithCode(ErrUnknownContractCode, "Unknown contract")
|
||||||
|
// ErrUnknownTransaction represents an error with code [ErrUnknownTransactionCode].
|
||||||
|
// Call that accepts as a parameter or searches for a transaction as a part of its job can't find it.
|
||||||
|
ErrUnknownTransaction = NewErrorWithCode(ErrUnknownTransactionCode, "Unknown transaction")
|
||||||
|
// ErrUnknownStorageItem represents an error with code [ErrUnknownStorageItemCode].
|
||||||
|
// Call that looks for an item in the contract storage as part of its job can't find it.
|
||||||
|
ErrUnknownStorageItem = NewErrorWithCode(ErrUnknownStorageItemCode, "Unknown storage item")
|
||||||
|
// ErrUnknownScriptContainer represents an error with code [ErrUnknownScriptContainerCode].
|
||||||
|
// Call that accepts as a parameter or searches for a script container (a block or transaction)
|
||||||
|
// as a part of its job can't find it (this error generalizes [ErrUnknownBlockCode] and [ErrUnknownTransactionCode]
|
||||||
|
// in cases where it's needed).
|
||||||
|
ErrUnknownScriptContainer = NewErrorWithCode(ErrUnknownScriptContainerCode, "Unknown script container")
|
||||||
|
// ErrUnknownStateRoot represents an error with code [ErrUnknownStateRootCode].
|
||||||
|
// Call that accepts as a parameter or searches for a state root as a part of its job can't find it.
|
||||||
|
ErrUnknownStateRoot = NewErrorWithCode(ErrUnknownStateRootCode, "Unknown state root")
|
||||||
|
// ErrUnknownSession represents an error with code [ErrUnknownSessionCode].
|
||||||
|
// Call that accepts as a parameter or searches for an iterator session as a part of its job can't find it.
|
||||||
|
ErrUnknownSession = NewErrorWithCode(ErrUnknownSessionCode, "Unknown session")
|
||||||
|
// ErrUnknownIterator represents an error with code [ErrUnknownIteratorCode].
|
||||||
|
// Call that accepts as a parameter or searches for a session iterator as a part of its job can't find it.
|
||||||
|
ErrUnknownIterator = NewErrorWithCode(ErrUnknownIteratorCode, "Unknown iterator")
|
||||||
|
// ErrUnknownHeight represents an error with code [ErrUnknownHeightCode].
|
||||||
|
// Block or header height passed as parameter or calculated during call execution is not correct
|
||||||
|
// (out of the range known to the node).
|
||||||
|
ErrUnknownHeight = NewErrorWithCode(ErrUnknownHeightCode, "Unknown height")
|
||||||
|
|
||||||
|
// ErrInsufficientFundsWallet represents an error with code [ErrInsufficientFundsWalletCode]. Can be returned only by the C# RPC server.
|
||||||
|
// Transaction that sends some assets can't be created because it fails.
|
||||||
|
ErrInsufficientFundsWallet = NewErrorWithCode(ErrInsufficientFundsWalletCode, "Insufficient funds")
|
||||||
|
// ErrWalletFeeLimit represents an error with code [ErrWalletFeeLimitCode]. Can be returned only by the C# RPC server.
|
||||||
|
// Transaction requires more network fee to be paid than is allowed by settings.
|
||||||
|
ErrWalletFeeLimit = NewErrorWithCode(ErrWalletFeeLimitCode, "Fee limit exceeded")
|
||||||
|
// ErrNoOpenedWallet represents an error with code [ErrNoOpenedWalletCode]. Can be returned only by the C# RPC server.
|
||||||
|
// Server doesn't have any opened wallet to operate with.
|
||||||
|
ErrNoOpenedWallet = NewErrorWithCode(ErrNoOpenedWalletCode, "No opened wallet")
|
||||||
|
// ErrWalletNotFound represents an error with code [ErrWalletNotFoundCode]. Can be returned only by the C# RPC server.
|
||||||
|
// Specified (or configured) wallet file path is invalid.
|
||||||
|
ErrWalletNotFound = NewErrorWithCode(ErrWalletNotFoundCode, "Wallet not found")
|
||||||
|
// ErrWalletNotSupported represents an error with code [ErrWalletNotSupportedCode]. Can be returned only by the C# RPC server.
|
||||||
|
// Specified (or configured) file can't be opened as a wallet.
|
||||||
|
ErrWalletNotSupported = NewErrorWithCode(ErrWalletNotSupportedCode, "Wallet not supported")
|
||||||
|
|
||||||
|
// ErrVerificationFailed represents an error with code [ErrVerificationFailedCode].
|
||||||
|
// Any verification error that can't be expressed by other codes.
|
||||||
|
ErrVerificationFailed = NewErrorWithCode(ErrVerificationFailedCode, "Unclassified inventory verification error")
|
||||||
|
// ErrAlreadyExists represents an error with code [ErrAlreadyExistsCode].
|
||||||
|
// Block or transaction is already accepted and processed on chain.
|
||||||
|
ErrAlreadyExists = NewErrorWithCode(ErrAlreadyExistsCode, "Inventory already exists on chain")
|
||||||
|
// ErrMempoolCapReached represents an error with code [ErrMempoolCapReachedCode].
|
||||||
|
// No more transactions can be accepted into the memory pool (unless they have a priority) as its full capacity is reached.
|
||||||
|
ErrMempoolCapReached = NewErrorWithCode(ErrMempoolCapReachedCode, "The memory pool is full and no more transactions can be sent")
|
||||||
|
// ErrAlreadyInPool represents an error with code [ErrAlreadyInPoolCode].
|
||||||
|
// Transaction is already pooled, but not yet accepted into a block.
|
||||||
|
ErrAlreadyInPool = NewErrorWithCode(ErrAlreadyInPoolCode, "Transaction already exists in the memory pool")
|
||||||
|
// ErrInsufficientNetworkFee represents an error with code [ErrInsufficientNetworkFeeCode].
|
||||||
|
// Transaction has incorrect (too small per Policy setting) network fee value.
|
||||||
|
ErrInsufficientNetworkFee = NewErrorWithCode(ErrInsufficientNetworkFeeCode, "Insufficient network fee")
|
||||||
|
// ErrPolicyFailed represents an error with code [ErrPolicyFailedCode].
|
||||||
|
// Denied by the Policy contract (one of signers is blocked).
|
||||||
|
ErrPolicyFailed = NewErrorWithCode(ErrPolicyFailedCode, "One of the Policy filters failed")
|
||||||
|
// ErrInvalidScript represents an error with code [ErrInvalidScriptCode].
|
||||||
|
// Transaction contains incorrect executable script.
|
||||||
|
ErrInvalidScript = NewErrorWithCode(ErrInvalidScriptCode, "Invalid script")
|
||||||
|
// ErrInvalidAttribute represents an error with code [ErrInvalidAttributeCode].
|
||||||
|
// Transaction contains an invalid attribute.
|
||||||
|
ErrInvalidAttribute = NewErrorWithCode(ErrInvalidAttributeCode, "Invalid transaction attribute")
|
||||||
|
// ErrInvalidSignature represents an error with code [ErrInvalidSignatureCode].
|
||||||
|
// One of the verification scripts failed.
|
||||||
|
ErrInvalidSignature = NewErrorWithCode(ErrInvalidSignatureCode, "Invalid signature")
|
||||||
|
// ErrInvalidSize represents an error with code [ErrInvalidSizeCode].
|
||||||
|
// Transaction or its script is too big.
|
||||||
|
ErrInvalidSize = NewErrorWithCode(ErrInvalidSizeCode, "Invalid inventory size")
|
||||||
|
// ErrExpiredTransaction represents an error with code [ErrExpiredTransactionCode].
|
||||||
|
// Transaction's ValidUntilBlock value is already in the past.
|
||||||
|
ErrExpiredTransaction = NewErrorWithCode(ErrExpiredTransactionCode, "Expired transaction")
|
||||||
|
// ErrInsufficientFunds represents an error with code [ErrInsufficientFundsCode].
|
||||||
|
// Sender doesn't have enough GAS to pay for all currently pooled transactions.
|
||||||
|
ErrInsufficientFunds = NewErrorWithCode(ErrInsufficientFundsCode, "Insufficient funds")
|
||||||
|
// ErrInvalidVerificationFunction represents an error with code [ErrInvalidVerificationFunctionCode].
|
||||||
|
// Contract doesn't have a verify method or this method doesn't return proper value.
|
||||||
|
ErrInvalidVerificationFunction = NewErrorWithCode(ErrInvalidVerificationFunctionCode, "Invalid verification function")
|
||||||
|
|
||||||
|
// ErrSessionsDisabled represents an error with code [ErrSessionsDisabledCode].
|
||||||
|
// Iterator session support is not enabled on the server.
|
||||||
|
ErrSessionsDisabled = NewErrorWithCode(ErrSessionsDisabledCode, "Sessions disabled")
|
||||||
|
// ErrOracleDisabled represents an error with code [ErrOracleDisabledCode].
|
||||||
|
// Service is not enabled in the configuration.
|
||||||
|
ErrOracleDisabled = NewErrorWithCode(ErrOracleDisabledCode, "Oracle service is not running")
|
||||||
|
// ErrOracleRequestFinished represents an error with code [ErrOracleRequestFinishedCode]. Can be returned only by the C# RPC server.
|
||||||
|
// The oracle request submitted is already completely processed.
|
||||||
|
ErrOracleRequestFinished = NewErrorWithCode(ErrOracleRequestFinishedCode, "Oracle request has already been finished")
|
||||||
|
// ErrOracleRequestNotFound represents an error with code [ErrOracleRequestNotFoundCode]. Can be returned only by the C# RPC server.
|
||||||
|
// The oracle request submitted is not known to this node.
|
||||||
|
ErrOracleRequestNotFound = NewErrorWithCode(ErrOracleRequestNotFoundCode, "Oracle request is not found")
|
||||||
|
// ErrOracleNotDesignatedNode represents an error with code [ErrOracleNotDesignatedNodeCode]. Can be returned only by the C# RPC server.
|
||||||
|
// Oracle service is enabled, but this node is not designated to provide this functionality.
|
||||||
|
ErrOracleNotDesignatedNode = NewErrorWithCode(ErrOracleNotDesignatedNodeCode, "Not a designated oracle node")
|
||||||
|
// ErrUnsupportedState represents an error with code [ErrUnsupportedStateCode].
|
||||||
|
// This node can't answer requests for old state because it's configured to keep only the latest one.
|
||||||
|
ErrUnsupportedState = NewErrorWithCode(ErrUnsupportedStateCode, "Old state requests are not supported")
|
||||||
|
// ErrInvalidProof represents an error with code [ErrInvalidProofCode].
|
||||||
|
// State proof verification failed.
|
||||||
|
ErrInvalidProof = NewErrorWithCode(ErrInvalidProofCode, "Invalid proof")
|
||||||
|
// ErrExecutionFailed represents an error with code [ErrExecutionFailedCode].
|
||||||
|
// Call made a VM execution, but it has failed.
|
||||||
|
ErrExecutionFailed = NewErrorWithCode(ErrExecutionFailedCode, "Execution failed")
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewError is an Error constructor that takes Error contents from its parameters.
|
// NewError is an Error constructor that takes Error contents from its parameters.
|
||||||
|
@ -98,15 +309,9 @@ func NewInternalServerError(data string) *Error {
|
||||||
return NewError(InternalServerErrorCode, "Internal error", data)
|
return NewError(InternalServerErrorCode, "Internal error", data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRPCError creates a new error with
|
// NewErrorWithCode creates a new error with
|
||||||
// code -100.
|
|
||||||
func NewRPCError(message string, data string) *Error {
|
|
||||||
return NewError(RPCErrorCode, message, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewSubmitError creates a new error with
|
|
||||||
// specified error code and error message.
|
// specified error code and error message.
|
||||||
func NewSubmitError(code int64, message string) *Error {
|
func NewErrorWithCode(code int64, message string) *Error {
|
||||||
return NewError(code, message, "")
|
return NewError(code, message, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1723,7 +1723,8 @@ func TestClient_IteratorSessions(t *testing.T) {
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
|
|
||||||
ok, err = c.TerminateSession(sID)
|
ok, err = c.TerminateSession(sID)
|
||||||
require.NoError(t, err)
|
require.Error(t, err)
|
||||||
|
require.ErrorIs(t, err, neorpc.ErrUnknownSession)
|
||||||
require.False(t, ok) // session has already been terminated.
|
require.False(t, ok) // session has already been terminated.
|
||||||
})
|
})
|
||||||
t.Run("automatically", func(t *testing.T) {
|
t.Run("automatically", func(t *testing.T) {
|
||||||
|
@ -1746,7 +1747,8 @@ func TestClient_IteratorSessions(t *testing.T) {
|
||||||
time.Duration(rpcSrv.config.SessionExpirationTime)*time.Second/4)
|
time.Duration(rpcSrv.config.SessionExpirationTime)*time.Second/4)
|
||||||
|
|
||||||
ok, err := c.TerminateSession(sID)
|
ok, err := c.TerminateSession(sID)
|
||||||
require.NoError(t, err)
|
require.Error(t, err)
|
||||||
|
require.ErrorIs(t, err, neorpc.ErrUnknownSession)
|
||||||
require.False(t, ok) // session has already been terminated.
|
require.False(t, ok) // session has already been terminated.
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -44,8 +44,6 @@ func getHTTPCodeForError(respErr *neorpc.Error) int {
|
||||||
switch respErr.Code {
|
switch respErr.Code {
|
||||||
case neorpc.BadRequestCode:
|
case neorpc.BadRequestCode:
|
||||||
httpCode = http.StatusBadRequest
|
httpCode = http.StatusBadRequest
|
||||||
case neorpc.InvalidRequestCode, neorpc.RPCErrorCode, neorpc.InvalidParamsCode:
|
|
||||||
httpCode = http.StatusUnprocessableEntity
|
|
||||||
case neorpc.MethodNotFoundCode:
|
case neorpc.MethodNotFoundCode:
|
||||||
httpCode = http.StatusMethodNotAllowed
|
httpCode = http.StatusMethodNotAllowed
|
||||||
case neorpc.InternalServerErrorCode:
|
case neorpc.InternalServerErrorCode:
|
||||||
|
|
|
@ -250,10 +250,6 @@ var rpcWsHandlers = map[string]func(*Server, params.Params, *subscriber) (any, *
|
||||||
"unsubscribe": (*Server).unsubscribe,
|
"unsubscribe": (*Server).unsubscribe,
|
||||||
}
|
}
|
||||||
|
|
||||||
var invalidBlockHeightError = func(index int, height int) *neorpc.Error {
|
|
||||||
return neorpc.NewRPCError("Invalid block height", fmt.Sprintf("param at index %d should be greater than or equal to 0 and less then or equal to current block height, got: %d", index, height))
|
|
||||||
}
|
|
||||||
|
|
||||||
// New creates a new Server struct. Pay attention that orc is expected to be either
|
// New creates a new Server struct. Pay attention that orc is expected to be either
|
||||||
// untyped nil or non-nil structure implementing OracleHandler interface.
|
// untyped nil or non-nil structure implementing OracleHandler interface.
|
||||||
func New(chain Ledger, conf config.RPC, coreServer *network.Server,
|
func New(chain Ledger, conf config.RPC, coreServer *network.Server,
|
||||||
|
@ -783,7 +779,7 @@ func (s *Server) getBlock(reqParams params.Params) (any, *neorpc.Error) {
|
||||||
|
|
||||||
block, err := s.chain.GetBlock(hash)
|
block, err := s.chain.GetBlock(hash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, neorpc.NewRPCError("Failed to get block", err.Error())
|
return nil, neorpc.WrapErrorWithData(neorpc.ErrUnknownBlock, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
if v, _ := reqParams.Value(1).GetBoolean(); v {
|
if v, _ := reqParams.Value(1).GetBoolean(); v {
|
||||||
|
@ -801,7 +797,7 @@ func (s *Server) getBlock(reqParams params.Params) (any, *neorpc.Error) {
|
||||||
func (s *Server) getBlockHash(reqParams params.Params) (any, *neorpc.Error) {
|
func (s *Server) getBlockHash(reqParams params.Params) (any, *neorpc.Error) {
|
||||||
num, err := s.blockHeightFromParam(reqParams.Value(0))
|
num, err := s.blockHeightFromParam(reqParams.Value(0))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, neorpc.ErrInvalidParams
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.chain.GetHeaderHash(num), nil
|
return s.chain.GetHeaderHash(num), nil
|
||||||
|
@ -900,11 +896,11 @@ func (s *Server) calculateNetworkFee(reqParams params.Params) (any, *neorpc.Erro
|
||||||
if len(w.VerificationScript) == 0 { // Contract-based verification
|
if len(w.VerificationScript) == 0 { // Contract-based verification
|
||||||
cs := s.chain.GetContractState(signer.Account)
|
cs := s.chain.GetContractState(signer.Account)
|
||||||
if cs == nil {
|
if cs == nil {
|
||||||
return 0, neorpc.WrapErrorWithData(neorpc.ErrInvalidParams, fmt.Sprintf("signer %d has no verification script and no deployed contract", i))
|
return 0, neorpc.WrapErrorWithData(neorpc.ErrInvalidVerificationFunction, fmt.Sprintf("signer %d has no verification script and no deployed contract", i))
|
||||||
}
|
}
|
||||||
md := cs.Manifest.ABI.GetMethod(manifest.MethodVerify, -1)
|
md := cs.Manifest.ABI.GetMethod(manifest.MethodVerify, -1)
|
||||||
if md == nil || md.ReturnType != smartcontract.BoolType {
|
if md == nil || md.ReturnType != smartcontract.BoolType {
|
||||||
return 0, neorpc.WrapErrorWithData(neorpc.ErrInvalidParams, fmt.Sprintf("signer %d has no verify method in deployed contract", i))
|
return 0, neorpc.WrapErrorWithData(neorpc.ErrInvalidVerificationFunction, fmt.Sprintf("signer %d has no verify method in deployed contract", i))
|
||||||
}
|
}
|
||||||
paramz = md.Parameters // Might as well have none params and it's OK.
|
paramz = md.Parameters // Might as well have none params and it's OK.
|
||||||
} else { // Regular signature verification.
|
} else { // Regular signature verification.
|
||||||
|
@ -1004,7 +1000,7 @@ func (s *Server) getNEP11Balances(ps params.Params) (any, *neorpc.Error) {
|
||||||
}
|
}
|
||||||
lastUpdated, err := s.chain.GetTokenLastUpdated(u)
|
lastUpdated, err := s.chain.GetTokenLastUpdated(u)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, neorpc.NewRPCError("Failed to get NEP-11 last updated block", err.Error())
|
return nil, neorpc.NewInternalServerError(fmt.Sprintf("Failed to get NEP-11 last updated block: %s", err.Error()))
|
||||||
}
|
}
|
||||||
var count int
|
var count int
|
||||||
stateSyncPoint := lastUpdated[math.MinInt32]
|
stateSyncPoint := lastUpdated[math.MinInt32]
|
||||||
|
@ -1092,7 +1088,7 @@ func (s *Server) getNEP11Properties(ps params.Params) (any, *neorpc.Error) {
|
||||||
}
|
}
|
||||||
props, err := s.invokeNEP11Properties(asset, token, nil)
|
props, err := s.invokeNEP11Properties(asset, token, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, neorpc.NewRPCError("Failed to get NEP-11 properties", err.Error())
|
return nil, neorpc.WrapErrorWithData(neorpc.ErrExecutionFailed, fmt.Sprintf("Failed to get NEP-11 properties: %s", err.Error()))
|
||||||
}
|
}
|
||||||
res := make(map[string]any)
|
res := make(map[string]any)
|
||||||
for _, kv := range props {
|
for _, kv := range props {
|
||||||
|
@ -1129,7 +1125,7 @@ func (s *Server) getNEP17Balances(ps params.Params) (any, *neorpc.Error) {
|
||||||
}
|
}
|
||||||
lastUpdated, err := s.chain.GetTokenLastUpdated(u)
|
lastUpdated, err := s.chain.GetTokenLastUpdated(u)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, neorpc.NewRPCError("Failed to get NEP-17 last updated block", err.Error())
|
return nil, neorpc.NewInternalServerError(fmt.Sprintf("Failed to get NEP-17 last updated block: %s", err.Error()))
|
||||||
}
|
}
|
||||||
stateSyncPoint := lastUpdated[math.MinInt32]
|
stateSyncPoint := lastUpdated[math.MinInt32]
|
||||||
bw := io.NewBufBinWriter()
|
bw := io.NewBufBinWriter()
|
||||||
|
@ -1426,7 +1422,7 @@ func (s *Server) contractIDFromParam(param *params.Param) (int32, *neorpc.Error)
|
||||||
if scriptHash, err := param.GetUint160FromHex(); err == nil {
|
if scriptHash, err := param.GetUint160FromHex(); err == nil {
|
||||||
cs := s.chain.GetContractState(scriptHash)
|
cs := s.chain.GetContractState(scriptHash)
|
||||||
if cs == nil {
|
if cs == nil {
|
||||||
return 0, neorpc.ErrUnknown
|
return 0, neorpc.ErrUnknownContract
|
||||||
}
|
}
|
||||||
result = cs.ID
|
result = cs.ID
|
||||||
} else {
|
} else {
|
||||||
|
@ -1462,14 +1458,14 @@ func (s *Server) contractScriptHashFromParam(param *params.Param) (util.Uint160,
|
||||||
}
|
}
|
||||||
id, err := strconv.Atoi(nameOrHashOrIndex)
|
id, err := strconv.Atoi(nameOrHashOrIndex)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return result, neorpc.NewRPCError("Invalid contract identifier (name/hash/index is expected)", err.Error())
|
return result, neorpc.NewInvalidParamsError(fmt.Sprintf("Invalid contract identifier (name/hash/index is expected) : %s", err.Error()))
|
||||||
}
|
}
|
||||||
if err := checkInt32(id); err != nil {
|
if err := checkInt32(id); err != nil {
|
||||||
return result, neorpc.WrapErrorWithData(neorpc.ErrInvalidParams, err.Error())
|
return result, neorpc.WrapErrorWithData(neorpc.ErrInvalidParams, err.Error())
|
||||||
}
|
}
|
||||||
result, err = s.chain.GetContractScriptHash(int32(id))
|
result, err = s.chain.GetContractScriptHash(int32(id))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return result, neorpc.NewRPCError("Unknown contract", "")
|
return result, neorpc.ErrUnknownContract
|
||||||
}
|
}
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
@ -1485,7 +1481,7 @@ var errKeepOnlyLatestState = errors.New("'KeepOnlyLatestState' setting is enable
|
||||||
|
|
||||||
func (s *Server) getProof(ps params.Params) (any, *neorpc.Error) {
|
func (s *Server) getProof(ps params.Params) (any, *neorpc.Error) {
|
||||||
if s.chain.GetConfig().Ledger.KeepOnlyLatestState {
|
if s.chain.GetConfig().Ledger.KeepOnlyLatestState {
|
||||||
return nil, neorpc.NewInvalidRequestError(fmt.Sprintf("'getproof' is not supported: %s", errKeepOnlyLatestState))
|
return nil, neorpc.WrapErrorWithData(neorpc.ErrUnsupportedState, fmt.Sprintf("'getproof' is not supported: %s", errKeepOnlyLatestState))
|
||||||
}
|
}
|
||||||
root, err := ps.Value(0).GetUint256()
|
root, err := ps.Value(0).GetUint256()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1506,6 +1502,9 @@ func (s *Server) getProof(ps params.Params) (any, *neorpc.Error) {
|
||||||
skey := makeStorageKey(cs.ID, key)
|
skey := makeStorageKey(cs.ID, key)
|
||||||
proof, err := s.chain.GetStateModule().GetStateProof(root, skey)
|
proof, err := s.chain.GetStateModule().GetStateProof(root, skey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if errors.Is(err, mpt.ErrNotFound) {
|
||||||
|
return nil, neorpc.ErrUnknownStorageItem
|
||||||
|
}
|
||||||
return nil, neorpc.NewInternalServerError(fmt.Sprintf("failed to get proof: %s", err))
|
return nil, neorpc.NewInternalServerError(fmt.Sprintf("failed to get proof: %s", err))
|
||||||
}
|
}
|
||||||
return &result.ProofWithKey{
|
return &result.ProofWithKey{
|
||||||
|
@ -1516,7 +1515,7 @@ func (s *Server) getProof(ps params.Params) (any, *neorpc.Error) {
|
||||||
|
|
||||||
func (s *Server) verifyProof(ps params.Params) (any, *neorpc.Error) {
|
func (s *Server) verifyProof(ps params.Params) (any, *neorpc.Error) {
|
||||||
if s.chain.GetConfig().Ledger.KeepOnlyLatestState {
|
if s.chain.GetConfig().Ledger.KeepOnlyLatestState {
|
||||||
return nil, neorpc.NewInvalidRequestError(fmt.Sprintf("'verifyproof' is not supported: %s", errKeepOnlyLatestState))
|
return nil, neorpc.WrapErrorWithData(neorpc.ErrUnsupportedState, fmt.Sprintf("'verifyproof' is not supported: %s", errKeepOnlyLatestState))
|
||||||
}
|
}
|
||||||
root, err := ps.Value(0).GetUint256()
|
root, err := ps.Value(0).GetUint256()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1532,9 +1531,10 @@ func (s *Server) verifyProof(ps params.Params) (any, *neorpc.Error) {
|
||||||
}
|
}
|
||||||
vp := new(result.VerifyProof)
|
vp := new(result.VerifyProof)
|
||||||
val, ok := mpt.VerifyProof(root, p.Key, p.Proof)
|
val, ok := mpt.VerifyProof(root, p.Key, p.Proof)
|
||||||
if ok {
|
if !ok {
|
||||||
vp.Value = val
|
return nil, neorpc.ErrInvalidProof
|
||||||
}
|
}
|
||||||
|
vp.Value = val
|
||||||
return vp, nil
|
return vp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1549,7 +1549,7 @@ func (s *Server) getState(ps params.Params) (any, *neorpc.Error) {
|
||||||
return nil, neorpc.NewInternalServerError(fmt.Sprintf("failed to get current stateroot: %s", err))
|
return nil, neorpc.NewInternalServerError(fmt.Sprintf("failed to get current stateroot: %s", err))
|
||||||
}
|
}
|
||||||
if !curr.Root.Equals(root) {
|
if !curr.Root.Equals(root) {
|
||||||
return nil, neorpc.NewInvalidRequestError(fmt.Sprintf("'getstate' is not supported for old states: %s", errKeepOnlyLatestState))
|
return nil, neorpc.WrapErrorWithData(neorpc.ErrUnsupportedState, fmt.Sprintf("'getstate' is not supported for old states: %s", errKeepOnlyLatestState))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
csHash, err := ps.Value(1).GetUint160FromHex()
|
csHash, err := ps.Value(1).GetUint160FromHex()
|
||||||
|
@ -1567,7 +1567,10 @@ func (s *Server) getState(ps params.Params) (any, *neorpc.Error) {
|
||||||
sKey := makeStorageKey(cs.ID, key)
|
sKey := makeStorageKey(cs.ID, key)
|
||||||
res, err := s.chain.GetStateModule().GetState(root, sKey)
|
res, err := s.chain.GetStateModule().GetState(root, sKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, neorpc.NewRPCError("Failed to get historical item state", err.Error())
|
if errors.Is(err, mpt.ErrNotFound) {
|
||||||
|
return nil, neorpc.WrapErrorWithData(neorpc.ErrInvalidParams, fmt.Sprintf("invalid key: %s", err.Error()))
|
||||||
|
}
|
||||||
|
return nil, neorpc.NewInternalServerError(fmt.Sprintf("Failed to get historical item state: %s", err.Error()))
|
||||||
}
|
}
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
@ -1583,7 +1586,7 @@ func (s *Server) findStates(ps params.Params) (any, *neorpc.Error) {
|
||||||
return nil, neorpc.NewInternalServerError(fmt.Sprintf("failed to get current stateroot: %s", err))
|
return nil, neorpc.NewInternalServerError(fmt.Sprintf("failed to get current stateroot: %s", err))
|
||||||
}
|
}
|
||||||
if !curr.Root.Equals(root) {
|
if !curr.Root.Equals(root) {
|
||||||
return nil, neorpc.NewInvalidRequestError(fmt.Sprintf("'findstates' is not supported for old states: %s", errKeepOnlyLatestState))
|
return nil, neorpc.WrapErrorWithData(neorpc.ErrUnsupportedState, fmt.Sprintf("'findstates' is not supported for old states: %s", errKeepOnlyLatestState))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
csHash, err := ps.Value(1).GetUint160FromHex()
|
csHash, err := ps.Value(1).GetUint160FromHex()
|
||||||
|
@ -1670,7 +1673,7 @@ func (s *Server) getHistoricalContractState(root util.Uint256, csHash util.Uint1
|
||||||
csKey := makeStorageKey(native.ManagementContractID, native.MakeContractKey(csHash))
|
csKey := makeStorageKey(native.ManagementContractID, native.MakeContractKey(csHash))
|
||||||
csBytes, err := s.chain.GetStateModule().GetState(root, csKey)
|
csBytes, err := s.chain.GetStateModule().GetState(root, csKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, neorpc.NewRPCError("Failed to get historical contract state", err.Error())
|
return nil, neorpc.WrapErrorWithData(neorpc.ErrUnknownContract, fmt.Sprintf("Failed to get historical contract state: %s", err.Error()))
|
||||||
}
|
}
|
||||||
contract := new(state.Contract)
|
contract := new(state.Contract)
|
||||||
err = stackitem.DeserializeConvertible(csBytes, contract)
|
err = stackitem.DeserializeConvertible(csBytes, contract)
|
||||||
|
@ -1720,9 +1723,6 @@ func (s *Server) getStateRoot(ps params.Params) (any, *neorpc.Error) {
|
||||||
|
|
||||||
func (s *Server) getStorage(ps params.Params) (any, *neorpc.Error) {
|
func (s *Server) getStorage(ps params.Params) (any, *neorpc.Error) {
|
||||||
id, rErr := s.contractIDFromParam(ps.Value(0))
|
id, rErr := s.contractIDFromParam(ps.Value(0))
|
||||||
if rErr == neorpc.ErrUnknown {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
if rErr != nil {
|
if rErr != nil {
|
||||||
return nil, rErr
|
return nil, rErr
|
||||||
}
|
}
|
||||||
|
@ -1734,7 +1734,7 @@ func (s *Server) getStorage(ps params.Params) (any, *neorpc.Error) {
|
||||||
|
|
||||||
item := s.chain.GetStorageItem(id, key)
|
item := s.chain.GetStorageItem(id, key)
|
||||||
if item == nil {
|
if item == nil {
|
||||||
return "", nil
|
return "", neorpc.ErrUnknownStorageItem
|
||||||
}
|
}
|
||||||
|
|
||||||
return []byte(item), nil
|
return []byte(item), nil
|
||||||
|
@ -1759,14 +1759,14 @@ func (s *Server) getrawtransaction(reqParams params.Params) (any, *neorpc.Error)
|
||||||
_header := s.chain.GetHeaderHash(height)
|
_header := s.chain.GetHeaderHash(height)
|
||||||
header, err := s.chain.GetHeader(_header)
|
header, err := s.chain.GetHeader(_header)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, neorpc.NewRPCError("Failed to get header for the transaction", err.Error())
|
return nil, neorpc.NewInternalServerError(fmt.Sprintf("Failed to get header for the transaction: %s", err.Error()))
|
||||||
}
|
}
|
||||||
aers, err := s.chain.GetAppExecResults(txHash, trigger.Application)
|
aers, err := s.chain.GetAppExecResults(txHash, trigger.Application)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, neorpc.NewRPCError("Failed to get application log for the transaction", err.Error())
|
return nil, neorpc.NewInternalServerError(fmt.Sprintf("Failed to get application log for the transaction: %s", err.Error()))
|
||||||
}
|
}
|
||||||
if len(aers) == 0 {
|
if len(aers) == 0 {
|
||||||
return nil, neorpc.NewRPCError("Inconsistent application log", "application log for the transaction is empty")
|
return nil, neorpc.NewInternalServerError("Inconsistent application log: application log for the transaction is empty")
|
||||||
}
|
}
|
||||||
res.TransactionMetadata = result.TransactionMetadata{
|
res.TransactionMetadata = result.TransactionMetadata{
|
||||||
Blockhash: header.Hash(),
|
Blockhash: header.Hash(),
|
||||||
|
@ -1802,7 +1802,7 @@ func (s *Server) getContractState(reqParams params.Params) (any, *neorpc.Error)
|
||||||
}
|
}
|
||||||
cs := s.chain.GetContractState(scriptHash)
|
cs := s.chain.GetContractState(scriptHash)
|
||||||
if cs == nil {
|
if cs == nil {
|
||||||
return nil, neorpc.NewRPCError("Unknown contract", "")
|
return nil, neorpc.ErrUnknownContract
|
||||||
}
|
}
|
||||||
return cs, nil
|
return cs, nil
|
||||||
}
|
}
|
||||||
|
@ -1815,7 +1815,7 @@ func (s *Server) getNativeContracts(_ params.Params) (any, *neorpc.Error) {
|
||||||
func (s *Server) getBlockSysFee(reqParams params.Params) (any, *neorpc.Error) {
|
func (s *Server) getBlockSysFee(reqParams params.Params) (any, *neorpc.Error) {
|
||||||
num, err := s.blockHeightFromParam(reqParams.Value(0))
|
num, err := s.blockHeightFromParam(reqParams.Value(0))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, neorpc.NewRPCError("Invalid height", "invalid block identifier")
|
return 0, neorpc.WrapErrorWithData(err, fmt.Sprintf("invalid block height: %s", err.Data))
|
||||||
}
|
}
|
||||||
|
|
||||||
headerHash := s.chain.GetHeaderHash(num)
|
headerHash := s.chain.GetHeaderHash(num)
|
||||||
|
@ -1843,7 +1843,7 @@ func (s *Server) getBlockHeader(reqParams params.Params) (any, *neorpc.Error) {
|
||||||
verbose, _ := reqParams.Value(1).GetBoolean()
|
verbose, _ := reqParams.Value(1).GetBoolean()
|
||||||
h, err := s.chain.GetHeader(hash)
|
h, err := s.chain.GetHeader(hash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, neorpc.ErrUnknownHeader
|
return nil, neorpc.ErrUnknownBlock
|
||||||
}
|
}
|
||||||
|
|
||||||
if verbose {
|
if verbose {
|
||||||
|
@ -1877,7 +1877,7 @@ func (s *Server) getUnclaimedGas(ps params.Params) (any, *neorpc.Error) {
|
||||||
}
|
}
|
||||||
gas, err := s.chain.CalculateClaimable(u, s.chain.BlockHeight()+1) // +1 as in C#, for the next block.
|
gas, err := s.chain.CalculateClaimable(u, s.chain.BlockHeight()+1) // +1 as in C#, for the next block.
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, neorpc.NewRPCError("Can't calculate claimable", err.Error())
|
return nil, neorpc.NewInternalServerError(fmt.Sprintf("Can't calculate claimable: %s", err.Error()))
|
||||||
}
|
}
|
||||||
return result.UnclaimedGas{
|
return result.UnclaimedGas{
|
||||||
Address: u,
|
Address: u,
|
||||||
|
@ -1891,11 +1891,11 @@ func (s *Server) getCandidates(_ params.Params) (any, *neorpc.Error) {
|
||||||
|
|
||||||
validators, err := s.chain.GetNextBlockValidators()
|
validators, err := s.chain.GetNextBlockValidators()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, neorpc.NewRPCError("Can't get next block validators", err.Error())
|
return nil, neorpc.NewInternalServerError(fmt.Sprintf("Can't get next block validators: %s", err.Error()))
|
||||||
}
|
}
|
||||||
enrollments, err := s.chain.GetEnrollments()
|
enrollments, err := s.chain.GetEnrollments()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, neorpc.NewRPCError("Can't get enrollments", err.Error())
|
return nil, neorpc.NewInternalServerError(fmt.Sprintf("Can't get enrollments: %s", err.Error()))
|
||||||
}
|
}
|
||||||
var res = make([]result.Candidate, 0)
|
var res = make([]result.Candidate, 0)
|
||||||
for _, v := range enrollments {
|
for _, v := range enrollments {
|
||||||
|
@ -1914,11 +1914,11 @@ func (s *Server) getNextBlockValidators(_ params.Params) (any, *neorpc.Error) {
|
||||||
|
|
||||||
validators, err := s.chain.GetNextBlockValidators()
|
validators, err := s.chain.GetNextBlockValidators()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, neorpc.NewRPCError("Can't get next block validators", err.Error())
|
return nil, neorpc.NewInternalServerError(fmt.Sprintf("Can't get next block validators: %s", err.Error()))
|
||||||
}
|
}
|
||||||
enrollments, err := s.chain.GetEnrollments()
|
enrollments, err := s.chain.GetEnrollments()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, neorpc.NewRPCError("Can't get enrollments", err.Error())
|
return nil, neorpc.NewInternalServerError(fmt.Sprintf("Can't get enrollments: %s", err.Error()))
|
||||||
}
|
}
|
||||||
var res = make([]result.Validator, 0)
|
var res = make([]result.Validator, 0)
|
||||||
for _, v := range enrollments {
|
for _, v := range enrollments {
|
||||||
|
@ -2003,7 +2003,7 @@ func (s *Server) getInvokeFunctionParams(reqParams params.Params) (*transaction.
|
||||||
}
|
}
|
||||||
script, err := params.CreateFunctionInvocationScript(scriptHash, method, invparams)
|
script, err := params.CreateFunctionInvocationScript(scriptHash, method, invparams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, neorpc.NewInternalServerError(fmt.Sprintf("can't create invocation script: %s", err))
|
return nil, false, neorpc.WrapErrorWithData(neorpc.ErrInvalidParams, fmt.Sprintf("can't create invocation script: %s", err))
|
||||||
}
|
}
|
||||||
tx.Script = script
|
tx.Script = script
|
||||||
return tx, verbose, nil
|
return tx, verbose, nil
|
||||||
|
@ -2130,7 +2130,7 @@ func (s *Server) getInvokeContractVerifyParams(reqParams params.Params) (util.Ui
|
||||||
// handling consistency.
|
// handling consistency.
|
||||||
func (s *Server) getHistoricParams(reqParams params.Params) (uint32, *neorpc.Error) {
|
func (s *Server) getHistoricParams(reqParams params.Params) (uint32, *neorpc.Error) {
|
||||||
if s.chain.GetConfig().Ledger.KeepOnlyLatestState {
|
if s.chain.GetConfig().Ledger.KeepOnlyLatestState {
|
||||||
return 0, neorpc.NewInvalidRequestError(fmt.Sprintf("only latest state is supported: %s", errKeepOnlyLatestState))
|
return 0, neorpc.WrapErrorWithData(neorpc.ErrUnsupportedState, fmt.Sprintf("only latest state is supported: %s", errKeepOnlyLatestState))
|
||||||
}
|
}
|
||||||
if len(reqParams) < 1 {
|
if len(reqParams) < 1 {
|
||||||
return 0, neorpc.ErrInvalidParams
|
return 0, neorpc.ErrInvalidParams
|
||||||
|
@ -2185,7 +2185,14 @@ func (s *Server) prepareInvocationContext(t trigger.Type, script []byte, contrac
|
||||||
|
|
||||||
err = s.chain.InitVerificationContext(ic, contractScriptHash, &transaction.Witness{InvocationScript: script, VerificationScript: []byte{}})
|
err = s.chain.InitVerificationContext(ic, contractScriptHash, &transaction.Witness{InvocationScript: script, VerificationScript: []byte{}})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, neorpc.NewInternalServerError(fmt.Sprintf("can't prepare verification VM: %s", err))
|
switch {
|
||||||
|
case errors.Is(err, core.ErrUnknownVerificationContract):
|
||||||
|
return nil, neorpc.WrapErrorWithData(neorpc.ErrUnknownContract, err.Error())
|
||||||
|
case errors.Is(err, core.ErrInvalidVerificationContract):
|
||||||
|
return nil, neorpc.WrapErrorWithData(neorpc.ErrInvalidVerificationFunction, err.Error())
|
||||||
|
default:
|
||||||
|
return nil, neorpc.NewInternalServerError(fmt.Sprintf("can't prepare verification VM: %s", err))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ic.VM.LoadScriptWithFlags(script, callflag.All)
|
ic.VM.LoadScriptWithFlags(script, callflag.All)
|
||||||
|
@ -2319,7 +2326,7 @@ func (s *Server) registerOrDumpIterator(item stackitem.Item) (stackitem.Item, uu
|
||||||
|
|
||||||
func (s *Server) traverseIterator(reqParams params.Params) (any, *neorpc.Error) {
|
func (s *Server) traverseIterator(reqParams params.Params) (any, *neorpc.Error) {
|
||||||
if !s.config.SessionEnabled {
|
if !s.config.SessionEnabled {
|
||||||
return nil, neorpc.NewInvalidRequestError("sessions are disabled")
|
return nil, neorpc.ErrSessionsDisabled
|
||||||
}
|
}
|
||||||
sID, err := reqParams.Value(0).GetUUID()
|
sID, err := reqParams.Value(0).GetUUID()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -2344,7 +2351,7 @@ func (s *Server) traverseIterator(reqParams params.Params) (any, *neorpc.Error)
|
||||||
session, ok := s.sessions[sID.String()]
|
session, ok := s.sessions[sID.String()]
|
||||||
if !ok {
|
if !ok {
|
||||||
s.sessionsLock.Unlock()
|
s.sessionsLock.Unlock()
|
||||||
return []json.RawMessage{}, nil
|
return nil, neorpc.ErrUnknownSession
|
||||||
}
|
}
|
||||||
session.iteratorsLock.Lock()
|
session.iteratorsLock.Lock()
|
||||||
// Perform `till` update only after session.iteratorsLock is taken in order to have more
|
// Perform `till` update only after session.iteratorsLock is taken in order to have more
|
||||||
|
@ -2355,14 +2362,19 @@ func (s *Server) traverseIterator(reqParams params.Params) (any, *neorpc.Error)
|
||||||
var (
|
var (
|
||||||
iIDStr = iID.String()
|
iIDStr = iID.String()
|
||||||
iVals []stackitem.Item
|
iVals []stackitem.Item
|
||||||
|
found bool
|
||||||
)
|
)
|
||||||
for _, it := range session.iteratorIdentifiers {
|
for _, it := range session.iteratorIdentifiers {
|
||||||
if iIDStr == it.ID {
|
if iIDStr == it.ID {
|
||||||
iVals = iterator.Values(it.Item, count)
|
iVals = iterator.Values(it.Item, count)
|
||||||
|
found = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
session.iteratorsLock.Unlock()
|
session.iteratorsLock.Unlock()
|
||||||
|
if !found {
|
||||||
|
return nil, neorpc.ErrUnknownIterator
|
||||||
|
}
|
||||||
|
|
||||||
result := make([]json.RawMessage, len(iVals))
|
result := make([]json.RawMessage, len(iVals))
|
||||||
for j := range iVals {
|
for j := range iVals {
|
||||||
|
@ -2376,7 +2388,7 @@ func (s *Server) traverseIterator(reqParams params.Params) (any, *neorpc.Error)
|
||||||
|
|
||||||
func (s *Server) terminateSession(reqParams params.Params) (any, *neorpc.Error) {
|
func (s *Server) terminateSession(reqParams params.Params) (any, *neorpc.Error) {
|
||||||
if !s.config.SessionEnabled {
|
if !s.config.SessionEnabled {
|
||||||
return nil, neorpc.NewInvalidRequestError("sessions are disabled")
|
return nil, neorpc.ErrSessionsDisabled
|
||||||
}
|
}
|
||||||
sID, err := reqParams.Value(0).GetUUID()
|
sID, err := reqParams.Value(0).GetUUID()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -2386,17 +2398,18 @@ func (s *Server) terminateSession(reqParams params.Params) (any, *neorpc.Error)
|
||||||
s.sessionsLock.Lock()
|
s.sessionsLock.Lock()
|
||||||
defer s.sessionsLock.Unlock()
|
defer s.sessionsLock.Unlock()
|
||||||
session, ok := s.sessions[strSID]
|
session, ok := s.sessions[strSID]
|
||||||
if ok {
|
if !ok {
|
||||||
// Iterators access Seek channel under the hood; finalizer closes this channel, thus,
|
return nil, neorpc.ErrUnknownSession
|
||||||
// we need to perform finalisation under iteratorsLock.
|
|
||||||
session.iteratorsLock.Lock()
|
|
||||||
session.finalize()
|
|
||||||
if !session.timer.Stop() {
|
|
||||||
<-session.timer.C
|
|
||||||
}
|
|
||||||
delete(s.sessions, strSID)
|
|
||||||
session.iteratorsLock.Unlock()
|
|
||||||
}
|
}
|
||||||
|
// Iterators access Seek channel under the hood; finalizer closes this channel, thus,
|
||||||
|
// we need to perform finalisation under iteratorsLock.
|
||||||
|
session.iteratorsLock.Lock()
|
||||||
|
session.finalize()
|
||||||
|
if !session.timer.Stop() {
|
||||||
|
<-session.timer.C
|
||||||
|
}
|
||||||
|
delete(s.sessions, strSID)
|
||||||
|
session.iteratorsLock.Unlock()
|
||||||
return ok, nil
|
return ok, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2412,24 +2425,13 @@ func (s *Server) submitBlock(reqParams params.Params) (any, *neorpc.Error) {
|
||||||
if r.Err != nil {
|
if r.Err != nil {
|
||||||
return nil, neorpc.NewInvalidParamsError(fmt.Sprintf("can't decode block: %s", r.Err))
|
return nil, neorpc.NewInvalidParamsError(fmt.Sprintf("can't decode block: %s", r.Err))
|
||||||
}
|
}
|
||||||
err = s.chain.AddBlock(b)
|
return getRelayResult(s.chain.AddBlock(b), b.Hash())
|
||||||
if err != nil {
|
|
||||||
switch {
|
|
||||||
case errors.Is(err, core.ErrInvalidBlockIndex) || errors.Is(err, core.ErrAlreadyExists):
|
|
||||||
return nil, neorpc.WrapErrorWithData(neorpc.ErrAlreadyExists, err.Error())
|
|
||||||
default:
|
|
||||||
return nil, neorpc.WrapErrorWithData(neorpc.ErrValidationFailed, err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &result.RelayResult{
|
|
||||||
Hash: b.Hash(),
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// submitNotaryRequest broadcasts P2PNotaryRequest over the Neo network.
|
// submitNotaryRequest broadcasts P2PNotaryRequest over the Neo network.
|
||||||
func (s *Server) submitNotaryRequest(ps params.Params) (any, *neorpc.Error) {
|
func (s *Server) submitNotaryRequest(ps params.Params) (any, *neorpc.Error) {
|
||||||
if !s.chain.P2PSigExtensionsEnabled() {
|
if !s.chain.P2PSigExtensionsEnabled() {
|
||||||
return nil, neorpc.NewRPCError("P2PSignatureExtensions are disabled", "")
|
return nil, neorpc.NewInternalServerError("P2PSignatureExtensions are disabled")
|
||||||
}
|
}
|
||||||
|
|
||||||
bytePayload, err := ps.Value(0).GetBytesBase64()
|
bytePayload, err := ps.Value(0).GetBytesBase64()
|
||||||
|
@ -2450,21 +2452,37 @@ func getRelayResult(err error, hash util.Uint256) (any, *neorpc.Error) {
|
||||||
return result.RelayResult{
|
return result.RelayResult{
|
||||||
Hash: hash,
|
Hash: hash,
|
||||||
}, nil
|
}, nil
|
||||||
case errors.Is(err, core.ErrAlreadyExists):
|
case errors.Is(err, core.ErrTxExpired):
|
||||||
|
return nil, neorpc.WrapErrorWithData(neorpc.ErrExpiredTransaction, err.Error())
|
||||||
|
case errors.Is(err, core.ErrAlreadyExists) || errors.Is(err, core.ErrInvalidBlockIndex):
|
||||||
return nil, neorpc.WrapErrorWithData(neorpc.ErrAlreadyExists, err.Error())
|
return nil, neorpc.WrapErrorWithData(neorpc.ErrAlreadyExists, err.Error())
|
||||||
|
case errors.Is(err, core.ErrAlreadyInPool):
|
||||||
|
return nil, neorpc.WrapErrorWithData(neorpc.ErrAlreadyInPool, err.Error())
|
||||||
case errors.Is(err, core.ErrOOM):
|
case errors.Is(err, core.ErrOOM):
|
||||||
return nil, neorpc.WrapErrorWithData(neorpc.ErrOutOfMemory, err.Error())
|
return nil, neorpc.WrapErrorWithData(neorpc.ErrMempoolCapReached, err.Error())
|
||||||
case errors.Is(err, core.ErrPolicy):
|
case errors.Is(err, core.ErrPolicy):
|
||||||
return nil, neorpc.WrapErrorWithData(neorpc.ErrPolicyFail, err.Error())
|
return nil, neorpc.WrapErrorWithData(neorpc.ErrPolicyFailed, err.Error())
|
||||||
|
case errors.Is(err, core.ErrInvalidScript):
|
||||||
|
return nil, neorpc.WrapErrorWithData(neorpc.ErrInvalidScript, err.Error())
|
||||||
|
case errors.Is(err, core.ErrTxTooBig):
|
||||||
|
return nil, neorpc.WrapErrorWithData(neorpc.ErrInvalidSize, err.Error())
|
||||||
|
case errors.Is(err, core.ErrTxSmallNetworkFee):
|
||||||
|
return nil, neorpc.WrapErrorWithData(neorpc.ErrInsufficientNetworkFee, err.Error())
|
||||||
|
case errors.Is(err, core.ErrInvalidAttribute):
|
||||||
|
return nil, neorpc.WrapErrorWithData(neorpc.ErrInvalidAttribute, err.Error())
|
||||||
|
case errors.Is(err, core.ErrInsufficientFunds):
|
||||||
|
return nil, neorpc.WrapErrorWithData(neorpc.ErrInsufficientFunds, err.Error())
|
||||||
|
case errors.Is(err, core.ErrInvalidSignature):
|
||||||
|
return nil, neorpc.WrapErrorWithData(neorpc.ErrInvalidSignature, err.Error())
|
||||||
default:
|
default:
|
||||||
return nil, neorpc.WrapErrorWithData(neorpc.ErrValidationFailed, err.Error())
|
return nil, neorpc.WrapErrorWithData(neorpc.ErrVerificationFailed, err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) submitOracleResponse(ps params.Params) (any, *neorpc.Error) {
|
func (s *Server) submitOracleResponse(ps params.Params) (any, *neorpc.Error) {
|
||||||
oraclePtr := s.oracle.Load()
|
oraclePtr := s.oracle.Load()
|
||||||
if oraclePtr == nil {
|
if oraclePtr == nil {
|
||||||
return nil, neorpc.NewRPCError("Oracle is not enabled", "")
|
return nil, neorpc.ErrOracleDisabled
|
||||||
}
|
}
|
||||||
oracle := oraclePtr.(OracleHandler)
|
oracle := oraclePtr.(OracleHandler)
|
||||||
var pub *keys.PublicKey
|
var pub *keys.PublicKey
|
||||||
|
@ -2481,15 +2499,15 @@ func (s *Server) submitOracleResponse(ps params.Params) (any, *neorpc.Error) {
|
||||||
}
|
}
|
||||||
txSig, err := ps.Value(2).GetBytesBase64()
|
txSig, err := ps.Value(2).GetBytesBase64()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, neorpc.NewInvalidParamsError(fmt.Sprintf("tx signature is missing: %s", err))
|
return nil, neorpc.WrapErrorWithData(neorpc.ErrInvalidParams, fmt.Sprintf("tx signature is missing: %s", err))
|
||||||
}
|
}
|
||||||
msgSig, err := ps.Value(3).GetBytesBase64()
|
msgSig, err := ps.Value(3).GetBytesBase64()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, neorpc.NewInvalidParamsError(fmt.Sprintf("msg signature is missing: %s", err))
|
return nil, neorpc.WrapErrorWithData(neorpc.ErrInvalidParams, fmt.Sprintf("msg signature is missing: %s", err))
|
||||||
}
|
}
|
||||||
data := broadcaster.GetMessage(pubBytes, uint64(reqID), txSig)
|
data := broadcaster.GetMessage(pubBytes, uint64(reqID), txSig)
|
||||||
if !pub.Verify(msgSig, hash.Sha256(data).BytesBE()) {
|
if !pub.Verify(msgSig, hash.Sha256(data).BytesBE()) {
|
||||||
return nil, neorpc.NewRPCError("Invalid request signature", "")
|
return nil, neorpc.ErrInvalidSignature
|
||||||
}
|
}
|
||||||
oracle.AddResponse(pub, uint64(reqID), txSig)
|
oracle.AddResponse(pub, uint64(reqID), txSig)
|
||||||
return json.RawMessage([]byte("{}")), nil
|
return json.RawMessage([]byte("{}")), nil
|
||||||
|
@ -2803,7 +2821,7 @@ func (s *Server) blockHeightFromParam(param *params.Param) (uint32, *neorpc.Erro
|
||||||
}
|
}
|
||||||
|
|
||||||
if num < 0 || int64(num) > int64(s.chain.BlockHeight()) {
|
if num < 0 || int64(num) > int64(s.chain.BlockHeight()) {
|
||||||
return 0, invalidBlockHeightError(0, num)
|
return 0, neorpc.WrapErrorWithData(neorpc.ErrUnknownHeight, fmt.Sprintf("param at index %d should be greater than or equal to 0 and less then or equal to current block height, got: %d", 0, num))
|
||||||
}
|
}
|
||||||
return uint32(num), nil
|
return uint32(num), nil
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue