Skip to content
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

[stateless_validation] Missing main transition state proof for old block pytest repro #11188

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions chain/client/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ pub struct Client {
#[cfg(feature = "test_features")]
pub adv_produce_blocks: Option<AdvProduceBlocksMode>,
#[cfg(feature = "test_features")]
pub adv_disable_chunk_validation: bool,
#[cfg(feature = "test_features")]
pub produce_invalid_chunks: bool,
#[cfg(feature = "test_features")]
pub produce_invalid_tx_in_chunks: bool,
Expand Down Expand Up @@ -371,6 +373,8 @@ impl Client {
produce_invalid_chunks: false,
#[cfg(feature = "test_features")]
produce_invalid_tx_in_chunks: false,
#[cfg(feature = "test_features")]
adv_disable_chunk_validation: false,
#[cfg(feature = "sandbox")]
accrued_fastforward_delta: 0,
clock: clock.clone(),
Expand Down
6 changes: 6 additions & 0 deletions chain/client/src/client_actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ pub enum NetworkAdversarialMessage {
AdvSwitchToHeight(u64),
AdvDisableHeaderSync,
AdvDisableDoomslug,
AdvDisableChunkValidation(bool),
AdvGetSavedBlocks,
AdvCheckStorageConsistency,
}
Expand Down Expand Up @@ -237,6 +238,11 @@ impl ClientActionHandler<NetworkAdversarialMessage> for ClientActions {
self.adv.set_disable_header_sync(true);
None
}
NetworkAdversarialMessage::AdvDisableChunkValidation(value) => {
info!(target: "adversary", "Disabling chunk validation: {value}");
self.client.adv_disable_chunk_validation = value;
None
}
NetworkAdversarialMessage::AdvProduceBlocks(num_blocks, only_valid) => {
info!(target: "adversary", num_blocks, "Starting adversary blocks production");
if only_valid {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -703,6 +703,10 @@ impl Client {
)));
}

#[cfg(feature = "test_features")]
if self.adv_disable_chunk_validation {
return Ok(());
}
self.chunk_validator.start_validating_chunk(witness, &self.chain, processing_done_tracker)
}

Expand Down
7 changes: 7 additions & 0 deletions chain/jsonrpc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,7 @@ impl JsonRpcHandler {
Ok(match request.method.as_ref() {
"adv_disable_header_sync" => self.adv_disable_header_sync(request.params).await,
"adv_disable_doomslug" => self.adv_disable_doomslug(request.params).await,
"adv_disable_chunk_validation" => self.adv_disable_chunk_validation(request.params).await,
"adv_produce_blocks" => self.adv_produce_blocks(request.params).await,
"adv_switch_to_height" => self.adv_switch_to_height(request.params).await,
"adv_get_saved_blocks" => self.adv_get_saved_blocks(request.params).await,
Expand Down Expand Up @@ -1256,6 +1257,12 @@ impl JsonRpcHandler {
Ok(Value::String(String::new()))
}

async fn adv_disable_chunk_validation(&self, params: Value) -> Result<Value, RpcError> {
let value = crate::api::Params::parse(params)?;
self.client_sender.send(near_client::NetworkAdversarialMessage::AdvDisableChunkValidation(value));
Ok(Value::String(String::new()))
}

async fn adv_produce_blocks(&self, params: Value) -> Result<Value, RpcError> {
let (num_blocks, only_valid) = crate::api::Params::parse(params)?;
self.client_sender
Expand Down
82 changes: 82 additions & 0 deletions pytest/tests/adversarial/not_validating.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#!/usr/bin/env python3
# Spins up 4 validating nodes. Wait until the third epoch ends.
# Direct validators to not validate chunks for 1 epoch.
# Let validators validate again, for 2 more epochs.

import logging
import pathlib
import sys
import time

sys.path.append(str(pathlib.Path(__file__).resolve().parents[2] / 'lib'))

from cluster import start_cluster
import state_sync_lib

EPOCH_LENGTH = 10
NUM_VALIDATORS = 4


def wait_until(nodes, target_height):
last_height = -1
while True:
statuses = sorted((enumerate(node.get_latest_block() for node in nodes)),
key=lambda element: element[1].height)
last = statuses.pop()
height = last[1].height
if height > target_height:
break
if height != last_height:
logging.info(
f'@{height}, epoch_height: {state_sync_lib.approximate_epoch_height(height, EPOCH_LENGTH)}'
)
last_height = height
node = nodes[last[0]]
success = True
for _, block in statuses:
try:
node.get_block(block.hash)
except Exception:
success = True
break
if not success:
return False
time.sleep(0.25)
return True

def main():
node_config_dump, node_config_sync = state_sync_lib.get_state_sync_configs_pair()
node_config_sync["tracked_shards"] = []
node_config_sync["store.load_mem_tries_for_tracked_shards"] = True
configs = {x: node_config_sync for x in range(NUM_VALIDATORS)}
configs[NUM_VALIDATORS] = node_config_dump

nodes = start_cluster(NUM_VALIDATORS, 1, NUM_VALIDATORS, None, [["epoch_length", EPOCH_LENGTH],
["shuffle_shard_assignment_for_chunk_producers", True],
["block_producer_kickout_threshold", 20],
["chunk_producer_kickout_threshold", 20]], configs)

for node in nodes:
node.stop_checking_store()

print("nodes started")
assert wait_until(nodes, EPOCH_LENGTH * 3)

for i in range(NUM_VALIDATORS):
res = nodes[i].json_rpc('adv_disable_chunk_validation', True)
assert 'result' in res, res

print("disabled chunk validation")
assert wait_until(nodes, EPOCH_LENGTH * 4)

for i in range(NUM_VALIDATORS):
res = nodes[i].json_rpc('adv_disable_chunk_validation', False)
assert 'result' in res, res

print("enabled chunk validation back")
assert wait_until(nodes, EPOCH_LENGTH * 6)

logging.info("Success")

if __name__ == "__main__":
main()
Loading