Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Changes from 2 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
38299d3
don't modify inherent data on heavy block
coriolinus Dec 2, 2020
fd587b8
write up current thinking on block weight detection
coriolinus Dec 7, 2020
5e59e4e
extract inherent inclusion check into its own function
coriolinus Dec 8, 2020
0f373fd
put heavy block check into runtime
coriolinus Dec 8, 2020
e58858d
the `inclusion` inherent call is Operational, not Mandatory
coriolinus Dec 10, 2020
f670124
Revert "the `inclusion` inherent call is Operational, not Mandatory"
coriolinus Dec 14, 2020
d1c570f
Revert "write up current thinking on block weight detection"
coriolinus Dec 14, 2020
c260f94
Revert "don't modify inherent data on heavy block"
coriolinus Dec 14, 2020
684309d
add backed candidate block weight assumption to configuration
coriolinus Dec 14, 2020
66834f5
Limit backed candidates according to a candidate weight heuristic.
coriolinus Dec 14, 2020
174f906
simplify limit_backed_candidates and weight assumption
coriolinus Dec 14, 2020
63b4869
don't trust the provisioner to fairly distribute candidates
coriolinus Dec 14, 2020
e8d16fd
use saturating subtraction
coriolinus Dec 15, 2020
13bf41b
empty commit to restart ci
coriolinus Dec 15, 2020
38e5f66
Merge remote-tracking branch 'origin/master' into prgn-heavy-blocks
coriolinus Dec 16, 2020
5bc1f4f
use new mechanism for getting max block weight
coriolinus Dec 16, 2020
3dbed6d
apply weight refunds to the inclusion inherent
coriolinus Dec 16, 2020
8aa71bd
use a correct fixed weight for the inclusion inherent
coriolinus Dec 16, 2020
88fe99a
use dynamic inclusion weight so we reduce calculated weight when excl…
coriolinus Dec 16, 2020
84afca7
don't double-count this intrinsic's weight in the block weight
coriolinus Dec 16, 2020
d43f2ab
add unit tests of fn limit_backed_candidates
coriolinus Dec 18, 2020
accd5f7
add tests that the inclusion inherent's weight correctly updates
coriolinus Jan 4, 2021
bb6a038
Merge remote-tracking branch 'origin/master' into prgn-heavy-blocks
coriolinus Jan 5, 2021
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
54 changes: 49 additions & 5 deletions node/core/proposer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,12 +193,56 @@ where
record_proof: RecordProof,
) -> Self::Proposal {
async move {
let provisioner_data = match self.get_provisioner_data().await {
Ok(pd) => pd,
Err(err) => {
tracing::warn!(err = ?err, "could not get provisioner inherent data; injecting default data");
Default::default()
// TODO: how can we tell, here, if we expect a heavy block?
//
// The runtime exposes `frame_system::Module::block_weight`
// (https://substrate.dev/rustdocs/v2.0.0/frame_system/struct.Module.html?search=#method.block_weight)
// and the `MaximumBlockWeight`
// (https://substrate.dev/rustdocs/v2.0.0/frame_system/trait.Trait.html#associatedtype.MaximumBlockWeight),
// so fundamentally this is a question of propagating the necessary runtime information
// through the Runtime API. At that point, it's a simple inequality:
//
// ```rust
// let expect_heavy_block = block_weight > maximum_block_weight - MARGIN;
// ```
//
// Unfortunately, it's not quite that simple, because the whole point of this proposer
// is to inject the provisioner data before the substrate proposer runs. Before it runs,
// the `block_weight` function isn't going to give us any useful information, beacuse
// nothing has yet been proposed to be included in the block.
//
// The naive option is very simple: run the proposer, then weigh the block. Either add a
// dry-run mode to the internal proposer, or run the internal proposer and then revert
// all state changes that it's made. The downside of this approach is that it runs
// everything twice, cutting runtime performance literally in half. That would be
// suboptimal.
//
// A somewhat more sophisticated approach takes advantage of the fact that Substrate's
// proposer is greedy: if it is possible to include all proposed transactions, then it
// will do so. This means that we can just compute the weight of all the transactions in
// the pool, and use essentially the same inequality:
//
// ```rust
// let expect_heavy_block = sum_of_tx_weights > maximum_block_weight - MARGIN;
// ```
//
// This is complicated by the fact that transactions are code, not data: in principle,
// it would be possible for an attacker to craft a transaction which is heavy and looks
// valid to the transaction pool, but which aborts cheaply when it is executed,
// preventing its costs from being deducted from the attacker. Spamming the relay chain
// with sufficient of these transactions would prevent all parachain progress.
let expect_heavy_block = false;

let provisioner_data = if !expect_heavy_block {
match self.get_provisioner_data().await {
Ok(pd) => pd,
Err(err) => {
tracing::warn!(err = ?err, "could not get provisioner inherent data; injecting default data");
Default::default()
}
}
} else {
Default::default()
};

inherent_data.put_data(
Expand Down