[#971] *: Add notification TX hash to neofs/netmap morph client calls

Add hash of the TX that generated notification
to neofs/netmap event structures. Adapt all
neofs/netmap wrapper calls to new structures.

Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
This commit is contained in:
Pavel Karpy 2021-11-10 14:05:51 +03:00 committed by Alex Vanin
parent c25f5a86ae
commit bad739258e
19 changed files with 220 additions and 60 deletions

View file

@ -476,7 +476,10 @@ func (c *cfg) bootstrap() error {
ni := c.cfgNodeInfo.localInfo ni := c.cfgNodeInfo.localInfo
ni.SetState(netmap.NodeStateOnline) ni.SetState(netmap.NodeStateOnline)
return c.cfgNetmap.wrapper.AddPeer(&ni) prm := nmwrapper.AddPeerPrm{}
prm.SetNodeInfo(&ni)
return c.cfgNetmap.wrapper.AddPeer(prm)
} }
// needBootstrap checks if local node should be registered in network on bootup. // needBootstrap checks if local node should be registered in network on bootup.

View file

@ -9,6 +9,7 @@ import (
netmapGRPC "github.com/nspcc-dev/neofs-api-go/v2/netmap/grpc" netmapGRPC "github.com/nspcc-dev/neofs-api-go/v2/netmap/grpc"
"github.com/nspcc-dev/neofs-api-go/v2/refs" "github.com/nspcc-dev/neofs-api-go/v2/refs"
"github.com/nspcc-dev/neofs-node/pkg/core/netmap" "github.com/nspcc-dev/neofs-node/pkg/core/netmap"
"github.com/nspcc-dev/neofs-node/pkg/morph/client/netmap/wrapper"
"github.com/nspcc-dev/neofs-node/pkg/morph/event" "github.com/nspcc-dev/neofs-node/pkg/morph/event"
netmapEvent "github.com/nspcc-dev/neofs-node/pkg/morph/event/netmap" netmapEvent "github.com/nspcc-dev/neofs-node/pkg/morph/event/netmap"
"github.com/nspcc-dev/neofs-node/pkg/network" "github.com/nspcc-dev/neofs-node/pkg/network"
@ -283,10 +284,12 @@ func (c *cfg) SetNetmapStatus(st control.NetmapStatus) error {
c.cfgNetmap.reBoostrapTurnedOff.Store(true) c.cfgNetmap.reBoostrapTurnedOff.Store(true)
return c.cfgNetmap.wrapper.UpdatePeerState( prm := wrapper.UpdatePeerPrm{}
c.key.PublicKey().Bytes(),
apiState, prm.SetKey(c.key.PublicKey().Bytes())
) prm.SetState(apiState)
return c.cfgNetmap.wrapper.UpdatePeerState(prm)
} }
type netInfo struct { type netInfo struct {

View file

@ -191,8 +191,11 @@ func (s *Server) Start(ctx context.Context, intError chan<- error) (err error) {
} }
} }
prm := governance.VoteValidatorPrm{}
prm.Validators = s.predefinedValidators
// vote for sidechain validator if it is prepared in config // vote for sidechain validator if it is prepared in config
err = s.voteForSidechainValidator(s.predefinedValidators) err = s.voteForSidechainValidator(prm)
if err != nil { if err != nil {
// we don't stop inner ring execution on this error // we don't stop inner ring execution on this error
s.log.Warn("can't vote for prepared validators", s.log.Warn("can't vote for prepared validators",

View file

@ -1,6 +1,7 @@
package balance package balance
import ( import (
neofscontract "github.com/nspcc-dev/neofs-node/pkg/morph/client/neofs/wrapper"
balanceEvent "github.com/nspcc-dev/neofs-node/pkg/morph/event/balance" balanceEvent "github.com/nspcc-dev/neofs-node/pkg/morph/event/balance"
"go.uber.org/zap" "go.uber.org/zap"
) )
@ -13,11 +14,15 @@ func (bp *Processor) processLock(lock *balanceEvent.Lock) {
return return
} }
err := bp.neofsClient.Cheque( prm := neofscontract.ChequePrm{}
lock.ID(),
lock.User(), prm.SetID(lock.ID())
bp.converter.ToFixed8(lock.Amount()), prm.SetUser(lock.User())
lock.LockAccount()) prm.SetAmount(bp.converter.ToFixed8(lock.Amount()))
prm.SetLock(lock.LockAccount())
prm.SetHash(lock.TxHash())
err := bp.neofsClient.Cheque(prm)
if err != nil { if err != nil {
bp.log.Error("can't send lock asset tx", zap.Error(err)) bp.log.Error("can't send lock asset tx", zap.Error(err))
} }

View file

@ -1,11 +1,26 @@
package governance package governance
// Sync is a event to start governance synchronization. import "github.com/nspcc-dev/neo-go/pkg/util"
type Sync struct{}
// Sync is an event to start governance synchronization.
type Sync struct {
// txHash is used in notary environmental
// for calculating unique but same for
// all notification receivers values.
txHash util.Uint256
}
// TxHash returns hash of the TX that triggers
// synchronization process.
func (s Sync) TxHash() util.Uint256 {
return s.txHash
}
// MorphEvent implements Event interface. // MorphEvent implements Event interface.
func (s Sync) MorphEvent() {} func (s Sync) MorphEvent() {}
func NewSyncEvent() Sync { // NewSyncEvent creates Sync event that was produced
return Sync{} // in transaction with txHash hash.
func NewSyncEvent(txHash util.Uint256) Sync {
return Sync{txHash: txHash}
} }

View file

@ -3,22 +3,29 @@ package governance
import ( import (
"github.com/nspcc-dev/neo-go/pkg/core/native" "github.com/nspcc-dev/neo-go/pkg/core/native"
"github.com/nspcc-dev/neo-go/pkg/core/native/noderoles" "github.com/nspcc-dev/neo-go/pkg/core/native/noderoles"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neofs-node/pkg/morph/event" "github.com/nspcc-dev/neofs-node/pkg/morph/event"
"github.com/nspcc-dev/neofs-node/pkg/morph/event/rolemanagement" "github.com/nspcc-dev/neofs-node/pkg/morph/event/rolemanagement"
"go.uber.org/zap" "go.uber.org/zap"
) )
func (gp *Processor) HandleAlphabetSync(e event.Event) { func (gp *Processor) HandleAlphabetSync(e event.Event) {
var typ string var (
typ string
hash util.Uint256
)
switch et := e.(type) { switch et := e.(type) {
case Sync: case Sync:
typ = "sync" typ = "sync"
hash = et.TxHash()
case rolemanagement.Designate: case rolemanagement.Designate:
if et.Role != noderoles.NeoFSAlphabet { if et.Role != noderoles.NeoFSAlphabet {
return return
} }
typ = native.DesignationEventName typ = native.DesignationEventName
hash = et.TxHash
default: default:
return return
} }
@ -27,7 +34,7 @@ func (gp *Processor) HandleAlphabetSync(e event.Event) {
// send event to the worker pool // send event to the worker pool
err := gp.pool.Submit(func() { gp.processAlphabetSync() }) err := gp.pool.Submit(func() { gp.processAlphabetSync(hash) })
if err != nil { if err != nil {
// there system can be moved into controlled degradation stage // there system can be moved into controlled degradation stage
gp.log.Warn("governance worker pool drained", gp.log.Warn("governance worker pool drained",

View file

@ -6,7 +6,12 @@ import (
"sort" "sort"
"strings" "strings"
"github.com/nspcc-dev/neofs-node/pkg/morph/client/netmap/wrapper"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neofs-node/pkg/morph/client"
neofscontract "github.com/nspcc-dev/neofs-node/pkg/morph/client/neofs/wrapper"
"go.uber.org/zap" "go.uber.org/zap"
) )
@ -14,7 +19,7 @@ const (
alphabetUpdateIDPrefix = "AlphabetUpdate" alphabetUpdateIDPrefix = "AlphabetUpdate"
) )
func (gp *Processor) processAlphabetSync() { func (gp *Processor) processAlphabetSync(txHash util.Uint256) {
if !gp.alphabetState.IsAlphabet() { if !gp.alphabetState.IsAlphabet() {
gp.log.Info("non alphabet mode, ignore alphabet sync") gp.log.Info("non alphabet mode, ignore alphabet sync")
return return
@ -51,8 +56,13 @@ func (gp *Processor) processAlphabetSync() {
zap.String("new_alphabet", prettyKeys(newAlphabet)), zap.String("new_alphabet", prettyKeys(newAlphabet)),
) )
votePrm := VoteValidatorPrm{
Validators: newAlphabet,
Hash: &txHash,
}
// 1. Vote to side chain committee via alphabet contracts. // 1. Vote to side chain committee via alphabet contracts.
err = gp.voter.VoteForSidechainValidator(newAlphabet) err = gp.voter.VoteForSidechainValidator(votePrm)
if err != nil { if err != nil {
gp.log.Error("can't vote for side chain committee", gp.log.Error("can't vote for side chain committee",
zap.String("error", err.Error())) zap.String("error", err.Error()))
@ -77,9 +87,19 @@ func (gp *Processor) processAlphabetSync() {
) )
if gp.notaryDisabled { if gp.notaryDisabled {
err = gp.netmapClient.UpdateInnerRing(newInnerRing) updPrm := wrapper.UpdateIRPrm{}
updPrm.SetKeys(newInnerRing)
updPrm.SetHash(txHash)
err = gp.netmapClient.UpdateInnerRing(updPrm)
} else { } else {
err = gp.morphClient.UpdateNeoFSAlphabetList(newInnerRing) updPrm := client.UpdateAlphabetListPrm{}
updPrm.SetList(newInnerRing)
updPrm.SetHash(txHash)
err = gp.morphClient.UpdateNeoFSAlphabetList(updPrm)
} }
if err != nil { if err != nil {
@ -91,7 +111,13 @@ func (gp *Processor) processAlphabetSync() {
if !gp.notaryDisabled { if !gp.notaryDisabled {
// 3. Update notary role in side chain. // 3. Update notary role in side chain.
err = gp.morphClient.UpdateNotaryList(newAlphabet)
updPrm := client.UpdateNotaryListPrm{}
updPrm.SetList(newAlphabet)
updPrm.SetHash(txHash)
err = gp.morphClient.UpdateNotaryList(updPrm)
if err != nil { if err != nil {
gp.log.Error("can't update list of notary nodes in side chain", gp.log.Error("can't update list of notary nodes in side chain",
zap.String("error", err.Error())) zap.String("error", err.Error()))
@ -106,7 +132,12 @@ func (gp *Processor) processAlphabetSync() {
id := append([]byte(alphabetUpdateIDPrefix), buf...) id := append([]byte(alphabetUpdateIDPrefix), buf...)
err = gp.neofsClient.AlphabetUpdate(id, newAlphabet) prm := neofscontract.AlphabetUpdatePrm{}
prm.SetID(id)
prm.SetPubs(newAlphabet)
err = gp.neofsClient.AlphabetUpdate(prm)
if err != nil { if err != nil {
gp.log.Error("can't update list of alphabet nodes in neofs contract", gp.log.Error("can't update list of alphabet nodes in neofs contract",
zap.String("error", err.Error())) zap.String("error", err.Error()))

View file

@ -26,12 +26,21 @@ type (
AlphabetState interface { AlphabetState interface {
IsAlphabet() bool IsAlphabet() bool
} }
)
// Voter is a callback interface for alphabet contract voting. // VoteValidatorPrm groups parameters of the VoteForSidechainValidator
Voter interface { // operation.
VoteForSidechainValidator(keys keys.PublicKeys) error type VoteValidatorPrm struct {
Validators keys.PublicKeys
Hash *util.Uint256 // hash of the transaction that triggered voting
} }
// Voter is a callback interface for alphabet contract voting.
type Voter interface {
VoteForSidechainValidator(VoteValidatorPrm) error
}
type (
// EpochState is a callback interface for innerring global state. // EpochState is a callback interface for innerring global state.
EpochState interface { EpochState interface {
EpochCounter() uint64 EpochCounter() uint64

View file

@ -1,6 +1,7 @@
package neofs package neofs
import ( import (
"github.com/nspcc-dev/neofs-node/pkg/morph/client/netmap/wrapper"
neofsEvent "github.com/nspcc-dev/neofs-node/pkg/morph/event/neofs" neofsEvent "github.com/nspcc-dev/neofs-node/pkg/morph/event/neofs"
"go.uber.org/zap" "go.uber.org/zap"
) )
@ -13,7 +14,14 @@ func (np *Processor) processConfig(config *neofsEvent.Config) {
return return
} }
err := np.netmapClient.SetConfig(config.ID(), config.Key(), config.Value()) prm := wrapper.SetConfigPrm{}
prm.SetID(config.ID())
prm.SetKey(config.Key())
prm.SetValue(config.Value())
prm.SetHash(config.TxHash())
err := np.netmapClient.SetConfig(prm)
if err != nil { if err != nil {
np.log.Error("can't relay set config event", zap.Error(err)) np.log.Error("can't relay set config event", zap.Error(err))
} }

View file

@ -1,8 +1,21 @@
package netmap package netmap
import "github.com/nspcc-dev/neo-go/pkg/util"
// netmapCleanupTick is a event to remove offline nodes. // netmapCleanupTick is a event to remove offline nodes.
type netmapCleanupTick struct { type netmapCleanupTick struct {
epoch uint64 epoch uint64
// txHash is used in notary environmental
// for calculating unique but same for
// all notification receivers values.
txHash util.Uint256
}
// TxHash returns hash of the TX that triggers
// synchronization process.
func (s netmapCleanupTick) TxHash() util.Uint256 {
return s.txHash
} }
// MorphEvent implements Event interface. // MorphEvent implements Event interface.

View file

@ -2,7 +2,7 @@ package netmap
import ( import (
"github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/crypto/keys"
netmapEvent "github.com/nspcc-dev/neofs-node/pkg/morph/event/netmap" netmapclient "github.com/nspcc-dev/neofs-node/pkg/morph/client/netmap/wrapper"
"github.com/nspcc-dev/neofs-sdk-go/netmap" "github.com/nspcc-dev/neofs-sdk-go/netmap"
"go.uber.org/zap" "go.uber.org/zap"
) )
@ -25,20 +25,13 @@ func (np *Processor) processNetmapCleanupTick(ev netmapCleanupTick) {
np.log.Info("vote to remove node from netmap", zap.String("key", s)) np.log.Info("vote to remove node from netmap", zap.String("key", s))
if np.notaryDisabled { prm := netmapclient.UpdatePeerPrm{}
err = np.netmapClient.UpdatePeerState(key.Bytes(), netmap.NodeStateOffline)
} else {
// use epoch as TX nonce to prevent collisions
err = np.netmapClient.Morph().NotaryInvoke(
np.netmapClient.ContractAddress(),
0,
uint32(ev.epoch),
netmapEvent.UpdateStateNotaryEvent,
int64(netmap.NodeStateOffline.ToV2()),
key.Bytes(),
)
}
prm.SetKey(key.Bytes())
prm.SetState(netmap.NodeStateOffline)
prm.SetHash(ev.TxHash())
err = np.netmapClient.UpdatePeerState(prm)
if err != nil { if err != nil {
np.log.Error("can't invoke netmap.UpdateState", zap.Error(err)) np.log.Error("can't invoke netmap.UpdateState", zap.Error(err))
} }

View file

@ -10,8 +10,8 @@ import (
// Process new epoch notification by setting global epoch value and resetting // Process new epoch notification by setting global epoch value and resetting
// local epoch timer. // local epoch timer.
func (np *Processor) processNewEpoch(event netmapEvent.NewEpoch) { func (np *Processor) processNewEpoch(ev netmapEvent.NewEpoch) {
epoch := event.EpochNumber() epoch := ev.EpochNumber()
epochDuration, err := np.netmapClient.EpochDuration() epochDuration, err := np.netmapClient.EpochDuration()
if err != nil { if err != nil {
@ -47,11 +47,11 @@ func (np *Processor) processNewEpoch(event netmapEvent.NewEpoch) {
} }
np.netmapSnapshot.update(networkMap, epoch) np.netmapSnapshot.update(networkMap, epoch)
np.handleCleanupTick(netmapCleanupTick{epoch: epoch}) np.handleCleanupTick(netmapCleanupTick{epoch: epoch, txHash: ev.TxHash()})
np.handleNewAudit(audit.NewAuditStartEvent(epoch)) np.handleNewAudit(audit.NewAuditStartEvent(epoch))
np.handleAuditSettlements(settlement.NewAuditEvent(epoch)) np.handleAuditSettlements(settlement.NewAuditEvent(epoch))
np.handleAlphabetSync(governance.NewSyncEvent()) np.handleAlphabetSync(governance.NewSyncEvent(ev.TxHash()))
np.handleNotaryDeposit(event) np.handleNotaryDeposit(ev)
} }
// Process new epoch tick by invoking new epoch method in network map contract. // Process new epoch tick by invoking new epoch method in network map contract.

View file

@ -5,6 +5,7 @@ import (
"sort" "sort"
"strings" "strings"
netmapclient "github.com/nspcc-dev/neofs-node/pkg/morph/client/netmap/wrapper"
netmapEvent "github.com/nspcc-dev/neofs-node/pkg/morph/event/netmap" netmapEvent "github.com/nspcc-dev/neofs-node/pkg/morph/event/netmap"
"github.com/nspcc-dev/neofs-sdk-go/netmap" "github.com/nspcc-dev/neofs-sdk-go/netmap"
"go.uber.org/zap" "go.uber.org/zap"
@ -81,18 +82,22 @@ func (np *Processor) processAddPeer(ev netmapEvent.AddPeer) {
np.log.Info("approving network map candidate", np.log.Info("approving network map candidate",
zap.String("key", keyString)) zap.String("key", keyString))
prm := netmapclient.AddPeerPrm{}
prm.SetNodeInfo(nodeInfo)
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.Morph().NotaryInvoke(
np.netmapClient.ContractAddress(), np.netmapClient.ContractAddress(),
0, 0,
nr.MainTransaction.Nonce, nr.MainTransaction.Nonce,
nil,
netmapEvent.AddPeerNotaryEvent, netmapEvent.AddPeerNotaryEvent,
nodeInfoBinary, nodeInfoBinary,
) )
} else { } else {
// notification event case // notification event case
err = np.netmapClient.AddPeer(nodeInfo) err = np.netmapClient.AddPeer(prm)
} }
if err != nil { if err != nil {
@ -126,7 +131,12 @@ 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.Morph().NotarySignAndInvokeTX(nr.MainTransaction)
} else { } else {
err = np.netmapClient.UpdatePeerState(ev.PublicKey().Bytes(), ev.Status()) prm := netmapclient.UpdatePeerPrm{}
prm.SetState(ev.Status())
prm.SetKey(ev.PublicKey().Bytes())
err = np.netmapClient.UpdatePeerState(prm)
} }
if err != nil { if err != nil {
np.log.Error("can't invoke netmap.UpdatePeer", zap.Error(err)) np.log.Error("can't invoke netmap.UpdatePeer", zap.Error(err))

View file

@ -4,8 +4,8 @@ import (
"fmt" "fmt"
"sort" "sort"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neofs-node/pkg/innerring/processors/governance"
"github.com/nspcc-dev/neofs-node/pkg/services/audit" "github.com/nspcc-dev/neofs-node/pkg/services/audit"
control "github.com/nspcc-dev/neofs-node/pkg/services/control/ir" control "github.com/nspcc-dev/neofs-node/pkg/services/control/ir"
"github.com/nspcc-dev/neofs-node/pkg/util/state" "github.com/nspcc-dev/neofs-node/pkg/util/state"
@ -88,7 +88,9 @@ func (s *Server) AlphabetIndex() int {
return int(index) return int(index)
} }
func (s *Server) voteForSidechainValidator(validators keys.PublicKeys) error { func (s *Server) voteForSidechainValidator(prm governance.VoteValidatorPrm) error {
validators := prm.Validators
index := s.InnerRingIndex() index := s.InnerRingIndex()
if s.contracts.alphabet.indexOutOfRange(index) { if s.contracts.alphabet.indexOutOfRange(index) {
s.log.Info("ignore validator vote: node not in alphabet range") s.log.Info("ignore validator vote: node not in alphabet range")
@ -104,9 +106,21 @@ func (s *Server) voteForSidechainValidator(validators keys.PublicKeys) error {
epoch := s.EpochCounter() epoch := s.EpochCounter()
var (
nonce uint32 = 1
vub uint32
err error
)
if prm.Hash != nil {
nonce, vub, err = s.morphClient.CalculateNonceAndVUB(*prm.Hash)
if err != nil {
return fmt.Errorf("could not calculate nonce and `validUntilBlock` values: %w", err)
}
}
s.contracts.alphabet.iterate(func(letter GlagoliticLetter, contract util.Uint160) { s.contracts.alphabet.iterate(func(letter GlagoliticLetter, contract util.Uint160) {
// FIXME: do not use constant nonce for alphabet NR: #844 err := s.morphClient.NotaryInvoke(contract, s.feeConfig.SideChainFee(), nonce, &vub, voteMethod, int64(epoch), validators)
err := s.morphClient.NotaryInvoke(contract, s.feeConfig.SideChainFee(), 1, voteMethod, int64(epoch), validators)
if err != nil { if err != nil {
s.log.Warn("can't invoke vote method in alphabet contract", s.log.Warn("can't invoke vote method in alphabet contract",
zap.Int8("alphabet_index", int8(letter)), zap.Int8("alphabet_index", int8(letter)),
@ -120,9 +134,9 @@ func (s *Server) voteForSidechainValidator(validators keys.PublicKeys) error {
// VoteForSidechainValidator calls vote method on alphabet contracts with // VoteForSidechainValidator calls vote method on alphabet contracts with
// provided list of keys. // provided list of keys.
func (s *Server) VoteForSidechainValidator(validators keys.PublicKeys) error { func (s *Server) VoteForSidechainValidator(prm governance.VoteValidatorPrm) error {
sort.Sort(validators) sort.Sort(prm.Validators)
return s.voteForSidechainValidator(validators) return s.voteForSidechainValidator(prm)
} }
// WriteReport composes audit result structure from audit report // WriteReport composes audit result structure from audit report

View file

@ -17,6 +17,11 @@ type Lock struct {
lock util.Uint160 lock util.Uint160
amount int64 // Fixed16 amount int64 // Fixed16
until int64 until int64
// txHash is used in notary environmental
// for calculating unique but same for
// all notification receivers values.
txHash util.Uint256
} }
// MorphEvent implements Neo:Morph Event interface. // MorphEvent implements Neo:Morph Event interface.
@ -34,9 +39,13 @@ func (l Lock) LockAccount() util.Uint160 { return l.lock }
// Amount of the locked assets. // Amount of the locked assets.
func (l Lock) Amount() int64 { return l.amount } func (l Lock) Amount() int64 { return l.amount }
// Until is a epoch before locked account exists. // Until is an epoch before locked account exists.
func (l Lock) Until() int64 { return l.until } func (l Lock) Until() int64 { return l.until }
// TxHash returns hash of the TX with lock
// notification.
func (l Lock) TxHash() util.Uint256 { return l.txHash }
// ParseLock from notification into lock structure. // ParseLock from notification into lock structure.
func ParseLock(e *subscriptions.NotificationEvent) (event.Event, error) { func ParseLock(e *subscriptions.NotificationEvent) (event.Event, error) {
var ( var (
@ -93,5 +102,7 @@ func ParseLock(e *subscriptions.NotificationEvent) (event.Event, error) {
return nil, fmt.Errorf("could not get lock deadline: %w", err) return nil, fmt.Errorf("could not get lock deadline: %w", err)
} }
ev.txHash = e.Container
return ev, nil return ev, nil
} }

View file

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"github.com/nspcc-dev/neo-go/pkg/rpc/response/result/subscriptions" "github.com/nspcc-dev/neo-go/pkg/rpc/response/result/subscriptions"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neofs-node/pkg/morph/client" "github.com/nspcc-dev/neofs-node/pkg/morph/client"
"github.com/nspcc-dev/neofs-node/pkg/morph/event" "github.com/nspcc-dev/neofs-node/pkg/morph/event"
) )
@ -12,6 +13,17 @@ type Config struct {
key []byte key []byte
value []byte value []byte
id []byte id []byte
// txHash is used in notary environmental
// for calculating unique but same for
// all notification receivers values.
txHash util.Uint256
}
// TxHash returns hash of the TX with new epoch
// notification.
func (u Config) TxHash() util.Uint256 {
return u.txHash
} }
// MorphEvent implements Neo:Morph Event interface. // MorphEvent implements Neo:Morph Event interface.
@ -56,5 +68,7 @@ func ParseConfig(e *subscriptions.NotificationEvent) (event.Event, error) {
return nil, fmt.Errorf("could not get config value: %w", err) return nil, fmt.Errorf("could not get config value: %w", err)
} }
ev.txHash = e.Container
return ev, nil return ev, nil
} }

View file

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"github.com/nspcc-dev/neo-go/pkg/rpc/response/result/subscriptions" "github.com/nspcc-dev/neo-go/pkg/rpc/response/result/subscriptions"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neofs-node/pkg/morph/client" "github.com/nspcc-dev/neofs-node/pkg/morph/client"
"github.com/nspcc-dev/neofs-node/pkg/morph/event" "github.com/nspcc-dev/neofs-node/pkg/morph/event"
) )
@ -11,6 +12,11 @@ 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
// for calculating unique but same for
// all notification receivers values.
txHash util.Uint256
} }
// MorphEvent implements Neo:Morph Event interface. // MorphEvent implements Neo:Morph Event interface.
@ -21,6 +27,12 @@ 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
}
// ParseNewEpoch is a parser of new epoch notification event. // ParseNewEpoch is a parser of new epoch notification event.
// //
// Result is type of NewEpoch. // Result is type of NewEpoch.
@ -41,5 +53,6 @@ func ParseNewEpoch(e *subscriptions.NotificationEvent) (event.Event, error) {
return NewEpoch{ return NewEpoch{
num: uint64(prmEpochNum), num: uint64(prmEpochNum),
txHash: e.Container,
}, nil }, nil
} }

View file

@ -8,7 +8,6 @@ import (
"github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/network/payload" "github.com/nspcc-dev/neo-go/pkg/network/payload"
"github.com/nspcc-dev/neofs-api-go/pkg/netmap"
v2netmap "github.com/nspcc-dev/neofs-api-go/v2/netmap" v2netmap "github.com/nspcc-dev/neofs-api-go/v2/netmap"
"github.com/nspcc-dev/neofs-node/pkg/morph/client" "github.com/nspcc-dev/neofs-node/pkg/morph/client"
"github.com/nspcc-dev/neofs-node/pkg/morph/event" "github.com/nspcc-dev/neofs-node/pkg/morph/event"

View file

@ -5,12 +5,18 @@ import (
"github.com/nspcc-dev/neo-go/pkg/core/native/noderoles" "github.com/nspcc-dev/neo-go/pkg/core/native/noderoles"
"github.com/nspcc-dev/neo-go/pkg/rpc/response/result/subscriptions" "github.com/nspcc-dev/neo-go/pkg/rpc/response/result/subscriptions"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neofs-node/pkg/morph/event" "github.com/nspcc-dev/neofs-node/pkg/morph/event"
) )
// Designate represents designation event of the mainnet RoleManagement contract. // Designate represents designation event of the mainnet RoleManagement contract.
type Designate struct { type Designate struct {
Role noderoles.Role Role noderoles.Role
// TxHash is used in notary environmental
// for calculating unique but same for
// all notification receivers values.
TxHash util.Uint256
} }
// MorphEvent implements Neo:Morph Event interface. // MorphEvent implements Neo:Morph Event interface.
@ -32,5 +38,8 @@ func ParseDesignate(e *subscriptions.NotificationEvent) (event.Event, error) {
return nil, fmt.Errorf("invalid stackitem type: %w", err) return nil, fmt.Errorf("invalid stackitem type: %w", err)
} }
return Designate{Role: noderoles.Role(bi.Int64())}, nil return Designate{
Role: noderoles.Role(bi.Int64()),
TxHash: e.Container,
}, nil
} }