From 722b844aa284f037dc910c5365921384e09314e4 Mon Sep 17 00:00:00 2001 From: Pavel Karpy Date: Wed, 25 Aug 2021 13:49:59 +0300 Subject: [PATCH] [#770] node: Add notary deposit timer Storage Node needs to have notary deposit for successful notary request sending. Add notary deposit on startup(and wait for its acceptance). Add notary deposit timer, its config in `morph` section and env vars for its tuning. Signed-off-by: Pavel Karpy --- cmd/neofs-node/config.go | 5 +++ cmd/neofs-node/main.go | 1 + cmd/neofs-node/morph.go | 84 +++++++++++++++++++++++++++++++++++++++- cmd/neofs-node/timers.go | 16 ++++++++ 4 files changed, 104 insertions(+), 2 deletions(-) diff --git a/cmd/neofs-node/config.go b/cmd/neofs-node/config.go index 90cc3002c..9832d7cdd 100644 --- a/cmd/neofs-node/config.go +++ b/cmd/neofs-node/config.go @@ -8,6 +8,7 @@ import ( "time" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" neogoutil "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neofs-api-go/pkg" apiclient "github.com/nspcc-dev/neofs-api-go/pkg/client" @@ -127,6 +128,10 @@ type cfgGRPC struct { type cfgMorph struct { client *client.Client + notaryEnabled bool + notaryDepositAmount fixedn.Fixed8 + notaryDepositDuration uint32 + disableCache bool blockTimers []*timer.BlockTimer // all combined timers diff --git a/cmd/neofs-node/main.go b/cmd/neofs-node/main.go index 4be7b62c0..2a44288ee 100644 --- a/cmd/neofs-node/main.go +++ b/cmd/neofs-node/main.go @@ -90,6 +90,7 @@ func initApp(c *cfg) { func bootUp(c *cfg) { serveGRPC(c) bootstrapNode(c) + makeAndWaitNotaryDeposit(c) startWorkers(c) startBlockTimers(c) } diff --git a/cmd/neofs-node/morph.go b/cmd/neofs-node/morph.go index ded1efa29..89096a238 100644 --- a/cmd/neofs-node/morph.go +++ b/cmd/neofs-node/morph.go @@ -2,11 +2,13 @@ package main import ( "context" + "errors" "fmt" "time" "github.com/nspcc-dev/neo-go/pkg/core/block" "github.com/nspcc-dev/neo-go/pkg/util" + contractsconfig "github.com/nspcc-dev/neofs-node/cmd/neofs-node/config/contracts" mainchainconfig "github.com/nspcc-dev/neofs-node/cmd/neofs-node/config/mainchain" morphconfig "github.com/nspcc-dev/neofs-node/cmd/neofs-node/config/morph" "github.com/nspcc-dev/neofs-node/pkg/core/netmap" @@ -19,7 +21,18 @@ import ( "go.uber.org/zap" ) -const newEpochNotification = "NewEpoch" +const ( + newEpochNotification = "NewEpoch" + + // notaryDepositExtraBlocks is amount of extra blocks to overlap two deposits, + // we do that to make sure that there won't be any blocks without deposited + // assets in notary contract; make sure it is bigger than any extra rounding + // value in notary client. + notaryDepositExtraBlocks = 300 + + // amount of tries(blocks) before notary deposit timeout. + notaryDepositRetriesAmount +) func initMorphComponents(c *cfg) { var err error @@ -62,8 +75,24 @@ func initMorphComponents(c *cfg) { fn(morphconfig.RPCEndpoint(c.appCfg), morphconfig.DialTimeout(c.appCfg), func(cli *client.Client) { c.cfgMorph.client = cli + c.cfgMorph.notaryEnabled = cli.ProbeNotary() + + if c.cfgMorph.notaryEnabled { + err = c.cfgMorph.client.EnableNotarySupport( + client.WithProxyContract( + contractsconfig.Proxy(c.appCfg), + ), + ) + fatalOnErr(err) + + c.cfgMorph.notaryDepositAmount = morphconfig.Notary(c.appCfg).Amount() + c.cfgMorph.notaryDepositDuration = morphconfig.Notary(c.appCfg).Duration() + + newDepositTimer(c) + } + c.log.Debug("notary support", - zap.Bool("sidechain_enabled", cli.ProbeNotary()), + zap.Bool("sidechain_enabled", c.cfgMorph.notaryEnabled), ) }) @@ -85,6 +114,57 @@ func initMorphComponents(c *cfg) { c.cfgNetmap.wrapper = wrap } +func makeAndWaitNotaryDeposit(c *cfg) { + // skip notary deposit in non-notary environments + if !c.cfgMorph.notaryEnabled { + return + } + + tx, err := makeNotaryDeposit(c) + fatalOnErr(err) + + err = waitNotaryDeposit(c, tx) + fatalOnErr(err) +} + +func makeNotaryDeposit(c *cfg) (util.Uint256, error) { + return c.cfgMorph.client.DepositNotary( + c.cfgMorph.notaryDepositAmount, + c.cfgMorph.notaryDepositDuration+notaryDepositExtraBlocks, + ) +} + +var ( + errNotaryDepositFail = errors.New("notary deposit tx has faulted") + errNotaryDepositTimeout = errors.New("notary deposit tx has not appeared in the network") +) + +func waitNotaryDeposit(c *cfg, tx util.Uint256) error { + for i := 0; i < notaryDepositRetriesAmount; i++ { + select { + case <-c.ctx.Done(): + return nil + default: + } + + ok, err := c.cfgMorph.client.TxHalt(tx) + if err == nil { + if ok { + return nil + } + + return errNotaryDepositFail + } + + err = c.cfgMorph.client.Wait(c.ctx, 1) + if err != nil { + return fmt.Errorf("could not wait for one block in chain: %w", err) + } + } + + return errNotaryDepositTimeout +} + func listenMorphNotifications(c *cfg) { var ( err error diff --git a/cmd/neofs-node/timers.go b/cmd/neofs-node/timers.go index 692337aa6..fd690bf0a 100644 --- a/cmd/neofs-node/timers.go +++ b/cmd/neofs-node/timers.go @@ -5,6 +5,7 @@ import ( wrapNetmap "github.com/nspcc-dev/neofs-node/pkg/morph/client/netmap/wrapper" "github.com/nspcc-dev/neofs-node/pkg/morph/timer" + "go.uber.org/zap" ) type ( @@ -83,3 +84,18 @@ func newEigenTrustIterTimer(c *cfg, it *EigenTrustDuration, handler timer.BlockT c.cfgMorph.blockTimers = append(c.cfgMorph.blockTimers, c.cfgMorph.eigenTrustTimer) } + +func newDepositTimer(c *cfg) { + c.cfgMorph.blockTimers = append(c.cfgMorph.blockTimers, + timer.NewBlockTimer( + timer.StaticBlockMeter(c.cfgMorph.notaryDepositDuration), + func() { + _, err := makeNotaryDeposit(c) + if err != nil { + c.log.Warn("can't deposit notary contract", + zap.String("error", err.Error())) + } + }, + ), + ) +}