2022-12-23 17:35:35 +00:00
|
|
|
package frostfs
|
2020-07-24 13:54:03 +00:00
|
|
|
|
|
|
|
import (
|
2024-10-21 07:22:54 +00:00
|
|
|
"context"
|
|
|
|
|
2023-04-12 14:35:10 +00:00
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
|
2023-03-07 13:38:26 +00:00
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/balance"
|
|
|
|
frostfsEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/frostfs"
|
2020-07-24 13:54:03 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
|
|
|
"go.uber.org/zap"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
2022-04-21 11:28:05 +00:00
|
|
|
// lockAccountLifeTime defines the amount of epochs when lock account is valid.
|
2020-07-24 13:54:03 +00:00
|
|
|
lockAccountLifetime uint64 = 20
|
|
|
|
)
|
|
|
|
|
2022-04-21 11:28:05 +00:00
|
|
|
// Process deposit event by invoking a balance contract and sending native
|
|
|
|
// gas in the sidechain.
|
2024-10-21 13:27:28 +00:00
|
|
|
func (np *Processor) processDeposit(ctx context.Context, deposit frostfsEvent.Deposit) bool {
|
|
|
|
if !np.alphabetState.IsAlphabet(ctx) {
|
|
|
|
np.log.Info(ctx, logs.FrostFSNonAlphabetModeIgnoreDeposit)
|
2023-05-26 10:24:41 +00:00
|
|
|
return true
|
2020-07-24 13:54:03 +00:00
|
|
|
}
|
|
|
|
|
2022-01-31 09:24:25 +00:00
|
|
|
prm := balance.MintPrm{}
|
2021-11-14 22:07:39 +00:00
|
|
|
|
|
|
|
prm.SetTo(deposit.To())
|
|
|
|
prm.SetAmount(np.converter.ToBalancePrecision(deposit.Amount()))
|
|
|
|
prm.SetID(deposit.ID())
|
|
|
|
|
2022-04-21 11:28:05 +00:00
|
|
|
// send transferX to a balance contract
|
2024-10-21 13:27:28 +00:00
|
|
|
err := np.balanceClient.Mint(ctx, prm)
|
2020-07-24 13:54:03 +00:00
|
|
|
if err != nil {
|
2024-10-21 13:27:28 +00:00
|
|
|
np.log.Error(ctx, logs.FrostFSCantTransferAssetsToBalanceContract, zap.Error(err))
|
2020-07-24 13:54:03 +00:00
|
|
|
}
|
|
|
|
|
2020-11-03 11:16:32 +00:00
|
|
|
curEpoch := np.epochState.EpochCounter()
|
|
|
|
receiver := deposit.To()
|
|
|
|
|
2022-04-21 11:28:05 +00:00
|
|
|
// check if the receiver has already received some mint GAS emissions
|
2020-11-03 11:16:32 +00:00
|
|
|
// 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())
|
2022-12-30 09:51:49 +00:00
|
|
|
if ok && val+np.mintEmitThreshold >= curEpoch {
|
2024-10-21 13:27:28 +00:00
|
|
|
np.log.Warn(ctx, logs.FrostFSDoubleMintEmissionDeclined,
|
2023-08-14 11:08:18 +00:00
|
|
|
zap.Stringer("receiver", receiver),
|
2022-12-30 09:51:49 +00:00
|
|
|
zap.Uint64("last_emission", val),
|
2020-11-03 11:16:32 +00:00
|
|
|
zap.Uint64("current_epoch", curEpoch))
|
|
|
|
|
2023-05-26 10:24:41 +00:00
|
|
|
return false
|
2020-11-03 11:16:32 +00:00
|
|
|
}
|
|
|
|
|
2021-03-18 17:42:35 +00:00
|
|
|
// get gas balance of the node
|
2022-04-21 11:28:05 +00:00
|
|
|
// before gas transfer check if the balance is greater than the threshold
|
2021-03-18 17:42:35 +00:00
|
|
|
balance, err := np.morphClient.GasBalance()
|
|
|
|
if err != nil {
|
2024-10-21 13:27:28 +00:00
|
|
|
np.log.Error(ctx, logs.FrostFSCantGetGasBalanceOfTheNode, zap.Error(err))
|
2023-05-26 10:24:41 +00:00
|
|
|
return false
|
2021-03-18 17:42:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if balance < np.gasBalanceThreshold {
|
2024-10-21 13:27:28 +00:00
|
|
|
np.log.Warn(ctx, logs.FrostFSGasBalanceThresholdHasBeenReached,
|
2021-03-18 17:42:35 +00:00
|
|
|
zap.Int64("balance", balance),
|
|
|
|
zap.Int64("threshold", np.gasBalanceThreshold))
|
|
|
|
|
2023-05-26 10:24:41 +00:00
|
|
|
return false
|
2021-03-18 17:42:35 +00:00
|
|
|
}
|
|
|
|
|
2020-11-03 11:16:32 +00:00
|
|
|
err = np.morphClient.TransferGas(receiver, np.mintEmitValue)
|
2020-07-24 13:54:03 +00:00
|
|
|
if err != nil {
|
2024-10-21 13:27:28 +00:00
|
|
|
np.log.Error(ctx, logs.FrostFSCantTransferNativeGasToReceiver,
|
2024-12-13 08:44:56 +00:00
|
|
|
zap.Error(err))
|
2020-11-03 11:16:32 +00:00
|
|
|
|
2023-05-26 10:24:41 +00:00
|
|
|
return false
|
2020-07-24 13:54:03 +00:00
|
|
|
}
|
2020-11-03 11:16:32 +00:00
|
|
|
|
|
|
|
np.mintEmitCache.Add(receiver.String(), curEpoch)
|
2023-05-26 10:24:41 +00:00
|
|
|
|
|
|
|
return true
|
2020-07-24 13:54:03 +00:00
|
|
|
}
|
|
|
|
|
2022-04-21 11:28:05 +00:00
|
|
|
// Process withdraw event by locking assets in the balance account.
|
2024-10-21 13:27:28 +00:00
|
|
|
func (np *Processor) processWithdraw(ctx context.Context, withdraw frostfsEvent.Withdraw) bool {
|
|
|
|
if !np.alphabetState.IsAlphabet(ctx) {
|
|
|
|
np.log.Info(ctx, logs.FrostFSNonAlphabetModeIgnoreWithdraw)
|
2023-05-26 10:24:41 +00:00
|
|
|
return true
|
2020-07-24 13:54:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// create lock account
|
|
|
|
lock, err := util.Uint160DecodeBytesBE(withdraw.ID()[:util.Uint160Size])
|
|
|
|
if err != nil {
|
2024-10-21 13:27:28 +00:00
|
|
|
np.log.Error(ctx, logs.FrostFSCantCreateLockAccount, zap.Error(err))
|
2023-05-26 10:24:41 +00:00
|
|
|
return false
|
2020-07-24 13:54:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
curEpoch := np.epochState.EpochCounter()
|
|
|
|
|
2022-01-31 09:24:25 +00:00
|
|
|
prm := balance.LockPrm{}
|
2021-11-14 22:07:39 +00:00
|
|
|
|
|
|
|
prm.SetID(withdraw.ID())
|
|
|
|
prm.SetUser(withdraw.User())
|
|
|
|
prm.SetLock(lock)
|
|
|
|
prm.SetAmount(np.converter.ToBalancePrecision(withdraw.Amount()))
|
|
|
|
prm.SetDueEpoch(int64(curEpoch + lockAccountLifetime))
|
|
|
|
|
2024-10-21 13:27:28 +00:00
|
|
|
err = np.balanceClient.Lock(ctx, prm)
|
2020-07-24 13:54:03 +00:00
|
|
|
if err != nil {
|
2024-10-21 13:27:28 +00:00
|
|
|
np.log.Error(ctx, logs.FrostFSCantLockAssetsForWithdraw, zap.Error(err))
|
2023-05-26 10:24:41 +00:00
|
|
|
return false
|
2020-07-24 13:54:03 +00:00
|
|
|
}
|
2023-05-26 10:24:41 +00:00
|
|
|
|
|
|
|
return true
|
2020-07-24 13:54:03 +00:00
|
|
|
}
|
|
|
|
|
2022-04-21 11:28:05 +00:00
|
|
|
// Process cheque event by transferring assets from the lock account back to
|
|
|
|
// the reserve account.
|
2024-10-21 13:27:28 +00:00
|
|
|
func (np *Processor) processCheque(ctx context.Context, cheque frostfsEvent.Cheque) bool {
|
|
|
|
if !np.alphabetState.IsAlphabet(ctx) {
|
|
|
|
np.log.Info(ctx, logs.FrostFSNonAlphabetModeIgnoreCheque)
|
2023-05-26 10:24:41 +00:00
|
|
|
return true
|
2020-07-24 13:54:03 +00:00
|
|
|
}
|
|
|
|
|
2022-01-31 09:24:25 +00:00
|
|
|
prm := balance.BurnPrm{}
|
2021-11-14 22:07:39 +00:00
|
|
|
|
|
|
|
prm.SetTo(cheque.LockAccount())
|
|
|
|
prm.SetAmount(np.converter.ToBalancePrecision(cheque.Amount()))
|
|
|
|
prm.SetID(cheque.ID())
|
|
|
|
|
2024-10-21 13:27:28 +00:00
|
|
|
err := np.balanceClient.Burn(ctx, prm)
|
2020-07-24 13:54:03 +00:00
|
|
|
if err != nil {
|
2024-10-21 13:27:28 +00:00
|
|
|
np.log.Error(ctx, logs.FrostFSCantTransferAssetsToFedContract, zap.Error(err))
|
2023-05-26 10:24:41 +00:00
|
|
|
return false
|
2020-07-24 13:54:03 +00:00
|
|
|
}
|
2023-05-26 10:24:41 +00:00
|
|
|
|
|
|
|
return true
|
2020-07-24 13:54:03 +00:00
|
|
|
}
|