Skip to content

Commit 79369a0

Browse files
authored
feat: disable state network history header validation (#1667)
1 parent 0043f6b commit 79369a0

File tree

2 files changed

+60
-30
lines changed

2 files changed

+60
-30
lines changed

crates/subnetworks/state/src/validation/trie.rs

Lines changed: 44 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use super::error::{check_node_hash, StateValidationError};
1313

1414
/// Validate the trie proof.
1515
pub fn validate_node_trie_proof(
16-
root_hash: B256,
16+
root_hash: Option<B256>,
1717
node_hash: B256,
1818
path: &Nibbles,
1919
proof: &TrieProof,
@@ -33,7 +33,7 @@ pub fn validate_node_trie_proof(
3333

3434
/// Validate the trie proof associated with the account state.
3535
pub fn validate_account_state(
36-
root_hash: B256,
36+
root_hash: Option<B256>,
3737
address_hash: &B256,
3838
proof: &TrieProof,
3939
) -> Result<AccountState, StateValidationError> {
@@ -58,7 +58,7 @@ pub fn validate_account_state(
5858
/// - last node in the proof (whose presence we are proving)
5959
/// - remaining (unused) nibbles from the path
6060
fn validate_trie_proof<'proof, 'path>(
61-
root_hash: B256,
61+
root_hash: Option<B256>,
6262
path: &'path [u8],
6363
proof: &'proof TrieProof,
6464
) -> Result<(&'proof EncodedTrieNode, &'path [u8]), StateValidationError> {
@@ -68,7 +68,9 @@ fn validate_trie_proof<'proof, 'path>(
6868
};
6969

7070
// Check root hash
71-
check_node_hash(first_node, &root_hash)?;
71+
if let Some(root_hash) = &root_hash {
72+
check_node_hash(first_node, root_hash)?;
73+
}
7274

7375
let mut node = first_node;
7476
let mut remaining_path = path;
@@ -160,7 +162,7 @@ mod tests {
160162
let path = Nibbles::try_from_unpacked_nibbles(&[]).unwrap();
161163
let proof = TrieProof::from(vec![node.clone()]);
162164

163-
assert!(validate_node_trie_proof(node_hash, node_hash, &path, &proof).is_ok());
165+
assert!(validate_node_trie_proof(Some(node_hash), node_hash, &path, &proof).is_ok());
164166
}
165167

166168
#[test]
@@ -175,7 +177,7 @@ mod tests {
175177
let proof = TrieProof::from(vec![root_node.clone(), last_node.clone()]);
176178

177179
assert!(validate_node_trie_proof(
178-
root_node.node_hash(),
180+
Some(root_node.node_hash()),
179181
last_node.node_hash(),
180182
&path,
181183
&proof,
@@ -208,7 +210,7 @@ mod tests {
208210
]);
209211

210212
assert!(validate_node_trie_proof(
211-
root_node.node_hash(),
213+
Some(root_node.node_hash()),
212214
last_node.node_hash(),
213215
&path,
214216
&proof,
@@ -228,8 +230,13 @@ mod tests {
228230
let path = Nibbles::try_from_unpacked_nibbles(&[4, 3, 2, 1]).unwrap();
229231
let proof = TrieProof::from(vec![root_node.clone(), last_node.clone()]);
230232

231-
validate_node_trie_proof(root_node.node_hash(), last_node.node_hash(), &path, &proof)
232-
.unwrap();
233+
validate_node_trie_proof(
234+
Some(root_node.node_hash()),
235+
last_node.node_hash(),
236+
&path,
237+
&proof,
238+
)
239+
.unwrap();
233240
}
234241

235242
#[test]
@@ -246,8 +253,13 @@ mod tests {
246253

247254
// This should be the hash of the last_node, and it should fail if it is anything else
248255
let wrong_last_node_hash = root_node.node_hash();
249-
validate_node_trie_proof(root_node.node_hash(), wrong_last_node_hash, &path, &proof)
250-
.unwrap();
256+
validate_node_trie_proof(
257+
Some(root_node.node_hash()),
258+
wrong_last_node_hash,
259+
&path,
260+
&proof,
261+
)
262+
.unwrap();
251263
}
252264

253265
#[test]
@@ -280,7 +292,11 @@ mod tests {
280292
].map(|trie_node| EncodedTrieNode::from(hex_decode(trie_node).unwrap()));
281293

282294
assert_eq!(
283-
validate_account_state(state_root, &address_hash, &account_proof.to_vec().into())?,
295+
validate_account_state(
296+
Some(state_root),
297+
&address_hash,
298+
&account_proof.to_vec().into()
299+
)?,
284300
account_state
285301
);
286302

@@ -299,7 +315,8 @@ mod tests {
299315
};
300316
let node = EncodedTrieNode::from(&create_leaf(&path, &alloy::rlp::encode(&account_state)));
301317
assert_eq!(
302-
validate_account_state(node.node_hash(), &address_hash, &vec![node].into()).unwrap(),
318+
validate_account_state(Some(node.node_hash()), &address_hash, &vec![node].into())
319+
.unwrap(),
303320
account_state
304321
);
305322
}
@@ -309,7 +326,7 @@ mod tests {
309326
fn validate_account_state_last_node_is_not_leaf() {
310327
let address_hash = B256::random();
311328
let node = EncodedTrieNode::from(&create_branch());
312-
validate_account_state(node.node_hash(), &address_hash, &vec![node].into()).unwrap();
329+
validate_account_state(Some(node.node_hash()), &address_hash, &vec![node].into()).unwrap();
313330
}
314331

315332
#[test]
@@ -327,7 +344,7 @@ mod tests {
327344
code_hash: B256::random(),
328345
};
329346
let node = EncodedTrieNode::from(&create_leaf(&path, &alloy::rlp::encode(account_state)));
330-
validate_account_state(node.node_hash(), &address_hash, &vec![node].into()).unwrap();
347+
validate_account_state(Some(node.node_hash()), &address_hash, &vec![node].into()).unwrap();
331348
}
332349

333350
#[test]
@@ -336,15 +353,15 @@ mod tests {
336353
let address_hash = B256::random();
337354
let path = Nibbles::unpack_nibbles(address_hash.as_slice());
338355
let node = EncodedTrieNode::from(&create_leaf(&path, &[0x12, 0x34]));
339-
validate_account_state(node.node_hash(), &address_hash, &vec![node].into()).unwrap();
356+
validate_account_state(Some(node.node_hash()), &address_hash, &vec![node].into()).unwrap();
340357
}
341358

342359
#[test]
343360
#[should_panic = "DecodingNode"]
344361
fn validate_account_state_non_decodable_leaf() {
345362
let address_hash = B256::random();
346363
let node = EncodedTrieNode::from(vec![0x12, 0x34]);
347-
validate_account_state(node.node_hash(), &address_hash, &vec![node].into()).unwrap();
364+
validate_account_state(Some(node.node_hash()), &address_hash, &vec![node].into()).unwrap();
348365
}
349366

350367
#[test]
@@ -356,7 +373,7 @@ mod tests {
356373

357374
let proof = TrieProof::from(vec![node.clone()]);
358375
let path = [2, 3, 4];
359-
let validation_info = validate_trie_proof(node.node_hash(), &path, &proof).unwrap();
376+
let validation_info = validate_trie_proof(Some(node.node_hash()), &path, &proof).unwrap();
360377

361378
assert_eq!(validation_info, (&node, path.as_slice()));
362379
}
@@ -370,7 +387,7 @@ mod tests {
370387

371388
let proof = TrieProof::from(vec![node.clone()]);
372389
let path = [2, 3, 4];
373-
let validation_info = validate_trie_proof(node.node_hash(), &path, &proof).unwrap();
390+
let validation_info = validate_trie_proof(Some(node.node_hash()), &path, &proof).unwrap();
374391

375392
assert_eq!(validation_info, (&node, path.as_slice()));
376393
}
@@ -398,7 +415,8 @@ mod tests {
398415
branch_node,
399416
last_node.clone(),
400417
]);
401-
let validation_info = validate_trie_proof(root_node.node_hash(), &path, &proof).unwrap();
418+
let validation_info =
419+
validate_trie_proof(Some(root_node.node_hash()), &path, &proof).unwrap();
402420

403421
assert_eq!(validation_info, (&last_node, &path[4..]));
404422
}
@@ -416,11 +434,11 @@ mod tests {
416434

417435
// First verify that correct order pass the validation
418436
let proof = TrieProof::from(vec![root_node.clone(), last_node.clone()]);
419-
assert!(validate_trie_proof(root_node.node_hash(), &[2, 1], &proof).is_ok());
437+
assert!(validate_trie_proof(Some(root_node.node_hash()), &[2, 1], &proof).is_ok());
420438

421439
// Now verify that wrong order fails because root hash doesn't match
422440
let proof = TrieProof::from(vec![last_node.clone(), root_node.clone()]);
423-
let error = validate_trie_proof(root_node.node_hash(), &[2, 1], &proof).unwrap_err();
441+
let error = validate_trie_proof(Some(root_node.node_hash()), &[2, 1], &proof).unwrap_err();
424442
assert!(matches!(
425443
error,
426444
StateValidationError::InvalidNodeHash {
@@ -431,7 +449,7 @@ mod tests {
431449

432450
// And that if fails even if root hash that corresponds to the first node is given
433451
let proof = TrieProof::from(vec![last_node.clone(), root_node.clone()]);
434-
let error = validate_trie_proof(last_node.node_hash(), &[2, 1], &proof).unwrap_err();
452+
let error = validate_trie_proof(Some(last_node.node_hash()), &[2, 1], &proof).unwrap_err();
435453
dbg!(&error);
436454
dbg!(last_node.node_hash());
437455
assert!(matches!(
@@ -443,7 +461,7 @@ mod tests {
443461
));
444462

445463
// And that it fails even if we reverse order in path
446-
let error = validate_trie_proof(last_node.node_hash(), &[1, 2], &proof).unwrap_err();
464+
let error = validate_trie_proof(Some(last_node.node_hash()), &[1, 2], &proof).unwrap_err();
447465
assert!(matches!(
448466
error,
449467
StateValidationError::InvalidNodeHash {
@@ -456,14 +474,14 @@ mod tests {
456474
#[test]
457475
#[should_panic = "EmptyTrieProof"]
458476
fn validate_trie_proof_empty_proof() {
459-
validate_trie_proof(B256::random(), &[], &TrieProof::default()).unwrap();
477+
validate_trie_proof(Some(B256::random()), &[], &TrieProof::default()).unwrap();
460478
}
461479

462480
#[test]
463481
#[should_panic = "InvalidNodeHash"]
464482
fn validate_trie_proof_invalid_root_hash() {
465483
let node = Node::from_branch(empty_children(), None);
466484
let proof = TrieProof::from(vec![EncodedTrieNode::from(&node)]);
467-
validate_trie_proof(B256::random(), &[], &proof).unwrap();
485+
validate_trie_proof(Some(B256::random()), &[], &proof).unwrap();
468486
}
469487
}

crates/subnetworks/state/src/validation/validator.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ use super::{
1919
trie::{validate_account_state, validate_node_trie_proof},
2020
};
2121

22+
// todo: remove this constant once the history network implements full chain header validation
23+
const DISABLE_HISTORY_HEADER_CHECK: bool = true;
24+
2225
pub struct StateValidator {
2326
pub header_oracle: Arc<RwLock<HeaderOracle>>,
2427
}
@@ -58,7 +61,10 @@ impl StateValidator {
5861
Ok(ValidationResult::new(/* valid_for_storing= */ false))
5962
}
6063
StateContentValue::AccountTrieNodeWithProof(value) => {
61-
let state_root = self.get_state_root(value.block_hash).await?;
64+
let state_root = match DISABLE_HISTORY_HEADER_CHECK {
65+
true => None,
66+
false => Some(self.get_state_root(value.block_hash).await?),
67+
};
6268
validate_node_trie_proof(state_root, key.node_hash, &key.path, &value.proof)?;
6369

6470
Ok(ValidationResult::new(/* valid_for_storing= */ true))
@@ -80,11 +86,14 @@ impl StateValidator {
8086
Ok(ValidationResult::new(/* valid_for_storing= */ false))
8187
}
8288
StateContentValue::ContractStorageTrieNodeWithProof(value) => {
83-
let state_root = self.get_state_root(value.block_hash).await?;
89+
let state_root = match DISABLE_HISTORY_HEADER_CHECK {
90+
true => None,
91+
false => Some(self.get_state_root(value.block_hash).await?),
92+
};
8493
let account_state =
8594
validate_account_state(state_root, &key.address_hash, &value.account_proof)?;
8695
validate_node_trie_proof(
87-
account_state.storage_root,
96+
Some(account_state.storage_root),
8897
key.node_hash,
8998
&key.path,
9099
&value.storage_proof,
@@ -124,7 +133,10 @@ impl StateValidator {
124133
});
125134
}
126135

127-
let state_root = self.get_state_root(value.block_hash).await?;
136+
let state_root = match DISABLE_HISTORY_HEADER_CHECK {
137+
true => None,
138+
false => Some(self.get_state_root(value.block_hash).await?),
139+
};
128140
let account_state =
129141
validate_account_state(state_root, &key.address_hash, &value.account_proof)?;
130142
if account_state.code_hash == key.code_hash {

0 commit comments

Comments
 (0)