Skip to content

Commit

Permalink
Node Balance Monitoring for STOM (#414)
Browse files Browse the repository at this point in the history
  • Loading branch information
augustbleeds authored Apr 25, 2024
1 parent 8cf7b7f commit 79d5810
Show file tree
Hide file tree
Showing 20 changed files with 722 additions and 94 deletions.
8 changes: 4 additions & 4 deletions integration-tests/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ require (
github.com/smartcontractkit/chainlink-testing-framework v1.27.0
github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240215151806-009c99876c4c
github.com/smartcontractkit/chainlink/v2 v2.9.0-beta0.0.20240215151806-009c99876c4c
github.com/stretchr/testify v1.8.4
github.com/stretchr/testify v1.9.0
github.com/testcontainers/testcontainers-go v0.28.0
go.uber.org/zap v1.26.0
golang.org/x/text v0.14.0
Expand Down Expand Up @@ -222,7 +222,7 @@ require (
github.com/gtank/merlin v0.1.1 // indirect
github.com/gtank/ristretto255 v0.1.2 // indirect
github.com/hashicorp/consul/api v1.25.1 // indirect
github.com/hashicorp/consul/sdk v0.14.1 // indirect
github.com/hashicorp/consul/sdk v0.16.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-envparse v0.1.0 // indirect
Expand Down Expand Up @@ -355,7 +355,7 @@ require (
github.com/smartcontractkit/chainlink-feeds v0.0.0-20240119021347-3c541a78cdb8 // indirect
github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240213161921-c4d342b761b0 // indirect
github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 // indirect
github.com/smartcontractkit/libocr v0.0.0-20240112202000-6359502d2ff1 // indirect
github.com/smartcontractkit/libocr v0.0.0-20240326191951-2bbe9382d052 // indirect
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect
github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 // indirect
github.com/smartcontractkit/wasp v0.4.2 // indirect
Expand All @@ -369,7 +369,7 @@ require (
github.com/spf13/pflag v1.0.5 // indirect
github.com/spf13/viper v1.16.0 // indirect
github.com/status-im/keycard-go v0.2.0 // indirect
github.com/stretchr/objx v0.5.0 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/subosito/gotenv v1.4.2 // indirect
github.com/supranational/blst v0.3.11 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect
Expand Down
14 changes: 8 additions & 6 deletions integration-tests/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -837,8 +837,8 @@ github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBt
github.com/hashicorp/consul/api v1.25.1 h1:CqrdhYzc8XZuPnhIYZWH45toM0LB9ZeYr/gvpLVI3PE=
github.com/hashicorp/consul/api v1.25.1/go.mod h1:iiLVwR/htV7mas/sy0O+XSuEnrdBUUydemjxcUrAt4g=
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
github.com/hashicorp/consul/sdk v0.14.1 h1:ZiwE2bKb+zro68sWzZ1SgHF3kRMBZ94TwOCFRF4ylPs=
github.com/hashicorp/consul/sdk v0.14.1/go.mod h1:vFt03juSzocLRFo59NkeQHHmQa6+g7oU0pfzdI1mUhg=
github.com/hashicorp/consul/sdk v0.16.0 h1:SE9m0W6DEfgIVCJX7xU+iv/hUl4m/nxqMTnCdMxDpJ8=
github.com/hashicorp/consul/sdk v0.16.0/go.mod h1:7pxqqhqoaPqnBnzXD1StKed62LqJeClzVsUEy85Zr0A=
github.com/hashicorp/cronexpr v1.1.2 h1:wG/ZYIKT+RT3QkOdgYc+xsKWVRgnxJ1OJtjjy84fJ9A=
github.com/hashicorp/cronexpr v1.1.2/go.mod h1:P4wA0KBl9C5q2hABiMO7cp6jcIg96CDh1Efb3g1PWA4=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
Expand Down Expand Up @@ -1426,8 +1426,8 @@ github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306 h1:ko88
github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306/go.mod h1:w1sAEES3g3PuV/RzUrgow20W2uErMly84hhD3um1WL4=
github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU=
github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f/go.mod h1:MvMXoufZAtqExNexqi4cjrNYE9MefKddKylxjS+//n0=
github.com/smartcontractkit/libocr v0.0.0-20240112202000-6359502d2ff1 h1:3y9WsXkZ5lxFrmfH7DQHs/q308lylKId5l/3VC0QAdM=
github.com/smartcontractkit/libocr v0.0.0-20240112202000-6359502d2ff1/go.mod h1:kC0qmVPUaVkFqGiZMNhmRmjdphuUmeyLEdlWFOQzFWI=
github.com/smartcontractkit/libocr v0.0.0-20240326191951-2bbe9382d052 h1:1WFjrrVrWoQ9UpVMh7Mx4jDpzhmo1h8hFUKd9awIhIU=
github.com/smartcontractkit/libocr v0.0.0-20240326191951-2bbe9382d052/go.mod h1:SJEZCHgMCAzzBvo9vMV2DQ9onfEcIJCYSViyP4JI6c4=
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 h1:yiKnypAqP8l0OX0P3klzZ7SCcBUxy5KqTAKZmQOvSQE=
github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:q6f4fe39oZPdsh1i57WznEZgxd8siidMaSFq3wdPmVg=
github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 h1:Dai1bn+Q5cpeGMQwRdjOdVjG8mmFFROVkSKuUgBErRQ=
Expand Down Expand Up @@ -1476,8 +1476,9 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
Expand All @@ -1489,8 +1490,9 @@ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1F
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8=
github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
Expand Down
26 changes: 23 additions & 3 deletions monitoring/cmd/monitoring/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/smartcontractkit/chainlink-common/pkg/logger"

"github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/erc20"
"github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/ocr2"
"github.com/smartcontractkit/chainlink-starknet/relayer/pkg/starknet"

Expand Down Expand Up @@ -50,6 +51,16 @@ func main() {
log.Fatalw("failed to build a ocr2.Client", "error", err)
}

strTokenClient, err := erc20.NewClient(
starknetClient,
logger.With(log, "component", "erc20-client"),
starknetConfig.GetStrkTokenAddress(),
)

if err != nil {
log.Fatalw("failed to build erc20-client", "error", err)
}

envelopeSourceFactory := monitoring.NewEnvelopeSourceFactory(ocr2Client)
txResultsFactory := monitoring.NewTxResultsSourceFactory(ocr2Client)

Expand All @@ -70,11 +81,20 @@ func main() {
proxySourceFactory := monitoring.NewProxySourceFactory(ocr2Client)
monitor.SourceFactories = append(monitor.SourceFactories, proxySourceFactory)

prometheusExporterFactory := monitoring.NewPrometheusExporterFactory(
monitoring.NewMetrics(logger.With(log, "component", "starknet-metrics")),
)
metricsBuilder := monitoring.NewMetrics(logger.With(log, "component", "starknet-metrics-builder"))

prometheusExporterFactory := monitoring.NewPrometheusExporterFactory(metricsBuilder)
monitor.ExporterFactories = append(monitor.ExporterFactories, prometheusExporterFactory)

nodeBalancesSourceFactory := monitoring.NewNodeBalancesSourceFactory(strTokenClient)
monitor.NetworkSourceFactories = append(monitor.NetworkSourceFactories, nodeBalancesSourceFactory)

nodeBalancesExporterFactory := monitoring.NewNodeBalancesExporterFactory(
logger.With(log, "node-balances-exporter"),
metricsBuilder,
)
monitor.NetworkExporterFactories = append(monitor.NetworkExporterFactories, nodeBalancesExporterFactory)

monitor.Run()
log.Info("monitor stopped")
}
27 changes: 19 additions & 8 deletions monitoring/pkg/monitoring/config_chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"os"
"time"

"github.com/NethermindEth/juno/core/felt"
starknetutils "github.com/NethermindEth/starknet.go/utils"
relayMonitoring "github.com/smartcontractkit/chainlink-common/pkg/monitoring"
)

Expand All @@ -18,18 +20,20 @@ type StarknetConfig struct {
readTimeout time.Duration
pollInterval time.Duration
linkTokenAddress string
strkTokenAddress *felt.Felt
}

var _ relayMonitoring.ChainConfig = StarknetConfig{}

func (s StarknetConfig) GetRPCEndpoint() string { return s.rpcEndpoint }
func (s StarknetConfig) GetRPCApiKey() string { return s.rpcApiKey }
func (s StarknetConfig) GetNetworkName() string { return s.networkName }
func (s StarknetConfig) GetNetworkID() string { return s.networkID }
func (s StarknetConfig) GetChainID() string { return s.chainID }
func (s StarknetConfig) GetReadTimeout() time.Duration { return s.readTimeout }
func (s StarknetConfig) GetPollInterval() time.Duration { return s.pollInterval }
func (s StarknetConfig) GetLinkTokenAddress() string { return s.linkTokenAddress }
func (s StarknetConfig) GetRPCEndpoint() string { return s.rpcEndpoint }
func (s StarknetConfig) GetRPCApiKey() string { return s.rpcApiKey }
func (s StarknetConfig) GetNetworkName() string { return s.networkName }
func (s StarknetConfig) GetNetworkID() string { return s.networkID }
func (s StarknetConfig) GetChainID() string { return s.chainID }
func (s StarknetConfig) GetReadTimeout() time.Duration { return s.readTimeout }
func (s StarknetConfig) GetPollInterval() time.Duration { return s.pollInterval }
func (s StarknetConfig) GetLinkTokenAddress() string { return s.linkTokenAddress }
func (s StarknetConfig) GetStrkTokenAddress() *felt.Felt { return s.strkTokenAddress }

func (s StarknetConfig) ToMapping() map[string]interface{} {
return map[string]interface{}{
Expand Down Expand Up @@ -85,6 +89,13 @@ func parseEnvVars(cfg *StarknetConfig) error {
if value, isPresent := os.LookupEnv("STARKNET_LINK_TOKEN_ADDRESS"); isPresent {
cfg.linkTokenAddress = value
}
if value, isPresent := os.LookupEnv("STRK_TOKEN_ADDRESS"); isPresent {
feltValue, err := starknetutils.HexToFelt(value)
if err != nil {
return fmt.Errorf("failed to parse env var STRK_TOKEN_ADDRESS %w", err)
}
cfg.strkTokenAddress = feltValue
}
return nil
}

Expand Down
6 changes: 3 additions & 3 deletions monitoring/pkg/monitoring/config_node.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (

"github.com/smartcontractkit/libocr/offchainreporting2/types"

relayMonitoring "github.com/smartcontractkit/chainlink-common/pkg/monitoring"
commonMonitoring "github.com/smartcontractkit/chainlink-common/pkg/monitoring"
)

type StarknetNodeConfig struct {
Expand All @@ -27,13 +27,13 @@ func (s StarknetNodeConfig) GetAccount() types.Account {
return types.Account(address)
}

func StarknetNodesParser(buf io.ReadCloser) ([]relayMonitoring.NodeConfig, error) {
func StarknetNodesParser(buf io.ReadCloser) ([]commonMonitoring.NodeConfig, error) {
rawNodes := []StarknetNodeConfig{}
decoder := json.NewDecoder(buf)
if err := decoder.Decode(&rawNodes); err != nil {
return nil, fmt.Errorf("unable to unmarshal nodes config data: %w", err)
}
nodes := make([]relayMonitoring.NodeConfig, len(rawNodes))
nodes := make([]commonMonitoring.NodeConfig, len(rawNodes))
for i, rawNode := range rawNodes {
nodes[i] = rawNode
}
Expand Down
79 changes: 79 additions & 0 deletions monitoring/pkg/monitoring/exporter_contract_balance.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package monitoring

import (
"context"
"math/big"
"sync"

commonMonitoring "github.com/smartcontractkit/chainlink-common/pkg/monitoring"
)

func NewNodeBalancesExporterFactory(log commonMonitoring.Logger, metrics Metrics) commonMonitoring.ExporterFactory {
return &nodeBalancesExporterFactory{
log,
metrics,
}
}

type nodeBalancesExporterFactory struct {
log commonMonitoring.Logger
metrics Metrics
}

func (f *nodeBalancesExporterFactory) NewExporter(params commonMonitoring.ExporterParams) (commonMonitoring.Exporter, error) {
return &nodeBalancesExporter{
log: f.log,
metrics: f.metrics,
chainConfig: params.ChainConfig,
}, nil
}

type nodeBalancesExporter struct {
log commonMonitoring.Logger
metrics Metrics
chainConfig commonMonitoring.ChainConfig
addrsSet []ContractAddressWithBalance
addrsMu sync.Mutex
}

func (e *nodeBalancesExporter) Export(ctx context.Context, data interface{}) {
balanceEnvelope, isBalanceEnvelope := data.(BalanceEnvelope)
if !isBalanceEnvelope {
return
}

decimals := balanceEnvelope.Decimals
divisor := new(big.Int).Exp(new(big.Int).SetUint64(10), decimals, nil) // 10^(decimals)

for _, c := range balanceEnvelope.Contracts {
balanceAns := new(big.Int).Div(c.Balance, divisor)

e.metrics.SetBalance(
toFloat64(balanceAns),
c.Address.String(),
c.Name,
e.chainConfig.GetNetworkID(),
e.chainConfig.GetNetworkName(),
e.chainConfig.GetChainID())
}

e.addrsMu.Lock()
defer e.addrsMu.Unlock()

e.addrsSet = balanceEnvelope.Contracts

}

func (e *nodeBalancesExporter) Cleanup(_ context.Context) {
e.addrsMu.Lock()
defer e.addrsMu.Unlock()

for _, c := range e.addrsSet {
e.metrics.CleanupBalance(c.Address.String(), c.Name, e.chainConfig.GetNetworkID(), e.chainConfig.GetNetworkName(), e.chainConfig.GetChainID())
}
}

func toFloat64(bignum *big.Int) float64 {
val, _ := new(big.Float).SetInt(bignum).Float64()
return val
}
2 changes: 1 addition & 1 deletion monitoring/pkg/monitoring/exporter_prometheus.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ func (p *prometheusExporter) Cleanup(_ context.Context) {
p.addressesMu.Lock()
defer p.addressesMu.Unlock()
for address := range p.addressesSet {
p.metrics.Cleanup(
p.metrics.CleanupProxy(
address,
p.feedConfig.GetContractAddress(),
p.chainConfig.GetChainID(),
Expand Down
36 changes: 34 additions & 2 deletions monitoring/pkg/monitoring/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ import (
type Metrics interface {
SetProxyAnswersRaw(answer float64, proxyContractAddress, feedID, chainID, contractStatus, contractType, feedName, feedPath, networkID, networkName string)
SetProxyAnswers(answer float64, proxyContractAddress, feedID, chainID, contractStatus, contractType, feedName, feedPath, networkID, networkName string)
Cleanup(proxyContractAddress, feedID, chainID, contractStatus, contractType, feedName, feedPath, networkID, networkName string)
CleanupProxy(proxyContractAddress, feedID, chainID, contractStatus, contractType, feedName, feedPath, networkID, networkName string)
SetBalance(answer float64, contractAddress, alias, networkId, networkName, chainID string)
CleanupBalance(contractAddress, alias, networkId, networkName, chainID string)
}

var (
Expand All @@ -29,6 +31,13 @@ var (
},
[]string{"proxy_contract_address", "feed_id", "chain_id", "contract_status", "contract_type", "feed_name", "feed_path", "network_id", "network_name"},
)
contractBalance = promauto.NewGaugeVec(
prometheus.GaugeOpts{
Name: "strk_contract_balance",
Help: "Reports the latest STRK balance of a contract address",
},
[]string{"contract_address", "alias", "network_id", "network_name"},
)
)

// NewMetrics does wisott
Expand All @@ -40,6 +49,29 @@ type defaultMetrics struct {
log relayMonitoring.Logger
}

func (d *defaultMetrics) SetBalance(answer float64, contractAddress, alias, networkId, networkName, chainID string) {
contractBalance.With(prometheus.Labels{
"contract_address": contractAddress,
"alias": alias,
"network_id": networkId,
"network_name": networkName,
"chain_id": chainID,
}).Set(answer)
}

func (d *defaultMetrics) CleanupBalance(contractAddress, alias, networkId, networkName, chainID string) {
labels := prometheus.Labels{
"contract_address": contractAddress,
"alias": alias,
"network_id": networkId,
"network_name": networkName,
"chain_id": chainID,
}
if !contractBalance.Delete(labels) {
d.log.Errorw("failed to delete metric", "name", "strk_contract_balance", "labels", labels)
}
}

func (d *defaultMetrics) SetProxyAnswersRaw(answer float64, proxyContractAddress, feedID, chainID, contractStatus, contractType, feedName, feedPath, networkID, networkName string) {
proxyAnswersRaw.With(prometheus.Labels{
"proxy_contract_address": proxyContractAddress,
Expand Down Expand Up @@ -68,7 +100,7 @@ func (d *defaultMetrics) SetProxyAnswers(answer float64, proxyContractAddress, f
}).Set(answer)
}

func (d *defaultMetrics) Cleanup(
func (d *defaultMetrics) CleanupProxy(
proxyContractAddress, feedID, chainID, contractStatus, contractType string,
feedName, feedPath, networkID, networkName string,
) {
Expand Down
Loading

0 comments on commit 79d5810

Please sign in to comment.