-
Notifications
You must be signed in to change notification settings - Fork 619
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
Always record storage when stateless validation is enabled #10859
Changes from all commits
72f7558
31fbeeb
6c64c7d
9f14cf6
730b616
6c5dfac
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -145,10 +145,11 @@ impl<'a> ChainUpdate<'a> { | |
&mut self, | ||
block: &Block, | ||
apply_results: Vec<ShardUpdateResult>, | ||
should_save_state_transition_data: bool, | ||
) -> Result<(), Error> { | ||
let _span = tracing::debug_span!(target: "chain", "apply_chunk_postprocessing").entered(); | ||
for result in apply_results { | ||
self.process_apply_chunk_result(block, result)?; | ||
self.process_apply_chunk_result(block, result, should_save_state_transition_data)?; | ||
} | ||
Ok(()) | ||
} | ||
|
@@ -299,6 +300,7 @@ impl<'a> ChainUpdate<'a> { | |
&mut self, | ||
block: &Block, | ||
result: ShardUpdateResult, | ||
should_save_state_transition_data: bool, | ||
) -> Result<(), Error> { | ||
let block_hash = block.hash(); | ||
let prev_hash = block.header().prev_hash(); | ||
|
@@ -351,12 +353,14 @@ impl<'a> ChainUpdate<'a> { | |
apply_result.outcomes, | ||
outcome_paths, | ||
); | ||
self.chain_store_update.save_state_transition_data( | ||
*block_hash, | ||
shard_id, | ||
apply_result.proof, | ||
apply_result.applied_receipts_hash, | ||
); | ||
if should_save_state_transition_data { | ||
self.chain_store_update.save_state_transition_data( | ||
*block_hash, | ||
shard_id, | ||
apply_result.proof, | ||
apply_result.applied_receipts_hash, | ||
); | ||
} | ||
if let Some(resharding_results) = resharding_results { | ||
self.process_resharding_results(block, &shard_uid, resharding_results)?; | ||
} | ||
|
@@ -383,12 +387,14 @@ impl<'a> ChainUpdate<'a> { | |
|
||
self.chain_store_update.save_chunk_extra(block_hash, &shard_uid, new_extra); | ||
self.chain_store_update.save_trie_changes(apply_result.trie_changes); | ||
self.chain_store_update.save_state_transition_data( | ||
*block_hash, | ||
shard_uid.shard_id(), | ||
apply_result.proof, | ||
apply_result.applied_receipts_hash, | ||
); | ||
if should_save_state_transition_data { | ||
self.chain_store_update.save_state_transition_data( | ||
*block_hash, | ||
shard_uid.shard_id(), | ||
apply_result.proof, | ||
apply_result.applied_receipts_hash, | ||
); | ||
} | ||
|
||
if let Some(resharding_config) = resharding_results { | ||
self.process_resharding_results(block, &shard_uid, resharding_config)?; | ||
|
@@ -413,6 +419,7 @@ impl<'a> ChainUpdate<'a> { | |
block: &Block, | ||
block_preprocess_info: BlockPreprocessInfo, | ||
apply_chunks_results: Vec<(ShardId, Result<ShardUpdateResult, Error>)>, | ||
should_save_state_transition_data: bool, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can be computed here, because There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's true, but I guess it would be possible to move There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Uhh right. Okay, makes sense, feel free to merge |
||
) -> Result<Option<Tip>, Error> { | ||
let shard_ids = self.epoch_manager.shard_ids(block.header().epoch_id())?; | ||
let prev_hash = block.header().prev_hash(); | ||
|
@@ -422,7 +429,7 @@ impl<'a> ChainUpdate<'a> { | |
} | ||
x | ||
}).collect::<Result<Vec<_>, Error>>()?; | ||
self.apply_chunk_postprocessing(block, results)?; | ||
self.apply_chunk_postprocessing(block, results, should_save_state_transition_data)?; | ||
|
||
let BlockPreprocessInfo { | ||
is_caught_up, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,7 @@ use near_epoch_manager::{EpochManagerAdapter, EpochManagerHandle}; | |
use near_parameters::{ActionCosts, ExtCosts, RuntimeConfigStore}; | ||
use near_pool::types::TransactionGroupIterator; | ||
use near_primitives::account::{AccessKey, Account}; | ||
use near_primitives::checked_feature; | ||
use near_primitives::errors::{InvalidTxError, RuntimeError, StorageError}; | ||
use near_primitives::hash::{hash, CryptoHash}; | ||
use near_primitives::receipt::{DelayedReceiptIndices, Receipt}; | ||
|
@@ -30,7 +31,7 @@ use near_primitives::types::{ | |
AccountId, Balance, BlockHeight, EpochHeight, EpochId, EpochInfoProvider, Gas, MerkleHash, | ||
ShardId, StateChangeCause, StateChangesForResharding, StateRoot, StateRootNode, | ||
}; | ||
use near_primitives::version::ProtocolVersion; | ||
use near_primitives::version::{ProtocolVersion, PROTOCOL_VERSION}; | ||
use near_primitives::views::{ | ||
AccessKeyInfoView, CallResult, ContractCodeView, QueryRequest, QueryResponse, | ||
QueryResponseKind, ViewApplyState, ViewStateResult, | ||
|
@@ -704,7 +705,9 @@ impl RuntimeAdapter for NightshadeRuntime { | |
storage_config.use_flat_storage, | ||
), | ||
}; | ||
if storage_config.record_storage { | ||
if checked_feature!("stable", StatelessValidationV0, PROTOCOL_VERSION) | ||
|| cfg!(feature = "shadow_chunk_validation") | ||
{ | ||
Comment on lines
+708
to
+710
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as below. If we want to be super precise, we can use current epoch protocol version, because that recorded storage is not saved anythere, it is used immediately on chunk production. |
||
trie = trie.recording_reads(); | ||
} | ||
let mut state_update = TrieUpdate::new(trie); | ||
|
@@ -865,7 +868,9 @@ impl RuntimeAdapter for NightshadeRuntime { | |
storage_config.use_flat_storage, | ||
), | ||
}; | ||
if storage_config.record_storage { | ||
if checked_feature!("stable", StatelessValidationV0, PROTOCOL_VERSION) | ||
|| cfg!(feature = "shadow_chunk_validation") | ||
{ | ||
Comment on lines
+871
to
+873
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm I imagined that before switching to stateless validation we would enable this feature (or make it the default), and then all nodes would start recording the data needed for stateless validation. At some point the protocol version would change and the nodes would start using this recorded data, but it's okay to start recording much earlier, without stateless validation the data would just be discarded. Is it this that much of a performance hit? We have to do it on the epoch before switching to stateless validation, so it has to be performant enough for normal traffic. Anton's There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Oh, that's nice. |
||
trie = trie.recording_reads(); | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -9,8 +9,10 @@ use near_epoch_manager::{EpochManager, RngSeed}; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
use near_pool::{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
InsertTransactionResult, PoolIteratorWrapper, TransactionGroupIteratorWrapper, TransactionPool, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
use near_primitives::checked_feature; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
use near_primitives::test_utils::create_test_signer; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
use near_primitives::types::validator_stake::{ValidatorStake, ValidatorStakeIter}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
use near_primitives::version::PROTOCOL_VERSION; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
use near_store::flat::{FlatStateChanges, FlatStateDelta, FlatStateDeltaMetadata}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
use near_store::genesis::initialize_genesis_state; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
use num_rational::Ratio; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -1601,6 +1603,11 @@ fn prepare_transactions( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// Check that transactions validation works the same when using recorded storage proof instead of db. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
#[test] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
fn test_prepare_transactions_storage_proof() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if !checked_feature!("stable", StatelessValidationV0, PROTOCOL_VERSION) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
println!("Test not applicable without StatelessValidation enabled"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+1606
to
+1607
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this mean that this test won't kick in before hitting testnet (with stable build)? isn't it too late? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This means that the test will only execute in builds where the default protocol version has stateless validation enabled. Tbh I don't know what #[macro_export]
macro_rules! checked_feature {
("stable", $feature:ident, $current_protocol_version:expr) => {{
$crate::version::ProtocolFeature::$feature.protocol_version() <= $current_protocol_version
}}; The code is here if anyone wants to take a look: nearcore/core/primitives-core/src/version.rs Lines 224 to 256 in f2e87c0
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We already have this kind of check in many other tests that don't work without stateless validation, e.g:
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let (env, chain, mut transaction_pool) = get_test_env_with_chain_and_pool(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let transactions_count = transaction_pool.len(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -1609,7 +1616,6 @@ fn test_prepare_transactions_storage_proof() { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
use_flat_storage: true, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
source: StorageDataSource::Db, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
state_patch: Default::default(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
record_storage: true, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let proposed_transactions = prepare_transactions( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -1630,7 +1636,6 @@ fn test_prepare_transactions_storage_proof() { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
nodes: proposed_transactions.storage_proof.unwrap(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
state_patch: Default::default(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
record_storage: false, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let validated_transactions = prepare_transactions( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -1647,6 +1652,11 @@ fn test_prepare_transactions_storage_proof() { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// Check that transactions validation fails if provided empty storage proof. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
#[test] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
fn test_prepare_transactions_empty_storage_proof() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if !checked_feature!("stable", StatelessValidationV0, PROTOCOL_VERSION) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
println!("Test not applicable without StatelessValidation enabled"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let (env, chain, mut transaction_pool) = get_test_env_with_chain_and_pool(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let transactions_count = transaction_pool.len(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -1655,7 +1665,6 @@ fn test_prepare_transactions_empty_storage_proof() { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
use_flat_storage: true, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
source: StorageDataSource::Db, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
state_patch: Default::default(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
record_storage: true, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let proposed_transactions = prepare_transactions( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -1676,7 +1685,6 @@ fn test_prepare_transactions_empty_storage_proof() { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
nodes: PartialState::default(), // We use empty storage proof here. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
state_patch: Default::default(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
record_storage: false, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let validation_result = prepare_transactions( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
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_produce_state_witness_for_this_or_next_epoch
is used in one other place inprepare_transactions
. We should remove it from there as well and delete the function.