From d00b1c0d2988403df3e0b7485d58abcab7052a8c Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 27 Apr 2023 17:57:27 +0300 Subject: [PATCH] [#280] ir: Add netmap processor unit tests Signed-off-by: Dmitrii Stepanov --- pkg/innerring/initialization.go | 2 +- .../processors/netmap/handlers_test.go | 570 ++++++++++++++++++ .../processors/netmap/process_cleanup.go | 2 +- .../processors/netmap/process_epoch.go | 2 +- .../processors/netmap/process_peers.go | 6 +- pkg/innerring/processors/netmap/processor.go | 32 +- pkg/innerring/processors/netmap/wrappers.go | 59 ++ pkg/morph/event/netmap/add_peer.go | 10 +- pkg/morph/event/netmap/add_peer_notary.go | 4 +- pkg/morph/event/netmap/add_peer_test.go | 2 +- pkg/morph/event/netmap/epoch.go | 14 +- pkg/morph/event/netmap/epoch_test.go | 2 +- pkg/morph/event/netmap/update_peer.go | 18 +- pkg/morph/event/netmap/update_peer_notary.go | 4 +- pkg/morph/event/netmap/update_peer_test.go | 4 +- 15 files changed, 690 insertions(+), 41 deletions(-) create mode 100644 pkg/innerring/processors/netmap/handlers_test.go create mode 100644 pkg/innerring/processors/netmap/wrappers.go diff --git a/pkg/innerring/initialization.go b/pkg/innerring/initialization.go index cb9b10648..84d08c4c6 100644 --- a/pkg/innerring/initialization.go +++ b/pkg/innerring/initialization.go @@ -54,7 +54,7 @@ func (s *Server) initNetmapProcessor(cfg *viper.Viper, s.netmapProcessor, err = netmap.New(&netmap.Params{ Log: s.log, PoolSize: cfg.GetInt("workers.netmap"), - NetmapClient: s.netmapClient, + NetmapClient: netmap.NewNetmapClient(s.netmapClient), EpochTimer: s, EpochState: s, AlphabetState: s, diff --git a/pkg/innerring/processors/netmap/handlers_test.go b/pkg/innerring/processors/netmap/handlers_test.go new file mode 100644 index 000000000..576d6c5dd --- /dev/null +++ b/pkg/innerring/processors/netmap/handlers_test.go @@ -0,0 +1,570 @@ +package netmap + +import ( + "fmt" + "testing" + "time" + + v2netmap "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap" + netmapContract "git.frostfs.info/TrueCloudLab/frostfs-contract/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/audit" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/governance" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/settlement" + 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" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" + netmapEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" + "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/network/payload" + "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/stretchr/testify/require" +) + +func TestNewEpochTick(t *testing.T) { + t.Parallel() + es := &testEpochState{ + counter: 100, + } + nc := &testNetmapClient{} + + proc, err := newTestProc(t, func(p *Params) { + p.NotaryDisabled = true + p.CleanupEnabled = true + p.EpochState = es + p.NetmapClient = nc + }) + + require.NoError(t, err, "failed to create processor") + + ev := timerEvent.NewEpochTick{} + proc.HandleNewEpochTick(ev) + + for proc.pool.Running() > 0 { + time.Sleep(10 * time.Millisecond) + } + + require.EqualValues(t, []uint64{101}, nc.newEpochs, "invalid epochs") +} + +func TestNewEpoch(t *testing.T) { + t.Parallel() + var node1 netmap.NodeInfo + key1, err := keys.NewPublicKeyFromString("038c862959e56b43e20f79187c4fe9e0bc7c8c66c1603e6cf0ec7f87ab6b08dc35") + require.NoError(t, err, "failed to parse key1") + node1.SetPublicKey(key1.Bytes()) + + var node2 netmap.NodeInfo + key2, err := keys.NewPublicKeyFromString("02ac920cd7df0b61b289072e6b946e2da4e1a31b9ab1c621bb475e30fa4ab102c3") + require.NoError(t, err, "failed to parse key2") + node2.SetPublicKey(key2.Bytes()) + + network := &netmap.NetMap{} + network.SetNodes([]netmap.NodeInfo{node1, node2}) + + es := &testEpochState{ + counter: 100, + duration: 10, + } + r := &testEpochResetter{} + cc := &testContainerClient{} + nc := &testNetmapClient{ + epochDuration: 20, + txHeights: map[util.Uint256]uint32{ + {101}: 10_000, + }, + netmap: network, + } + eh := &testEventHandler{} + + proc, err := newTestProc(t, func(p *Params) { + p.NotaryDisabled = true + p.NotaryDepositHandler = eh.Handle + p.HandleAudit = eh.Handle + p.AuditSettlementsHandler = eh.Handle + p.AlphabetSyncHandler = eh.Handle + p.NetmapClient = nc + p.ContainerWrapper = cc + p.EpochTimer = r + p.EpochState = es + }) + + require.NoError(t, err, "failed to create processor") + + ev := netmapEvent.NewEpoch{ + Num: 101, + Hash: util.Uint256{101}, + } + proc.handleNewEpoch(ev) + + for proc.pool.Running() > 0 { + time.Sleep(10 * time.Millisecond) + } + + require.Equal(t, nc.epochDuration, es.duration, "invalid epoch duration") + require.Equal(t, ev.Num, es.counter, "invalid epoch counter") + 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{ + audit.NewAuditStartEvent(ev.Num), + settlement.NewAuditEvent(ev.Num), + governance.NewSyncEvent(ev.TxHash()), + ev, + }, eh.handledEvents, "invalid handled events") +} + +func TestAddPeer(t *testing.T) { + t.Parallel() + + t.Run("with notary", func(t *testing.T) { + t.Parallel() + nc := &testNetmapClient{ + contractAddress: util.Uint160{47}, + } + + proc, err := newTestProc(t, func(p *Params) { + p.NotaryDisabled = true + p.NetmapClient = nc + }) + + require.NoError(t, err, "failed to create processor") + + var node netmap.NodeInfo + key, err := keys.NewPublicKeyFromString("038c862959e56b43e20f79187c4fe9e0bc7c8c66c1603e6cf0ec7f87ab6b08dc35") + require.NoError(t, err, "failed to parse key1") + node.SetPublicKey(key.Bytes()) + + ev := netmapEvent.AddPeer{ + NodeBytes: node.Marshal(), + Request: &payload.P2PNotaryRequest{ + MainTransaction: &transaction.Transaction{ + Nonce: 100, + }, + }, + } + proc.handleAddPeer(ev) + + for proc.pool.Running() > 0 { + time.Sleep(10 * time.Millisecond) + } + + require.EqualValues(t, []notaryInvoke{ + { + contract: nc.contractAddress, + fee: 0, + nonce: ev.Request.MainTransaction.Nonce, + vub: nil, + method: "addPeerIR", + args: []any{ev.Node()}, + }, + }, nc.notaryInvokes, "invalid notary invokes") + }) + + t.Run("without notary", func(t *testing.T) { + t.Parallel() + + nc := &testNetmapClient{ + contractAddress: util.Uint160{47}, + } + + proc, err := newTestProc(t, func(p *Params) { + p.NotaryDisabled = true + p.NetmapClient = nc + }) + + require.NoError(t, err, "failed to create processor") + + var node netmap.NodeInfo + key, err := keys.NewPublicKeyFromString("038c862959e56b43e20f79187c4fe9e0bc7c8c66c1603e6cf0ec7f87ab6b08dc35") + require.NoError(t, err, "failed to parse key") + node.SetPublicKey(key.Bytes()) + + ev := netmapEvent.AddPeer{ + NodeBytes: node.Marshal(), + } + proc.handleAddPeer(ev) + + for proc.pool.Running() > 0 { + time.Sleep(10 * time.Millisecond) + } + + var addPeerExp netmapclient.AddPeerPrm + addPeerExp.SetNodeInfo(node) + require.EqualValues(t, []netmapclient.AddPeerPrm{addPeerExp}, nc.addPeers, "invalid peers") + }) +} + +func TestUpdateState(t *testing.T) { + t.Parallel() + + t.Run("with notary", func(t *testing.T) { + t.Parallel() + ns := &testNodeStateSettings{ + maintAllowed: true, + } + nc := &testNetmapClient{} + + proc, err := newTestProc(t, func(p *Params) { + p.NotaryDisabled = true + p.NodeStateSettings = ns + p.NetmapClient = nc + }) + + require.NoError(t, err, "failed to create processor") + + key, err := keys.NewPublicKeyFromString("038c862959e56b43e20f79187c4fe9e0bc7c8c66c1603e6cf0ec7f87ab6b08dc35") + require.NoError(t, err, "failed to parse key") + + ev := netmapEvent.UpdatePeer{ + State: netmapContract.NodeStateOnline, + PubKey: key, + Request: &payload.P2PNotaryRequest{ + MainTransaction: &transaction.Transaction{ + Nonce: 100, + }, + }, + } + proc.handleUpdateState(ev) + + for proc.pool.Running() > 0 { + time.Sleep(10 * time.Millisecond) + } + + require.EqualValues(t, []*transaction.Transaction{ + ev.Request.MainTransaction, + }, nc.invokedTxs, "invalid invoked transactions") + }) + + t.Run("without notary", func(t *testing.T) { + t.Parallel() + ns := &testNodeStateSettings{ + maintAllowed: true, + } + nc := &testNetmapClient{} + + proc, err := newTestProc(t, func(p *Params) { + p.NetmapClient = nc + p.NodeStateSettings = ns + }) + + require.NoError(t, err, "failed to create processor") + + key, err := keys.NewPublicKeyFromString("038c862959e56b43e20f79187c4fe9e0bc7c8c66c1603e6cf0ec7f87ab6b08dc35") + require.NoError(t, err, "failed to parse key") + + ev := netmapEvent.UpdatePeer{ + State: netmapContract.NodeStateOnline, + PubKey: key, + } + proc.handleUpdateState(ev) + + for proc.pool.Running() > 0 { + time.Sleep(10 * time.Millisecond) + } + + var expUpdPeer netmapclient.UpdatePeerPrm + expUpdPeer.SetMaintenance() + expUpdPeer.SetOnline() + expUpdPeer.SetKey(ev.PubKey.Bytes()) + + require.EqualValues(t, []netmapclient.UpdatePeerPrm{expUpdPeer}, nc.peerStateUpdates, "invalid peer state updates") + }) +} + +func TestCleanupTick(t *testing.T) { + t.Parallel() + + t.Run("notary disabled", func(t *testing.T) { + t.Parallel() + + nc := &testNetmapClient{} + + proc, err := newTestProc(t, func(p *Params) { + p.NetmapClient = nc + p.NotaryDisabled = true + p.CleanupEnabled = true + }) + + require.NoError(t, err, "failed to create processor") + + key1Str := "038c862959e56b43e20f79187c4fe9e0bc7c8c66c1603e6cf0ec7f87ab6b08dc35" + proc.netmapSnapshot.lastAccess[key1Str] = epochStampWithNodeInfo{ + epochStamp: epochStamp{ + epoch: 95, + removeFlag: false, + }, + } + key2Str := "02ac920cd7df0b61b289072e6b946e2da4e1a31b9ab1c621bb475e30fa4ab102c3" + proc.netmapSnapshot.lastAccess[key2Str] = epochStampWithNodeInfo{ + epochStamp: epochStamp{ + epoch: 98, + removeFlag: false, + }, + } + + ev := netmapCleanupTick{ + epoch: 100, + txHash: util.Uint256{123}, + } + + proc.handleCleanupTick(ev) + + for proc.pool.Running() > 0 { + time.Sleep(10 * time.Millisecond) + } + + keyExp, err := keys.NewPublicKeyFromString(key1Str) + require.NoError(t, err, "failed to parse expired key") + + updExp := netmapclient.UpdatePeerPrm{} + updExp.SetKey(keyExp.Bytes()) + updExp.SetHash(ev.TxHash()) + + require.EqualValues(t, []netmapclient.UpdatePeerPrm{updExp}, nc.peerStateUpdates, "invalid peer updates") + require.True(t, proc.netmapSnapshot.lastAccess[key1Str].removeFlag, "invalid expired removed flag") + require.False(t, proc.netmapSnapshot.lastAccess[key2Str].removeFlag, "invalid non expired removed flag") + }) + + t.Run("notary enabled", func(t *testing.T) { + t.Parallel() + + nc := &testNetmapClient{ + contractAddress: util.Uint160{111}, + } + proc, err := newTestProc(t, + func(p *Params) { + p.NetmapClient = nc + p.CleanupEnabled = true + }, + ) + + require.NoError(t, err, "failed to create processor") + + key1Str := "038c862959e56b43e20f79187c4fe9e0bc7c8c66c1603e6cf0ec7f87ab6b08dc35" + proc.netmapSnapshot.lastAccess[key1Str] = epochStampWithNodeInfo{ + epochStamp: epochStamp{ + epoch: 95, + removeFlag: false, + }, + } + key2Str := "02ac920cd7df0b61b289072e6b946e2da4e1a31b9ab1c621bb475e30fa4ab102c3" + proc.netmapSnapshot.lastAccess[key2Str] = epochStampWithNodeInfo{ + epochStamp: epochStamp{ + epoch: 98, + removeFlag: false, + }, + } + + ev := netmapCleanupTick{ + epoch: 100, + txHash: util.Uint256{123}, + } + + proc.handleCleanupTick(ev) + + for proc.pool.Running() > 0 { + time.Sleep(10 * time.Millisecond) + } + + keyExp, err := keys.NewPublicKeyFromString(key1Str) + require.NoError(t, err, "failed to parse expired key") + + updExp := netmapclient.UpdatePeerPrm{} + updExp.SetKey(keyExp.Bytes()) + updExp.SetHash(ev.TxHash()) + + require.EqualValues(t, []notaryInvoke{ + { + contract: nc.contractAddress, + fee: 0, + nonce: uint32(ev.epoch), + vub: nil, + method: "updateStateIR", + args: []any{int64(v2netmap.Offline), keyExp.Bytes()}, + }, + }, nc.notaryInvokes, "invalid notary invokes") + require.True(t, proc.netmapSnapshot.lastAccess[key1Str].removeFlag, "invalid expired removed flag") + require.False(t, proc.netmapSnapshot.lastAccess[key2Str].removeFlag, "invalid non expired removed flag") + }) +} + +func newTestProc(t *testing.T, nonDefault func(p *Params)) (*Processor, error) { + ns := &testNodeStateSettings{} + es := &testEpochState{} + r := &testEpochResetter{} + as := &testAlphabetState{ + isAlphabet: true, + } + cc := &testContainerClient{} + nc := &testNetmapClient{} + eh := &testEventHandler{} + + p := &Params{ + Log: test.NewLogger(t, true), + PoolSize: 1, + CleanupEnabled: false, + CleanupThreshold: 3, + NotaryDisabled: false, + NodeStateSettings: ns, + NodeValidator: &testValidator{}, + EpochState: es, + EpochTimer: r, + AlphabetState: as, + ContainerWrapper: cc, + NetmapClient: nc, + NotaryDepositHandler: eh.Handle, + HandleAudit: eh.Handle, + AuditSettlementsHandler: eh.Handle, + AlphabetSyncHandler: eh.Handle, + } + + nonDefault(p) + + return New(p) +} + +type testNodeStateSettings struct { + maintAllowed bool +} + +func (s *testNodeStateSettings) MaintenanceModeAllowed() error { + if s.maintAllowed { + return nil + } + return fmt.Errorf("maintenance mode not allowed") +} + +type testValidator struct{} + +func (v *testValidator) VerifyAndUpdate(*netmap.NodeInfo) error { + return nil +} + +type testEpochState struct { + counter uint64 + duration uint64 +} + +func (s *testEpochState) SetEpochCounter(c uint64) { + s.counter = c +} +func (s *testEpochState) EpochCounter() uint64 { + return s.counter +} +func (s *testEpochState) SetEpochDuration(d uint64) { + s.duration = d +} +func (s *testEpochState) EpochDuration() uint64 { + return s.duration +} + +type testEpochResetter struct { + timers []uint32 +} + +func (r *testEpochResetter) ResetEpochTimer(t uint32) error { + r.timers = append(r.timers, t) + return nil +} + +type testAlphabetState struct { + isAlphabet bool +} + +func (s *testAlphabetState) IsAlphabet() bool { + 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 { + contract util.Uint160 + fee fixedn.Fixed8 + nonce uint32 + vub *uint32 + method string + args []any +} + +type testNetmapClient struct { + contractAddress util.Uint160 + epochDuration uint64 + netmap *netmap.NetMap + txHeights map[util.Uint256]uint32 + + peerStateUpdates []netmapclient.UpdatePeerPrm + notaryInvokes []notaryInvoke + newEpochs []uint64 + addPeers []netmapclient.AddPeerPrm + invokedTxs []*transaction.Transaction +} + +func (c *testNetmapClient) UpdatePeerState(p netmapclient.UpdatePeerPrm) error { + c.peerStateUpdates = append(c.peerStateUpdates, p) + return nil +} +func (c *testNetmapClient) MorphNotaryInvoke(contract util.Uint160, fee fixedn.Fixed8, nonce uint32, vub *uint32, method string, args ...any) error { + c.notaryInvokes = append(c.notaryInvokes, notaryInvoke{ + contract: contract, + fee: fee, + nonce: nonce, + vub: vub, + method: method, + args: args, + }) + return nil +} +func (c *testNetmapClient) ContractAddress() util.Uint160 { + return c.contractAddress +} +func (c *testNetmapClient) EpochDuration() (uint64, error) { + return c.epochDuration, nil +} +func (c *testNetmapClient) MorphTxHeight(h util.Uint256) (uint32, error) { + if res, found := c.txHeights[h]; found { + return res, nil + } + return 0, fmt.Errorf("not found") +} +func (c *testNetmapClient) NetMap() (*netmap.NetMap, error) { + return c.netmap, nil +} +func (c *testNetmapClient) NewEpoch(epoch uint64, force bool) error { + c.newEpochs = append(c.newEpochs, epoch) + return nil +} +func (c *testNetmapClient) MorphIsValidScript(script []byte, signers []transaction.Signer) (valid bool, err error) { + return true, nil +} +func (c *testNetmapClient) AddPeer(p netmapclient.AddPeerPrm) error { + c.addPeers = append(c.addPeers, p) + return nil +} +func (c *testNetmapClient) MorphNotarySignAndInvokeTX(mainTx *transaction.Transaction) error { + c.invokedTxs = append(c.invokedTxs, mainTx) + return nil +} + +type testEventHandler struct { + handledEvents []event.Event +} + +func (h *testEventHandler) Handle(e event.Event) { + h.handledEvents = append(h.handledEvents, e) +} diff --git a/pkg/innerring/processors/netmap/process_cleanup.go b/pkg/innerring/processors/netmap/process_cleanup.go index d50c69c78..45a08b377 100644 --- a/pkg/innerring/processors/netmap/process_cleanup.go +++ b/pkg/innerring/processors/netmap/process_cleanup.go @@ -39,7 +39,7 @@ func (np *Processor) processNetmapCleanupTick(ev netmapCleanupTick) { err = np.netmapClient.UpdatePeerState(prm) } else { - err = np.netmapClient.Morph().NotaryInvoke( + err = np.netmapClient.MorphNotaryInvoke( np.netmapClient.ContractAddress(), 0, uint32(ev.epoch), diff --git a/pkg/innerring/processors/netmap/process_epoch.go b/pkg/innerring/processors/netmap/process_epoch.go index 96ea4a01a..b655db9aa 100644 --- a/pkg/innerring/processors/netmap/process_epoch.go +++ b/pkg/innerring/processors/netmap/process_epoch.go @@ -23,7 +23,7 @@ func (np *Processor) processNewEpoch(ev netmapEvent.NewEpoch) { np.epochState.SetEpochCounter(epoch) - h, err := np.netmapClient.Morph().TxHeight(ev.TxHash()) + h, err := np.netmapClient.MorphTxHeight(ev.TxHash()) if err != nil { np.log.Warn(logs.NetmapCantGetTransactionHeight, zap.String("hash", ev.TxHash().StringLE()), diff --git a/pkg/innerring/processors/netmap/process_peers.go b/pkg/innerring/processors/netmap/process_peers.go index bf54ed341..9e6eeb53e 100644 --- a/pkg/innerring/processors/netmap/process_peers.go +++ b/pkg/innerring/processors/netmap/process_peers.go @@ -21,7 +21,7 @@ func (np *Processor) processAddPeer(ev netmapEvent.AddPeer) { // check if notary transaction is valid, see #976 if originalRequest := ev.NotaryRequest(); originalRequest != nil { tx := originalRequest.MainTransaction - ok, err := np.netmapClient.Morph().IsValidScript(tx.Script, tx.Signers) + ok, err := np.netmapClient.MorphIsValidScript(tx.Script, tx.Signers) if err != nil || !ok { np.log.Warn(logs.NetmapNonhaltNotaryTransaction, zap.String("method", "netmap.AddPeer"), @@ -73,7 +73,7 @@ func (np *Processor) processAddPeer(ev netmapEvent.AddPeer) { if nr := ev.NotaryRequest(); nr != nil { // create new notary request with the original nonce - err = np.netmapClient.Morph().NotaryInvoke( + err = np.netmapClient.MorphNotaryInvoke( np.netmapClient.ContractAddress(), 0, nr.MainTransaction.Nonce, @@ -117,7 +117,7 @@ func (np *Processor) processUpdatePeer(ev netmapEvent.UpdatePeer) { } if nr := ev.NotaryRequest(); nr != nil { - err = np.netmapClient.Morph().NotarySignAndInvokeTX(nr.MainTransaction) + err = np.netmapClient.MorphNotarySignAndInvokeTX(nr.MainTransaction) } else { prm := netmapclient.UpdatePeerPrm{} diff --git a/pkg/innerring/processors/netmap/processor.go b/pkg/innerring/processors/netmap/processor.go index 39069a963..522fa8b86 100644 --- a/pkg/innerring/processors/netmap/processor.go +++ b/pkg/innerring/processors/netmap/processor.go @@ -6,13 +6,16 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/netmap/nodevalidation/state" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container" - nmClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" + cntClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container" + netmapclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" 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-sdk-go/netmap" "github.com/nspcc-dev/neo-go/pkg/core/mempoolevent" + "github.com/nspcc-dev/neo-go/pkg/core/transaction" + "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" + "github.com/nspcc-dev/neo-go/pkg/util" "github.com/panjf2000/ants/v2" "go.uber.org/zap" ) @@ -51,6 +54,23 @@ type ( VerifyAndUpdate(*netmap.NodeInfo) error } + Client interface { + UpdatePeerState(p netmapclient.UpdatePeerPrm) error + MorphNotaryInvoke(contract util.Uint160, fee fixedn.Fixed8, nonce uint32, vub *uint32, method string, args ...any) error + ContractAddress() util.Uint160 + EpochDuration() (uint64, error) + MorphTxHeight(h util.Uint256) (res uint32, err error) + NetMap() (*netmap.NetMap, error) + NewEpoch(epoch uint64, force bool) error + MorphIsValidScript(script []byte, signers []transaction.Signer) (valid bool, err error) + AddPeer(p netmapclient.AddPeerPrm) error + MorphNotarySignAndInvokeTX(mainTx *transaction.Transaction) error + } + + ContainerClient interface { + StartEstimation(p cntClient.StartEstimationPrm) error + } + // Processor of events produced by network map contract // and new epoch ticker, because it is related to contract. Processor struct { @@ -60,8 +80,8 @@ type ( epochState EpochState alphabetState AlphabetState - netmapClient *nmClient.Client - containerWrp *container.Client + netmapClient Client + containerWrp ContainerClient netmapSnapshot cleanupTable @@ -79,13 +99,13 @@ type ( Params struct { Log *logger.Logger PoolSize int - NetmapClient *nmClient.Client + NetmapClient Client EpochTimer EpochTimerReseter EpochState EpochState AlphabetState AlphabetState CleanupEnabled bool CleanupThreshold uint64 // in epochs - ContainerWrapper *container.Client + ContainerWrapper ContainerClient AlphabetSyncHandler event.Handler NotaryDepositHandler event.Handler diff --git a/pkg/innerring/processors/netmap/wrappers.go b/pkg/innerring/processors/netmap/wrappers.go new file mode 100644 index 000000000..255d498d3 --- /dev/null +++ b/pkg/innerring/processors/netmap/wrappers.go @@ -0,0 +1,59 @@ +package netmap + +import ( + netmapclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" + "github.com/nspcc-dev/neo-go/pkg/core/transaction" + "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" + "github.com/nspcc-dev/neo-go/pkg/util" +) + +func NewNetmapClient(netmapClient *netmapclient.Client) Client { + return &netmapClientWrapper{ + netmapClient: netmapClient, + } +} + +type netmapClientWrapper struct { + netmapClient *netmapclient.Client +} + +func (w *netmapClientWrapper) UpdatePeerState(p netmapclient.UpdatePeerPrm) error { + return w.netmapClient.UpdatePeerState(p) +} + +func (w *netmapClientWrapper) MorphNotaryInvoke(contract util.Uint160, fee fixedn.Fixed8, nonce uint32, vub *uint32, method string, args ...any) error { + return w.netmapClient.Morph().NotaryInvoke(contract, fee, nonce, vub, method, args...) +} + +func (w *netmapClientWrapper) ContractAddress() util.Uint160 { + return w.netmapClient.ContractAddress() +} + +func (w *netmapClientWrapper) EpochDuration() (uint64, error) { + return w.netmapClient.EpochDuration() +} + +func (w *netmapClientWrapper) MorphTxHeight(h util.Uint256) (res uint32, err error) { + return w.netmapClient.Morph().TxHeight(h) +} + +func (w *netmapClientWrapper) NetMap() (*netmap.NetMap, error) { + return w.netmapClient.NetMap() +} + +func (w *netmapClientWrapper) NewEpoch(epoch uint64, force bool) error { + return w.netmapClient.NewEpoch(epoch, force) +} + +func (w *netmapClientWrapper) MorphIsValidScript(script []byte, signers []transaction.Signer) (valid bool, err error) { + return w.netmapClient.Morph().IsValidScript(script, signers) +} + +func (w *netmapClientWrapper) AddPeer(p netmapclient.AddPeerPrm) error { + return w.netmapClient.AddPeer(p) +} + +func (w *netmapClientWrapper) MorphNotarySignAndInvokeTX(mainTx *transaction.Transaction) error { + return w.netmapClient.Morph().NotarySignAndInvokeTX(mainTx) +} diff --git a/pkg/morph/event/netmap/add_peer.go b/pkg/morph/event/netmap/add_peer.go index 87cf94082..6f839bada 100644 --- a/pkg/morph/event/netmap/add_peer.go +++ b/pkg/morph/event/netmap/add_peer.go @@ -10,24 +10,24 @@ import ( ) type AddPeer struct { - node []byte + NodeBytes []byte // For notary notifications only. // Contains raw transactions of notary request. - notaryRequest *payload.P2PNotaryRequest + Request *payload.P2PNotaryRequest } // MorphEvent implements Neo:Morph Event interface. func (AddPeer) MorphEvent() {} func (s AddPeer) Node() []byte { - return s.node + return s.NodeBytes } // NotaryRequest returns raw notary request if notification // was received via notary service. Otherwise, returns nil. func (s AddPeer) NotaryRequest() *payload.P2PNotaryRequest { - return s.notaryRequest + return s.Request } const expectedItemNumAddPeer = 1 @@ -47,7 +47,7 @@ func ParseAddPeer(e *state.ContainedNotificationEvent) (event.Event, error) { return nil, event.WrongNumberOfParameters(expectedItemNumAddPeer, ln) } - ev.node, err = client.BytesFromStackItem(params[0]) + ev.NodeBytes, err = client.BytesFromStackItem(params[0]) if err != nil { return nil, fmt.Errorf("could not get raw nodeinfo: %w", err) } diff --git a/pkg/morph/event/netmap/add_peer_notary.go b/pkg/morph/event/netmap/add_peer_notary.go index a506b052d..a24722a97 100644 --- a/pkg/morph/event/netmap/add_peer_notary.go +++ b/pkg/morph/event/netmap/add_peer_notary.go @@ -7,7 +7,7 @@ import ( func (s *AddPeer) setNode(v []byte) { if v != nil { - s.node = v + s.NodeBytes = v } } @@ -43,7 +43,7 @@ func ParseAddPeerNotary(ne event.NotaryEvent) (event.Event, error) { } } - ev.notaryRequest = ne.Raw() + ev.Request = ne.Raw() return ev, nil } diff --git a/pkg/morph/event/netmap/add_peer_test.go b/pkg/morph/event/netmap/add_peer_test.go index 1b8bcf40a..0574c4048 100644 --- a/pkg/morph/event/netmap/add_peer_test.go +++ b/pkg/morph/event/netmap/add_peer_test.go @@ -37,7 +37,7 @@ func TestParseAddPeer(t *testing.T) { require.NoError(t, err) require.Equal(t, AddPeer{ - node: info, + NodeBytes: info, }, ev) }) } diff --git a/pkg/morph/event/netmap/epoch.go b/pkg/morph/event/netmap/epoch.go index 0eaa9f285..e454e2a6a 100644 --- a/pkg/morph/event/netmap/epoch.go +++ b/pkg/morph/event/netmap/epoch.go @@ -11,12 +11,12 @@ import ( // NewEpoch is a new epoch Neo:Morph event. type NewEpoch struct { - num uint64 + Num uint64 - // txHash is used in notary environmental + // Hash is used in notary environmental // for calculating unique but same for // all notification receivers values. - txHash util.Uint256 + Hash util.Uint256 } // MorphEvent implements Neo:Morph Event interface. @@ -24,13 +24,13 @@ func (NewEpoch) MorphEvent() {} // EpochNumber returns new epoch number. func (s NewEpoch) EpochNumber() uint64 { - return s.num + return s.Num } // TxHash returns hash of the TX with new epoch // notification. func (s NewEpoch) TxHash() util.Uint256 { - return s.txHash + return s.Hash } // ParseNewEpoch is a parser of new epoch notification event. @@ -52,7 +52,7 @@ func ParseNewEpoch(e *state.ContainedNotificationEvent) (event.Event, error) { } return NewEpoch{ - num: uint64(prmEpochNum), - txHash: e.Container, + Num: uint64(prmEpochNum), + Hash: e.Container, }, nil } diff --git a/pkg/morph/event/netmap/epoch_test.go b/pkg/morph/event/netmap/epoch_test.go index b175b5275..bc267ecb6 100644 --- a/pkg/morph/event/netmap/epoch_test.go +++ b/pkg/morph/event/netmap/epoch_test.go @@ -37,7 +37,7 @@ func TestParseNewEpoch(t *testing.T) { require.NoError(t, err) require.Equal(t, NewEpoch{ - num: epochNum, + Num: epochNum, }, ev) }) } diff --git a/pkg/morph/event/netmap/update_peer.go b/pkg/morph/event/netmap/update_peer.go index 535d57e4d..f02ca408d 100644 --- a/pkg/morph/event/netmap/update_peer.go +++ b/pkg/morph/event/netmap/update_peer.go @@ -13,13 +13,13 @@ import ( ) type UpdatePeer struct { - publicKey *keys.PublicKey + PubKey *keys.PublicKey - state netmap.NodeState + State netmap.NodeState // For notary notifications only. // Contains raw transactions of notary request. - notaryRequest *payload.P2PNotaryRequest + Request *payload.P2PNotaryRequest } // MorphEvent implements Neo:Morph Event interface. @@ -28,27 +28,27 @@ func (UpdatePeer) MorphEvent() {} // Online returns true if node's state is requested to be switched // to "online". func (s UpdatePeer) Online() bool { - return s.state == netmap.NodeStateOnline + return s.State == netmap.NodeStateOnline } // Maintenance returns true if node's state is requested to be switched // to "maintenance". func (s UpdatePeer) Maintenance() bool { - return s.state == netmap.NodeStateMaintenance + return s.State == netmap.NodeStateMaintenance } func (s UpdatePeer) PublicKey() *keys.PublicKey { - return s.publicKey + return s.PubKey } // NotaryRequest returns raw notary request if notification // was received via notary service. Otherwise, returns nil. func (s UpdatePeer) NotaryRequest() *payload.P2PNotaryRequest { - return s.notaryRequest + return s.Request } func (s *UpdatePeer) decodeState(state int64) error { - switch s.state = netmap.NodeState(state); s.state { + switch s.State = netmap.NodeState(state); s.State { default: return fmt.Errorf("unsupported node state %d", state) case @@ -82,7 +82,7 @@ func ParseUpdatePeer(e *state.ContainedNotificationEvent) (event.Event, error) { return nil, fmt.Errorf("could not get public key: %w", err) } - ev.publicKey, err = keys.NewPublicKeyFromBytes(key, elliptic.P256()) + ev.PubKey, err = keys.NewPublicKeyFromBytes(key, elliptic.P256()) if err != nil { return nil, fmt.Errorf("could not parse public key: %w", err) } diff --git a/pkg/morph/event/netmap/update_peer_notary.go b/pkg/morph/event/netmap/update_peer_notary.go index b7a251f98..0260810b8 100644 --- a/pkg/morph/event/netmap/update_peer_notary.go +++ b/pkg/morph/event/netmap/update_peer_notary.go @@ -17,7 +17,7 @@ func (s *UpdatePeer) setPublicKey(v []byte) (err error) { return errNilPubKey } - s.publicKey, err = keys.NewPublicKeyFromBytes(v, elliptic.P256()) + s.PubKey, err = keys.NewPublicKeyFromBytes(v, elliptic.P256()) if err != nil { return fmt.Errorf("could not parse public key: %w", err) } @@ -73,7 +73,7 @@ func ParseUpdatePeerNotary(ne event.NotaryEvent) (event.Event, error) { } } - ev.notaryRequest = ne.Raw() + ev.Request = ne.Raw() return ev, nil } diff --git a/pkg/morph/event/netmap/update_peer_test.go b/pkg/morph/event/netmap/update_peer_test.go index 1772c88a7..b79dd6385 100644 --- a/pkg/morph/event/netmap/update_peer_test.go +++ b/pkg/morph/event/netmap/update_peer_test.go @@ -52,8 +52,8 @@ func TestParseUpdatePeer(t *testing.T) { require.NoError(t, err) require.Equal(t, UpdatePeer{ - publicKey: publicKey, - state: state, + PubKey: publicKey, + State: state, }, ev) }) }