From 6c45a17af66843ac5757fcd4b8f8e6acd0bca087 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 31 Oct 2024 13:13:03 +0300 Subject: [PATCH] [#1467] node: Break notary deposit wait after VUB Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/morph.go | 70 ++++++++++++++++++++++---------------- cmd/frostfs-node/netmap.go | 2 +- internal/logs/logs.go | 1 - pkg/innerring/notary.go | 5 +-- pkg/morph/client/client.go | 23 +++++++++++++ pkg/morph/client/notary.go | 17 ++++----- 6 files changed, 77 insertions(+), 41 deletions(-) diff --git a/cmd/frostfs-node/morph.go b/cmd/frostfs-node/morph.go index e85209059..0969f5579 100644 --- a/cmd/frostfs-node/morph.go +++ b/cmd/frostfs-node/morph.go @@ -17,15 +17,16 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/rand" "github.com/nspcc-dev/neo-go/pkg/core/block" "github.com/nspcc-dev/neo-go/pkg/core/state" + "github.com/nspcc-dev/neo-go/pkg/neorpc/result" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/waiter" + "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger" "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/vm/vmstate" "go.uber.org/zap" ) const ( newEpochNotification = "NewEpoch" - - // amount of tries(blocks) before notary deposit timeout. - notaryDepositRetriesAmount = 300 ) func (c *cfg) initMorphComponents(ctx context.Context) { @@ -128,7 +129,7 @@ func makeAndWaitNotaryDeposit(ctx context.Context, c *cfg) { return } - tx, err := makeNotaryDeposit(c) + tx, vub, err := makeNotaryDeposit(c) fatalOnErr(err) if tx.Equals(util.Uint256{}) { @@ -139,11 +140,11 @@ func makeAndWaitNotaryDeposit(ctx context.Context, c *cfg) { return } - err = waitNotaryDeposit(ctx, c, tx) + err = waitNotaryDeposit(ctx, c, tx, vub) fatalOnErr(err) } -func makeNotaryDeposit(c *cfg) (util.Uint256, error) { +func makeNotaryDeposit(c *cfg) (util.Uint256, uint32, error) { const ( // gasMultiplier defines how many times more the notary // balance must be compared to the GAS balance of the node: @@ -157,7 +158,7 @@ func makeNotaryDeposit(c *cfg) (util.Uint256, error) { depositAmount, err := client.CalculateNotaryDepositAmount(c.cfgMorph.client, gasMultiplier, gasDivisor) if err != nil { - return util.Uint256{}, fmt.Errorf("could not calculate notary deposit: %w", err) + return util.Uint256{}, 0, fmt.Errorf("could not calculate notary deposit: %w", err) } return c.cfgMorph.client.DepositEndlessNotary(depositAmount) @@ -168,32 +169,43 @@ var ( errNotaryDepositTimeout = errors.New("notary deposit tx has not appeared in the network") ) -func waitNotaryDeposit(ctx context.Context, c *cfg, tx util.Uint256) error { - for range notaryDepositRetriesAmount { - c.log.Debug(logs.ClientAttemptToWaitForNotaryDepositTransactionToGetPersisted) - select { - case <-ctx.Done(): - return ctx.Err() - default: - } +type waiterClient struct { + c *client.Client +} - ok, err := c.cfgMorph.client.TxHalt(tx) - if err == nil { - if ok { - c.log.Info(logs.ClientNotaryDepositTransactionWasSuccessfullyPersisted) - return nil - } +func (w *waiterClient) Context() context.Context { + return context.Background() +} - return errNotaryDepositFail - } +func (w *waiterClient) GetApplicationLog(hash util.Uint256, trig *trigger.Type) (*result.ApplicationLog, error) { + return w.c.GetApplicationLog(hash, trig) +} - err = c.cfgMorph.client.Wait(ctx, 1) - if err != nil { - return fmt.Errorf("could not wait for one block in chain: %w", err) - } +func (w *waiterClient) GetBlockCount() (uint32, error) { + return w.c.BlockCount() +} + +func (w *waiterClient) GetVersion() (*result.Version, error) { + return w.c.GetVersion() +} + +func waitNotaryDeposit(ctx context.Context, c *cfg, tx util.Uint256, vub uint32) error { + w, err := waiter.NewPollingBased(&waiterClient{c: c.cfgMorph.client}) + if err != nil { + return fmt.Errorf("could not create notary deposit waiter: %w", err) } - - return errNotaryDepositTimeout + res, err := w.WaitAny(ctx, vub, tx) + if err != nil { + if errors.Is(err, waiter.ErrTxNotAccepted) { + return errNotaryDepositTimeout + } + return fmt.Errorf("could not wait for notary deposit persists in chain: %w", err) + } + if res.Execution.VMState.HasFlag(vmstate.Halt) { + c.log.Info(logs.ClientNotaryDepositTransactionWasSuccessfullyPersisted) + return nil + } + return errNotaryDepositFail } func listenMorphNotifications(ctx context.Context, c *cfg) { diff --git a/cmd/frostfs-node/netmap.go b/cmd/frostfs-node/netmap.go index 0e0571760..6e2a7c44a 100644 --- a/cmd/frostfs-node/netmap.go +++ b/cmd/frostfs-node/netmap.go @@ -192,7 +192,7 @@ func addNewEpochNotificationHandlers(c *cfg) { if c.cfgMorph.notaryEnabled { addNewEpochAsyncNotificationHandler(c, func(_ event.Event) { - _, err := makeNotaryDeposit(c) + _, _, err := makeNotaryDeposit(c) if err != nil { c.log.Error(logs.FrostFSNodeCouldNotMakeNotaryDeposit, zap.String("error", err.Error()), diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 0e9d58f32..e4bac4930 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -142,7 +142,6 @@ const ( ClientNotaryRequestWithPreparedMainTXInvoked = "notary request with prepared main TX invoked" ClientNotaryRequestInvoked = "notary request invoked" ClientNotaryDepositTransactionWasSuccessfullyPersisted = "notary deposit transaction was successfully persisted" - ClientAttemptToWaitForNotaryDepositTransactionToGetPersisted = "attempt to wait for notary deposit transaction to get persisted" ClientNeoClientInvoke = "neo client invoke" ClientNativeGasTransferInvoke = "native gas transfer invoke" ClientBatchGasTransferInvoke = "batch gas transfer invoke" diff --git a/pkg/innerring/notary.go b/pkg/innerring/notary.go index e6f2b1de4..5cdbb971c 100644 --- a/pkg/innerring/notary.go +++ b/pkg/innerring/notary.go @@ -40,13 +40,14 @@ func (s *Server) depositMainNotary() (tx util.Uint256, err error) { ) } -func (s *Server) depositSideNotary() (tx util.Uint256, err error) { +func (s *Server) depositSideNotary() (util.Uint256, error) { depositAmount, err := client.CalculateNotaryDepositAmount(s.morphClient, gasMultiplier, gasDivisor) if err != nil { return util.Uint256{}, fmt.Errorf("could not calculate side notary deposit amount: %w", err) } - return s.morphClient.DepositEndlessNotary(depositAmount) + tx, _, err := s.morphClient.DepositEndlessNotary(depositAmount) + return tx, err } func (s *Server) notaryHandler(_ event.Event) { diff --git a/pkg/morph/client/client.go b/pkg/morph/client/client.go index df521f56b..933f1039f 100644 --- a/pkg/morph/client/client.go +++ b/pkg/morph/client/client.go @@ -19,6 +19,7 @@ import ( "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/encoding/fixedn" + "github.com/nspcc-dev/neo-go/pkg/neorpc/result" "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/gas" @@ -461,6 +462,28 @@ func (c *Client) TxHalt(h util.Uint256) (res bool, err error) { return len(aer.Executions) > 0 && aer.Executions[0].VMState.HasFlag(vmstate.Halt), nil } +func (c *Client) GetApplicationLog(hash util.Uint256, trig *trigger.Type) (*result.ApplicationLog, error) { + c.switchLock.RLock() + defer c.switchLock.RUnlock() + + if c.inactive { + return nil, ErrConnectionLost + } + + return c.client.GetApplicationLog(hash, trig) +} + +func (c *Client) GetVersion() (*result.Version, error) { + c.switchLock.RLock() + defer c.switchLock.RUnlock() + + if c.inactive { + return nil, ErrConnectionLost + } + + return c.client.GetVersion() +} + // TxHeight returns true if transaction has been successfully executed and persisted. func (c *Client) TxHeight(h util.Uint256) (res uint32, err error) { c.switchLock.RLock() diff --git a/pkg/morph/client/notary.go b/pkg/morph/client/notary.go index 616b3b5c3..2a500b31b 100644 --- a/pkg/morph/client/notary.go +++ b/pkg/morph/client/notary.go @@ -140,7 +140,7 @@ func (c *Client) ProbeNotary() (res bool) { // use this function. // // This function must be invoked with notary enabled otherwise it throws panic. -func (c *Client) DepositNotary(amount fixedn.Fixed8, delta uint32) (res util.Uint256, err error) { +func (c *Client) DepositNotary(amount fixedn.Fixed8, delta uint32) (util.Uint256, error) { c.switchLock.RLock() defer c.switchLock.RUnlock() @@ -163,7 +163,8 @@ func (c *Client) DepositNotary(amount fixedn.Fixed8, delta uint32) (res util.Uin } till := max(int64(bc+delta), currentTill) - return c.depositNotary(amount, till) + res, _, err := c.depositNotary(amount, till) + return res, err } // DepositEndlessNotary calls notary deposit method. Unlike `DepositNotary`, @@ -171,12 +172,12 @@ func (c *Client) DepositNotary(amount fixedn.Fixed8, delta uint32) (res util.Uin // This allows to avoid ValidAfterDeposit failures. // // This function must be invoked with notary enabled otherwise it throws panic. -func (c *Client) DepositEndlessNotary(amount fixedn.Fixed8) (res util.Uint256, err error) { +func (c *Client) DepositEndlessNotary(amount fixedn.Fixed8) (util.Uint256, uint32, error) { c.switchLock.RLock() defer c.switchLock.RUnlock() if c.inactive { - return util.Uint256{}, ErrConnectionLost + return util.Uint256{}, 0, ErrConnectionLost } if c.notary == nil { @@ -187,7 +188,7 @@ func (c *Client) DepositEndlessNotary(amount fixedn.Fixed8) (res util.Uint256, e return c.depositNotary(amount, math.MaxUint32) } -func (c *Client) depositNotary(amount fixedn.Fixed8, till int64) (res util.Uint256, err error) { +func (c *Client) depositNotary(amount fixedn.Fixed8, till int64) (util.Uint256, uint32, error) { txHash, vub, err := c.gasToken.Transfer( c.accAddr, c.notary.notary, @@ -195,7 +196,7 @@ func (c *Client) depositNotary(amount fixedn.Fixed8, till int64) (res util.Uint2 []any{c.acc.PrivateKey().GetScriptHash(), till}) if err != nil { if !errors.Is(err, neorpc.ErrAlreadyExists) { - return util.Uint256{}, fmt.Errorf("can't make notary deposit: %w", err) + return util.Uint256{}, 0, fmt.Errorf("can't make notary deposit: %w", err) } // Transaction is already in mempool waiting to be processed. @@ -205,7 +206,7 @@ func (c *Client) depositNotary(amount fixedn.Fixed8, till int64) (res util.Uint2 zap.Int64("expire_at", till), zap.Uint32("vub", vub), zap.Error(err)) - return util.Uint256{}, nil + return util.Uint256{}, 0, nil } c.logger.Info(logs.ClientNotaryDepositInvoke, @@ -214,7 +215,7 @@ func (c *Client) depositNotary(amount fixedn.Fixed8, till int64) (res util.Uint2 zap.Uint32("vub", vub), zap.Stringer("tx_hash", txHash.Reverse())) - return txHash, nil + return txHash, vub, nil } // GetNotaryDeposit returns deposit of client's account in notary contract.