package alphabet import ( "context" "crypto/elliptic" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" "github.com/nspcc-dev/neo-go/pkg/util" "go.uber.org/zap" ) const emitMethod = "emit" func (ap *Processor) processEmit(ctx context.Context) bool { index := ap.irList.AlphabetIndex(ctx) if index < 0 { ap.log.Info(ctx, logs.AlphabetNonAlphabetModeIgnoreGasEmissionEvent) return true } contract, ok := ap.alphabetContracts.GetByIndex(index) if !ok { ap.log.Debug(ctx, logs.AlphabetNodeIsOutOfAlphabetRangeIgnoreGasEmissionEvent, zap.Int("index", index)) return false } // there is no signature collecting, so we don't need extra fee _, err := ap.morphClient.Invoke(ctx, contract, 0, emitMethod) if err != nil { ap.log.Warn(ctx, logs.AlphabetCantInvokeAlphabetEmitMethod, zap.String("error", err.Error())) return false } if ap.storageEmission == 0 { ap.log.Info(ctx, logs.AlphabetStorageNodeEmissionIsOff) return true } networkMap, err := ap.netmapClient.NetMap() if err != nil { ap.log.Warn(ctx, logs.AlphabetCantGetNetmapSnapshotToEmitGasToStorageNodes, zap.String("error", err.Error())) return false } nmNodes := networkMap.Nodes() nmLen := len(nmNodes) ap.pwLock.RLock() pw := ap.parsedWallets ap.pwLock.RUnlock() extraLen := len(pw) ap.log.Debug(ctx, logs.AlphabetGasEmission, zap.Int("network_map", nmLen), zap.Int("extra_wallets", extraLen)) if nmLen+extraLen == 0 { return true } gasPerNode := fixedn.Fixed8(ap.storageEmission / uint64(nmLen+extraLen)) ap.transferGasToNetmapNodes(ctx, nmNodes, gasPerNode) ap.transferGasToExtraNodes(ctx, pw, gasPerNode) return true } func (ap *Processor) transferGasToNetmapNodes(ctx context.Context, nmNodes []netmap.NodeInfo, gasPerNode fixedn.Fixed8) { for i := range nmNodes { keyBytes := nmNodes[i].PublicKey() key, err := keys.NewPublicKeyFromBytes(keyBytes, elliptic.P256()) if err != nil { ap.log.Warn(ctx, logs.AlphabetCantParseNodePublicKey, zap.String("error", err.Error())) continue } err = ap.morphClient.TransferGas(key.GetScriptHash(), gasPerNode) if err != nil { ap.log.Warn(ctx, logs.AlphabetCantTransferGas, zap.String("receiver", key.Address()), zap.Int64("amount", int64(gasPerNode)), zap.String("error", err.Error()), ) } } } func (ap *Processor) transferGasToExtraNodes(ctx context.Context, pw []util.Uint160, gasPerNode fixedn.Fixed8) { if len(pw) > 0 { err := ap.morphClient.BatchTransferGas(pw, gasPerNode) if err != nil { receiversLog := make([]string, len(pw)) for i, addr := range pw { receiversLog[i] = addr.StringLE() } ap.log.Warn(ctx, logs.AlphabetCantTransferGasToWallet, zap.Strings("receivers", receiversLog), zap.Int64("amount", int64(gasPerNode)), zap.String("error", err.Error()), ) } } }