feat(runtime): configurable per-block transaction capacity - #2026
Draft
chrispalaskas wants to merge 1 commit into
Draft
feat(runtime): configurable per-block transaction capacity#2026chrispalaskas wants to merge 1 commit into
chrispalaskas wants to merge 1 commit into
Conversation
Adds `tx_weight_factor_permille` to `res/<network>/system-parameters-config.json`: one value deciding how many ledger transactions a block holds relative to the ledger's own block limits. `1000` (the default, and what configs without the field deserialize to) is unscaled; `500` means "half the weight per transaction", i.e. roughly twice as many per block. A transaction's weight has two parts, and the factor reaches them by two routes: - The ledger-derived part is the transaction's cost normalised against `LedgerParameters::limits::block_limits`. `generate-genesis` divides those limits by the factor, which widens the ledger's own per-block capacity and narrows this part of the weight by the same ratio, so FRAME's view of a full block and the ledger's stay in step without a governance transaction. - The flat `ConfigurableTransactionSizeWeight` term does not follow the block limits, so `pallet_midnight` applies the factor to it directly. The chain spec seeds the new `TxWeightFactorPermille` storage from the same config file; `set_tx_weight_factor` (root) can change it on a running chain. Genesis verification takes `--system-parameters-config` and applies the same scaling to the config file before comparing it against the genesis state, so the generator and the verifier share one implementation (`midnight_node_ledger_helpers::block_capacity::scale_block_limits`). Assisted-by: Claude:claude-opus-5 Signed-off-by: chrispalaskas <chris.palaskas@gmail.com>
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Overview - DO NOT MERGE - Only for testing
Adds one config value,
tx_weight_factor_permilleinres/<network>/system-parameters-config.json, that decides how many ledger transactions a block holds relative to the ledger's own block limits.1000(the default, and what configs without the field deserialize to) is unscaled;500means "half the weight per transaction", i.e. roughly twice as many per block.This is for perf/test networks, where we want to pack more transactions into a block than the shipped limits allow. Today that needs an
update-ledger-parametersgovernance transaction against a running chain; with this change the ledger genesis is prebaked with the same value the node uses.Why the factor is applied in two different ways. A transaction's weight has two parts:
LedgerParameters::limits::block_limits(Bridge::get_transaction_cost→cost.normalize(limits)→scale_normalized_cost(..., max_block)).generate-genesisnow divides those block limits by the factor, which widens the ledger's own per-block capacity and narrows this part of the weight by exactly the same ratio — so FRAME's view of a full block and the ledger's stay in step.ConfigurableTransactionSizeWeightterm (20 ms today) is independent of the block limits, so nothing else would rescale it.pallet_midnightapplies the factor to that term, seeded from the same config file via the chain spec.Deliberately not applying the factor to the ledger-derived part in the pallet: that would count it twice, letting FRAME pack ~4x while the ledger admits 2x, and the surplus transactions would be included in the block but fail with
BlockLimitExceededError.doubling_block_limits_halves_the_scaled_costpins the property this rests on.Genesis verification takes
--system-parameters-configtoo and applies the same scaling to the config file before comparing against the genesis state — otherwise it would flag the scaled limits as a mismatch. Generator and verifier share one implementation,midnight_node_ledger_helpers::block_capacity::scale_block_limits.Changing the factor requires regenerating the network's genesis state and chain spec. All networks default to
1000, so this is a no-op until a network sets it.🗹 TODO before merging
/bot rebuild-metadata— newset_tx_weight_factorcall andTxWeightFactorPermillestorage item change runtime metadata📌 Submission Checklist
git commit -s) for the DCOBackward compatibility:
tx_weight_factor_permillehas a serde default, so network configs that predate it parse unchanged; the pallet's genesis field isOption<u32>andNoneleaves the storage default; raw chain specs without the storage item fall back to the same default.--system-parameters-configis optional on bothgenerate-genesisandverify-ledger-state-genesis.🧪 Testing Evidence
Workspace
cargo check --all-targetsandcargo clippy --workspace --all-targetsclean;cargo fmt --allapplied.New tests:
pallet_midnight::tests::tx_weight_factor_rescales_only_the_flat_term— the factor movesConfigurableTransactionSizeWeightand leaves the ledger-derived term alone.pallet_midnight::tests::tx_weight_factor_comes_from_genesis_config— the chain-spec path seeds the storage value.pallet_midnight::tests::tx_weight_factor_requires_root.block_capacity::tests::*— 500 doubles every block-limit dimension, 2000 halves them, 1000 is a no-op, 0 is rejected.ledger::...::doubling_block_limits_halves_the_scaled_cost— the coupling the design rests on: doubling the block limits halves the scaled cost.Measured weight split on the undeployed fixtures, for context on what the factor buys (normal-class limit 1.5e12):
CHECK_TX)DEPLOY_TX)Not run: the toolkit's end-to-end
generate-genesistest (needs a proof server). An actual perfnet genesis rebuild at500is the remaining validation.🔱 Fork Strategy
No migration needed: the new storage item is
ValueQuerywith a default of1000, so an existing chain reads unscaled until root callsset_tx_weight_factor. Changing the factor for a network means regenerating its genesis state and chain spec, i.e. a new network rather than an upgrade.Links