package container import ( "errors" "fmt" frostfsidclient "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" containerEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "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/util" "github.com/panjf2000/ants/v2" "go.uber.org/zap" ) type ( // AlphabetState is a callback interface for inner ring global state. AlphabetState interface { IsAlphabet() bool } ContClient interface { ContractAddress() util.Uint160 Get(cid []byte) (*containercore.Container, error) } MorphClient interface { NotarySignAndInvokeTX(mainTx *transaction.Transaction) error } FrostFSIDClient interface { GetSubject(addr util.Uint160) (*frostfsidclient.Subject, error) } // Processor of events produced by container contract in the sidechain. Processor struct { log *logger.Logger metrics metrics.Register pool *ants.Pool alphabetState AlphabetState cnrClient ContClient // notary must be enabled morphClient MorphClient netState NetworkState frostFSIDClient FrostFSIDClient } // Params of the processor constructor. Params struct { Log *logger.Logger Metrics metrics.Register PoolSize int AlphabetState AlphabetState ContainerClient ContClient MorphClient MorphClient NetworkState NetworkState FrostFSIDClient FrostFSIDClient } ) // NetworkState is an interface of a component // that provides access to network state. type NetworkState interface { // Epoch must return the number of the current epoch. // // Must return any error encountered // which did not allow reading the value. Epoch() (uint64, error) // HomomorphicHashDisabled must return boolean that // represents homomorphic network state: // * true if hashing is disabled; // * false if hashing is enabled. // // which did not allow reading the value. HomomorphicHashDisabled() (bool, error) } // New creates a container contract processor instance. func New(p *Params) (*Processor, error) { switch { case p.Log == nil: return nil, errors.New("ir/container: logger is not set") case p.AlphabetState == nil: return nil, errors.New("ir/container: global state is not set") case p.ContainerClient == nil: return nil, errors.New("ir/container: Container client is not set") case p.MorphClient == nil: return nil, errors.New("ir/container: Morph client is not set") case p.NetworkState == nil: return nil, errors.New("ir/container: network state is not set") case p.FrostFSIDClient == nil: return nil, errors.New("ir/container: FrostFSID client is not set") } p.Log.Debug(logs.ContainerContainerWorkerPool, zap.Int("size", p.PoolSize)) pool, err := ants.NewPool(p.PoolSize, ants.WithNonblocking(true)) if err != nil { return nil, fmt.Errorf("ir/container: can't create worker pool: %w", err) } metricsRegister := p.Metrics if metricsRegister == nil { metricsRegister = metrics.DefaultRegister{} } return &Processor{ log: p.Log, metrics: metricsRegister, pool: pool, alphabetState: p.AlphabetState, cnrClient: p.ContainerClient, netState: p.NetworkState, morphClient: p.MorphClient, frostFSIDClient: p.FrostFSIDClient, }, nil } // ListenerNotificationParsers for the 'event.Listener' event producer. func (cp *Processor) ListenerNotificationParsers() []event.NotificationParserInfo { return nil } // ListenerNotificationHandlers for the 'event.Listener' event producer. func (cp *Processor) ListenerNotificationHandlers() []event.NotificationHandlerInfo { return nil } // ListenerNotaryParsers for the 'event.Listener' notary event producer. func (cp *Processor) ListenerNotaryParsers() []event.NotaryParserInfo { var ( p event.NotaryParserInfo pp = make([]event.NotaryParserInfo, 0, 4) ) p.SetMempoolType(mempoolevent.TransactionAdded) p.SetScriptHash(cp.cnrClient.ContractAddress()) // container put p.SetRequestType(containerEvent.PutNotaryEvent) p.SetParser(containerEvent.ParsePutNotary) pp = append(pp, p) // container named put p.SetRequestType(containerEvent.PutNamedNotaryEvent) p.SetParser(containerEvent.ParsePutNamedNotary) pp = append(pp, p) // container delete p.SetRequestType(containerEvent.DeleteNotaryEvent) p.SetParser(containerEvent.ParseDeleteNotary) pp = append(pp, p) // set EACL p.SetRequestType(containerEvent.SetEACLNotaryEvent) p.SetParser(containerEvent.ParseSetEACLNotary) pp = append(pp, p) return pp } // ListenerNotaryHandlers for the 'event.Listener' notary event producer. func (cp *Processor) ListenerNotaryHandlers() []event.NotaryHandlerInfo { var ( h event.NotaryHandlerInfo hh = make([]event.NotaryHandlerInfo, 0, 4) ) h.SetScriptHash(cp.cnrClient.ContractAddress()) h.SetMempoolType(mempoolevent.TransactionAdded) // container put h.SetRequestType(containerEvent.PutNotaryEvent) h.SetHandler(cp.handlePut) hh = append(hh, h) // container named put (same handler) h.SetRequestType(containerEvent.PutNamedNotaryEvent) hh = append(hh, h) // container delete h.SetRequestType(containerEvent.DeleteNotaryEvent) h.SetHandler(cp.handleDelete) hh = append(hh, h) // set eACL h.SetRequestType(containerEvent.SetEACLNotaryEvent) h.SetHandler(cp.handleSetEACL) hh = append(hh, h) return hh }