From 4582b8f0d4fb95d59868d66bc868d8af72e4d0b0 Mon Sep 17 00:00:00 2001 From: Pavel Karpy Date: Mon, 29 Aug 2022 18:32:54 +0300 Subject: [PATCH] [#1711] morph: Drop deprecated neo-go calls Does not include notary actor and does not drop the deprecated `AddNetworkFee`. Signed-off-by: Pavel Karpy --- pkg/morph/client/client.go | 61 +++++++++--------------- pkg/morph/client/constructor.go | 82 ++++++++++++++++++++++++++------- pkg/morph/client/multi.go | 15 ++---- pkg/morph/client/notary.go | 16 +++---- pkg/morph/client/util.go | 14 ++++++ 5 files changed, 112 insertions(+), 76 deletions(-) diff --git a/pkg/morph/client/client.go b/pkg/morph/client/client.go index 8ec9e724..00824d36 100644 --- a/pkg/morph/client/client.go +++ b/pkg/morph/client/client.go @@ -15,6 +15,8 @@ import ( "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" "github.com/nspcc-dev/neo-go/pkg/rpcclient" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/nep17" sc "github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger" "github.com/nspcc-dev/neo-go/pkg/util" @@ -44,9 +46,12 @@ type Client struct { logger *logger.Logger // logging component - client *rpcclient.WSClient // neo-go websocket client + client *rpcclient.WSClient // neo-go websocket client + rpcActor *actor.Actor // neo-go RPC actor + gasToken *nep17.Token // neo-go GAS token wrapper - acc *wallet.Account // neo account + acc *wallet.Account // neo account + accAddr util.Uint160 // account's address signer *transaction.Signer @@ -185,46 +190,14 @@ func (c *Client) Invoke(contract util.Uint160, fee fixedn.Fixed8, method string, params = append(params, param) } - cosigner := []transaction.Signer{ - { - Account: c.acc.PrivateKey().PublicKey().GetScriptHash(), - Scopes: c.signer.Scopes, - AllowedContracts: c.signer.AllowedContracts, - AllowedGroups: c.signer.AllowedGroups, - }, - } - - cosignerAcc := []rpcclient.SignerAccount{ - { - Signer: cosigner[0], - Account: c.acc, - }, - } - - resp, err := c.client.InvokeFunction(contract, method, params, cosigner) + txHash, vub, err := c.rpcActor.SendTunedCall(contract, method, nil, addFeeCheckerModifier(int64(fee)), params) if err != nil { - return err - } - - if resp.State != HaltState { - return wrapNeoFSError(¬HaltStateError{state: resp.State, exception: resp.FaultException}) - } - - if len(resp.Script) == 0 { - return wrapNeoFSError(errEmptyInvocationScript) - } - - script := resp.Script - - sysFee := resp.GasConsumed + int64(fee) // consumed gas + extra fee - - txHash, err := c.client.SignAndPushInvocationTx(script, c.acc, sysFee, 0, cosignerAcc) - if err != nil { - return err + return fmt.Errorf("could not invoke %s: %w", method, err) } c.logger.Debug("neo client invoke", zap.String("method", method), + zap.Uint32("vub", vub), zap.Stringer("tx_hash", txHash.Reverse())) return nil @@ -284,14 +257,16 @@ func (c *Client) TransferGas(receiver util.Uint160, amount fixedn.Fixed8) error return err } - txHash, err := c.client.TransferNEP17(c.acc, receiver, gas, int64(amount), 0, nil, nil) + gasToken := nep17.New(c.rpcActor, gas) + txHash, vub, err := gasToken.Transfer(c.accAddr, receiver, big.NewInt(int64(amount)), nil) if err != nil { return err } c.logger.Debug("native gas transfer invoke", zap.String("to", receiver.StringLE()), - zap.Stringer("tx_hash", txHash.Reverse())) + zap.Stringer("tx_hash", txHash.Reverse()), + zap.Uint32("vub", vub)) return nil } @@ -356,7 +331,13 @@ func (c *Client) GasBalance() (res int64, err error) { return 0, err } - return c.client.NEP17BalanceOf(gas, c.acc.PrivateKey().GetScriptHash()) + gasToken := nep17.New(c.rpcActor, gas) + bal, err := gasToken.BalanceOf(c.accAddr) + if err != nil { + return 0, err + } + + return bal.Int64(), nil } // Committee returns keys of chain committee from neo native contract. diff --git a/pkg/morph/client/constructor.go b/pkg/morph/client/constructor.go index 34dc04ca..699b16aa 100644 --- a/pkg/morph/client/constructor.go +++ b/pkg/morph/client/constructor.go @@ -8,9 +8,12 @@ import ( "time" lru "github.com/hashicorp/golang-lru" + "github.com/nspcc-dev/neo-go/pkg/core/native/nativenames" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/rpcclient" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/nep17" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/wallet" "github.com/nspcc-dev/neofs-node/pkg/util/logger" @@ -82,6 +85,9 @@ func New(key *keys.PrivateKey, opts ...Option) (*Client, error) { panic("empty private key") } + acc := wallet.NewAccountFromPrivateKey(key) + accAddr := key.GetScriptHash() + // build default configuration cfg := defaultConfig() @@ -97,7 +103,8 @@ func New(key *keys.PrivateKey, opts ...Option) (*Client, error) { cli := &Client{ cache: newClientCache(), logger: cfg.logger, - acc: wallet.NewAccountFromPrivateKey(key), + acc: acc, + accAddr: accAddr, signer: cfg.signer, cfg: *cfg, switchLock: &sync.RWMutex{}, @@ -109,6 +116,7 @@ func New(key *keys.PrivateKey, opts ...Option) (*Client, error) { cli.endpoints.init(cfg.endpoints) + var err error if cfg.singleCli != nil { // return client in single RPC node mode that uses // predefined WS client @@ -118,18 +126,21 @@ func New(key *keys.PrivateKey, opts ...Option) (*Client, error) { // they will be used in switch process, otherwise // inactive mode will be enabled cli.client = cfg.singleCli + + cli.rpcActor, err = newActor(cfg.singleCli, acc, *cfg) + if err != nil { + return nil, fmt.Errorf("could not create RPC actor: %w", err) + } + + cli.gasToken, err = newGasToken(cli.client, cli.rpcActor) + if err != nil { + return nil, fmt.Errorf("could not create gas token actor: %w", err) + } } else { - ws, err := newWSClient(*cfg, cli.endpoints.list[0].Address) + cli.client, cli.rpcActor, cli.gasToken, err = cli.newCli(cli.endpoints.list[0].Address) if err != nil { - return nil, fmt.Errorf("could not create morph client: %w", err) + return nil, fmt.Errorf("could not create RPC client: %w", err) } - - err = ws.Init() - if err != nil { - return nil, fmt.Errorf("could not init morph client: %w", err) - } - - cli.client = ws } go cli.notificationLoop() @@ -137,12 +148,51 @@ func New(key *keys.PrivateKey, opts ...Option) (*Client, error) { return cli, nil } -func newWSClient(cfg cfg, endpoint string) (*rpcclient.WSClient, error) { - return rpcclient.NewWS( - cfg.ctx, - endpoint, - rpcclient.Options{DialTimeout: cfg.dialTimeout}, - ) +func (c *Client) newCli(endpoint string) (*rpcclient.WSClient, *actor.Actor, *nep17.Token, error) { + cli, err := rpcclient.NewWS(c.cfg.ctx, endpoint, rpcclient.Options{ + DialTimeout: c.cfg.dialTimeout, + }) + if err != nil { + return nil, nil, nil, fmt.Errorf("WS client creation: %w", err) + } + + err = cli.Init() + if err != nil { + return nil, nil, nil, fmt.Errorf("WS client initialization: %w", err) + } + + act, err := newActor(cli, c.acc, c.cfg) + if err != nil { + return nil, nil, nil, fmt.Errorf("RPC actor creation: %w", err) + } + + gas, err := newGasToken(cli, act) + if err != nil { + return nil, nil, nil, fmt.Errorf("gas token actor: %w", err) + } + + return cli, act, gas, nil +} + +func newActor(ws *rpcclient.WSClient, acc *wallet.Account, cfg cfg) (*actor.Actor, error) { + return actor.New(ws, []actor.SignerAccount{{ + Signer: transaction.Signer{ + Account: acc.PrivateKey().PublicKey().GetScriptHash(), + Scopes: cfg.signer.Scopes, + AllowedContracts: cfg.signer.AllowedContracts, + AllowedGroups: cfg.signer.AllowedGroups, + }, + Account: acc, + }}) +} + +func newGasToken(cli *rpcclient.WSClient, a *actor.Actor) (*nep17.Token, error) { + gasHash, err := cli.GetNativeContractHash(nativenames.Gas) + if err != nil { + return nil, fmt.Errorf("gas contract hash: %w", err) + } + + return nep17.New(a, gasHash), nil } func newClientCache() cache { diff --git a/pkg/morph/client/multi.go b/pkg/morph/client/multi.go index aab2b1d9..fe95777f 100644 --- a/pkg/morph/client/multi.go +++ b/pkg/morph/client/multi.go @@ -36,7 +36,7 @@ func (c *Client) switchRPC() bool { // Skip the current endpoint. for c.endpoints.curr = range c.endpoints.list { newEndpoint := c.endpoints.list[c.endpoints.curr].Address - cli, err := newWSClient(c.cfg, newEndpoint) + cli, act, gas, err := c.newCli(newEndpoint) if err != nil { c.logger.Warn("could not establish connection to the switched RPC node", zap.String("endpoint", newEndpoint), @@ -46,19 +46,10 @@ func (c *Client) switchRPC() bool { continue } - err = cli.Init() - if err != nil { - cli.Close() - c.logger.Warn("could not init the switched RPC node", - zap.String("endpoint", newEndpoint), - zap.Error(err), - ) - - continue - } - c.cache.invalidate() c.client = cli + c.rpcActor = act + c.gasToken = gas c.logger.Info("connection to the new RPC node has been established", zap.String("endpoint", newEndpoint)) diff --git a/pkg/morph/client/notary.go b/pkg/morph/client/notary.go index 28da0860..36be292f 100644 --- a/pkg/morph/client/notary.go +++ b/pkg/morph/client/notary.go @@ -4,6 +4,7 @@ import ( "encoding/binary" "errors" "fmt" + "math/big" "strings" "github.com/nspcc-dev/neo-go/pkg/core/native/nativenames" @@ -12,6 +13,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/nep17" "github.com/nspcc-dev/neo-go/pkg/smartcontract" sc "github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/util" @@ -167,15 +169,12 @@ func (c *Client) DepositNotary(amount fixedn.Fixed8, delta uint32) (res util.Uin return util.Uint256{}, fmt.Errorf("can't get GAS script hash: %w", err) } - txHash, err := c.client.TransferNEP17( - c.acc, + gasToken := nep17.New(c.rpcActor, gas) + txHash, vub, err := gasToken.Transfer( + c.accAddr, c.notary.notary, - gas, - int64(amount), - 0, - []interface{}{c.acc.PrivateKey().GetScriptHash(), till}, - nil, - ) + big.NewInt(int64(amount)), + []interface{}{c.acc.PrivateKey().GetScriptHash(), till}) if err != nil { return util.Uint256{}, fmt.Errorf("can't make notary deposit: %w", err) } @@ -183,6 +182,7 @@ func (c *Client) DepositNotary(amount fixedn.Fixed8, delta uint32) (res util.Uin c.logger.Debug("notary deposit invoke", zap.Int64("amount", int64(amount)), zap.Int64("expire_at", till), + zap.Uint32("vub", vub), zap.Stringer("tx_hash", txHash.Reverse())) return txHash, nil diff --git a/pkg/morph/client/util.go b/pkg/morph/client/util.go index 1e18d68b..82044216 100644 --- a/pkg/morph/client/util.go +++ b/pkg/morph/client/util.go @@ -4,6 +4,8 @@ import ( "fmt" "math/big" + "github.com/nspcc-dev/neo-go/pkg/core/transaction" + "github.com/nspcc-dev/neo-go/pkg/neorpc/result" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" ) @@ -92,3 +94,15 @@ func StringFromStackItem(param stackitem.Item) (string, error) { return stackitem.ToString(param) } + +func addFeeCheckerModifier(add int64) func(r *result.Invoke, t *transaction.Transaction) error { + return func(r *result.Invoke, t *transaction.Transaction) error { + if r.State != HaltState { + return wrapNeoFSError(¬HaltStateError{state: r.State, exception: r.FaultException}) + } + + t.SystemFee += add + + return nil + } +}