Introduce new concept of "slot portion for proposing" #8280
Conversation
Currently when building a block we actually give the proposer all of the time in the slot, while this is wrong. The slot is actually split in at least two phases proposing and propagation or in the polkadot case into three phases validating pov's, proposing and propagation. As we don't want to bring that much polkadot concepts into Substrate, we only support splitting the slot into proposing and propagation. The portion can now be passed as parameter to AuRa and BABE to configure this value. However, this slot portion for propagation doesn't mean that the proposer can not go over this limit. When we miss slots we still apply the lenience factor to increase the proposing time, so that we have enough time to build a heavy block. Besides all what was said above, this is especially required for parachains. Parachains have a much more constraint proposing window. Currently the slot duration is at minimum 12 seconds, but we only have around 500ms for proposing. So, this slot portion for proposing is really required to make it working without hacks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good!
let proposing = awaiting_proposer.and_then(move |proposer| proposer.propose( | ||
slot_info.inherent_data, | ||
sp_runtime::generic::Digest { | ||
logs, | ||
}, | ||
slot_remaining_duration, | ||
proposing_remaining_duration.mul_f32(0.98), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a risk that the 2% ends up being too small when the remaining duration becomes very small? As opposed to use a % of the proposing time or slot time which should be a pretty stable duration?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is a good question. For parachains this will currently be 500ms for proposing, so leaving us with 10ms buffer. I would say that this is enough buffer, especially as the select is biased to the proposing
, meaning this will be polled first.
Do you have some better idea?
I think we should use this for now and adapt if someone complains.
WDYT @andresilva ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently the margin was 0% so this is better :P
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the default case, but with a lenience factor applied, the timeout was always > than the remaining time of the slot. (Before if there was a runtime upgrade that maybe took 7 seconds and a proposing time of 8 seconds after applying the lenience factor, we would have build the block and ended the proposing. Now, it could theoretically happen that we still add one or 2 transactions 😬 as we propagate the real proposing time to the block builder.)
let proposing = awaiting_proposer.and_then(move |proposer| proposer.propose( | ||
slot_info.inherent_data, | ||
sp_runtime::generic::Digest { | ||
logs, | ||
}, | ||
slot_remaining_duration, | ||
proposing_remaining_duration.mul_f32(0.98), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently the margin was 0% so this is better :P
client/consensus/slots/src/lib.rs
Outdated
@@ -613,7 +621,7 @@ pub fn slot_lenience_linear(parent_slot: Slot, slot_info: &SlotInfo) -> Option<D | |||
None | |||
} else { | |||
let slot_lenience = std::cmp::min(skipped_slots, BACKOFF_CAP); | |||
Some(Duration::from_millis(slot_lenience * slot_info.duration)) | |||
Some(slot_info.duration.mul_f64(slot_lenience as f64)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some(slot_info.duration.mul_f64(slot_lenience as f64)) | |
Some(slot_lenience * slot_info.duration) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I first had this, but they don't implement Mull<f64>
for Duration :D
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
slot_lenience
should not be f64
here, we are just multiplying by the number of skipped slots.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh now I remember. slot_lenience
is an u64
and they don't support multiplication with that. BUT, they support multiplication with f64
.
But yeah, I think the maximum value is 20. So, I can just cast it to an u32.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I was reviewing the PR I noticed that above for the exponential case we just multiply, and I found it strange that here it was different :P
bot merge |
Trying merge. |
* Substrate companion #8280 paritytech/substrate#8280 * "Update Substrate" Co-authored-by: parity-processbot <>
* Introduce new concept of "slot portion for proposing" Currently when building a block we actually give the proposer all of the time in the slot, while this is wrong. The slot is actually split in at least two phases proposing and propagation or in the polkadot case into three phases validating pov's, proposing and propagation. As we don't want to bring that much polkadot concepts into Substrate, we only support splitting the slot into proposing and propagation. The portion can now be passed as parameter to AuRa and BABE to configure this value. However, this slot portion for propagation doesn't mean that the proposer can not go over this limit. When we miss slots we still apply the lenience factor to increase the proposing time, so that we have enough time to build a heavy block. Besides all what was said above, this is especially required for parachains. Parachains have a much more constraint proposing window. Currently the slot duration is at minimum 12 seconds, but we only have around 500ms for proposing. So, this slot portion for proposing is really required to make it working without hacks. * Offgit feedback * Cast cast cast
Currently when building a block we actually give the proposer all of the
time in the slot, while this is wrong. The slot is actually split in at
least two phases proposing and propagation or in the polkadot case into
three phases validating pov's, proposing and propagation. As we don't
want to bring that much polkadot concepts into Substrate, we only
support splitting the slot into proposing and propagation. The portion
can now be passed as parameter to AuRa and BABE to configure this value.
However, this slot portion for propagation doesn't mean that the
proposer can not go over this limit. When we miss slots we still apply
the lenience factor to increase the proposing time, so that we have
enough time to build a heavy block.
Besides all what was said above, this is especially required for
parachains. Parachains have a much more constraint proposing window.
Currently the slot duration is at minimum 12 seconds, but we only have
around 500ms for proposing. So, this slot portion for proposing is
really required to make it working without hacks.
polkadot companion: paritytech/polkadot#2578