Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make it single network per chain #107

Merged
merged 7 commits into from
Dec 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,17 @@ Changelog for NeoFS Monitor

### Changed
- Usage of Locode DB Go package (#100)
- Configuration supports only one chain in a moment (#103)

### Removed
- Locode DB configuration options (#100)

### Upgrading from v0.9.5

The configuration sections `mainnet` and `morph` were replaced with similar `chain` sections. To choice between
main (Neo) chain and side (NeoFS) chain, use `chain.fschain` option. If true, monitor connects to the NeoFS chain,
otherwise, to the Neo chain.

## [0.9.5] - 2022-12-29

### Changed
Expand Down
12 changes: 5 additions & 7 deletions cmd/neofs-net-monitor/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ const (
cfgNeoFSContract = "contracts.neofs"

// neo rpc node related config values
mainPrefix = "mainnet"
sidePrefix = "morph"
prefix = "chain"

cfgChainFSChain = "chain.fschain"

cfgNeoRPCEndpoint = "rpc.endpoint"
cfgNeoRPCDialTimeout = "rpc.dial_timeout"
Expand All @@ -31,11 +32,8 @@ const (
)

func DefaultConfiguration(cfg *viper.Viper) {
cfg.SetDefault(sidePrefix+delimiter+cfgNeoRPCEndpoint, "")
cfg.SetDefault(sidePrefix+delimiter+cfgNeoRPCDialTimeout, 5*time.Second)

cfg.SetDefault(mainPrefix+delimiter+cfgNeoRPCEndpoint, "")
cfg.SetDefault(mainPrefix+delimiter+cfgNeoRPCDialTimeout, 5*time.Second)
cfg.SetDefault(prefix+delimiter+cfgNeoRPCEndpoint, "")
cfg.SetDefault(prefix+delimiter+cfgNeoRPCDialTimeout, 5*time.Second)

cfg.SetDefault(cfgMetricsEndpoint, ":16512")
cfg.SetDefault(cfgMetricsInterval, 15*time.Minute)
Expand Down
136 changes: 74 additions & 62 deletions cmd/neofs-net-monitor/monitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,9 @@ func New(ctx context.Context, cfg *viper.Viper) (*monitor.Monitor, error) {
return nil, err
}

sideChainEndpoints := cfg.GetStringSlice(sidePrefix + delimiter + cfgNeoRPCEndpoint)
sideChainTimeout := cfg.GetDuration(sidePrefix + delimiter + cfgNeoRPCDialTimeout)
sideChainRecheck := cfg.GetDuration(sidePrefix + delimiter + cfgNeoRPCRecheckInterval)

mainChainEndpoints := cfg.GetStringSlice(mainPrefix + delimiter + cfgNeoRPCEndpoint)
mainChainTimeout := cfg.GetDuration(mainPrefix + delimiter + cfgNeoRPCDialTimeout)
mainChainRecheck := cfg.GetDuration(mainPrefix + delimiter + cfgNeoRPCRecheckInterval)
sideChainEndpoints := cfg.GetStringSlice(prefix + delimiter + cfgNeoRPCEndpoint)
sideChainTimeout := cfg.GetDuration(prefix + delimiter + cfgNeoRPCDialTimeout)
sideChainRecheck := cfg.GetDuration(prefix + delimiter + cfgNeoRPCRecheckInterval)

sideNeogoClient, err := pool.NewPool(ctx, pool.PrmPool{
Endpoints: sideChainEndpoints,
Expand All @@ -40,109 +36,125 @@ func New(ctx context.Context, cfg *viper.Viper) (*monitor.Monitor, error) {
return nil, fmt.Errorf("can't create side chain neo-go client: %w", err)
}

mainNeogoClient, err := pool.NewPool(ctx, pool.PrmPool{
Endpoints: mainChainEndpoints,
DialTimeout: mainChainTimeout,
RecheckInterval: mainChainRecheck,
})
var job monitor.Job
if cfg.GetBool(cfgChainFSChain) {
monitor.RegisterSideChainMetrics()
job, err = sideChainJob(ctx, cfg, sideNeogoClient, logger, sideChainEndpoints)
} else {
monitor.RegisterMainChainMetrics()
job, err = mainChainJob(cfg, sideNeogoClient, logger)
}

if err != nil {
return nil, fmt.Errorf("can't create main chain neo-go client: %w", err)
return nil, err
}

return monitor.New(
job,
cfg.GetString(cfgMetricsEndpoint),
cfg.GetDuration(cfgMetricsInterval),
logger,
), nil
}

func mainChainJob(cfg *viper.Viper, neogoClient *pool.Pool, logger *zap.Logger) (*monitor.MainJob, error) {
alphabetFetcher := morphchain.NewMainChainAlphabetFetcher(neogoClient)

balanceFetcher, err := morphchain.NewBalanceFetcher(
morphchain.BalanceFetcherArgs{
Cli: neogoClient,
})
if err != nil {
return nil, fmt.Errorf("can't initialize Neo chain balance reader: %w", err)
}

var neofs *util.Uint160

neofsContract := cfg.GetString(cfgNeoFSContract)
if len(neofsContract) != 0 {
sh, err := util.Uint160DecodeStringLE(neofsContract)
if err != nil {
return nil, fmt.Errorf("decode configured NeoFS contract address %q: %w", cfgNeoFSContract, err)
}
neofs = &sh
} else {
logger.Info("NeoFS contract address not configured, continue without it")
}

netmapContract, err := sideNeogoClient.ResolveContract(rpcnns.NameNetmap)
return monitor.NewMainJob(monitor.MainJobArgs{
AlphabetFetcher: alphabetFetcher,
BalanceFetcher: balanceFetcher,
Neofs: neofs,
Logger: logger,
}), nil
}

func sideChainJob(ctx context.Context, cfg *viper.Viper, neogoClient *pool.Pool, logger *zap.Logger, sideChainEndpoints []string) (*monitor.SideJob, error) {
netmapContract, err := neogoClient.ResolveContract(rpcnns.NameNetmap)
if err != nil {
return nil, fmt.Errorf("can't read netmap scripthash: %w", err)
}

containerContract, err := sideNeogoClient.ResolveContract(rpcnns.NameContainer)
containerContract, err := neogoClient.ResolveContract(rpcnns.NameContainer)
if err != nil {
return nil, fmt.Errorf("can't read container scripthash: %w", err)
}

nmFetcher, err := contracts.NewNetmap(contracts.NetmapArgs{
Pool: sideNeogoClient,
Pool: neogoClient,
NetmapContract: netmapContract,
Logger: logger,
})
if err != nil {
return nil, fmt.Errorf("can't initialize netmap fetcher: %w", err)
}

cnrFetcher, err := contracts.NewContainer(sideNeogoClient, containerContract)
cnrFetcher, err := contracts.NewContainer(neogoClient, containerContract)
if err != nil {
return nil, fmt.Errorf("can't initialize container fetcher: %w", err)
}

alphabetFetcher, err := morphchain.NewAlphabetFetcher(morphchain.AlphabetFetcherArgs{
Committeer: sideNeogoClient,
Designater: mainNeogoClient,
})
if err != nil {
return nil, fmt.Errorf("can't initialize alphabet fetcher: %w", err)
}
alphabetFetcher := morphchain.NewSideChainAlphabetFetcher(neogoClient)

sideBalanceFetcher, err := morphchain.NewBalanceFetcher(morphchain.BalanceFetcherArgs{
Cli: sideNeogoClient,
balanceFetcher, err := morphchain.NewBalanceFetcher(morphchain.BalanceFetcherArgs{
Cli: neogoClient,
})
if err != nil {
return nil, fmt.Errorf("can't initialize side balance fetcher: %w", err)
}

mainBalanceFetcher, err := morphchain.NewBalanceFetcher(morphchain.BalanceFetcherArgs{
Cli: mainNeogoClient,
})
if err != nil {
return nil, fmt.Errorf("can't initialize main balance fetcher: %w", err)
}

var (
balance util.Uint160
proxy *util.Uint160
neofs *util.Uint160
)

balance, err = sideNeogoClient.ResolveContract(rpcnns.NameBalance)
balance, err = neogoClient.ResolveContract(rpcnns.NameBalance)
if err != nil {
return nil, fmt.Errorf("balance contract is not available: %w", err)
}

proxyContract, err := sideNeogoClient.ResolveContract(rpcnns.NameProxy)
proxyContract, err := neogoClient.ResolveContract(rpcnns.NameProxy)
if err != nil {
logger.Info("proxy disabled")
} else {
proxy = &proxyContract
}

neofsContract := cfg.GetString(cfgNeoFSContract)
if len(neofsContract) != 0 {
sh, err := util.Uint160DecodeStringLE(neofsContract)
if err != nil {
return nil, fmt.Errorf("NNS u160 decode: %w", err)
}
neofs = &sh
} else {
logger.Info("neofs contract ignored")
}

mnPool := multinodepool.NewPool(sideChainEndpoints, cfg.GetDuration(cfgMetricsInterval))
if err = mnPool.Dial(ctx); err != nil {
return nil, fmt.Errorf("multinodepool: %w", err)
}

return monitor.New(monitor.Args{
Balance: balance,
Proxy: proxy,
Neofs: neofs,
Logger: logger,
Sleep: cfg.GetDuration(cfgMetricsInterval),
MetricsAddress: cfg.GetString(cfgMetricsEndpoint),
AlpFetcher: alphabetFetcher,
NmFetcher: nmFetcher,
IRFetcher: nmFetcher,
SideBlFetcher: sideBalanceFetcher,
MainBlFetcher: mainBalanceFetcher,
CnrFetcher: cnrFetcher,
HeightFetcher: mnPool,
StateFetcher: mnPool,
return monitor.NewSideJob(monitor.SideJobArgs{
Logger: logger,
Balance: balance,
Proxy: proxy,
AlphabetFetcher: alphabetFetcher,
NmFetcher: nmFetcher,
IRFetcher: nmFetcher,
BalanceFetcher: balanceFetcher,
CnrFetcher: cnrFetcher,
HeightFetcher: mnPool,
StateFetcher: mnPool,
}), nil
}
15 changes: 4 additions & 11 deletions config/config.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Mainchain NEO RPC related configuration.
mainnet:
# Neo RPC related configuration.
chain:
# If true, monitor connects to the NeoFS chain, otherwise, to the Neo chain.
fschain: false
rpc:
dial_timeout: 5s
# stores the interval after which a current connection health check is performed.
Expand All @@ -8,15 +10,6 @@ mainnet:
- https://rpc1.t5.n3.nspcc.ru:21331
- https://rpc2.t5.n3.nspcc.ru:21331

# Sidechain NEO RPC related configuration.
morph:
rpc:
dial_timeout: 5s
health_recheck_interval: 5s
endpoint:
- https://rpc1.morph.t5.fs.neo.org:51331
- https://rpc2.morph.t5.fs.neo.org:51331

# Prometheus metric configuration.
metrics:
# Interval between NeoFS metric scrapping.
Expand Down
79 changes: 79 additions & 0 deletions pkg/monitor/main_job.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package monitor

import (
"encoding/hex"

"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/util"
"go.uber.org/zap"
)

type (
MainJobArgs struct {
AlphabetFetcher AlphabetFetcher
BalanceFetcher BalanceFetcher
Neofs *util.Uint160
Logger *zap.Logger
}

MainJob struct {
alphabetFetcher AlphabetFetcher
balanceFetcher BalanceFetcher
logger *zap.Logger
neofs *util.Uint160
}
)

func NewMainJob(args MainJobArgs) *MainJob {
return &MainJob{
alphabetFetcher: args.AlphabetFetcher,
balanceFetcher: args.BalanceFetcher,
logger: args.Logger,
neofs: args.Neofs,
}
}

func (m *MainJob) Process() {
if mainAlphabet, err := m.alphabetFetcher.FetchAlphabet(); err != nil {
m.logger.Warn("can't read NeoFS Aphabet members", zap.Error(err))
} else {
processAlphabetPublicKeys(mainAlphabet)
m.processMainAlphabet(mainAlphabet)
}

m.processMainChainSupply()
}

func (m *MainJob) processMainAlphabet(alphabet keys.PublicKeys) {
exportGasBalances := make(map[string]int64, len(alphabet))

for _, key := range alphabet {
keyHex := hex.EncodeToString(key.Bytes())

balanceGAS, err := m.balanceFetcher.FetchGAS(*key)
if err != nil {
m.logger.Debug("can't fetch gas balance", zap.String("key", keyHex), zap.Error(err))
} else {
exportGasBalances[keyHex] = balanceGAS
}
}

alphabetGASBalances.Reset()
for k, v := range exportGasBalances {
alphabetGASBalances.WithLabelValues(k).Set(float64(v))
}
}

func (m *MainJob) processMainChainSupply() {
if m.neofs == nil {
return
}

balance, err := m.balanceFetcher.FetchGASByScriptHash(*m.neofs)
if err != nil {
m.logger.Debug("can't fetch NeoFS contract's GAS balance", zap.Error(err))
return
}

mainChainSupply.Set(float64(balance))
}
Loading