Remove container estimation code #1475
13 changed files with 9 additions and 499 deletions
|
@ -17,8 +17,6 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
InnerringNonalphabetModeDoNotStopContainerEstimations = "non-alphabet mode, do not stop container estimations"
|
|
||||||
InnerringCantStopEpochEstimation = "can't stop epoch estimation"
|
|
||||||
InnerringCantMakeNotaryDepositInMainChain = "can't make notary deposit in main chain"
|
InnerringCantMakeNotaryDepositInMainChain = "can't make notary deposit in main chain"
|
||||||
InnerringCantMakeNotaryDepositInSideChain = "can't make notary deposit in side chain"
|
InnerringCantMakeNotaryDepositInSideChain = "can't make notary deposit in side chain"
|
||||||
InnerringNotaryDepositHasAlreadyBeenMade = "notary deposit has already been made"
|
InnerringNotaryDepositHasAlreadyBeenMade = "notary deposit has already been made"
|
||||||
|
@ -343,7 +341,6 @@ const (
|
||||||
NetmapCantGetTransactionHeight = "can't get transaction height"
|
NetmapCantGetTransactionHeight = "can't get transaction height"
|
||||||
NetmapCantResetEpochTimer = "can't reset epoch timer"
|
NetmapCantResetEpochTimer = "can't reset epoch timer"
|
||||||
NetmapCantGetNetmapSnapshotToPerformCleanup = "can't get netmap snapshot to perform cleanup"
|
NetmapCantGetNetmapSnapshotToPerformCleanup = "can't get netmap snapshot to perform cleanup"
|
||||||
NetmapCantStartContainerSizeEstimation = "can't start container size estimation"
|
|
||||||
NetmapNonAlphabetModeIgnoreNewEpochTick = "non alphabet mode, ignore new epoch tick"
|
NetmapNonAlphabetModeIgnoreNewEpochTick = "non alphabet mode, ignore new epoch tick"
|
||||||
NetmapNextEpoch = "next epoch"
|
NetmapNextEpoch = "next epoch"
|
||||||
NetmapCantInvokeNetmapNewEpoch = "can't invoke netmap.NewEpoch"
|
NetmapCantInvokeNetmapNewEpoch = "can't invoke netmap.NewEpoch"
|
||||||
|
|
|
@ -3,14 +3,10 @@ package innerring
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/alphabet"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/alphabet"
|
||||||
timerEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/timers"
|
timerEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/timers"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/timer"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/timer"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
"go.uber.org/zap"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
@ -19,28 +15,12 @@ type (
|
||||||
EpochDuration() uint64
|
EpochDuration() uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
alphaState interface {
|
|
||||||
IsAlphabet() bool
|
|
||||||
}
|
|
||||||
|
|
||||||
newEpochHandler func()
|
newEpochHandler func()
|
||||||
|
|
||||||
containerEstimationStopper interface {
|
|
||||||
StopEstimation(p container.StopEstimationPrm) error
|
|
||||||
}
|
|
||||||
|
|
||||||
epochTimerArgs struct {
|
epochTimerArgs struct {
|
||||||
l *logger.Logger
|
|
||||||
|
|
||||||
alphabetState alphaState
|
|
||||||
|
|
||||||
newEpochHandlers []newEpochHandler
|
newEpochHandlers []newEpochHandler
|
||||||
|
|
||||||
cnrWrapper containerEstimationStopper // to invoke stop container estimation
|
epoch epochState // to specify which epoch to stop, and epoch duration
|
||||||
epoch epochState // to specify which epoch to stop, and epoch duration
|
|
||||||
|
|
||||||
stopEstimationDMul uint32 // X: X/Y of epoch in blocks
|
|
||||||
stopEstimationDDiv uint32 // Y: X/Y of epoch in blocks
|
|
||||||
}
|
}
|
||||||
|
|
||||||
emitTimerArgs struct {
|
emitTimerArgs struct {
|
||||||
|
@ -74,7 +54,7 @@ func (s *Server) tickTimers(h uint32) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func newEpochTimer(args *epochTimerArgs) *timer.BlockTimer {
|
func newEpochTimer(args *epochTimerArgs) *timer.BlockTimer {
|
||||||
epochTimer := timer.NewBlockTimer(
|
return timer.NewBlockTimer(
|
||||||
func() (uint32, error) {
|
func() (uint32, error) {
|
||||||
return uint32(args.epoch.EpochDuration()), nil
|
return uint32(args.epoch.EpochDuration()), nil
|
||||||
},
|
},
|
||||||
|
@ -84,35 +64,6 @@ func newEpochTimer(args *epochTimerArgs) *timer.BlockTimer {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
// sub-timer for epoch timer to tick stop container estimation events at
|
|
||||||
// some block in epoch
|
|
||||||
epochTimer.OnDelta(
|
|
||||||
args.stopEstimationDMul,
|
|
||||||
args.stopEstimationDDiv,
|
|
||||||
func() {
|
|
||||||
if !args.alphabetState.IsAlphabet() {
|
|
||||||
args.l.Debug(logs.InnerringNonalphabetModeDoNotStopContainerEstimations)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
epochN := args.epoch.EpochCounter()
|
|
||||||
if epochN == 0 { // estimates are invalid in genesis epoch
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
prm := container.StopEstimationPrm{}
|
|
||||||
prm.SetEpoch(epochN - 1)
|
|
||||||
|
|
||||||
err := args.cnrWrapper.StopEstimation(prm)
|
|
||||||
if err != nil {
|
|
||||||
args.l.Warn(logs.InnerringCantStopEpochEstimation,
|
|
||||||
zap.Uint64("epoch", epochN),
|
|
||||||
zap.String("error", err.Error()))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return epochTimer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newEmissionTimer(args *emitTimerArgs) *timer.BlockTimer {
|
func newEmissionTimer(args *emitTimerArgs) *timer.BlockTimer {
|
||||||
|
|
|
@ -3,29 +3,20 @@ package innerring
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test"
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestEpochTimer(t *testing.T) {
|
func TestEpochTimer(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
alphaState := &testAlphabetState{isAlphabet: true}
|
|
||||||
neh := &testNewEpochHandler{}
|
neh := &testNewEpochHandler{}
|
||||||
cnrStopper := &testContainerEstStopper{}
|
|
||||||
epochState := &testEpochState{
|
epochState := &testEpochState{
|
||||||
counter: 99,
|
counter: 99,
|
||||||
duration: 10,
|
duration: 10,
|
||||||
}
|
}
|
||||||
|
|
||||||
args := &epochTimerArgs{
|
args := &epochTimerArgs{
|
||||||
l: test.NewLogger(t),
|
newEpochHandlers: []newEpochHandler{neh.Handle},
|
||||||
alphabetState: alphaState,
|
epoch: epochState,
|
||||||
newEpochHandlers: []newEpochHandler{neh.Handle},
|
|
||||||
cnrWrapper: cnrStopper,
|
|
||||||
epoch: epochState,
|
|
||||||
stopEstimationDMul: 2,
|
|
||||||
stopEstimationDDiv: 10,
|
|
||||||
}
|
}
|
||||||
et := newEpochTimer(args)
|
et := newEpochTimer(args)
|
||||||
err := et.Reset()
|
err := et.Reset()
|
||||||
|
@ -33,63 +24,43 @@ func TestEpochTimer(t *testing.T) {
|
||||||
|
|
||||||
et.Tick(100)
|
et.Tick(100)
|
||||||
require.Equal(t, 0, neh.called, "invalid new epoch handler calls")
|
require.Equal(t, 0, neh.called, "invalid new epoch handler calls")
|
||||||
require.Equal(t, 0, cnrStopper.called, "invalid container stop handler calls")
|
|
||||||
|
|
||||||
et.Tick(101)
|
et.Tick(101)
|
||||||
require.Equal(t, 0, neh.called, "invalid new epoch handler calls")
|
require.Equal(t, 0, neh.called, "invalid new epoch handler calls")
|
||||||
require.Equal(t, 1, cnrStopper.called, "invalid container stop handler calls")
|
|
||||||
|
|
||||||
et.Tick(102)
|
et.Tick(102)
|
||||||
require.Equal(t, 0, neh.called, "invalid new epoch handler calls")
|
require.Equal(t, 0, neh.called, "invalid new epoch handler calls")
|
||||||
require.Equal(t, 1, cnrStopper.called, "invalid container stop handler calls")
|
|
||||||
|
|
||||||
et.Tick(103)
|
et.Tick(103)
|
||||||
require.Equal(t, 0, neh.called, "invalid new epoch handler calls")
|
require.Equal(t, 0, neh.called, "invalid new epoch handler calls")
|
||||||
require.Equal(t, 1, cnrStopper.called, "invalid container stop handler calls")
|
|
||||||
|
|
||||||
var h uint32
|
var h uint32
|
||||||
for h = 104; h < 109; h++ {
|
for h = 104; h < 109; h++ {
|
||||||
et.Tick(h)
|
et.Tick(h)
|
||||||
require.Equal(t, 0, neh.called, "invalid new epoch handler calls")
|
require.Equal(t, 0, neh.called, "invalid new epoch handler calls")
|
||||||
require.Equal(t, 1, cnrStopper.called, "invalid container stop handler calls")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
et.Tick(109)
|
et.Tick(109)
|
||||||
require.Equal(t, 1, neh.called, "invalid new epoch handler calls")
|
require.Equal(t, 1, neh.called, "invalid new epoch handler calls")
|
||||||
require.Equal(t, 1, cnrStopper.called, "invalid container stop handler calls")
|
|
||||||
|
|
||||||
et.Tick(110)
|
et.Tick(110)
|
||||||
require.Equal(t, 1, neh.called, "invalid new epoch handler calls")
|
require.Equal(t, 1, neh.called, "invalid new epoch handler calls")
|
||||||
require.Equal(t, 1, cnrStopper.called, "invalid container stop handler calls")
|
|
||||||
|
|
||||||
et.Tick(111)
|
et.Tick(111)
|
||||||
require.Equal(t, 1, neh.called, "invalid new epoch handler calls")
|
require.Equal(t, 1, neh.called, "invalid new epoch handler calls")
|
||||||
require.Equal(t, 2, cnrStopper.called, "invalid container stop handler calls")
|
|
||||||
|
|
||||||
et.Tick(112)
|
et.Tick(112)
|
||||||
require.Equal(t, 1, neh.called, "invalid new epoch handler calls")
|
require.Equal(t, 1, neh.called, "invalid new epoch handler calls")
|
||||||
require.Equal(t, 2, cnrStopper.called, "invalid container stop handler calls")
|
|
||||||
|
|
||||||
et.Tick(113)
|
et.Tick(113)
|
||||||
require.Equal(t, 1, neh.called, "invalid new epoch handler calls")
|
require.Equal(t, 1, neh.called, "invalid new epoch handler calls")
|
||||||
require.Equal(t, 2, cnrStopper.called, "invalid container stop handler calls")
|
|
||||||
|
|
||||||
for h = 114; h < 119; h++ {
|
for h = 114; h < 119; h++ {
|
||||||
et.Tick(h)
|
et.Tick(h)
|
||||||
require.Equal(t, 1, neh.called, "invalid new epoch handler calls")
|
require.Equal(t, 1, neh.called, "invalid new epoch handler calls")
|
||||||
require.Equal(t, 2, cnrStopper.called, "invalid container stop handler calls")
|
|
||||||
}
|
}
|
||||||
et.Tick(120)
|
et.Tick(120)
|
||||||
require.Equal(t, 2, neh.called, "invalid new epoch handler calls")
|
require.Equal(t, 2, neh.called, "invalid new epoch handler calls")
|
||||||
require.Equal(t, 2, cnrStopper.called, "invalid container stop handler calls")
|
|
||||||
}
|
|
||||||
|
|
||||||
type testAlphabetState struct {
|
|
||||||
isAlphabet bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *testAlphabetState) IsAlphabet() bool {
|
|
||||||
return s.isAlphabet
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type testNewEpochHandler struct {
|
type testNewEpochHandler struct {
|
||||||
|
@ -100,15 +71,6 @@ func (h *testNewEpochHandler) Handle() {
|
||||||
h.called++
|
h.called++
|
||||||
}
|
}
|
||||||
|
|
||||||
type testContainerEstStopper struct {
|
|
||||||
called int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *testContainerEstStopper) StopEstimation(_ container.StopEstimationPrm) error {
|
|
||||||
s.called++
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type testEpochState struct {
|
type testEpochState struct {
|
||||||
counter uint64
|
counter uint64
|
||||||
duration uint64
|
duration uint64
|
||||||
|
|
|
@ -36,7 +36,6 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Server) initNetmapProcessor(cfg *viper.Viper,
|
func (s *Server) initNetmapProcessor(cfg *viper.Viper,
|
||||||
cnrClient *container.Client,
|
|
||||||
alphaSync event.Handler,
|
alphaSync event.Handler,
|
||||||
) error {
|
) error {
|
||||||
locodeValidator, err := s.newLocodeValidator(cfg)
|
locodeValidator, err := s.newLocodeValidator(cfg)
|
||||||
|
@ -59,7 +58,6 @@ func (s *Server) initNetmapProcessor(cfg *viper.Viper,
|
||||||
AlphabetState: s,
|
AlphabetState: s,
|
||||||
CleanupEnabled: cfg.GetBool("netmap_cleaner.enabled"),
|
CleanupEnabled: cfg.GetBool("netmap_cleaner.enabled"),
|
||||||
CleanupThreshold: cfg.GetUint64("netmap_cleaner.threshold"),
|
CleanupThreshold: cfg.GetUint64("netmap_cleaner.threshold"),
|
||||||
ContainerWrapper: cnrClient,
|
|
||||||
NotaryDepositHandler: s.onlyAlphabetEventHandler(
|
NotaryDepositHandler: s.onlyAlphabetEventHandler(
|
||||||
s.notaryHandler,
|
s.notaryHandler,
|
||||||
),
|
),
|
||||||
|
@ -198,15 +196,10 @@ func (s *Server) createIRFetcher() irFetcher {
|
||||||
return irf
|
return irf
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) initTimers(cfg *viper.Viper, morphClients *serverMorphClients) {
|
func (s *Server) initTimers(cfg *viper.Viper) {
|
||||||
s.epochTimer = newEpochTimer(&epochTimerArgs{
|
s.epochTimer = newEpochTimer(&epochTimerArgs{
|
||||||
l: s.log,
|
newEpochHandlers: s.newEpochTickHandlers(),
|
||||||
alphabetState: s,
|
epoch: s,
|
||||||
newEpochHandlers: s.newEpochTickHandlers(),
|
|
||||||
cnrWrapper: morphClients.CnrClient,
|
|
||||||
epoch: s,
|
|
||||||
stopEstimationDMul: cfg.GetUint32("timers.stop_estimation.mul"),
|
|
||||||
stopEstimationDDiv: cfg.GetUint32("timers.stop_estimation.div"),
|
|
||||||
})
|
})
|
||||||
|
|
||||||
s.addBlockTimer(s.epochTimer)
|
s.addBlockTimer(s.epochTimer)
|
||||||
|
@ -425,7 +418,7 @@ func (s *Server) initProcessors(cfg *viper.Viper, morphClients *serverMorphClien
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = s.initNetmapProcessor(cfg, morphClients.CnrClient, alphaSync)
|
err = s.initNetmapProcessor(cfg, alphaSync)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -405,7 +405,7 @@ func New(ctx context.Context, log *logger.Logger, cfg *viper.Viper, errChan chan
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
server.initTimers(cfg, morphClients)
|
server.initTimers(cfg)
|
||||||
|
|
||||||
err = server.initGRPCServer(cfg, log, audit)
|
err = server.initGRPCServer(cfg, log, audit)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -9,7 +9,6 @@ import (
|
||||||
netmapContract "git.frostfs.info/TrueCloudLab/frostfs-contract/netmap"
|
netmapContract "git.frostfs.info/TrueCloudLab/frostfs-contract/netmap"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/governance"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/governance"
|
||||||
timerEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/timers"
|
timerEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/timers"
|
||||||
cntClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container"
|
|
||||||
netmapclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap"
|
netmapclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event"
|
||||||
netmapEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/netmap"
|
netmapEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/netmap"
|
||||||
|
@ -68,7 +67,6 @@ func TestNewEpoch(t *testing.T) {
|
||||||
duration: 10,
|
duration: 10,
|
||||||
}
|
}
|
||||||
r := &testEpochResetter{}
|
r := &testEpochResetter{}
|
||||||
cc := &testContainerClient{}
|
|
||||||
nc := &testNetmapClient{
|
nc := &testNetmapClient{
|
||||||
epochDuration: 20,
|
epochDuration: 20,
|
||||||
txHeights: map[util.Uint256]uint32{
|
txHeights: map[util.Uint256]uint32{
|
||||||
|
@ -82,7 +80,6 @@ func TestNewEpoch(t *testing.T) {
|
||||||
p.NotaryDepositHandler = eh.Handle
|
p.NotaryDepositHandler = eh.Handle
|
||||||
p.AlphabetSyncHandler = eh.Handle
|
p.AlphabetSyncHandler = eh.Handle
|
||||||
p.NetmapClient = nc
|
p.NetmapClient = nc
|
||||||
p.ContainerWrapper = cc
|
|
||||||
p.EpochTimer = r
|
p.EpochTimer = r
|
||||||
p.EpochState = es
|
p.EpochState = es
|
||||||
})
|
})
|
||||||
|
@ -103,11 +100,6 @@ func TestNewEpoch(t *testing.T) {
|
||||||
require.Equal(t, ev.Num, es.counter, "invalid epoch counter")
|
require.Equal(t, ev.Num, es.counter, "invalid epoch counter")
|
||||||
require.EqualValues(t, []uint32{nc.txHeights[ev.Hash]}, r.timers, "invalid epoch timer resets")
|
require.EqualValues(t, []uint32{nc.txHeights[ev.Hash]}, r.timers, "invalid epoch timer resets")
|
||||||
|
|
||||||
var expEstimation cntClient.StartEstimationPrm
|
|
||||||
expEstimation.SetEpoch(ev.Num - 1)
|
|
||||||
expEstimation.SetHash(ev.Hash)
|
|
||||||
require.EqualValues(t, []cntClient.StartEstimationPrm{expEstimation}, cc.estimations, "invalid estimations")
|
|
||||||
|
|
||||||
require.EqualValues(t, []event.Event{
|
require.EqualValues(t, []event.Event{
|
||||||
governance.NewSyncEvent(ev.TxHash()),
|
governance.NewSyncEvent(ev.TxHash()),
|
||||||
ev,
|
ev,
|
||||||
|
@ -274,7 +266,6 @@ func newTestProc(t *testing.T, nonDefault func(p *Params)) (*Processor, error) {
|
||||||
as := &testAlphabetState{
|
as := &testAlphabetState{
|
||||||
isAlphabet: true,
|
isAlphabet: true,
|
||||||
}
|
}
|
||||||
cc := &testContainerClient{}
|
|
||||||
nc := &testNetmapClient{}
|
nc := &testNetmapClient{}
|
||||||
eh := &testEventHandler{}
|
eh := &testEventHandler{}
|
||||||
|
|
||||||
|
@ -288,7 +279,6 @@ func newTestProc(t *testing.T, nonDefault func(p *Params)) (*Processor, error) {
|
||||||
EpochState: es,
|
EpochState: es,
|
||||||
EpochTimer: r,
|
EpochTimer: r,
|
||||||
AlphabetState: as,
|
AlphabetState: as,
|
||||||
ContainerWrapper: cc,
|
|
||||||
NetmapClient: nc,
|
NetmapClient: nc,
|
||||||
NotaryDepositHandler: eh.Handle,
|
NotaryDepositHandler: eh.Handle,
|
||||||
AlphabetSyncHandler: eh.Handle,
|
AlphabetSyncHandler: eh.Handle,
|
||||||
|
@ -354,15 +344,6 @@ func (s *testAlphabetState) IsAlphabet() bool {
|
||||||
return s.isAlphabet
|
return s.isAlphabet
|
||||||
}
|
}
|
||||||
|
|
||||||
type testContainerClient struct {
|
|
||||||
estimations []cntClient.StartEstimationPrm
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *testContainerClient) StartEstimation(p cntClient.StartEstimationPrm) error {
|
|
||||||
c.estimations = append(c.estimations, p)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type notaryInvoke struct {
|
type notaryInvoke struct {
|
||||||
contract util.Uint160
|
contract util.Uint160
|
||||||
fee fixedn.Fixed8
|
fee fixedn.Fixed8
|
||||||
|
|
|
@ -3,7 +3,6 @@ package netmap
|
||||||
import (
|
import (
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/governance"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/governance"
|
||||||
cntClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container"
|
|
||||||
netmapEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/netmap"
|
netmapEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/netmap"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
@ -44,20 +43,6 @@ func (np *Processor) processNewEpoch(ev netmapEvent.NewEpoch) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
prm := cntClient.StartEstimationPrm{}
|
|
||||||
|
|
||||||
prm.SetEpoch(epoch - 1)
|
|
||||||
prm.SetHash(ev.TxHash())
|
|
||||||
|
|
||||||
if epoch > 0 && np.alphabetState.IsAlphabet() { // estimates are invalid in genesis epoch
|
|
||||||
err = np.containerWrp.StartEstimation(prm)
|
|
||||||
if err != nil {
|
|
||||||
np.log.Warn(logs.NetmapCantStartContainerSizeEstimation,
|
|
||||||
zap.Uint64("epoch", epoch),
|
|
||||||
zap.String("error", err.Error()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
np.netmapSnapshot.update(*networkMap, epoch)
|
np.netmapSnapshot.update(*networkMap, epoch)
|
||||||
np.handleCleanupTick(netmapCleanupTick{epoch: epoch, txHash: ev.TxHash()})
|
np.handleCleanupTick(netmapCleanupTick{epoch: epoch, txHash: ev.TxHash()})
|
||||||
np.handleAlphabetSync(governance.NewSyncEvent(ev.TxHash()))
|
np.handleAlphabetSync(governance.NewSyncEvent(ev.TxHash()))
|
||||||
|
|
|
@ -7,7 +7,6 @@ import (
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/metrics"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/metrics"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/netmap/nodevalidation/state"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/netmap/nodevalidation/state"
|
||||||
cntClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event"
|
||||||
netmapEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/netmap"
|
netmapEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/netmap"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger"
|
||||||
|
@ -65,10 +64,6 @@ type (
|
||||||
MorphNotarySignAndInvokeTX(mainTx *transaction.Transaction) error
|
MorphNotarySignAndInvokeTX(mainTx *transaction.Transaction) error
|
||||||
}
|
}
|
||||||
|
|
||||||
ContainerClient interface {
|
|
||||||
StartEstimation(p cntClient.StartEstimationPrm) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Processor of events produced by network map contract
|
// Processor of events produced by network map contract
|
||||||
// and new epoch ticker, because it is related to contract.
|
// and new epoch ticker, because it is related to contract.
|
||||||
Processor struct {
|
Processor struct {
|
||||||
|
@ -80,7 +75,6 @@ type (
|
||||||
alphabetState AlphabetState
|
alphabetState AlphabetState
|
||||||
|
|
||||||
netmapClient Client
|
netmapClient Client
|
||||||
containerWrp ContainerClient
|
|
||||||
|
|
||||||
netmapSnapshot cleanupTable
|
netmapSnapshot cleanupTable
|
||||||
|
|
||||||
|
@ -103,7 +97,6 @@ type (
|
||||||
AlphabetState AlphabetState
|
AlphabetState AlphabetState
|
||||||
CleanupEnabled bool
|
CleanupEnabled bool
|
||||||
CleanupThreshold uint64 // in epochs
|
CleanupThreshold uint64 // in epochs
|
||||||
ContainerWrapper ContainerClient
|
|
||||||
|
|
||||||
AlphabetSyncHandler event.Handler
|
AlphabetSyncHandler event.Handler
|
||||||
NotaryDepositHandler event.Handler
|
NotaryDepositHandler event.Handler
|
||||||
|
@ -133,8 +126,6 @@ func New(p *Params) (*Processor, error) {
|
||||||
return nil, errors.New("ir/netmap: alphabet sync handler is not set")
|
return nil, errors.New("ir/netmap: alphabet sync handler is not set")
|
||||||
case p.NotaryDepositHandler == nil:
|
case p.NotaryDepositHandler == nil:
|
||||||
return nil, errors.New("ir/netmap: notary deposit handler is not set")
|
return nil, errors.New("ir/netmap: notary deposit handler is not set")
|
||||||
case p.ContainerWrapper == nil:
|
|
||||||
return nil, errors.New("ir/netmap: container contract wrapper is not set")
|
|
||||||
case p.NodeValidator == nil:
|
case p.NodeValidator == nil:
|
||||||
return nil, errors.New("ir/netmap: node validator is not set")
|
return nil, errors.New("ir/netmap: node validator is not set")
|
||||||
case p.NodeStateSettings == nil:
|
case p.NodeStateSettings == nil:
|
||||||
|
@ -161,7 +152,6 @@ func New(p *Params) (*Processor, error) {
|
||||||
epochState: p.EpochState,
|
epochState: p.EpochState,
|
||||||
alphabetState: p.AlphabetState,
|
alphabetState: p.AlphabetState,
|
||||||
netmapClient: p.NetmapClient,
|
netmapClient: p.NetmapClient,
|
||||||
containerWrp: p.ContainerWrapper,
|
|
||||||
netmapSnapshot: newCleanupTable(p.CleanupEnabled, p.CleanupThreshold),
|
netmapSnapshot: newCleanupTable(p.CleanupEnabled, p.CleanupThreshold),
|
||||||
|
|
||||||
handleAlphabetSync: p.AlphabetSyncHandler,
|
handleAlphabetSync: p.AlphabetSyncHandler,
|
||||||
|
|
|
@ -30,12 +30,6 @@ const (
|
||||||
eaclMethod = "eACL"
|
eaclMethod = "eACL"
|
||||||
deletionInfoMethod = "deletionInfo"
|
deletionInfoMethod = "deletionInfo"
|
||||||
|
|
||||||
startEstimationMethod = "startContainerEstimation"
|
|
||||||
stopEstimationMethod = "stopContainerEstimation"
|
|
||||||
|
|
||||||
listSizesMethod = "listContainerSizes"
|
|
||||||
getSizeMethod = "getContainerSize"
|
|
||||||
|
|
||||||
// putNamedMethod is method name for container put with an alias. It is exported to provide custom fee.
|
// putNamedMethod is method name for container put with an alias. It is exported to provide custom fee.
|
||||||
putNamedMethod = "putNamed"
|
putNamedMethod = "putNamed"
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,54 +0,0 @@
|
||||||
package container
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
|
|
||||||
)
|
|
||||||
|
|
||||||
// StartEstimationPrm groups parameters of StartEstimation operation.
|
|
||||||
type StartEstimationPrm struct {
|
|
||||||
commonEstimationPrm
|
|
||||||
}
|
|
||||||
|
|
||||||
// StopEstimationPrm groups parameters of StopEstimation operation.
|
|
||||||
type StopEstimationPrm struct {
|
|
||||||
commonEstimationPrm
|
|
||||||
}
|
|
||||||
|
|
||||||
type commonEstimationPrm struct {
|
|
||||||
epoch uint64
|
|
||||||
|
|
||||||
client.InvokePrmOptional
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetEpoch sets epoch.
|
|
||||||
func (p *commonEstimationPrm) SetEpoch(epoch uint64) {
|
|
||||||
p.epoch = epoch
|
|
||||||
}
|
|
||||||
|
|
||||||
// StartEstimation votes to produce start estimation notification.
|
|
||||||
func (c *Client) StartEstimation(p StartEstimationPrm) error {
|
|
||||||
prm := client.InvokePrm{}
|
|
||||||
prm.SetMethod(startEstimationMethod)
|
|
||||||
prm.SetArgs(p.epoch)
|
|
||||||
prm.InvokePrmOptional = p.InvokePrmOptional
|
|
||||||
|
|
||||||
if _, err := c.client.Invoke(prm); err != nil {
|
|
||||||
return fmt.Errorf("could not invoke method (%s): %w", startEstimationMethod, err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// StopEstimation votes to produce stop estimation notification.
|
|
||||||
func (c *Client) StopEstimation(p StopEstimationPrm) error {
|
|
||||||
prm := client.InvokePrm{}
|
|
||||||
prm.SetMethod(stopEstimationMethod)
|
|
||||||
prm.SetArgs(p.epoch)
|
|
||||||
prm.InvokePrmOptional = p.InvokePrmOptional
|
|
||||||
|
|
||||||
if _, err := c.client.Invoke(prm); err != nil {
|
|
||||||
return fmt.Errorf("could not invoke method (%s): %w", stopEstimationMethod, err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,131 +0,0 @@
|
||||||
package container
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
v2refs "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
|
|
||||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
|
||||||
)
|
|
||||||
|
|
||||||
// EstimationID is an identity of container load estimation inside Container contract.
|
|
||||||
type EstimationID []byte
|
|
||||||
|
|
||||||
// ListLoadEstimationsByEpoch returns a list of container load estimations for to the specified epoch.
|
|
||||||
// The list is composed through Container contract call.
|
|
||||||
func (c *Client) ListLoadEstimationsByEpoch(epoch uint64) ([]EstimationID, error) {
|
|
||||||
invokePrm := client.TestInvokePrm{}
|
|
||||||
invokePrm.SetMethod(listSizesMethod)
|
|
||||||
invokePrm.SetArgs(epoch)
|
|
||||||
|
|
||||||
prms, err := c.client.TestInvoke(invokePrm)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("could not perform test invocation (%s): %w", listSizesMethod, err)
|
|
||||||
} else if ln := len(prms); ln != 1 {
|
|
||||||
return nil, fmt.Errorf("unexpected stack item count (%s): %d", listSizesMethod, ln)
|
|
||||||
}
|
|
||||||
|
|
||||||
prms, err = client.ArrayFromStackItem(prms[0])
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("could not get stack item array from stack item (%s): %w", listSizesMethod, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
res := make([]EstimationID, 0, len(prms))
|
|
||||||
for i := range prms {
|
|
||||||
id, err := client.BytesFromStackItem(prms[i])
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("could not get ID byte array from stack item (%s): %w", listSizesMethod, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
res = append(res, id)
|
|
||||||
}
|
|
||||||
|
|
||||||
return res, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Estimation is a structure of single container load estimation
|
|
||||||
// reported by storage node.
|
|
||||||
type Estimation struct {
|
|
||||||
Size uint64
|
|
||||||
|
|
||||||
Reporter []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
// Estimations is a structure of grouped container load estimation inside Container contract.
|
|
||||||
type Estimations struct {
|
|
||||||
ContainerID cid.ID
|
|
||||||
|
|
||||||
Values []Estimation
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetUsedSpaceEstimations returns a list of container load estimations by ID.
|
|
||||||
// The list is composed through Container contract call.
|
|
||||||
func (c *Client) GetUsedSpaceEstimations(id EstimationID) (*Estimations, error) {
|
|
||||||
prm := client.TestInvokePrm{}
|
|
||||||
prm.SetMethod(getSizeMethod)
|
|
||||||
prm.SetArgs([]byte(id))
|
|
||||||
|
|
||||||
prms, err := c.client.TestInvoke(prm)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("could not perform test invocation (%s): %w", getSizeMethod, err)
|
|
||||||
} else if ln := len(prms); ln != 1 {
|
|
||||||
return nil, fmt.Errorf("unexpected stack item count (%s): %d", getSizeMethod, ln)
|
|
||||||
}
|
|
||||||
|
|
||||||
prms, err = client.ArrayFromStackItem(prms[0])
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("could not get stack items of estimation fields from stack item (%s): %w", getSizeMethod, err)
|
|
||||||
} else if ln := len(prms); ln != 2 {
|
|
||||||
return nil, fmt.Errorf("unexpected stack item count of estimations fields (%s)", getSizeMethod)
|
|
||||||
}
|
|
||||||
|
|
||||||
rawCnr, err := client.BytesFromStackItem(prms[0])
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("could not get container ID byte array from stack item (%s): %w", getSizeMethod, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
prms, err = client.ArrayFromStackItem(prms[1])
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("could not get estimation list array from stack item (%s): %w", getSizeMethod, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var cnr cid.ID
|
|
||||||
|
|
||||||
err = cnr.Decode(rawCnr)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("decode container ID: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
v2 := new(v2refs.ContainerID)
|
|
||||||
v2.SetValue(rawCnr)
|
|
||||||
res := &Estimations{
|
|
||||||
ContainerID: cnr,
|
|
||||||
Values: make([]Estimation, 0, len(prms)),
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := range prms {
|
|
||||||
arr, err := client.ArrayFromStackItem(prms[i])
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("could not get estimation struct from stack item (%s): %w", getSizeMethod, err)
|
|
||||||
} else if ln := len(arr); ln != 2 {
|
|
||||||
return nil, fmt.Errorf("unexpected stack item count of estimation fields (%s)", getSizeMethod)
|
|
||||||
}
|
|
||||||
|
|
||||||
reporter, err := client.BytesFromStackItem(arr[0])
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("could not get reporter byte array from stack item (%s): %w", getSizeMethod, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
sz, err := client.IntFromStackItem(arr[1])
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("could not get estimation size from stack item (%s): %w", getSizeMethod, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
res.Values = append(res.Values, Estimation{
|
|
||||||
Reporter: reporter,
|
|
||||||
Size: uint64(sz),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return res, nil
|
|
||||||
}
|
|
|
@ -1,78 +0,0 @@
|
||||||
package container
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
|
||||||
)
|
|
||||||
|
|
||||||
// StartEstimation structure of container.StartEstimation notification from
|
|
||||||
// morph chain.
|
|
||||||
type StartEstimation struct {
|
|
||||||
epoch uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
// StopEstimation structure of container.StopEstimation notification from
|
|
||||||
// morph chain.
|
|
||||||
type StopEstimation struct {
|
|
||||||
epoch uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
// MorphEvent implements Neo:Morph Event interface.
|
|
||||||
func (StartEstimation) MorphEvent() {}
|
|
||||||
|
|
||||||
// MorphEvent implements Neo:Morph Event interface.
|
|
||||||
func (StopEstimation) MorphEvent() {}
|
|
||||||
|
|
||||||
// Epoch returns epoch value for which to start container size estimation.
|
|
||||||
func (s StartEstimation) Epoch() uint64 { return s.epoch }
|
|
||||||
|
|
||||||
// Epoch returns epoch value for which to stop container size estimation.
|
|
||||||
func (s StopEstimation) Epoch() uint64 { return s.epoch }
|
|
||||||
|
|
||||||
// ParseStartEstimation from notification into container event structure.
|
|
||||||
func ParseStartEstimation(e *state.ContainedNotificationEvent) (event.Event, error) {
|
|
||||||
params, err := event.ParseStackArray(e)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("could not parse stack items from notify event: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
epoch, err := parseEstimation(params)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return StartEstimation{epoch: epoch}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseStopEstimation from notification into container event structure.
|
|
||||||
func ParseStopEstimation(e *state.ContainedNotificationEvent) (event.Event, error) {
|
|
||||||
params, err := event.ParseStackArray(e)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("could not parse stack items from notify event: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
epoch, err := parseEstimation(params)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return StopEstimation{epoch: epoch}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseEstimation(params []stackitem.Item) (uint64, error) {
|
|
||||||
if ln := len(params); ln != 1 {
|
|
||||||
return 0, event.WrongNumberOfParameters(1, ln)
|
|
||||||
}
|
|
||||||
|
|
||||||
// parse container
|
|
||||||
epoch, err := client.IntFromStackItem(params[0])
|
|
||||||
if err != nil {
|
|
||||||
return 0, fmt.Errorf("could not get estimation epoch: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return uint64(epoch), nil
|
|
||||||
}
|
|
|
@ -1,80 +0,0 @@
|
||||||
package container
|
|
||||||
|
|
||||||
import (
|
|
||||||
"math/big"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestStartEstimation(t *testing.T) {
|
|
||||||
var epochNum uint64 = 100
|
|
||||||
epochItem := stackitem.NewBigInteger(new(big.Int).SetUint64(epochNum))
|
|
||||||
|
|
||||||
t.Run("wrong number of parameters", func(t *testing.T) {
|
|
||||||
prms := []stackitem.Item{
|
|
||||||
stackitem.NewMap(),
|
|
||||||
stackitem.NewMap(),
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := ParseStartEstimation(createNotifyEventFromItems(prms))
|
|
||||||
require.EqualError(t, err, event.WrongNumberOfParameters(1, len(prms)).Error())
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("wrong estimation parameter", func(t *testing.T) {
|
|
||||||
_, err := ParseStartEstimation(createNotifyEventFromItems([]stackitem.Item{
|
|
||||||
stackitem.NewMap(),
|
|
||||||
}))
|
|
||||||
|
|
||||||
require.Error(t, err)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("correct behavior", func(t *testing.T) {
|
|
||||||
ev, err := ParseStartEstimation(createNotifyEventFromItems([]stackitem.Item{
|
|
||||||
epochItem,
|
|
||||||
}))
|
|
||||||
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
require.Equal(t, StartEstimation{
|
|
||||||
epochNum,
|
|
||||||
}, ev)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestStopEstimation(t *testing.T) {
|
|
||||||
var epochNum uint64 = 100
|
|
||||||
epochItem := stackitem.NewBigInteger(new(big.Int).SetUint64(epochNum))
|
|
||||||
|
|
||||||
t.Run("wrong number of parameters", func(t *testing.T) {
|
|
||||||
prms := []stackitem.Item{
|
|
||||||
stackitem.NewMap(),
|
|
||||||
stackitem.NewMap(),
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := ParseStopEstimation(createNotifyEventFromItems(prms))
|
|
||||||
require.EqualError(t, err, event.WrongNumberOfParameters(1, len(prms)).Error())
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("wrong estimation parameter", func(t *testing.T) {
|
|
||||||
_, err := ParseStopEstimation(createNotifyEventFromItems([]stackitem.Item{
|
|
||||||
stackitem.NewMap(),
|
|
||||||
}))
|
|
||||||
|
|
||||||
require.Error(t, err)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("correct behavior", func(t *testing.T) {
|
|
||||||
ev, err := ParseStopEstimation(createNotifyEventFromItems([]stackitem.Item{
|
|
||||||
epochItem,
|
|
||||||
}))
|
|
||||||
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
require.Equal(t, StopEstimation{
|
|
||||||
epochNum,
|
|
||||||
}, ev)
|
|
||||||
})
|
|
||||||
}
|
|
Loading…
Reference in a new issue