package neofs import ( "sync" lru "github.com/hashicorp/golang-lru" "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/event" neofsEvent "github.com/nspcc-dev/neofs-node/pkg/morph/event/neofs" "github.com/panjf2000/ants/v2" "github.com/pkg/errors" "go.uber.org/zap" ) type ( // EpochState is a callback interface for inner ring global state EpochState interface { EpochCounter() uint64 } // ActiveState is a callback interface for inner ring global state ActiveState interface { IsActive() bool } // PrecisionConverter converts balance amount values. PrecisionConverter interface { ToBalancePrecision(int64) int64 } // Processor of events produced by neofs contract in main net. Processor struct { log *zap.Logger pool *ants.Pool neofsContract util.Uint160 balanceContract util.Uint160 netmapContract util.Uint160 morphClient *client.Client epochState EpochState activeState ActiveState converter PrecisionConverter mintEmitLock *sync.Mutex mintEmitCache *lru.Cache mintEmitThreshold uint64 mintEmitValue util.Fixed8 } // Params of the processor constructor. Params struct { Log *zap.Logger PoolSize int NeoFSContract util.Uint160 BalanceContract util.Uint160 NetmapContract util.Uint160 MorphClient *client.Client EpochState EpochState ActiveState ActiveState Converter PrecisionConverter MintEmitCacheSize int MintEmitThreshold uint64 // in epochs MintEmitValue util.Fixed8 } ) const ( depositNotification = "Deposit" withdrawNotification = "Withdraw" chequeNotification = "Cheque" configNotification = "SetConfig" updateIRNotification = "InnerRingUpdate" ) // New creates neofs mainnet contract processor instance. func New(p *Params) (*Processor, error) { switch { case p.Log == nil: return nil, errors.New("ir/neofs: logger is not set") case p.MorphClient == nil: return nil, errors.New("ir/neofs: neo:morph client is not set") case p.EpochState == nil: return nil, errors.New("ir/neofs: global state is not set") case p.ActiveState == nil: return nil, errors.New("ir/neofs: global state is not set") case p.Converter == nil: return nil, errors.New("ir/neofs: balance precision converter is not set") } p.Log.Debug("neofs worker pool", zap.Int("size", p.PoolSize)) pool, err := ants.NewPool(p.PoolSize, ants.WithNonblocking(true)) if err != nil { return nil, errors.Wrap(err, "ir/neofs: can't create worker pool") } lruCache, err := lru.New(p.MintEmitCacheSize) if err != nil { return nil, errors.Wrap(err, "ir/neofs: can't create LRU cache for gas emission") } return &Processor{ log: p.Log, pool: pool, neofsContract: p.NeoFSContract, balanceContract: p.BalanceContract, netmapContract: p.NetmapContract, morphClient: p.MorphClient, epochState: p.EpochState, activeState: p.ActiveState, converter: p.Converter, mintEmitLock: new(sync.Mutex), mintEmitCache: lruCache, mintEmitThreshold: p.MintEmitThreshold, mintEmitValue: p.MintEmitValue, }, nil } // ListenerParsers for the 'event.Listener' event producer. func (np *Processor) ListenerParsers() []event.ParserInfo { var parsers []event.ParserInfo // deposit event deposit := event.ParserInfo{} deposit.SetType(depositNotification) deposit.SetScriptHash(np.neofsContract) deposit.SetParser(neofsEvent.ParseDeposit) parsers = append(parsers, deposit) // withdraw event withdraw := event.ParserInfo{} withdraw.SetType(withdrawNotification) withdraw.SetScriptHash(np.neofsContract) withdraw.SetParser(neofsEvent.ParseWithdraw) parsers = append(parsers, withdraw) // cheque event cheque := event.ParserInfo{} cheque.SetType(chequeNotification) cheque.SetScriptHash(np.neofsContract) cheque.SetParser(neofsEvent.ParseCheque) parsers = append(parsers, cheque) // config event config := event.ParserInfo{} config.SetType(configNotification) config.SetScriptHash(np.neofsContract) config.SetParser(neofsEvent.ParseConfig) parsers = append(parsers, config) // update inner ring event updateIR := event.ParserInfo{} updateIR.SetType(updateIRNotification) updateIR.SetScriptHash(np.neofsContract) updateIR.SetParser(neofsEvent.ParseUpdateInnerRing) parsers = append(parsers, updateIR) return parsers } // ListenerHandlers for the 'event.Listener' event producer. func (np *Processor) ListenerHandlers() []event.HandlerInfo { var handlers []event.HandlerInfo // deposit handler deposit := event.HandlerInfo{} deposit.SetType(depositNotification) deposit.SetScriptHash(np.neofsContract) deposit.SetHandler(np.handleDeposit) handlers = append(handlers, deposit) // withdraw handler withdraw := event.HandlerInfo{} withdraw.SetType(withdrawNotification) withdraw.SetScriptHash(np.neofsContract) withdraw.SetHandler(np.handleWithdraw) handlers = append(handlers, withdraw) // cheque handler cheque := event.HandlerInfo{} cheque.SetType(chequeNotification) cheque.SetScriptHash(np.neofsContract) cheque.SetHandler(np.handleCheque) handlers = append(handlers, cheque) // config handler config := event.HandlerInfo{} config.SetType(configNotification) config.SetScriptHash(np.neofsContract) config.SetHandler(np.handleConfig) handlers = append(handlers, config) // updateIR handler updateIR := event.HandlerInfo{} updateIR.SetType(updateIRNotification) updateIR.SetScriptHash(np.neofsContract) updateIR.SetHandler(np.handleUpdateInnerRing) handlers = append(handlers, updateIR) return handlers } // TimersHandlers for the 'Timers' event producer. func (np *Processor) TimersHandlers() []event.HandlerInfo { return nil }