forked from TrueCloudLab/frostfs-node
[#746] morph/client: Distinguish between neo-go errors and NeoFS logic
Implement `error` interface on new `neofsError` type which is a wrapper over NeoFS-specific error. Wrap all `Client` errors except neo-go client API ones into `neofsError`. Wrapped errors are going to be used for multi-endpoint loop control. Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
parent
85bd2a1cdf
commit
3b7e884e74
2 changed files with 38 additions and 10 deletions
|
@ -79,6 +79,29 @@ var errEmptyInvocationScript = errors.New("got empty invocation script from neo
|
||||||
|
|
||||||
var errScriptDecode = errors.New("could not decode invocation script from neo node")
|
var errScriptDecode = errors.New("could not decode invocation script from neo node")
|
||||||
|
|
||||||
|
// implementation of error interface for NeoFS-specific errors.
|
||||||
|
type neofsError struct {
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e neofsError) Error() string {
|
||||||
|
return fmt.Sprintf("neofs error: %v", e.err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// wraps NeoFS-specific error into neofsError. Arg must not be nil.
|
||||||
|
func wrapNeoFSError(err error) error {
|
||||||
|
return neofsError{err}
|
||||||
|
}
|
||||||
|
|
||||||
|
// unwraps NeoFS-specific error if err is type of neofsError. Otherwise, returns nil.
|
||||||
|
func unwrapNeoFSError(err error) error {
|
||||||
|
if e := new(neofsError); errors.As(err, e) {
|
||||||
|
return e.err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Invoke invokes contract method by sending transaction into blockchain.
|
// Invoke invokes contract method by sending transaction into blockchain.
|
||||||
// Supported args types: int64, string, util.Uint160, []byte and bool.
|
// Supported args types: int64, string, util.Uint160, []byte and bool.
|
||||||
func (c *Client) Invoke(contract util.Uint160, fee fixedn.Fixed8, method string, args ...interface{}) error {
|
func (c *Client) Invoke(contract util.Uint160, fee fixedn.Fixed8, method string, args ...interface{}) error {
|
||||||
|
@ -121,11 +144,11 @@ func (c *Client) Invoke(contract util.Uint160, fee fixedn.Fixed8, method string,
|
||||||
}
|
}
|
||||||
|
|
||||||
if resp.State != HaltState {
|
if resp.State != HaltState {
|
||||||
return ¬HaltStateError{state: resp.State, exception: resp.FaultException}
|
return wrapNeoFSError(¬HaltStateError{state: resp.State, exception: resp.FaultException})
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(resp.Script) == 0 {
|
if len(resp.Script) == 0 {
|
||||||
return errEmptyInvocationScript
|
return wrapNeoFSError(errEmptyInvocationScript)
|
||||||
}
|
}
|
||||||
|
|
||||||
script := resp.Script
|
script := resp.Script
|
||||||
|
@ -178,7 +201,7 @@ func (c *Client) TestInvoke(contract util.Uint160, method string, args ...interf
|
||||||
}
|
}
|
||||||
|
|
||||||
if val.State != HaltState {
|
if val.State != HaltState {
|
||||||
return nil, ¬HaltStateError{state: val.State, exception: val.FaultException}
|
return nil, wrapNeoFSError(¬HaltStateError{state: val.State, exception: val.FaultException})
|
||||||
}
|
}
|
||||||
|
|
||||||
return val.Stack, nil
|
return val.Stack, nil
|
||||||
|
@ -330,6 +353,9 @@ func (c *Client) roleList(r noderoles.Role) (keys.PublicKeys, error) {
|
||||||
return c.client.GetDesignatedByRole(r, height)
|
return c.client.GetDesignatedByRole(r, height)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// tries to resolve sc.Parameter from the arg.
|
||||||
|
//
|
||||||
|
// Wraps any error to neofsError.
|
||||||
func toStackParameter(value interface{}) (sc.Parameter, error) {
|
func toStackParameter(value interface{}) (sc.Parameter, error) {
|
||||||
var result = sc.Parameter{
|
var result = sc.Parameter{
|
||||||
Value: value,
|
Value: value,
|
||||||
|
@ -380,7 +406,7 @@ func toStackParameter(value interface{}) (sc.Parameter, error) {
|
||||||
result.Value = int64(0)
|
result.Value = int64(0)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return result, fmt.Errorf("chain/client: unsupported parameter %v", value)
|
return result, wrapNeoFSError(fmt.Errorf("chain/client: unsupported parameter %v", value))
|
||||||
}
|
}
|
||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
|
|
|
@ -196,12 +196,12 @@ func (c *Client) GetNotaryDeposit() (res int64, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(items) != 1 {
|
if len(items) != 1 {
|
||||||
return 0, fmt.Errorf("%v: %w", notaryBalanceErrMsg, errUnexpectedItems)
|
return 0, wrapNeoFSError(fmt.Errorf("%v: %w", notaryBalanceErrMsg, errUnexpectedItems))
|
||||||
}
|
}
|
||||||
|
|
||||||
bigIntDeposit, err := items[0].TryInteger()
|
bigIntDeposit, err := items[0].TryInteger()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, fmt.Errorf("%v: %w", notaryBalanceErrMsg, err)
|
return 0, wrapNeoFSError(fmt.Errorf("%v: %w", notaryBalanceErrMsg, err))
|
||||||
}
|
}
|
||||||
|
|
||||||
return bigIntDeposit.Int64(), nil
|
return bigIntDeposit.Int64(), nil
|
||||||
|
@ -307,12 +307,12 @@ func (c *Client) notaryInvoke(committee bool, contract util.Uint160, method stri
|
||||||
|
|
||||||
// check invocation state
|
// check invocation state
|
||||||
if test.State != HaltState {
|
if test.State != HaltState {
|
||||||
return ¬HaltStateError{state: test.State, exception: test.FaultException}
|
return wrapNeoFSError(¬HaltStateError{state: test.State, exception: test.FaultException})
|
||||||
}
|
}
|
||||||
|
|
||||||
// if test invocation failed, then return error
|
// if test invocation failed, then return error
|
||||||
if len(test.Script) == 0 {
|
if len(test.Script) == 0 {
|
||||||
return errEmptyInvocationScript
|
return wrapNeoFSError(errEmptyInvocationScript)
|
||||||
}
|
}
|
||||||
|
|
||||||
// after test invocation we build main multisig transaction
|
// after test invocation we build main multisig transaction
|
||||||
|
@ -394,7 +394,8 @@ func (c *Client) notaryCosigners(ir []*keys.PublicKey, committee bool) ([]transa
|
||||||
|
|
||||||
multisigScript, err := sc.CreateMultiSigRedeemScript(m, ir)
|
multisigScript, err := sc.CreateMultiSigRedeemScript(m, ir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("can't create ir multisig redeem script: %w", err)
|
// wrap error as NeoFS-specific since the call is not related to any client
|
||||||
|
return nil, wrapNeoFSError(fmt.Errorf("can't create ir multisig redeem script: %w", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
s = append(s, transaction.Signer{
|
s = append(s, transaction.Signer{
|
||||||
|
@ -480,7 +481,8 @@ func (c *Client) notaryMultisigAccount(ir []*keys.PublicKey, committee bool) (*w
|
||||||
|
|
||||||
err := multisigAccount.ConvertMultisig(m, ir)
|
err := multisigAccount.ConvertMultisig(m, ir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("can't make inner ring multisig wallet: %w", err)
|
// wrap error as NeoFS-specific since the call is not related to any client
|
||||||
|
return nil, wrapNeoFSError(fmt.Errorf("can't make inner ring multisig wallet: %w", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
return multisigAccount, nil
|
return multisigAccount, nil
|
||||||
|
|
Loading…
Reference in a new issue