forked from TrueCloudLab/frostfs-node
[#280] ir: Add netmap processor unit tests
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
This commit is contained in:
parent
fb5dcc15d2
commit
d00b1c0d29
15 changed files with 690 additions and 41 deletions
|
@ -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,
|
||||
|
|
570
pkg/innerring/processors/netmap/handlers_test.go
Normal file
570
pkg/innerring/processors/netmap/handlers_test.go
Normal file
|
@ -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)
|
||||
}
|
|
@ -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),
|
||||
|
|
|
@ -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()),
|
||||
|
|
|
@ -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{}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
59
pkg/innerring/processors/netmap/wrappers.go
Normal file
59
pkg/innerring/processors/netmap/wrappers.go
Normal file
|
@ -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)
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ func TestParseAddPeer(t *testing.T) {
|
|||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, AddPeer{
|
||||
node: info,
|
||||
NodeBytes: info,
|
||||
}, ev)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ func TestParseNewEpoch(t *testing.T) {
|
|||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, NewEpoch{
|
||||
num: epochNum,
|
||||
Num: epochNum,
|
||||
}, ev)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue