[#280] ir: Add netmap processor unit tests
All checks were successful
ci/woodpecker/push/pre-commit Pipeline was successful

Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
This commit is contained in:
Dmitrii Stepanov 2023-04-27 17:57:27 +03:00 committed by Evgenii Stratonikov
parent fb5dcc15d2
commit d00b1c0d29
15 changed files with 690 additions and 41 deletions

View file

@ -54,7 +54,7 @@ func (s *Server) initNetmapProcessor(cfg *viper.Viper,
s.netmapProcessor, err = netmap.New(&netmap.Params{ s.netmapProcessor, err = netmap.New(&netmap.Params{
Log: s.log, Log: s.log,
PoolSize: cfg.GetInt("workers.netmap"), PoolSize: cfg.GetInt("workers.netmap"),
NetmapClient: s.netmapClient, NetmapClient: netmap.NewNetmapClient(s.netmapClient),
EpochTimer: s, EpochTimer: s,
EpochState: s, EpochState: s,
AlphabetState: s, AlphabetState: s,

View 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)
}

View file

@ -39,7 +39,7 @@ func (np *Processor) processNetmapCleanupTick(ev netmapCleanupTick) {
err = np.netmapClient.UpdatePeerState(prm) err = np.netmapClient.UpdatePeerState(prm)
} else { } else {
err = np.netmapClient.Morph().NotaryInvoke( err = np.netmapClient.MorphNotaryInvoke(
np.netmapClient.ContractAddress(), np.netmapClient.ContractAddress(),
0, 0,
uint32(ev.epoch), uint32(ev.epoch),

View file

@ -23,7 +23,7 @@ func (np *Processor) processNewEpoch(ev netmapEvent.NewEpoch) {
np.epochState.SetEpochCounter(epoch) np.epochState.SetEpochCounter(epoch)
h, err := np.netmapClient.Morph().TxHeight(ev.TxHash()) h, err := np.netmapClient.MorphTxHeight(ev.TxHash())
if err != nil { if err != nil {
np.log.Warn(logs.NetmapCantGetTransactionHeight, np.log.Warn(logs.NetmapCantGetTransactionHeight,
zap.String("hash", ev.TxHash().StringLE()), zap.String("hash", ev.TxHash().StringLE()),

View file

@ -21,7 +21,7 @@ func (np *Processor) processAddPeer(ev netmapEvent.AddPeer) {
// check if notary transaction is valid, see #976 // check if notary transaction is valid, see #976
if originalRequest := ev.NotaryRequest(); originalRequest != nil { if originalRequest := ev.NotaryRequest(); originalRequest != nil {
tx := originalRequest.MainTransaction 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 { if err != nil || !ok {
np.log.Warn(logs.NetmapNonhaltNotaryTransaction, np.log.Warn(logs.NetmapNonhaltNotaryTransaction,
zap.String("method", "netmap.AddPeer"), zap.String("method", "netmap.AddPeer"),
@ -73,7 +73,7 @@ func (np *Processor) processAddPeer(ev netmapEvent.AddPeer) {
if nr := ev.NotaryRequest(); nr != nil { if nr := ev.NotaryRequest(); nr != nil {
// create new notary request with the original nonce // create new notary request with the original nonce
err = np.netmapClient.Morph().NotaryInvoke( err = np.netmapClient.MorphNotaryInvoke(
np.netmapClient.ContractAddress(), np.netmapClient.ContractAddress(),
0, 0,
nr.MainTransaction.Nonce, nr.MainTransaction.Nonce,
@ -117,7 +117,7 @@ func (np *Processor) processUpdatePeer(ev netmapEvent.UpdatePeer) {
} }
if nr := ev.NotaryRequest(); nr != nil { if nr := ev.NotaryRequest(); nr != nil {
err = np.netmapClient.Morph().NotarySignAndInvokeTX(nr.MainTransaction) err = np.netmapClient.MorphNotarySignAndInvokeTX(nr.MainTransaction)
} else { } else {
prm := netmapclient.UpdatePeerPrm{} prm := netmapclient.UpdatePeerPrm{}

View file

@ -6,13 +6,16 @@ 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/netmap/nodevalidation/state" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/netmap/nodevalidation/state"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container" cntClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container"
nmClient "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"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "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/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" "github.com/panjf2000/ants/v2"
"go.uber.org/zap" "go.uber.org/zap"
) )
@ -51,6 +54,23 @@ type (
VerifyAndUpdate(*netmap.NodeInfo) error 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 // 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 {
@ -60,8 +80,8 @@ type (
epochState EpochState epochState EpochState
alphabetState AlphabetState alphabetState AlphabetState
netmapClient *nmClient.Client netmapClient Client
containerWrp *container.Client containerWrp ContainerClient
netmapSnapshot cleanupTable netmapSnapshot cleanupTable
@ -79,13 +99,13 @@ type (
Params struct { Params struct {
Log *logger.Logger Log *logger.Logger
PoolSize int PoolSize int
NetmapClient *nmClient.Client NetmapClient Client
EpochTimer EpochTimerReseter EpochTimer EpochTimerReseter
EpochState EpochState EpochState EpochState
AlphabetState AlphabetState AlphabetState AlphabetState
CleanupEnabled bool CleanupEnabled bool
CleanupThreshold uint64 // in epochs CleanupThreshold uint64 // in epochs
ContainerWrapper *container.Client ContainerWrapper ContainerClient
AlphabetSyncHandler event.Handler AlphabetSyncHandler event.Handler
NotaryDepositHandler event.Handler NotaryDepositHandler event.Handler

View 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)
}

View file

@ -10,24 +10,24 @@ import (
) )
type AddPeer struct { type AddPeer struct {
node []byte NodeBytes []byte
// For notary notifications only. // For notary notifications only.
// Contains raw transactions of notary request. // Contains raw transactions of notary request.
notaryRequest *payload.P2PNotaryRequest Request *payload.P2PNotaryRequest
} }
// MorphEvent implements Neo:Morph Event interface. // MorphEvent implements Neo:Morph Event interface.
func (AddPeer) MorphEvent() {} func (AddPeer) MorphEvent() {}
func (s AddPeer) Node() []byte { func (s AddPeer) Node() []byte {
return s.node return s.NodeBytes
} }
// NotaryRequest returns raw notary request if notification // NotaryRequest returns raw notary request if notification
// was received via notary service. Otherwise, returns nil. // was received via notary service. Otherwise, returns nil.
func (s AddPeer) NotaryRequest() *payload.P2PNotaryRequest { func (s AddPeer) NotaryRequest() *payload.P2PNotaryRequest {
return s.notaryRequest return s.Request
} }
const expectedItemNumAddPeer = 1 const expectedItemNumAddPeer = 1
@ -47,7 +47,7 @@ func ParseAddPeer(e *state.ContainedNotificationEvent) (event.Event, error) {
return nil, event.WrongNumberOfParameters(expectedItemNumAddPeer, ln) return nil, event.WrongNumberOfParameters(expectedItemNumAddPeer, ln)
} }
ev.node, err = client.BytesFromStackItem(params[0]) ev.NodeBytes, err = client.BytesFromStackItem(params[0])
if err != nil { if err != nil {
return nil, fmt.Errorf("could not get raw nodeinfo: %w", err) return nil, fmt.Errorf("could not get raw nodeinfo: %w", err)
} }

View file

@ -7,7 +7,7 @@ import (
func (s *AddPeer) setNode(v []byte) { func (s *AddPeer) setNode(v []byte) {
if v != nil { 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 return ev, nil
} }

View file

@ -37,7 +37,7 @@ func TestParseAddPeer(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, AddPeer{ require.Equal(t, AddPeer{
node: info, NodeBytes: info,
}, ev) }, ev)
}) })
} }

View file

@ -11,12 +11,12 @@ import (
// NewEpoch is a new epoch Neo:Morph event. // NewEpoch is a new epoch Neo:Morph event.
type NewEpoch struct { 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 // for calculating unique but same for
// all notification receivers values. // all notification receivers values.
txHash util.Uint256 Hash util.Uint256
} }
// MorphEvent implements Neo:Morph Event interface. // MorphEvent implements Neo:Morph Event interface.
@ -24,13 +24,13 @@ func (NewEpoch) MorphEvent() {}
// EpochNumber returns new epoch number. // EpochNumber returns new epoch number.
func (s NewEpoch) EpochNumber() uint64 { func (s NewEpoch) EpochNumber() uint64 {
return s.num return s.Num
} }
// TxHash returns hash of the TX with new epoch // TxHash returns hash of the TX with new epoch
// notification. // notification.
func (s NewEpoch) TxHash() util.Uint256 { func (s NewEpoch) TxHash() util.Uint256 {
return s.txHash return s.Hash
} }
// ParseNewEpoch is a parser of new epoch notification event. // ParseNewEpoch is a parser of new epoch notification event.
@ -52,7 +52,7 @@ func ParseNewEpoch(e *state.ContainedNotificationEvent) (event.Event, error) {
} }
return NewEpoch{ return NewEpoch{
num: uint64(prmEpochNum), Num: uint64(prmEpochNum),
txHash: e.Container, Hash: e.Container,
}, nil }, nil
} }

View file

@ -37,7 +37,7 @@ func TestParseNewEpoch(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, NewEpoch{ require.Equal(t, NewEpoch{
num: epochNum, Num: epochNum,
}, ev) }, ev)
}) })
} }

View file

@ -13,13 +13,13 @@ import (
) )
type UpdatePeer struct { type UpdatePeer struct {
publicKey *keys.PublicKey PubKey *keys.PublicKey
state netmap.NodeState State netmap.NodeState
// For notary notifications only. // For notary notifications only.
// Contains raw transactions of notary request. // Contains raw transactions of notary request.
notaryRequest *payload.P2PNotaryRequest Request *payload.P2PNotaryRequest
} }
// MorphEvent implements Neo:Morph Event interface. // 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 // Online returns true if node's state is requested to be switched
// to "online". // to "online".
func (s UpdatePeer) Online() bool { 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 // Maintenance returns true if node's state is requested to be switched
// to "maintenance". // to "maintenance".
func (s UpdatePeer) Maintenance() bool { func (s UpdatePeer) Maintenance() bool {
return s.state == netmap.NodeStateMaintenance return s.State == netmap.NodeStateMaintenance
} }
func (s UpdatePeer) PublicKey() *keys.PublicKey { func (s UpdatePeer) PublicKey() *keys.PublicKey {
return s.publicKey return s.PubKey
} }
// NotaryRequest returns raw notary request if notification // NotaryRequest returns raw notary request if notification
// was received via notary service. Otherwise, returns nil. // was received via notary service. Otherwise, returns nil.
func (s UpdatePeer) NotaryRequest() *payload.P2PNotaryRequest { func (s UpdatePeer) NotaryRequest() *payload.P2PNotaryRequest {
return s.notaryRequest return s.Request
} }
func (s *UpdatePeer) decodeState(state int64) error { func (s *UpdatePeer) decodeState(state int64) error {
switch s.state = netmap.NodeState(state); s.state { switch s.State = netmap.NodeState(state); s.State {
default: default:
return fmt.Errorf("unsupported node state %d", state) return fmt.Errorf("unsupported node state %d", state)
case case
@ -82,7 +82,7 @@ func ParseUpdatePeer(e *state.ContainedNotificationEvent) (event.Event, error) {
return nil, fmt.Errorf("could not get public key: %w", err) 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 { if err != nil {
return nil, fmt.Errorf("could not parse public key: %w", err) return nil, fmt.Errorf("could not parse public key: %w", err)
} }

View file

@ -17,7 +17,7 @@ func (s *UpdatePeer) setPublicKey(v []byte) (err error) {
return errNilPubKey return errNilPubKey
} }
s.publicKey, err = keys.NewPublicKeyFromBytes(v, elliptic.P256()) s.PubKey, err = keys.NewPublicKeyFromBytes(v, elliptic.P256())
if err != nil { if err != nil {
return fmt.Errorf("could not parse public key: %w", err) 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 return ev, nil
} }

View file

@ -52,8 +52,8 @@ func TestParseUpdatePeer(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, UpdatePeer{ require.Equal(t, UpdatePeer{
publicKey: publicKey, PubKey: publicKey,
state: state, State: state,
}, ev) }, ev)
}) })
} }