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

[Draft] PR for v9 #535

Draft
wants to merge 27 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
a040803
Delete old treegens
jshufro Sep 25, 2024
c483301
Initial ssz spec
jshufro Apr 12, 2024
f3ac3a7
Add SSZ and JSON interop
jshufro Apr 14, 2024
573d1e0
Add tests for rewards ssz
jshufro Apr 19, 2024
012023b
Add v9 as a copy of v8 with renames
jshufro May 5, 2024
36aecfb
Bump non-struct-8s
jshufro May 5, 2024
33263bb
Return serialized json after writing rewards files to disk
jshufro May 5, 2024
08e4a69
Parameterize rewards file extension
jshufro May 5, 2024
57e73e6
Rename paths to specify format
jshufro May 6, 2024
c0c23fc
treegen implementations save rewards files
jshufro May 19, 2024
ba4d7e4
Schedule v9 for holesky and mainnet
jshufro May 19, 2024
ab9d920
Implement stateless v9
jshufro May 20, 2024
9f4c292
Deduplicate some rewards tree structures
jshufro May 21, 2024
c4f985d
Fix some small bugs
jshufro May 21, 2024
fc0f79e
Move invalidNetworkRewards out of rewards file
jshufro May 21, 2024
1145d52
Remove InvalidNetworkNodes from the tree file, return it instead
jshufro May 21, 2024
02382d0
Return MinipoolPerformanceFile in GenerateTreeResult instead of overl…
jshufro May 21, 2024
26b9d76
Delete IRewardsFile GetHeader function
jshufro May 21, 2024
71b682e
Remove INodeRewardsInfo interface
jshufro May 22, 2024
6afeb98
Delete IRewardsFile GetNetworkRewards function
jshufro May 22, 2024
bd9974e
Allow RewardsFile v3 and SSZFile v1 to be saved. Ensure SSZFile v1 co…
jshufro May 22, 2024
b7eff7b
Switch underlying ssz bigint type to math/big.Int and only convert to…
jshufro May 23, 2024
63d1490
Clarifications around the term Network in SSZFile_v1
jshufro May 23, 2024
dbe270e
Add constructors for NodeReward/NetworkReward
jshufro Jun 18, 2024
80799e0
Use SSZFile_v1 in treegen v9
jshufro May 23, 2024
2d73b45
Implement rolling v9
jshufro Jun 18, 2024
b1deefe
Use SSZFile_v1 in treegen rolling v9
jshufro Jun 18, 2024
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
3 changes: 2 additions & 1 deletion rocketpool/api/network/generate-tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/fatih/color"
"github.com/rocket-pool/rocketpool-go/rewards"
"github.com/rocket-pool/smartnode/shared/services"
"github.com/rocket-pool/smartnode/shared/services/config"
"github.com/rocket-pool/smartnode/shared/types/api"
"github.com/urfave/cli"
)
Expand Down Expand Up @@ -39,7 +40,7 @@ func canGenerateRewardsTree(c *cli.Context, index uint64) (*api.CanNetworkGenera
response.CurrentIndex = currentIndexBig.Uint64()

// Get the path of the file to save
filePath := cfg.Smartnode.GetRewardsTreePath(index, true)
filePath := cfg.Smartnode.GetRewardsTreePath(index, true, config.RewardsExtensionJSON)
_, err = os.Stat(filePath)
if os.IsNotExist(err) {
response.TreeFileExists = false
Expand Down
7 changes: 5 additions & 2 deletions rocketpool/node/collectors/node-collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -321,8 +321,10 @@ func (collector *NodeCollector) Collect(channel chan<- prometheus.Metric) {
if !previousInterval.TreeFileExists {
return fmt.Errorf("Error retrieving previous interval's total node weight: rewards file %s doesn't exist for interval %d", previousInterval.TreeFilePath, previousRewardIndex)
}
// Convert to a float, accuracy loss is meaningless compared to the heuristic's natural inaccuracy.
previousIntervalTotalNodeWeight = &previousInterval.TotalNodeWeight.Int

if previousInterval.TotalNodeWeight != nil {
previousIntervalTotalNodeWeight.Set(previousInterval.TotalNodeWeight)
}

// Get the info for each claimed interval
for _, claimedInterval := range claimed {
Expand Down Expand Up @@ -533,6 +535,7 @@ func (collector *NodeCollector) Collect(channel chan<- prometheus.Metric) {

nodeWeightSum := big.NewInt(0).Add(nodeWeight, previousIntervalTotalNodeWeight)

// Convert to a float, accuracy loss is meaningless compared to the heuristic's natural inaccuracy.
// nodeWeightRatio = current_node_weight / (current_node_weight + previous_interval_total_node_weight)
nodeWeightRatio, _ := big.NewFloat(0).Quo(
big.NewFloat(0).SetInt(nodeWeight),
Expand Down
2 changes: 1 addition & 1 deletion rocketpool/node/download-reward-trees.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ func (d *downloadRewardsTrees) run(state *state.NetworkState) error {
missingIntervals := []uint64{}
for i := uint64(0); i < currentIndex; i++ {
// Check if the tree file exists
treeFilePath := d.cfg.Smartnode.GetRewardsTreePath(i, true)
treeFilePath := d.cfg.Smartnode.GetRewardsTreePath(i, true, config.RewardsExtensionJSON)
_, err = os.Stat(treeFilePath)
if os.IsNotExist(err) {
d.log.Printlnf("You are missing the rewards tree file for interval %d.", i)
Expand Down
45 changes: 19 additions & 26 deletions rocketpool/watchtower/generate-rewards-tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -234,53 +234,46 @@ func (t *generateRewardsTree) generateRewardsTree(index uint64) {
// Implementation for rewards tree generation using a viable EC
func (t *generateRewardsTree) generateRewardsTreeImpl(rp *rocketpool.RocketPool, index uint64, generationPrefix string, rewardsEvent rewards.RewardsEvent, elBlockHeader *types.Header, state *state.NetworkState) {

// Determine the end of the interval
snapshotEnd := &rprewards.SnapshotEnd{
ConsensusBlock: rewardsEvent.ConsensusBlock.Uint64(),
ExecutionBlock: rewardsEvent.ExecutionBlock.Uint64(),
Slot: state.BeaconConfig.FirstSlotAtLeast(rewardsEvent.IntervalEndTime.Unix()),
}

// Generate the rewards file
start := time.Now()
treegen, err := rprewards.NewTreeGenerator(&t.log, generationPrefix, rp, t.cfg, t.bc, index, rewardsEvent.IntervalStartTime, rewardsEvent.IntervalEndTime, rewardsEvent.ConsensusBlock.Uint64(), elBlockHeader, rewardsEvent.IntervalsPassed.Uint64(), state, nil)
treegen, err := rprewards.NewTreeGenerator(&t.log, generationPrefix, rp, t.cfg, t.bc, index, rewardsEvent.IntervalStartTime, rewardsEvent.IntervalEndTime, snapshotEnd, elBlockHeader, rewardsEvent.IntervalsPassed.Uint64(), state, nil)
if err != nil {
t.handleError(fmt.Errorf("%s Error creating Merkle tree generator: %w", generationPrefix, err))
return
}
rewardsFile, err := treegen.GenerateTree()
treeResult, err := treegen.GenerateTree()
if err != nil {
t.handleError(fmt.Errorf("%s Error generating Merkle tree: %w", generationPrefix, err))
return
}
header := rewardsFile.GetHeader()
for address, network := range header.InvalidNetworkNodes {
rewardsFile := treeResult.RewardsFile
for address, network := range treeResult.InvalidNetworkNodes {
t.log.Printlnf("%s WARNING: Node %s has invalid network %d assigned! Using 0 (mainnet) instead.", generationPrefix, address.Hex(), network)
}
t.log.Printlnf("%s Finished in %s", generationPrefix, time.Since(start).String())

// Validate the Merkle root
root := common.BytesToHash(header.MerkleTree.Root())
if root != rewardsEvent.MerkleRoot {
t.log.Printlnf("%s WARNING: your Merkle tree had a root of %s, but the canonical Merkle tree's root was %s. This file will not be usable for claiming rewards.", generationPrefix, root.Hex(), rewardsEvent.MerkleRoot.Hex())
root := rewardsFile.GetMerkleRoot()
if root != rewardsEvent.MerkleRoot.Hex() {
t.log.Printlnf("%s WARNING: your Merkle tree had a root of %s, but the canonical Merkle tree's root was %s. This file will not be usable for claiming rewards.", generationPrefix, root, rewardsEvent.MerkleRoot.Hex())
} else {
t.log.Printlnf("%s Your Merkle tree's root of %s matches the canonical root! You will be able to use this file for claiming rewards.", generationPrefix, header.MerkleRoot)
t.log.Printlnf("%s Your Merkle tree's root of %s matches the canonical root! You will be able to use this file for claiming rewards.", generationPrefix, root)
}

// Create the JSON files
rewardsFile.SetMinipoolPerformanceFileCID("---")

// Save the files
t.log.Printlnf("%s Saving JSON files...", generationPrefix)
localMinipoolPerformanceFile := rprewards.NewLocalFile[rprewards.IMinipoolPerformanceFile](
rewardsFile.GetMinipoolPerformanceFile(),
t.cfg.Smartnode.GetMinipoolPerformancePath(index, true),
)
localRewardsFile := rprewards.NewLocalFile[rprewards.IRewardsFile](
rewardsFile,
t.cfg.Smartnode.GetRewardsTreePath(index, true),
)

// Write the files
err = localMinipoolPerformanceFile.Write()
if err != nil {
t.handleError(fmt.Errorf("%s error saving minipool performance file: %w", generationPrefix, err))
return
}
err = localRewardsFile.Write()
_, _, err = treegen.SaveFiles(treeResult, false)
if err != nil {
t.handleError(fmt.Errorf("%s error saving rewards file: %w", generationPrefix, err))
t.handleError(fmt.Errorf("%s failed to save rewards artifacts: %w", generationPrefix, err))
return
}

Expand Down
8 changes: 7 additions & 1 deletion rocketpool/watchtower/submit-network-balances.go
Original file line number Diff line number Diff line change
Expand Up @@ -352,10 +352,16 @@ func (t *submitNetworkBalances) getNetworkBalances(elBlockHeader *types.Header,
timeSinceStart := slotTime.Sub(startTime)
intervalsPassed := timeSinceStart / intervalTime
endTime := slotTime
// Since we aren't generating an actual tree, just use beaconBlock as the snapshotEnd
snapshotEnd := &rprewards.SnapshotEnd{
Slot: beaconBlock,
ConsensusBlock: beaconBlock,
ExecutionBlock: state.ElBlockNumber,
}

// Approximate the staker's share of the smoothing pool balance
// NOTE: this will use the "vanilla" variant of treegen, without rolling records, to retain parity with other Oracle DAO nodes that aren't using rolling records
treegen, err := rprewards.NewTreeGenerator(t.log, "[Balances]", client, t.cfg, t.bc, currentIndex, startTime, endTime, beaconBlock, elBlockHeader, uint64(intervalsPassed), state, nil)
treegen, err := rprewards.NewTreeGenerator(t.log, "[Balances]", client, t.cfg, t.bc, currentIndex, startTime, endTime, snapshotEnd, elBlockHeader, uint64(intervalsPassed), state, nil)
if err != nil {
return fmt.Errorf("error creating merkle tree generator to approximate share of smoothing pool: %w", err)
}
Expand Down
Loading
Loading