frostfs-node/pkg/innerring/notary.go
Alex Vanin a437ffc3ed [#910] innerring: Make notary deposit on notification instead of timer
Timer is not suitable for notary deposits because it can never fire
in case of desynchronization or external epoch changes. Notary deposits
must be handled on new epoch event.

Signed-off-by: Alex Vanin <alexey@nspcc.ru>
2021-11-02 11:28:02 +03:00

127 lines
2.9 KiB
Go

package innerring
import (
"context"
"fmt"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neofs-node/pkg/morph/client"
"github.com/nspcc-dev/neofs-node/pkg/morph/event"
"github.com/spf13/viper"
"go.uber.org/zap"
)
type (
notaryConfig struct {
disabled bool // true if notary disabled on chain
}
)
const (
// gasMultiplier defines how many times more the notary
// balance must be compared to the GAS balance of the IR:
// notaryBalance = GASBalance * gasMultiplier
gasMultiplier = 3
// gasDivisor defines what part of GAS balance (1/gasDivisor)
// should be transferred to the notary service
gasDivisor = 2
)
func (s *Server) depositMainNotary() (tx util.Uint256, err error) {
depositAmount, err := client.CalculateNotaryDepositAmount(s.mainnetClient, gasMultiplier, gasDivisor)
if err != nil {
return util.Uint256{}, fmt.Errorf("could not calculate main notary deposit amount: %w", err)
}
return s.mainnetClient.DepositNotary(
depositAmount,
uint32(s.epochDuration.Load())+notaryExtraBlocks,
)
}
func (s *Server) depositSideNotary() (tx util.Uint256, err 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.DepositNotary(
depositAmount,
uint32(s.epochDuration.Load())+notaryExtraBlocks,
)
}
func (s *Server) notaryHandler(_ event.Event) {
if !s.mainNotaryConfig.disabled {
_, err := s.depositMainNotary()
if err != nil {
s.log.Error("can't make notary deposit in main chain", zap.Error(err))
}
}
if !s.sideNotaryConfig.disabled {
_, err := s.depositSideNotary()
if err != nil {
s.log.Error("can't make notary deposit in side chain", zap.Error(err))
}
}
}
func (s *Server) awaitMainNotaryDeposit(ctx context.Context, tx util.Uint256) error {
return awaitNotaryDepositInClient(ctx, s.mainnetClient, tx)
}
func (s *Server) awaitSideNotaryDeposit(ctx context.Context, tx util.Uint256) error {
return awaitNotaryDepositInClient(ctx, s.morphClient, tx)
}
func (s *Server) initNotary(ctx context.Context, deposit depositor, await awaiter, msg string) error {
tx, err := deposit()
if err != nil {
return err
}
s.log.Info(msg)
return await(ctx, tx)
}
func awaitNotaryDepositInClient(ctx context.Context, cli *client.Client, txHash util.Uint256) error {
for i := 0; i < notaryDepositTimeout; i++ {
select {
case <-ctx.Done():
return nil
default:
}
ok, err := cli.TxHalt(txHash)
if err == nil {
if ok {
return nil
}
return errDepositFail
}
_ = cli.Wait(ctx, 1)
}
return errDepositTimeout
}
func parseNotaryConfigs(cfg *viper.Viper, withSideNotary, withMainNotary bool) (main, side *notaryConfig) {
main = new(notaryConfig)
side = new(notaryConfig)
if !withSideNotary {
main.disabled = true
side.disabled = true
return
}
main.disabled = !withMainNotary
return
}