Skip to content

feat: p4-compatible resource recharging ledger #989

Open
charmful0x wants to merge 33 commits into
edgefrom
feat/recharging-ledger
Open

feat: p4-compatible resource recharging ledger #989
charmful0x wants to merge 33 commits into
edgefrom
feat/recharging-ledger

Conversation

@charmful0x

@charmful0x charmful0x commented Jun 24, 2026

Copy link
Copy Markdown

~recharging-ledger@1.0 device

a p4-compatible ledger where balances regenerate over time. each account starts at max and refills recharge units every period (default: a 24h bucket -- 86400 units, +1/sec), capped at max. p4 reads the effective balance for the preflight check and charges metered usage against it -- so instead of a hard prepaid balance, users get a continuously-refilling allowance

balances are integer ledger units (operators pick the granularity). an optional rates provider can return account specific recharge rates -- e.g. the trusted recharger-ao-balance@1.0 boosts the rate based on the account's AO balance

benchmarks

setup

  • local HyperBEAM HTTP nodes.
  • p4@1.0 + metering@1.0 + recharging-ledger@1.0 + bundler@1.0
  • AO-provider case used trusted published recharger-ao-balance@1.0
  • 25 rejected uploads per case (first attempt pass through, so expecting 24 402'd rejection)

results (before optimizations)

default recharging-ledger only

avg   58.855 ms
p50   56.208 ms
min   51.857 ms
max   87.227 ms
402   25/25

results (after)

case seq avg ms p99 ms throughput RPS
base_http (no hooks) 19.03 23.28 221.0
rate-limit@1.0 19.03 23.12 211.8
p4 + faff@1.0 19.53 23.32 210.8
p4 + simple-pay@1.0 34.89 38.12 138.6
p4 + recharging-ledger (signed) 32.36 35.32 150.2
p4 + recharging-ledger (p4-commit-charge=false) 19.13 21.40 217.2
p4 + metering→recharging (signed) 33.75 42.05 140.6
p4 + metering→recharging (p4-commit-charge=false) 19.37 22.65 213.4

grace window

added recharging-ledger-grace as a small post-metering tolerance window -- this dont increase the user's visible/spendable balance. balance/3 still return the actual account balance, and p4 still uses that actual balance for preflight checks.

the grace only applies at charge/3: if the post-metering charge drifts slightly below zero, the ledger can accept it down to -Grace instead of rejecting after the work already ran

-> Default: 3600 units

p4-commit-charge

added p4-commit-charge to make the hb_message:commit/2 at dev_p4:response/3 optional. that signed charge isnt actually read anywhere in the erlang-only p4 + ledger stack (faff, simple-pay, recharging-ledger) -- they all rederive the Req signer from the embedded request with hb_message:signers and never look at the node's signature on the charge

the commit/2 only matters for ledgers in a separate trust domain: the hyper-token lua ledger (it checks the charge committers against admin) and paranoid nodes (paranoid-verify re-verifies the request pre-dispatch). so it defaults to ON -- those setups stay untouched -- and only non-paranoid / non-lua-p4 nodes running a local ledger flip it off.

that per-charge RSA-4096 sign (~13ms) is the whole gap: the device itself is already ~0.16ms, so skipping the sign drops p4 + to ~19ms (~41%) and p4 + metering -> recharging from ~34ms to ~19ms -- basically on par with rate-limit / faff (see the table above)

-> Default: true

rates cache

added recharging-ledger-rates-cache-store (+ -cache-ttl) to cache the per-account rate from recharging-ledger-rates. resolving it is a live HTTP hit to the provider on every charge/balance read -- the cache makes repeat an ETS read instead

opt-in: store defaults to [] (off), reuses hb_store_volatile

"recharging-ledger-rates-cache-store": {
    "store-module": "hb_store_volatile", "name": "rates-cache", "max-ttl-ms": 300000
},
"recharging-ledger-rates-cache-ttl": 600

benchmarks vs the real recharger-ao-balance@1.0 provider, p4-commit-charge=false (p4 + metering -> recharging (p4-commit-charge=false) ):

writes -- POST /~bundler@1.0/tx

cache off cache on
seq avg ms 586.76 99.42
p99 ms 1123.28 568.70
throughput RPS 1.70 10.06

reads -- GET /~p4@1.0/balance

cache off cache on
steady-state ms 564.4 41.5

cache on pays the provider round-trip once (first-request miss), then serves from ETS: writes ~535 -> ~56ms, reads ~564 -> ~42ms

-> Default: [] (off), ttl 600s

@charmful0x charmful0x marked this pull request as draft June 24, 2026 17:23
@charmful0x charmful0x marked this pull request as ready for review June 26, 2026 18:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant