frostfs-node/pkg/innerring/processors/neofs/process_assets.go
Alex Vanin 0f01a69fd3 [#465] processor/neofs: Don't modify tx details
Mint, Burn and Cheque details should contain hash of
main net tx of Deposit and Withdraw invocation. They will
be formatted inside the contracts so alphabet nodes must
not modify them.

Signed-off-by: Alex Vanin <alexey@nspcc.ru>
2021-04-08 17:01:00 +03:00

127 lines
3.7 KiB
Go

package neofs
import (
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neofs-node/pkg/innerring/invoke"
neofsEvent "github.com/nspcc-dev/neofs-node/pkg/morph/event/neofs"
"go.uber.org/zap"
)
const (
// lockAccountLifeTime defines amount of epochs when lock account is valid.
lockAccountLifetime uint64 = 20
)
// Process deposit event by invoking balance contract and sending native
// gas in morph chain.
func (np *Processor) processDeposit(deposit *neofsEvent.Deposit) {
if !np.alphabetState.IsAlphabet() {
np.log.Info("non alphabet mode, ignore deposit")
return
}
// send transferX to balance contract
err := invoke.Mint(np.morphClient, np.balanceContract,
&invoke.MintBurnParams{
ScriptHash: deposit.To().BytesBE(),
Amount: np.converter.ToBalancePrecision(deposit.Amount()),
Comment: deposit.ID(),
})
if err != nil {
np.log.Error("can't transfer assets to balance contract", zap.Error(err))
}
curEpoch := np.epochState.EpochCounter()
receiver := deposit.To()
// check if receiver already received some mint GAS emissions
// we should lock there even though LRU cache is already thread save
// we lock there because GAS transfer AND cache update must be atomic
np.mintEmitLock.Lock()
defer np.mintEmitLock.Unlock()
val, ok := np.mintEmitCache.Get(receiver.String())
if ok && val.(uint64)+np.mintEmitThreshold >= curEpoch {
np.log.Warn("double mint emission declined",
zap.String("receiver", receiver.String()),
zap.Uint64("last_emission", val.(uint64)),
zap.Uint64("current_epoch", curEpoch))
return
}
// get gas balance of the node
// before gas transfer check if the balance is greater than threshold
balance, err := np.morphClient.GasBalance()
if err != nil {
np.log.Error("can't get gas balance of the node", zap.Error(err))
return
}
if balance < np.gasBalanceThreshold {
np.log.Warn("gas balance threshold has been reached",
zap.Int64("balance", balance),
zap.Int64("threshold", np.gasBalanceThreshold))
return
}
err = np.morphClient.TransferGas(receiver, np.mintEmitValue)
if err != nil {
np.log.Error("can't transfer native gas to receiver",
zap.String("error", err.Error()))
return
}
np.mintEmitCache.Add(receiver.String(), curEpoch)
}
// Process withdraw event by locking assets in balance account.
func (np *Processor) processWithdraw(withdraw *neofsEvent.Withdraw) {
if !np.alphabetState.IsAlphabet() {
np.log.Info("non alphabet mode, ignore withdraw")
return
}
// create lock account
// fixme: check collision there, consider reversed script hash
lock, err := util.Uint160DecodeBytesBE(withdraw.ID()[:util.Uint160Size])
if err != nil {
np.log.Error("can't create lock account", zap.Error(err))
return
}
curEpoch := np.epochState.EpochCounter()
err = invoke.LockAsset(np.morphClient, np.balanceContract,
&invoke.LockParams{
ID: withdraw.ID(),
User: withdraw.User(),
LockAccount: lock,
Amount: np.converter.ToBalancePrecision(withdraw.Amount()),
Until: curEpoch + lockAccountLifetime,
})
if err != nil {
np.log.Error("can't lock assets for withdraw", zap.Error(err))
}
}
// Process cheque event by transferring assets from lock account back to
// reserve account.
func (np *Processor) processCheque(cheque *neofsEvent.Cheque) {
if !np.alphabetState.IsAlphabet() {
np.log.Info("non alphabet mode, ignore cheque")
return
}
err := invoke.Burn(np.morphClient, np.balanceContract,
&invoke.MintBurnParams{
ScriptHash: cheque.LockAccount().BytesBE(),
Amount: np.converter.ToBalancePrecision(cheque.Amount()),
Comment: cheque.ID(),
})
if err != nil {
np.log.Error("can't transfer assets to fed contract", zap.Error(err))
}
}