[#556] innerring/neofs: Process Bind/Unbind events
Make IR processor of NeoFS contract to handle `Bind`/`Unbind` notification events. The processor verifies the format of wallet script hash and public keys, and call NeoFS ID client wrapper in order to approve adding/removing keys from NeoFS account. Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
parent
48d934ecf8
commit
ed80f704d0
4 changed files with 215 additions and 42 deletions
|
@ -602,6 +602,7 @@ func New(ctx context.Context, log *zap.Logger, cfg *viper.Viper) (*Server, error
|
||||||
NeoFSContract: server.contracts.neofs,
|
NeoFSContract: server.contracts.neofs,
|
||||||
BalanceContract: server.contracts.balance,
|
BalanceContract: server.contracts.balance,
|
||||||
NetmapContract: server.contracts.netmap,
|
NetmapContract: server.contracts.netmap,
|
||||||
|
NeoFSIDContract: server.contracts.neofsID,
|
||||||
MorphClient: server.morphClient,
|
MorphClient: server.morphClient,
|
||||||
EpochState: server,
|
EpochState: server,
|
||||||
AlphabetState: server,
|
AlphabetState: server,
|
||||||
|
|
|
@ -72,3 +72,35 @@ func (np *Processor) handleConfig(ev event.Event) {
|
||||||
zap.Int("capacity", np.pool.Cap()))
|
zap.Int("capacity", np.pool.Cap()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (np *Processor) handleBind(ev event.Event) {
|
||||||
|
e := ev.(neofsEvent.Bind)
|
||||||
|
np.log.Info("notification",
|
||||||
|
zap.String("type", "bind"),
|
||||||
|
)
|
||||||
|
|
||||||
|
// send event to the worker pool
|
||||||
|
|
||||||
|
err := np.pool.Submit(func() { np.processBind(e) })
|
||||||
|
if err != nil {
|
||||||
|
// there system can be moved into controlled degradation stage
|
||||||
|
np.log.Warn("neofs processor worker pool drained",
|
||||||
|
zap.Int("capacity", np.pool.Cap()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (np *Processor) handleUnbind(ev event.Event) {
|
||||||
|
e := ev.(neofsEvent.Unbind)
|
||||||
|
np.log.Info("notification",
|
||||||
|
zap.String("type", "unbind"),
|
||||||
|
)
|
||||||
|
|
||||||
|
// send event to the worker pool
|
||||||
|
|
||||||
|
err := np.pool.Submit(func() { np.processBind(e) })
|
||||||
|
if err != nil {
|
||||||
|
// there system can be moved into controlled degradation stage
|
||||||
|
np.log.Warn("neofs processor worker pool drained",
|
||||||
|
zap.Int("capacity", np.pool.Cap()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
110
pkg/innerring/processors/neofs/process_bind.go
Normal file
110
pkg/innerring/processors/neofs/process_bind.go
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
package neofs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/elliptic"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/mr-tron/base58"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
|
"github.com/nspcc-dev/neofs-node/pkg/morph/event/neofs"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
)
|
||||||
|
|
||||||
|
type bindCommon interface {
|
||||||
|
User() []byte
|
||||||
|
Keys() [][]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (np *Processor) processBind(e bindCommon) {
|
||||||
|
if !np.alphabetState.IsAlphabet() {
|
||||||
|
np.log.Info("non alphabet mode, ignore bind")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c := &bindCommonContext{
|
||||||
|
bindCommon: e,
|
||||||
|
}
|
||||||
|
|
||||||
|
_, c.bind = e.(neofs.Bind)
|
||||||
|
|
||||||
|
err := np.checkBindCommon(c)
|
||||||
|
if err != nil {
|
||||||
|
np.log.Error("invalid manage key event",
|
||||||
|
zap.Bool("bind", c.bind),
|
||||||
|
zap.String("error", err.Error()),
|
||||||
|
)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
np.approveBindCommon(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
type bindCommonContext struct {
|
||||||
|
bindCommon
|
||||||
|
|
||||||
|
bind bool
|
||||||
|
|
||||||
|
scriptHash util.Uint160
|
||||||
|
}
|
||||||
|
|
||||||
|
func (np *Processor) checkBindCommon(e *bindCommonContext) error {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
e.scriptHash, err = util.Uint160DecodeBytesBE(e.User())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
curve := elliptic.P256()
|
||||||
|
|
||||||
|
for _, key := range e.Keys() {
|
||||||
|
_, err = keys.NewPublicKeyFromBytes(key, curve)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (np *Processor) approveBindCommon(e *bindCommonContext) {
|
||||||
|
// calculate wallet address
|
||||||
|
// TODO: implement some utilities in API Go lib to do it
|
||||||
|
scriptHash := e.User()
|
||||||
|
|
||||||
|
u160, err := util.Uint160DecodeBytesBE(scriptHash)
|
||||||
|
if err != nil {
|
||||||
|
np.log.Error("could not decode script hash from bytes",
|
||||||
|
zap.String("error", err.Error()),
|
||||||
|
)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
wallet, err := base58.Decode(address.Uint160ToString(u160))
|
||||||
|
if err != nil {
|
||||||
|
np.log.Error("could not decode wallet address",
|
||||||
|
zap.String("error", err.Error()),
|
||||||
|
)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = np.neofsIDClient.ManageKeys(wallet, e.Keys(), e.bind)
|
||||||
|
if err != nil {
|
||||||
|
var typ string
|
||||||
|
|
||||||
|
if e.bind {
|
||||||
|
typ = "bind"
|
||||||
|
} else {
|
||||||
|
typ = "unbind"
|
||||||
|
}
|
||||||
|
|
||||||
|
np.log.Error(fmt.Sprintf("could not approve %s", typ),
|
||||||
|
zap.String("error", err.Error()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/innerring/config"
|
"github.com/nspcc-dev/neofs-node/pkg/innerring/config"
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/morph/client"
|
"github.com/nspcc-dev/neofs-node/pkg/morph/client"
|
||||||
|
neofsid "github.com/nspcc-dev/neofs-node/pkg/morph/client/neofsid/wrapper"
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/morph/event"
|
"github.com/nspcc-dev/neofs-node/pkg/morph/event"
|
||||||
neofsEvent "github.com/nspcc-dev/neofs-node/pkg/morph/event/neofs"
|
neofsEvent "github.com/nspcc-dev/neofs-node/pkg/morph/event/neofs"
|
||||||
"github.com/panjf2000/ants/v2"
|
"github.com/panjf2000/ants/v2"
|
||||||
|
@ -39,6 +40,7 @@ type (
|
||||||
neofsContract util.Uint160
|
neofsContract util.Uint160
|
||||||
balanceContract util.Uint160
|
balanceContract util.Uint160
|
||||||
netmapContract util.Uint160
|
netmapContract util.Uint160
|
||||||
|
neofsIDContract util.Uint160
|
||||||
morphClient *client.Client
|
morphClient *client.Client
|
||||||
epochState EpochState
|
epochState EpochState
|
||||||
alphabetState AlphabetState
|
alphabetState AlphabetState
|
||||||
|
@ -49,6 +51,8 @@ type (
|
||||||
mintEmitThreshold uint64
|
mintEmitThreshold uint64
|
||||||
mintEmitValue fixedn.Fixed8
|
mintEmitValue fixedn.Fixed8
|
||||||
gasBalanceThreshold int64
|
gasBalanceThreshold int64
|
||||||
|
|
||||||
|
neofsIDClient *neofsid.ClientWrapper
|
||||||
}
|
}
|
||||||
|
|
||||||
// Params of the processor constructor.
|
// Params of the processor constructor.
|
||||||
|
@ -58,6 +62,7 @@ type (
|
||||||
NeoFSContract util.Uint160
|
NeoFSContract util.Uint160
|
||||||
BalanceContract util.Uint160
|
BalanceContract util.Uint160
|
||||||
NetmapContract util.Uint160
|
NetmapContract util.Uint160
|
||||||
|
NeoFSIDContract util.Uint160
|
||||||
MorphClient *client.Client
|
MorphClient *client.Client
|
||||||
EpochState EpochState
|
EpochState EpochState
|
||||||
AlphabetState AlphabetState
|
AlphabetState AlphabetState
|
||||||
|
@ -75,6 +80,8 @@ const (
|
||||||
withdrawNotification = "Withdraw"
|
withdrawNotification = "Withdraw"
|
||||||
chequeNotification = "Cheque"
|
chequeNotification = "Cheque"
|
||||||
configNotification = "SetConfig"
|
configNotification = "SetConfig"
|
||||||
|
bindNotification = "Bind"
|
||||||
|
unbindNotification = "Unbind"
|
||||||
)
|
)
|
||||||
|
|
||||||
// New creates neofs mainnet contract processor instance.
|
// New creates neofs mainnet contract processor instance.
|
||||||
|
@ -106,6 +113,11 @@ func New(p *Params) (*Processor, error) {
|
||||||
return nil, fmt.Errorf("ir/neofs: can't create LRU cache for gas emission: %w", err)
|
return nil, fmt.Errorf("ir/neofs: can't create LRU cache for gas emission: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clientWrapper, err := neofsid.NewFromMorph(p.MorphClient, p.NeoFSIDContract, p.FeeProvider.SideChainFee())
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not create NeoFS ID client wrapper: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
return &Processor{
|
return &Processor{
|
||||||
log: p.Log,
|
log: p.Log,
|
||||||
pool: pool,
|
pool: pool,
|
||||||
|
@ -122,75 +134,93 @@ func New(p *Params) (*Processor, error) {
|
||||||
mintEmitThreshold: p.MintEmitThreshold,
|
mintEmitThreshold: p.MintEmitThreshold,
|
||||||
mintEmitValue: p.MintEmitValue,
|
mintEmitValue: p.MintEmitValue,
|
||||||
gasBalanceThreshold: p.GasBalanceThreshold,
|
gasBalanceThreshold: p.GasBalanceThreshold,
|
||||||
|
|
||||||
|
neofsIDClient: clientWrapper,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListenerParsers for the 'event.Listener' event producer.
|
// ListenerParsers for the 'event.Listener' event producer.
|
||||||
func (np *Processor) ListenerParsers() []event.ParserInfo {
|
func (np *Processor) ListenerParsers() []event.ParserInfo {
|
||||||
var parsers []event.ParserInfo
|
var (
|
||||||
|
parsers = make([]event.ParserInfo, 0, 6)
|
||||||
|
|
||||||
|
p event.ParserInfo
|
||||||
|
)
|
||||||
|
|
||||||
|
p.SetScriptHash(np.neofsContract)
|
||||||
|
|
||||||
// deposit event
|
// deposit event
|
||||||
deposit := event.ParserInfo{}
|
p.SetType(event.TypeFromString(depositNotification))
|
||||||
deposit.SetType(depositNotification)
|
p.SetParser(neofsEvent.ParseDeposit)
|
||||||
deposit.SetScriptHash(np.neofsContract)
|
parsers = append(parsers, p)
|
||||||
deposit.SetParser(neofsEvent.ParseDeposit)
|
|
||||||
parsers = append(parsers, deposit)
|
|
||||||
|
|
||||||
// withdraw event
|
// withdraw event
|
||||||
withdraw := event.ParserInfo{}
|
p.SetType(event.TypeFromString(withdrawNotification))
|
||||||
withdraw.SetType(withdrawNotification)
|
p.SetParser(neofsEvent.ParseWithdraw)
|
||||||
withdraw.SetScriptHash(np.neofsContract)
|
parsers = append(parsers, p)
|
||||||
withdraw.SetParser(neofsEvent.ParseWithdraw)
|
|
||||||
parsers = append(parsers, withdraw)
|
|
||||||
|
|
||||||
// cheque event
|
// cheque event
|
||||||
cheque := event.ParserInfo{}
|
p.SetType(event.TypeFromString(chequeNotification))
|
||||||
cheque.SetType(chequeNotification)
|
p.SetParser(neofsEvent.ParseCheque)
|
||||||
cheque.SetScriptHash(np.neofsContract)
|
parsers = append(parsers, p)
|
||||||
cheque.SetParser(neofsEvent.ParseCheque)
|
|
||||||
parsers = append(parsers, cheque)
|
|
||||||
|
|
||||||
// config event
|
// config event
|
||||||
config := event.ParserInfo{}
|
p.SetType(event.TypeFromString(configNotification))
|
||||||
config.SetType(configNotification)
|
p.SetParser(neofsEvent.ParseConfig)
|
||||||
config.SetScriptHash(np.neofsContract)
|
parsers = append(parsers, p)
|
||||||
config.SetParser(neofsEvent.ParseConfig)
|
|
||||||
parsers = append(parsers, config)
|
// bind event
|
||||||
|
p.SetType(event.TypeFromString(bindNotification))
|
||||||
|
p.SetParser(neofsEvent.ParseBind)
|
||||||
|
parsers = append(parsers, p)
|
||||||
|
|
||||||
|
// unbind event
|
||||||
|
p.SetType(event.TypeFromString(unbindNotification))
|
||||||
|
p.SetParser(neofsEvent.ParseUnbind)
|
||||||
|
parsers = append(parsers, p)
|
||||||
|
|
||||||
return parsers
|
return parsers
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListenerHandlers for the 'event.Listener' event producer.
|
// ListenerHandlers for the 'event.Listener' event producer.
|
||||||
func (np *Processor) ListenerHandlers() []event.HandlerInfo {
|
func (np *Processor) ListenerHandlers() []event.HandlerInfo {
|
||||||
var handlers []event.HandlerInfo
|
var (
|
||||||
|
handlers = make([]event.HandlerInfo, 0, 6)
|
||||||
|
|
||||||
|
h event.HandlerInfo
|
||||||
|
)
|
||||||
|
|
||||||
|
h.SetScriptHash(np.neofsContract)
|
||||||
|
|
||||||
// deposit handler
|
// deposit handler
|
||||||
deposit := event.HandlerInfo{}
|
h.SetType(event.TypeFromString(depositNotification))
|
||||||
deposit.SetType(depositNotification)
|
h.SetHandler(np.handleDeposit)
|
||||||
deposit.SetScriptHash(np.neofsContract)
|
handlers = append(handlers, h)
|
||||||
deposit.SetHandler(np.handleDeposit)
|
|
||||||
handlers = append(handlers, deposit)
|
|
||||||
|
|
||||||
// withdraw handler
|
// withdraw handler
|
||||||
withdraw := event.HandlerInfo{}
|
h.SetType(event.TypeFromString(withdrawNotification))
|
||||||
withdraw.SetType(withdrawNotification)
|
h.SetHandler(np.handleWithdraw)
|
||||||
withdraw.SetScriptHash(np.neofsContract)
|
handlers = append(handlers, h)
|
||||||
withdraw.SetHandler(np.handleWithdraw)
|
|
||||||
handlers = append(handlers, withdraw)
|
|
||||||
|
|
||||||
// cheque handler
|
// cheque handler
|
||||||
cheque := event.HandlerInfo{}
|
h.SetType(event.TypeFromString(chequeNotification))
|
||||||
cheque.SetType(chequeNotification)
|
h.SetHandler(np.handleCheque)
|
||||||
cheque.SetScriptHash(np.neofsContract)
|
handlers = append(handlers, h)
|
||||||
cheque.SetHandler(np.handleCheque)
|
|
||||||
handlers = append(handlers, cheque)
|
|
||||||
|
|
||||||
// config handler
|
// config handler
|
||||||
config := event.HandlerInfo{}
|
h.SetType(event.TypeFromString(configNotification))
|
||||||
config.SetType(configNotification)
|
h.SetHandler(np.handleConfig)
|
||||||
config.SetScriptHash(np.neofsContract)
|
handlers = append(handlers, h)
|
||||||
config.SetHandler(np.handleConfig)
|
|
||||||
handlers = append(handlers, config)
|
// bind handler
|
||||||
|
h.SetType(event.TypeFromString(bindNotification))
|
||||||
|
h.SetHandler(np.handleBind)
|
||||||
|
handlers = append(handlers, h)
|
||||||
|
|
||||||
|
// unbind handler
|
||||||
|
h.SetType(event.TypeFromString(unbindNotification))
|
||||||
|
h.SetHandler(np.handleUnbind)
|
||||||
|
handlers = append(handlers, h)
|
||||||
|
|
||||||
return handlers
|
return handlers
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue