Skip to content

Commit

Permalink
Merge pull request asymmetric-research#37 from asymmetric-research/fe…
Browse files Browse the repository at this point in the history
…e-rewards

WIP: Fee rewards!!!
  • Loading branch information
johnstonematt authored Oct 14, 2024
2 parents d32b15a + c65c347 commit a3c498d
Show file tree
Hide file tree
Showing 8 changed files with 344 additions and 71 deletions.
36 changes: 31 additions & 5 deletions cmd/solana_exporter/exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ var (
"",
"Comma-separated list of validator vote accounts to track inflationary rewards for",
)
feeRewardAddresses = flag.String(
"fee-reward-addresses",
"",
"Comma-separated list of validator identity accounts to track fee rewards for.",
)
)

func init() {
Expand All @@ -50,6 +55,7 @@ type solanaCollector struct {
balanceAddresses []string
leaderSlotAddresses []string
inflationRewardAddresses []string
feeRewardAddresses []string

/// descriptors:
totalValidatorsDesc *prometheus.Desc
Expand All @@ -67,13 +73,15 @@ func createSolanaCollector(
balanceAddresses []string,
leaderSlotAddresses []string,
inflationRewardAddresses []string,
feeRewardAddresses []string,
) *solanaCollector {
return &solanaCollector{
rpcClient: provider,
slotPace: slotPace,
balanceAddresses: balanceAddresses,
leaderSlotAddresses: leaderSlotAddresses,
inflationRewardAddresses: inflationRewardAddresses,
feeRewardAddresses: feeRewardAddresses,
totalValidatorsDesc: prometheus.NewDesc(
"solana_active_validators",
"Total number of active validators by state",
Expand Down Expand Up @@ -120,10 +128,19 @@ func createSolanaCollector(
}

func NewSolanaCollector(
rpcAddr string, balanceAddresses []string, leaderSlotAddresses []string, inflationRewardAddresses []string,
rpcAddr string,
balanceAddresses []string,
leaderSlotAddresses []string,
inflationRewardAddresses []string,
feeRewardAddresses []string,
) *solanaCollector {
return createSolanaCollector(
rpc.NewRPCClient(rpcAddr), slotPacerSchedule, balanceAddresses, leaderSlotAddresses, inflationRewardAddresses,
rpc.NewRPCClient(rpcAddr),
slotPacerSchedule,
balanceAddresses,
leaderSlotAddresses,
inflationRewardAddresses,
feeRewardAddresses,
)
}

Expand All @@ -138,7 +155,7 @@ func (c *solanaCollector) Describe(ch chan<- *prometheus.Desc) {
}

func (c *solanaCollector) collectVoteAccounts(ctx context.Context, ch chan<- prometheus.Metric) {
voteAccounts, err := c.rpcClient.GetVoteAccounts(ctx, rpc.CommitmentProcessed, votePubkey)
voteAccounts, err := c.rpcClient.GetVoteAccounts(ctx, rpc.CommitmentConfirmed, votePubkey)
if err != nil {
ch <- prometheus.NewInvalidMetric(c.totalValidatorsDesc, err)
ch <- prometheus.NewInvalidMetric(c.validatorActivatedStake, err)
Expand Down Expand Up @@ -217,7 +234,7 @@ func (c *solanaCollector) collectBalances(ctx context.Context, ch chan<- prometh
func fetchBalances(ctx context.Context, client rpc.Provider, addresses []string) (map[string]float64, error) {
balances := make(map[string]float64)
for _, address := range addresses {
balance, err := client.GetBalance(ctx, address)
balance, err := client.GetBalance(ctx, rpc.CommitmentConfirmed, address)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -255,18 +272,27 @@ func main() {
balAddresses []string
lsAddresses []string
irAddresses []string
frAddresses []string
)
if *balanceAddresses != "" {
balAddresses = strings.Split(*balanceAddresses, ",")
klog.Infof("Monitoring balances for %v", balAddresses)
}
if *leaderSlotAddresses != "" {
lsAddresses = strings.Split(*leaderSlotAddresses, ",")
klog.Infof("Monitoring leader-slot by epoch for %v", lsAddresses)

}
if *inflationRewardAddresses != "" {
irAddresses = strings.Split(*inflationRewardAddresses, ",")
klog.Infof("Monitoring inflation reward by epoch for %v", irAddresses)
}
if *feeRewardAddresses != "" {
frAddresses = strings.Split(*feeRewardAddresses, ",")
klog.Infof("Monitoring fee reward by epoch for %v", frAddresses)
}

collector := NewSolanaCollector(*rpcAddr, balAddresses, lsAddresses, irAddresses)
collector := NewSolanaCollector(*rpcAddr, balAddresses, lsAddresses, irAddresses, frAddresses)

slotWatcher := NewCollectorSlotWatcher(collector)
go slotWatcher.WatchSlots(context.Background(), collector.slotPace)
Expand Down
78 changes: 49 additions & 29 deletions cmd/solana_exporter/exporter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ var (
identityVotes = map[string]string{"aaa": "AAA", "bbb": "BBB", "ccc": "CCC"}
nv = len(identities)
staticEpochInfo = rpc.EpochInfo{
AbsoluteSlot: 166598,
AbsoluteSlot: 166599,
BlockHeight: 166500,
Epoch: 27,
SlotIndex: 2790,
Expand All @@ -70,25 +70,19 @@ var (
staticVoteAccounts = rpc.VoteAccounts{
Current: []rpc.VoteAccount{
{
ActivatedStake: 42,
Commission: 0,
EpochCredits: [][]int{
{1, 64, 0},
{2, 192, 64},
},
ActivatedStake: 42,
Commission: 0,
EpochCredits: [][]int{{1, 64, 0}, {2, 192, 64}},
EpochVoteAccount: true,
LastVote: 147,
NodePubkey: "bbb",
RootSlot: 18,
VotePubkey: "BBB",
},
{
ActivatedStake: 43,
Commission: 1,
EpochCredits: [][]int{
{2, 65, 1},
{3, 193, 65},
},
ActivatedStake: 43,
Commission: 1,
EpochCredits: [][]int{{2, 65, 1}, {3, 193, 65}},
EpochVoteAccount: true,
LastVote: 148,
NodePubkey: "ccc",
Expand All @@ -98,12 +92,9 @@ var (
},
Delinquent: []rpc.VoteAccount{
{
ActivatedStake: 49,
Commission: 2,
EpochCredits: [][]int{
{10, 594, 6},
{9, 98, 4},
},
ActivatedStake: 49,
Commission: 2,
EpochCredits: [][]int{{10, 594, 6}, {9, 98, 4}},
EpochVoteAccount: true,
LastVote: 92,
NodePubkey: "aaa",
Expand All @@ -112,6 +103,9 @@ var (
},
},
}
staticLeaderSchedule = map[string][]int64{
"aaa": {0, 3, 6, 9, 12}, "bbb": {1, 4, 7, 10, 13}, "ccc": {2, 5, 8, 11, 14},
}
)

/*
Expand All @@ -124,7 +118,7 @@ func (c *staticRPCClient) GetEpochInfo(ctx context.Context, commitment rpc.Commi
}

//goland:noinspection GoUnusedParameter
func (c *staticRPCClient) GetSlot(ctx context.Context) (int64, error) {
func (c *staticRPCClient) GetSlot(ctx context.Context, commitment rpc.Commitment) (int64, error) {
return staticEpochInfo.AbsoluteSlot, nil
}

Expand All @@ -143,23 +137,35 @@ func (c *staticRPCClient) GetVoteAccounts(

//goland:noinspection GoUnusedParameter
func (c *staticRPCClient) GetBlockProduction(
ctx context.Context, identity *string, firstSlot *int64, lastSlot *int64,
ctx context.Context, commitment rpc.Commitment, identity *string, firstSlot *int64, lastSlot *int64,
) (*rpc.BlockProduction, error) {
return &staticBlockProduction, nil
}

//goland:noinspection GoUnusedParameter
func (c *staticRPCClient) GetBalance(ctx context.Context, address string) (float64, error) {
func (c *staticRPCClient) GetBalance(ctx context.Context, commitment rpc.Commitment, address string) (float64, error) {
return balances[address], nil
}

//goland:noinspection GoUnusedParameter
func (c *staticRPCClient) GetInflationReward(
ctx context.Context, addresses []string, commitment rpc.Commitment, epoch *int64, minContextSlot *int64,
ctx context.Context, commitment rpc.Commitment, addresses []string, epoch *int64, minContextSlot *int64,
) ([]rpc.InflationReward, error) {
return staticInflationRewards, nil
}

//goland:noinspection GoUnusedParameter
func (c *staticRPCClient) GetLeaderSchedule(
ctx context.Context, commitment rpc.Commitment, slot int64,
) (map[string][]int64, error) {
return staticLeaderSchedule, nil
}

//goland:noinspection GoUnusedParameter
func (c *staticRPCClient) GetBlock(ctx context.Context, commitment rpc.Commitment, slot int64) (*rpc.Block, error) {
return nil, nil
}

/*
===== DYNAMIC CLIENT =====:
*/
Expand Down Expand Up @@ -271,7 +277,7 @@ func (c *dynamicRPCClient) GetEpochInfo(ctx context.Context, commitment rpc.Comm
}

//goland:noinspection GoUnusedParameter
func (c *dynamicRPCClient) GetSlot(ctx context.Context) (int64, error) {
func (c *dynamicRPCClient) GetSlot(ctx context.Context, commitment rpc.Commitment) (int64, error) {
return int64(c.Slot), nil
}

Expand Down Expand Up @@ -308,7 +314,7 @@ func (c *dynamicRPCClient) GetVoteAccounts(

//goland:noinspection GoUnusedParameter
func (c *dynamicRPCClient) GetBlockProduction(
ctx context.Context, identity *string, firstSlot *int64, lastSlot *int64,
ctx context.Context, commitment rpc.Commitment, identity *string, firstSlot *int64, lastSlot *int64,
) (*rpc.BlockProduction, error) {
byIdentity := make(map[string]rpc.HostProduction)
for _, identity := range identities {
Expand All @@ -330,17 +336,29 @@ func (c *dynamicRPCClient) GetBlockProduction(
}

//goland:noinspection GoUnusedParameter
func (c *dynamicRPCClient) GetBalance(ctx context.Context, address string) (float64, error) {
func (c *dynamicRPCClient) GetBalance(ctx context.Context, client rpc.Commitment, address string) (float64, error) {
return balances[address], nil
}

//goland:noinspection GoUnusedParameter
func (c *dynamicRPCClient) GetInflationReward(
ctx context.Context, addresses []string, commitment rpc.Commitment, epoch *int64, minContextSlot *int64,
ctx context.Context, commitment rpc.Commitment, addresses []string, epoch *int64, minContextSlot *int64,
) ([]rpc.InflationReward, error) {
return staticInflationRewards, nil
}

//goland:noinspection GoUnusedParameter
func (c *dynamicRPCClient) GetLeaderSchedule(
ctx context.Context, commitment rpc.Commitment, slot int64,
) (map[string][]int64, error) {
return nil, nil
}

//goland:noinspection GoUnusedParameter
func (c *dynamicRPCClient) GetBlock(ctx context.Context, commitment rpc.Commitment, slot int64) (*rpc.Block, error) {
return nil, nil
}

/*
===== OTHER TEST UTILITIES =====:
*/
Expand Down Expand Up @@ -376,7 +394,9 @@ func runCollectionTests(t *testing.T, collector prometheus.Collector, testCases
}

func TestSolanaCollector_Collect_Static(t *testing.T) {
collector := createSolanaCollector(&staticRPCClient{}, slotPacerSchedule, identities, []string{}, votekeys)
collector := createSolanaCollector(
&staticRPCClient{}, slotPacerSchedule, identities, []string{}, votekeys, identities,
)
prometheus.NewPedanticRegistry().MustRegister(collector)

testCases := []collectionTest{
Expand Down Expand Up @@ -454,7 +474,7 @@ solana_account_balance{address="ccc"} 3

func TestSolanaCollector_Collect_Dynamic(t *testing.T) {
client := newDynamicRPCClient()
collector := createSolanaCollector(client, slotPacerSchedule, identities, []string{}, votekeys)
collector := createSolanaCollector(client, slotPacerSchedule, identities, []string{}, votekeys, identities)
prometheus.NewPedanticRegistry().MustRegister(collector)

// start off by testing initial state:
Expand Down
Loading

0 comments on commit a3c498d

Please sign in to comment.