-
Notifications
You must be signed in to change notification settings - Fork 989
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fixDAA; implement wtema #3477
fixDAA; implement wtema #3477
Conversation
Posted a question related to wtema and FlyClient in the DAA RFC - |
core/src/core/block.rs
Outdated
> Utc::now() + Duration::seconds(12 * (consensus::BLOCK_TIME_SEC as i64)) | ||
{ | ||
// refuse blocks more than 12 blocks intervals in future (as in bitcoin) | ||
if header.timestamp > Utc::now() + Duration::seconds(5 * 60) { |
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.
@tromp this is what you were asking in keybase about?
We do not have access to config directly here. But we could potentially expose it via lazy_static!
and thread_local!
similar to what we do for CHAIN_TYPE
and NRD_FEATURE_ENABLED
.
That way we could have something like global::get_future_time_limit()
following the same pattern as global::get_chain_type()
.
The reason for introducing the thread_local!
complexity is to make this configurable in tests. Otherwise we have a single global config value that ends up causing havoc across multiple tests.
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'm not sure this is something we would want to test anytime soon.
Is implementation much simpler if we forego testing different settings?
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.
Not really. We're better off just following the existing pattern I think.
Or just leaving it as hardcoded for now. Maybe just move the constant to global.rs
and reference it from there.
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.
Following existing pattern now.
src/bin/grin.rs
Outdated
@@ -148,7 +148,7 @@ fn real_main() -> i32 { | |||
|
|||
// Initialize our global chain_type and feature flags (NRD kernel support currently). | |||
// These are read via global and not read from config beyond this point. | |||
global::init_global_chain_type(config.members.unwrap().server.chain_type); | |||
global::init_global_chain_type(config.members.as_mut().unwrap().server.chain_type); |
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.
as_mut()
not required here?
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.
my understanding is that all but the last access to config.members needs to have as_mut(),
as suggested by lines 127 and 128.
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.
Ugh.
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.
Yeah - this whole init of the config needs rethinking in grin.rs
. It looks like we have repeatedly just hacked this until it worked...
We should not need to have mut
config here as we do not want to inadvertently write to it. But it needs to be mut
because something else higher up in the file has modified a default via a mut
on some other piece of nested config.
👍 on getting this working for now - but we should revisit at some point.
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 see that grin-wallet uses
global::init_global_chain_type(
config
.members
.as_ref()
.unwrap()
.wallet
.chain_type
.as_ref()
.unwrap()
.clone(),
);
perhaps that's better than as_mut() ?
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.
do you agree with adding a global::init_global_accept_fee_base() method and associated
global::get_accept_fee_base() for the benefit of grin-wallet?
It would call global::init_global_accept_fee_base() after parsing the grin-wallet.toml file,
and then pass global::get_accept_fee_base() as 4th argument whenever calling txlib::mod::tx_fee
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 decided to have an accept_fee_base parameter in BOTH grin-server.toml and grin-wallet.toml,
and both using global::get_accept_fee_base() to query its value. It's even possible (but not particularly useful) to set then to different values in simultaneously running server and wallet.
As a result, we can simply libtx::mod::tx_fee to no longer have an optional fee base argument. If you want to deviate from the default, you can just change it locally, like I do in some tests.
core/src/global.rs
Outdated
ftl | ||
} else { | ||
// Global config unset, default to 5 minutes | ||
5 * 60 |
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.
We should call set_local_future_time_limit()
either way here so we just read local config next time.
This way we are simply lazily initializing the local config.
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.
Does that apply to is_nrd_enabled() as well?
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.
set_local_future_time_limit() always called now
servers/src/common/types.rs
Outdated
@@ -214,6 +217,7 @@ impl Default for ServerConfig { | |||
dandelion_config: pool::DandelionConfig::default(), | |||
stratum_mining_config: Some(StratumServerConfig::default()), | |||
chain_type: ChainTypes::default(), | |||
future_time_limit: 5 * 60, |
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.
We should make 5 * 60
a const
in global.rs
and reuse it in get_future_time_limit()
above.
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.
Sounds good; but then we should also use config::API_SECRET_FILE_NAME rather than ".api_secret" just above?
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.
default now defined as global::DEFAULT_FUTURE_TIME_LIMIT
Came across this and trying to wrap my head around some of it -
Is (2) here relevant to our decision to use a 5 minute FTL? |
zawy argues that an FTL shorter than the blocktime is the best guard against timestamp manipulation. Which is undeniably true; but other people think that doing so carries too much risk of having the local clocks move out of sync beyond the FTL. So our choice of 5 minutes is a compromise that allows some but not much timestamp manipulation, while keeping the risk of out of sync local time very small (the idea being that a clock off by 5 minutes is quite human noticeable, while 1 minute is not so much). |
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.
Looks good to me.
I did not review the actual next_wtema_difficulty()
implementation.
@@ -148,7 +215,7 @@ fn repeat(interval: u64, diff: HeaderInfo, len: u64, cur_time: Option<u64>) -> V | |||
.collect::<Vec<_>>() | |||
} | |||
|
|||
fn repeat_offs(from: u64, interval: u64, diff: u64, len: u64) -> Vec<HeaderInfo> { | |||
fn repeat_offs(interval: u64, diff: u64, len: u64, from: u64) -> Vec<HeaderInfo> { |
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.
Glad this is not called many times and we don't need to review those params getting juggled around... 😅
fixes: #3473 |
@quentinlesceller @j01tz I added you as reviewers (@tromp has you listed in the PR description). |
pub const DMA_WINDOW: u64 = HOUR_HEIGHT; | ||
|
||
/// Difficulty adjustment half life is 4 hours | ||
pub const WTEMA_HALF_LIFE: u64 = 4 * HOUR_SEC; |
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.
How was WTEMA_HALF_LIFE
parameter selection determined?
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.
it's a tradeoff between response speed and stability. the 240 blocks closely matches BTH's choice of the equivalent of 288 blocks.
let last_diff = last_header.difficulty.to_num(); | ||
|
||
// wtema difficulty update | ||
let next_diff = |
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'm struggling a bit verifying this algorithm against the details in the RFC and WTEMA specification. It seems straightforward enough here, but I think I need to better wrap my head around the WTEMA_HALF_LIFE
value. Maybe a line or two of documentation could be helpful here.
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.
Looks good! 👍
@@ -1,43 +1,34 @@ | |||
# Grin's Proof-of-Work |
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 think the changes in this doc are not relevant to the difficulty adjustment algorithm. Maybe we should have them in a separate PR instead?
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.
the doc fixes don't need review so this seemed the easiest way to get then applied.
|
||
// wtema difficulty update | ||
let next_diff = | ||
last_diff * WTEMA_HALF_LIFE / (WTEMA_HALF_LIFE - BLOCK_TIME_SEC + last_block_time); |
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.
Took me a bit to process so putting a note here: in terms of the RFC, WTEMA_HALF_LIFE
corresponds to W * T
. So in this PR we have a W
of 240, meaning the difficulty can change by a factor ~e
every 240 blocks (4 hours, hence the name of WTEMA_HALF_LIFE
) 👍
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.
correct. the name HALF_LIFE is a bit misleading in that sense, since it corresponds not to a doubling.
but that's the terminology that jtoomim and zawy seem to use.
name: [WIP] fixDAA
about: implement simpler wtema difficulty adjustment algorithm
title: fixDAA
labels: consensus breaking
assignees: antiochp, quentinlesceller, joltz
addresses mimblewimble/grin-rfcs#61