Skip to content

*: feerecipient command#4341

Merged
obol-bulldozer[bot] merged 16 commits intomainfrom
pinebit/feerecipient-cmd
Mar 16, 2026
Merged

*: feerecipient command#4341
obol-bulldozer[bot] merged 16 commits intomainfrom
pinebit/feerecipient-cmd

Conversation

@pinebit
Copy link
Collaborator

@pinebit pinebit commented Feb 26, 2026

This PR introduces new CLI commands: charon feerecipient sign|fetch. The fetch command eventually writes the overrides file, but it is NOT used yet in charon runtime (another PR will address this).

$ charon feerecipient --help
Sign and fetch updated builder registration messages with new fee recipients using a remote API, enabling the modification of fee recipient addresses without cluster restart.

Usage:
  charon feerecipient [command]

Available Commands:
  fetch       Fetch aggregated builder registrations.
  sign        Sign partial builder registration messages.
$ charon feerecipient fetch --help
Fetches builder registration messages from a remote API and aggregates those with quorum, writing fully signed registrations to a local JSON file.

Usage:
  charon feerecipient fetch [flags]

Flags:
  -h, --help                            Help for fetch
      --lock-file string                Path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json")
      --overrides-file string           Path to the builder registrations overrides file. (default ".charon/builder_registrations_overrides.json")
      --publish-address string          The URL of the remote API. (default "https://api.obol.tech/v1")
      --publish-timeout duration        Timeout for accessing the remote API. (default 5m0s)
      --validator-public-keys strings   Optional comma-separated list of validator public keys to fetch builder registrations for.
$ charon feerecipient sign --help
Signs new partial builder registration messages with updated fee recipients and publishes them to a remote API.

Usage:
  charon feerecipient sign [flags]

Flags:
      --fee-recipient string            [REQUIRED] New fee recipient address to be applied to all specified validators.
      --gas-limit uint                  Optional gas limit override for builder registrations. If not set, the existing gas limit from the cluster lock or overrides file is used.
  -h, --help                            Help for sign
      --lock-file string                Path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json")
      --overrides-file string           Path to the builder registrations overrides file. (default ".charon/builder_registrations_overrides.json")
      --private-key-file string         Path to the charon enr private key file. (default ".charon/charon-enr-private-key")
      --publish-address string          The URL of the remote API. (default "https://api.obol.tech/v1")
      --publish-timeout duration        Timeout for accessing the remote API. (default 5m0s)
      --timestamp int                   Optional Unix timestamp for the builder registration message. When set, all operators can sign independently with the same timestamp. If not set, the current time is used for new registrations.
      --validator-keys-dir string       Path to the directory containing the validator private key share files and passwords. (default ".charon/validator_keys")
      --validator-public-keys strings   [REQUIRED] Comma-separated list of validator public keys to sign builder registrations for.

Testing

  • Unit tests
  • Manually tested typical flows against a non-prod dev environment
  • Stress tested with ai-generated python scripts, no race conditions observed

category: feature
ticket: #4293

@pinebit pinebit force-pushed the pinebit/feerecipient-cmd branch from a2a4531 to 457aa4a Compare March 6, 2026 09:06
@codecov
Copy link

codecov bot commented Mar 6, 2026

Codecov Report

❌ Patch coverage is 53.91121% with 218 lines in your changes missing coverage. Please review.
✅ Project coverage is 56.28%. Comparing base (aea4746) to head (81e38d2).
⚠️ Report is 10 commits behind head on main.

Files with missing lines Patch % Lines
cmd/feerecipientsign.go 63.90% 58 Missing and 29 partials ⚠️
app/obolapi/feerecipient.go 0.00% 61 Missing ⚠️
cmd/feerecipientfetch.go 71.65% 23 Missing and 13 partials ⚠️
app/obolapi/feerecipient_model.go 0.00% 30 Missing ⚠️
cmd/cmd.go 0.00% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4341      +/-   ##
==========================================
- Coverage   56.67%   56.28%   -0.40%     
==========================================
  Files         237      242       +5     
  Lines       31681    32173     +492     
==========================================
+ Hits        17956    18107     +151     
- Misses      11438    11743     +305     
- Partials     2287     2323      +36     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@pinebit pinebit force-pushed the pinebit/feerecipient-cmd branch from 5be4c8f to c03b378 Compare March 12, 2026 07:27
@pinebit pinebit changed the title *: feerecipient cmd, wip *: feerecipient command Mar 12, 2026
@pinebit pinebit requested a review from OisinKyne March 12, 2026 12:15
@pinebit pinebit marked this pull request as ready for review March 12, 2026 12:17
@OisinKyne
Copy link
Contributor

Feature idea:
After a lot of edits, it might be hard to tell what the freshest / latest fee recipient is for a key / the whole cluster is. We might want a charon feerecipient get <pubkey>|all or charon feerecipient list, or something of the sort that lists summaries for one/all keys in the cluster. checking across the lock, their local overrides file, and best-effort our API, (and even some relays to confirm they see the same thing?) wdyt?

@pinebit
Copy link
Collaborator Author

pinebit commented Mar 16, 2026

Feature idea: After a lot of edits, it might be hard to tell what the freshest / latest fee recipient is for a key / the whole cluster is. We might want a charon feerecipient get <pubkey>|all or charon feerecipient list, or something of the sort that lists summaries for one/all keys in the cluster. checking across the lock, their local overrides file, and best-effort our API, (and even some relays to confirm they see the same thing?) wdyt?

Good idea, I can add list command maybe that will print the state for the selected or all the keys. But I can do in the next PR to not make overcomplicated and easy to review.

Co-authored-by: kalo <24719519+KaloyanTanev@users.noreply.github.com>
Signed-off-by: Andrei Smirnov <pinebit@gmail.com>
@OisinKyne
Copy link
Contributor

$ charon feerecipient --help
Manage the preferred fee recipient addresses for the cluster. These addresses receive transaction tips and MEV when a validator makes a proposal.

Usage:
  charon feerecipient [command]

Available Commands:
  fetch       Fetch new fee recipients (builder registrations).
  sign        Sign new builder registration messages.
$ charon feerecipient fetch --help
Fetches builder registration messages from a remote API and aggregates those with quorum, writing them to a local JSON file.

Usage:
  charon feerecipient fetch [flags]

Flags:
  -h, --help                            Help for fetch
      --lock-file string                Path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json")
      --overrides-file string           Path to the builder registrations overrides file. (default ".charon/builder_registrations_overrides.json")
      --publish-address string          The URL of the remote API. (default "https://api.obol.tech/v1")
      --publish-timeout duration        Timeout for accessing the remote API. (default 5m0s)
      --validator-public-keys strings   Optional comma-separated list of validator public keys to fetch builder registrations for.
$ charon feerecipient sign --help
Signs new builder registration messages to update the preferred fee recipient and publishes them to a remote API.

Usage:
  charon feerecipient sign [flags]

Flags:
      --fee-recipient string            [REQUIRED] New fee recipient address to be applied to all specified validators.
      --gas-limit uint                  Optional gas limit override for builder registrations. If not set, the existing gas limit from the cluster lock or overrides file is used.
  -h, --help                            Help for sign
      --lock-file string                Path to the cluster lock file defining the distributed validator cluster. (default ".charon/cluster-lock.json")
      --overrides-file string           Path to the builder registrations overrides file. (default ".charon/builder_registrations_overrides.json")
      --private-key-file string         Path to the charon enr private key file. (default ".charon/charon-enr-private-key")
      --publish-address string          The URL of the remote API. (default "https://api.obol.tech/v1")
      --publish-timeout duration        Timeout for accessing the remote API. (default 5m0s)
      --timestamp int                   Optional Unix timestamp for the builder registration message. When set, all operators can sign independently with the same timestamp. If not set, the current time is used for new registrations.
      --validator-keys-dir string       Path to the directory containing the validator private key share files and passwords. (default ".charon/validator_keys")
      --validator-public-keys strings   [REQUIRED] Comma-separated list of validator public keys to sign builder registrations for.

See tweaks above ^

One UX question (that can be additive in your next PR) is if we could optionally specify validators to sign for with --old-fee-recipient instead of/as well as -validator-public-keys. and maybe some sort of all option

@pinebit pinebit added the merge when ready Indicates bulldozer bot may merge when all checks pass label Mar 16, 2026
@sonarqubecloud
Copy link

@obol-bulldozer obol-bulldozer bot merged commit 23c07d2 into main Mar 16, 2026
10 of 11 checks passed
@obol-bulldozer obol-bulldozer bot deleted the pinebit/feerecipient-cmd branch March 16, 2026 14:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge when ready Indicates bulldozer bot may merge when all checks pass

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants