[#1467] node: Break notary deposit wait after VUB
All checks were successful
Tests and linters / Run gofumpt (pull_request) Successful in 1m24s
DCO action / DCO (pull_request) Successful in 1m35s
Vulncheck / Vulncheck (pull_request) Successful in 2m17s
Pre-commit hooks / Pre-commit (pull_request) Successful in 2m28s
Build / Build Components (pull_request) Successful in 2m36s
Tests and linters / gopls check (pull_request) Successful in 2m46s
Tests and linters / Staticcheck (pull_request) Successful in 3m3s
Tests and linters / Lint (pull_request) Successful in 3m44s
Tests and linters / Tests (pull_request) Successful in 4m27s
Tests and linters / Tests with -race (pull_request) Successful in 6m12s

Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
This commit is contained in:
Dmitrii Stepanov 2024-10-31 13:13:03 +03:00
parent 5bcf81d1cc
commit 1fd704a376
Signed by: dstepanov-yadro
GPG key ID: 237AF1A763293BC0
6 changed files with 77 additions and 41 deletions

View file

@ -17,15 +17,16 @@ import (
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/rand" "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/block"
"github.com/nspcc-dev/neo-go/pkg/core/state" "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/util"
"github.com/nspcc-dev/neo-go/pkg/vm/vmstate"
"go.uber.org/zap" "go.uber.org/zap"
) )
const ( const (
newEpochNotification = "NewEpoch" newEpochNotification = "NewEpoch"
// amount of tries(blocks) before notary deposit timeout.
notaryDepositRetriesAmount = 300
) )
func (c *cfg) initMorphComponents(ctx context.Context) { func (c *cfg) initMorphComponents(ctx context.Context) {
@ -128,7 +129,7 @@ func makeAndWaitNotaryDeposit(ctx context.Context, c *cfg) {
return return
} }
tx, err := makeNotaryDeposit(c) tx, vub, err := makeNotaryDeposit(c)
fatalOnErr(err) fatalOnErr(err)
if tx.Equals(util.Uint256{}) { if tx.Equals(util.Uint256{}) {
@ -139,11 +140,11 @@ func makeAndWaitNotaryDeposit(ctx context.Context, c *cfg) {
return return
} }
err = waitNotaryDeposit(ctx, c, tx) err = waitNotaryDeposit(ctx, c, tx, vub)
fatalOnErr(err) fatalOnErr(err)
} }
func makeNotaryDeposit(c *cfg) (util.Uint256, error) { func makeNotaryDeposit(c *cfg) (util.Uint256, uint32, error) {
const ( const (
// gasMultiplier defines how many times more the notary // gasMultiplier defines how many times more the notary
// balance must be compared to the GAS balance of the node: // 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) depositAmount, err := client.CalculateNotaryDepositAmount(c.cfgMorph.client, gasMultiplier, gasDivisor)
if err != nil { 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) return c.cfgMorph.client.DepositEndlessNotary(depositAmount)
@ -168,32 +169,43 @@ var (
errNotaryDepositTimeout = errors.New("notary deposit tx has not appeared in the network") errNotaryDepositTimeout = errors.New("notary deposit tx has not appeared in the network")
) )
func waitNotaryDeposit(ctx context.Context, c *cfg, tx util.Uint256) error { type waiterClient struct {
for range notaryDepositRetriesAmount { c *client.Client
c.log.Debug(logs.ClientAttemptToWaitForNotaryDepositTransactionToGetPersisted) }
select {
case <-ctx.Done():
return ctx.Err()
default:
}
ok, err := c.cfgMorph.client.TxHalt(tx) func (w *waiterClient) Context() context.Context {
if err == nil { return context.Background()
if ok { }
c.log.Info(logs.ClientNotaryDepositTransactionWasSuccessfullyPersisted)
return nil
}
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) func (w *waiterClient) GetBlockCount() (uint32, error) {
if err != nil { return w.c.BlockCount()
return fmt.Errorf("could not wait for one block in chain: %w", err) }
}
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)
} }
res, err := w.WaitAny(ctx, vub, tx)
return errNotaryDepositTimeout 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 success := res.Execution.VMState.HasFlag(vmstate.Halt); success {
c.log.Info(logs.ClientNotaryDepositTransactionWasSuccessfullyPersisted)
return nil
}
return errNotaryDepositFail
} }
func listenMorphNotifications(ctx context.Context, c *cfg) { func listenMorphNotifications(ctx context.Context, c *cfg) {

View file

@ -192,7 +192,7 @@ func addNewEpochNotificationHandlers(c *cfg) {
if c.cfgMorph.notaryEnabled { if c.cfgMorph.notaryEnabled {
addNewEpochAsyncNotificationHandler(c, func(_ event.Event) { addNewEpochAsyncNotificationHandler(c, func(_ event.Event) {
_, err := makeNotaryDeposit(c) _, _, err := makeNotaryDeposit(c)
if err != nil { if err != nil {
c.log.Error(logs.FrostFSNodeCouldNotMakeNotaryDeposit, c.log.Error(logs.FrostFSNodeCouldNotMakeNotaryDeposit,
zap.String("error", err.Error()), zap.String("error", err.Error()),

View file

@ -142,7 +142,6 @@ const (
ClientNotaryRequestWithPreparedMainTXInvoked = "notary request with prepared main TX invoked" ClientNotaryRequestWithPreparedMainTXInvoked = "notary request with prepared main TX invoked"
ClientNotaryRequestInvoked = "notary request invoked" ClientNotaryRequestInvoked = "notary request invoked"
ClientNotaryDepositTransactionWasSuccessfullyPersisted = "notary deposit transaction was successfully persisted" ClientNotaryDepositTransactionWasSuccessfullyPersisted = "notary deposit transaction was successfully persisted"
ClientAttemptToWaitForNotaryDepositTransactionToGetPersisted = "attempt to wait for notary deposit transaction to get persisted"
ClientNeoClientInvoke = "neo client invoke" ClientNeoClientInvoke = "neo client invoke"
ClientNativeGasTransferInvoke = "native gas transfer invoke" ClientNativeGasTransferInvoke = "native gas transfer invoke"
ClientBatchGasTransferInvoke = "batch gas transfer invoke" ClientBatchGasTransferInvoke = "batch gas transfer invoke"

View file

@ -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) depositAmount, err := client.CalculateNotaryDepositAmount(s.morphClient, gasMultiplier, gasDivisor)
if err != nil { if err != nil {
return util.Uint256{}, fmt.Errorf("could not calculate side notary deposit amount: %w", err) 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) { func (s *Server) notaryHandler(_ event.Event) {

View file

@ -19,6 +19,7 @@ import (
"github.com/nspcc-dev/neo-go/pkg/core/transaction" "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/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" "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"
"github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor"
"github.com/nspcc-dev/neo-go/pkg/rpcclient/gas" "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 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. // TxHeight returns true if transaction has been successfully executed and persisted.
func (c *Client) TxHeight(h util.Uint256) (res uint32, err error) { func (c *Client) TxHeight(h util.Uint256) (res uint32, err error) {
c.switchLock.RLock() c.switchLock.RLock()

View file

@ -140,7 +140,7 @@ func (c *Client) ProbeNotary() (res bool) {
// use this function. // use this function.
// //
// This function must be invoked with notary enabled otherwise it throws panic. // 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() c.switchLock.RLock()
defer c.switchLock.RUnlock() 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) 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`, // 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 allows to avoid ValidAfterDeposit failures.
// //
// This function must be invoked with notary enabled otherwise it throws panic. // 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() c.switchLock.RLock()
defer c.switchLock.RUnlock() defer c.switchLock.RUnlock()
if c.inactive { if c.inactive {
return util.Uint256{}, ErrConnectionLost return util.Uint256{}, 0, ErrConnectionLost
} }
if c.notary == nil { 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) 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( txHash, vub, err := c.gasToken.Transfer(
c.accAddr, c.accAddr,
c.notary.notary, 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}) []any{c.acc.PrivateKey().GetScriptHash(), till})
if err != nil { if err != nil {
if !errors.Is(err, neorpc.ErrAlreadyExists) { 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. // 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.Int64("expire_at", till),
zap.Uint32("vub", vub), zap.Uint32("vub", vub),
zap.Error(err)) zap.Error(err))
return util.Uint256{}, nil return util.Uint256{}, 0, nil
} }
c.logger.Info(logs.ClientNotaryDepositInvoke, 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.Uint32("vub", vub),
zap.Stringer("tx_hash", txHash.Reverse())) zap.Stringer("tx_hash", txHash.Reverse()))
return txHash, nil return txHash, vub, nil
} }
// GetNotaryDeposit returns deposit of client's account in notary contract. // GetNotaryDeposit returns deposit of client's account in notary contract.