-
Notifications
You must be signed in to change notification settings - Fork 632
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
(wip) (fix) Fix Storage Usage #4247
Conversation
Moving Account to primitives
Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
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.
where did you fix storage usage?
@@ -128,6 +145,16 @@ struct LegacyAccount { | |||
storage_usage: StorageUsage, | |||
} | |||
|
|||
#[cfg(feature = "protocol_feature_add_account_versions")] | |||
#[derive(BorshSerialize, BorshDeserialize)] | |||
struct SerializableAccount { |
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.
should we implement From<SerializableAccount>
for Account
?
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.
Considering it should ever be used only once I am not sure we need this
It is not in yet, safely stashed until this builds, that's why is added wip to it |
…fix-account-storage-usage
I've introduced test, see test_storage_usage_delta |
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.
Can we add at least an integration test to test that this protocol feature works fine with upgrades? You can do it in client/tests/process_blocks.rs
@@ -644,6 +673,13 @@ pub(crate) fn action_add_key( | |||
} | |||
); | |||
let storage_config = &apply_state.config.transaction_costs.storage_usage_config; | |||
#[cfg(feature = "protocol_feature_add_account_versions")] | |||
migrate_account( |
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 seems that you try to do this in every action. I wonder whether we can do it in apply_action
or some higher level function to avoid code duplication
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 in every action, only in those that change storage usage
Will do |
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 it possible to avoid the hardcoded CSV file and instead reproduce it on the fly? How long will it take? If that is not the way to go, how about generating .rs
file instead of .csv
? (I really don't like having more dependencies than necessary, and csv
in runtime
looks completely odd)
/// True iff this ApplyState is on mainnet | ||
#[cfg(feature = "protocol_feature_add_account_versions")] | ||
pub is_mainnet: bool, |
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 introduce so many hacks right into our core primitives that it makes me uneasy. Why do we need to know if it is mainnet here? Let's just have the STORAGE_USAGE_DELTA_FROM_FILE
empty on non-mainnet networks, and thus we won't need this ugly is_mainnet
everywhere since the lookup for a given account in the STORAGE_USAGE_DELTA_FROM_FILE
will never succeed on non-mainnet networks given the map is going to be empty.
fn main() -> Result<(), Error> { | ||
println!("Start"); | ||
|
||
let genesis = Genesis::from_file("output.json"); |
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 feel like you expect to have a state dump in this output.json
, but it is not clear. Please, provide more details in the doc comments as to how to use it.
let storage_usage = | ||
Runtime::compute_storage_usage(&genesis.records.0[..], &RuntimeConfig::default()); | ||
println!("Storage usage calculated"); | ||
for record in genesis.records.0 { |
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 believe this should work:
let storage_usage = | |
Runtime::compute_storage_usage(&genesis.records.0[..], &RuntimeConfig::default()); | |
println!("Storage usage calculated"); | |
for record in genesis.records.0 { | |
let storage_usage = | |
Runtime::compute_storage_usage(genesis.records.as_ref(), &RuntimeConfig::default()); | |
println!("Storage usage calculated"); | |
for record in genesis.records.into() { |
P.S. GenesisRecords
needs one more derive DeriveMore::Into
to support .into()
|
||
#[cfg(feature = "protocol_feature_add_account_versions")] | ||
lazy_static::lazy_static! { | ||
static ref STORAGE_USAGE_DELTA_FROM_FILE: HashMap<AccountId, u64> = read_storage_usage_delta(); |
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 already did enough hacks around by pulling a random CSV file right into the binary, let's at least have the HashMap properly propagated through the configuration. neard
should be the single source of configuration, we should not hijack runtime and get changed its operation due to some random global variable. Let neard
hold the file, parse it conditionally when the chain id is mainnet
, and pass it through the runtime configs down here if necessary.
Co-authored-by: Vlad Frolov <frolvlad@gmail.com>
I'd rather parse csv manually than put more than 3k lines of data directly into rs file |
Another option is to convert CSV to borsh once, and then, at/in runtime, |
Well, it will be even more magical and impossible to review, so I would not go with it |
We can go with serde, I guess |
@frol it is impossible to reproduce it while the node is running as it is prohibitively expensive to iterate over the state. More complex solutions are possible, but I don't think it is worth the effort here. |
JSON or manual CSV parsing is fine. Let's move the preparation logic and the artifact file to |
Storage usage is incorrect for some accounts on mainnet due to oversubtracting storage usage on access key deletion. Bug itself was already fixed. Delta between actual and expected storage usage was calculated on mainnet dump. Next time storage usage will be changed for such accounts they will be migrated to V2 and storage usage will be adjusted
Test plan
See test_storage_usage_delta