Skip to content
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
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- run: sudo apt install -y gcc-aarch64-linux-gnu libc6-dev-arm64-cross g++-aarch64-linux-gnu
- run: sudo apt update && sudo apt install -y gcc-aarch64-linux-gnu libc6-dev-arm64-cross g++-aarch64-linux-gnu
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
Expand Down
12 changes: 10 additions & 2 deletions rocketpool/watchtower/submit-network-balances.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,16 @@ func (t *submitNetworkBalances) run(state *state.NetworkState) error {
}
targetBlockNumber := targetBlockHeader.Number.Uint64()

if targetBlockNumber > state.ElBlockNumber {
// No submission needed: target block in the future
if targetBlockNumber > state.ElBlockNumber || targetBlockNumber == lastSubmissionBlock {
if targetBlockNumber > state.ElBlockNumber {
// No submission needed: Target block in the future
t.log.Println("not enough time has passed for the next price/balances submission")
return nil
}
if targetBlockNumber == lastSubmissionBlock {
// No submission needed: Already submitted for this block
t.log.Println("balances have already been submitted for this block")
}
return nil
}

Expand Down
79 changes: 35 additions & 44 deletions rocketpool/watchtower/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,34 +49,49 @@ func FindLastBlockWithExecutionPayload(bc beacon.Client, slotNumber uint64) (bea
}

func FindNextSubmissionTarget(rp *rocketpool.RocketPool, eth2Config beacon.Eth2Config, bc beacon.Client, ec rocketpool.ExecutionClient, lastSubmissionBlock uint64, referenceTimestamp int64, submissionIntervalInSeconds int64) (uint64, time.Time, *types.Header, error) {
// Get the time of the last submission
lastSubmissionBlockHeader, err := rp.Client.HeaderByNumber(context.Background(), big.NewInt(int64(lastSubmissionBlock)))
if err != nil {
return 0, time.Time{}, nil, fmt.Errorf("can't get the latest submission block header: %w", err)
}
lastSubmissionSlotTimestamp := referenceTimestamp

// Get the time of the latest block
latestEth1Block, err := rp.Client.HeaderByNumber(context.Background(), nil)
if err != nil {
return 0, time.Time{}, nil, fmt.Errorf("can't get the latest block time: %w", err)
}
latestBlockTimestamp := int64(latestEth1Block.Time)
genesisTime := time.Unix(int64(eth2Config.GenesisTime), 0)

if lastSubmissionBlock > 0 {
lastSubmissionBlockHeader, err := rp.Client.HeaderByNumber(context.Background(), big.NewInt(int64(lastSubmissionBlock)))
if err != nil {
return 0, time.Time{}, nil, fmt.Errorf("can't get the latest submission block header: %w", err)
}

lastSubmissionParent, _, err := bc.GetBeaconBlock(lastSubmissionBlockHeader.ParentBeaconRoot.Hex())
if err != nil {
return 0, time.Time{}, nil, fmt.Errorf("can't get the parent block: %w", err)
}

if int64(lastSubmissionBlockHeader.Time)+submissionIntervalInSeconds > latestBlockTimestamp {
return 0, time.Time{}, nil, fmt.Errorf("not enough time has passed for the next price/balances submission")
lastSubmissionSlot := lastSubmissionParent.Slot + 1
lastSubmissionSlotTimestamp = genesisTime.Add(time.Duration((lastSubmissionSlot)*eth2Config.SecondsPerSlot) * time.Second).Unix()
}

// Calculate the next submission timestamp
submissionTimestamp, err := FindNextSubmissionTimestamp(latestBlockTimestamp, referenceTimestamp, submissionIntervalInSeconds)
beaconHead, err := bc.GetBeaconHead()
if err != nil {
return 0, time.Time{}, nil, err
}
headEpoch := beaconHead.Epoch

// Calculate the timestamp at the start of the head epoch
headEpochStartSlot := headEpoch * eth2Config.SlotsPerEpoch
headEpochTimestamp := genesisTime.Add(time.Duration(headEpochStartSlot*eth2Config.SecondsPerSlot) * time.Second)

// Find the highest valid submissionTimestamp that is <= headTime
maxSubmissionTimestamp := int64(0)
n := int64(0)
for {
ts := lastSubmissionSlotTimestamp + n*submissionIntervalInSeconds
if ts > headEpochTimestamp.Unix() {
break
}
maxSubmissionTimestamp = ts
n++
}

// Convert the submission timestamp to time.Time
nextSubmissionTime := time.Unix(submissionTimestamp, 0)

// Get the Beacon block corresponding to this time
genesisTime := time.Unix(int64(eth2Config.GenesisTime), 0)
// Now, use this maxSubmissionTimestamp for slot calculations
nextSubmissionTime := time.Unix(maxSubmissionTimestamp, 0)
timeSinceGenesis := nextSubmissionTime.Sub(genesisTime)
slotNumber := uint64(timeSinceGenesis.Seconds()) / eth2Config.SecondsPerSlot

Expand All @@ -94,34 +109,10 @@ func FindNextSubmissionTarget(rp *rocketpool.RocketPool, eth2Config beacon.Eth2C
}
requiredEpoch := slotNumber / eth2Config.SlotsPerEpoch

// Check if the required epoch is finalized yet
beaconHead, err := bc.GetBeaconHead()
if err != nil {
return 0, time.Time{}, nil, err
}
finalizedEpoch := beaconHead.FinalizedEpoch
if requiredEpoch > finalizedEpoch {
return 0, time.Time{}, nil, fmt.Errorf("balances must be reported for EL block %d, waiting until Epoch %d is finalized (currently %d)", targetBlockNumber, requiredEpoch, finalizedEpoch)
}

return slotNumber, nextSubmissionTime, targetBlockHeader, nil
}

func FindNextSubmissionTimestamp(latestBlockTimestamp int64, referenceTimestamp int64, submissionIntervalInSeconds int64) (int64, error) {
if latestBlockTimestamp == 0 || referenceTimestamp == 0 || submissionIntervalInSeconds == 0 {
return 0, fmt.Errorf("FindNextSubmissionTimestamp can't use zero values")
}

// Calculate the difference between latestBlockTime and the reference timestamp
timeDifference := latestBlockTimestamp - referenceTimestamp
if timeDifference < 0 {
return 0, fmt.Errorf("FindNextSubmissionTimestamp referenceTimestamp in the future")
}

// Calculate the remainder to find out how far off from a multiple of the interval the current time is
remainder := timeDifference % submissionIntervalInSeconds

// Subtract the remainder from current time to find the first multiple of the interval in the past
submissionTimeRef := latestBlockTimestamp - remainder
return submissionTimeRef, nil
}
Loading