Skip to content

Commit b394328

Browse files
authored
ethereum: Handle mixed block formats in recent_blocks_cache (#6312)
The recent_blocks_cache can contain blocks in two formats: - Full format: {"block": {...}, "transaction_receipts": [...]} - Light format: just block fields (no wrapper) This happens because different code paths populate the cache with different formats (upsert_block uses full, blocks_from_store uses light). Changes: - load_blocks/parent_ptr: Extract block data from full format if needed using `value.get("block").unwrap_or(&value)` - ancestor_block: Explicit check for light format with clear logging, falls back to Firehose/RPC since receipts are needed for triggers - Improved log messages to show block number and hash on failures
1 parent 6f9fa54 commit b394328

2 files changed

Lines changed: 46 additions & 32 deletions

File tree

chain/ethereum/src/chain.rs

Lines changed: 40 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1075,32 +1075,42 @@ impl TriggersAdapterTrait<Chain> for TriggersAdapter {
10751075
.ancestor_block(ptr.clone(), offset, root.clone())
10761076
.await?;
10771077

1078-
// First check if we have the ancestor in cache and can deserialize it
1078+
// First check if we have the ancestor in cache and can deserialize it.
1079+
// recent_blocks_cache can have full format {"block": {...}, "transaction_receipts": [...]}
1080+
// or light format (just block fields). We need full format with receipts for
1081+
// ancestor_block since it's used for trigger processing.
10791082
let block_ptr = match cached {
10801083
Some((json, ptr)) => {
1081-
// Try to deserialize the cached block
1082-
match json::from_value::<EthereumBlock>(json.clone()) {
1083-
Ok(block) => {
1084-
// Successfully cached and deserialized
1085-
return Ok(Some(BlockFinality::NonFinal(EthereumBlockWithCalls {
1086-
ethereum_block: block,
1087-
calls: None,
1088-
})));
1089-
}
1090-
Err(e) => {
1091-
// Cache hit but deserialization failed
1092-
warn!(
1093-
self.logger,
1094-
"Failed to deserialize cached ancestor block #{} {} (offset {} from #{}): {}. \
1095-
This may indicate stale cache data from a previous version. \
1096-
Falling back to Firehose/RPC.",
1097-
ptr.number,
1098-
ptr.hash_hex(),
1099-
offset,
1100-
ptr_for_log.number,
1101-
e
1102-
);
1103-
ptr
1084+
if json.get("block").is_none() {
1085+
warn!(
1086+
self.logger,
1087+
"Cached ancestor block #{} {} has light format without receipts. \
1088+
Falling back to Firehose/RPC.",
1089+
ptr.number,
1090+
ptr.hash_hex(),
1091+
);
1092+
ptr
1093+
} else {
1094+
match json::from_value::<EthereumBlock>(json.clone()) {
1095+
Ok(block) => {
1096+
return Ok(Some(BlockFinality::NonFinal(EthereumBlockWithCalls {
1097+
ethereum_block: block,
1098+
calls: None,
1099+
})));
1100+
}
1101+
Err(e) => {
1102+
warn!(
1103+
self.logger,
1104+
"Failed to deserialize cached ancestor block #{} {} (offset {} from #{}): {}. \
1105+
Falling back to Firehose/RPC.",
1106+
ptr.number,
1107+
ptr.hash_hex(),
1108+
offset,
1109+
ptr_for_log.number,
1110+
e
1111+
);
1112+
ptr
1113+
}
11041114
}
11051115
}
11061116
}
@@ -1161,15 +1171,17 @@ impl TriggersAdapterTrait<Chain> for TriggersAdapter {
11611171
// First try to get the block from the store
11621172
if let Ok(blocks) = chain_store.blocks(vec![block.hash.clone()]).await {
11631173
if let Some(cached_json) = blocks.first() {
1164-
match json::from_value::<LightEthereumBlock>(cached_json.clone()) {
1165-
Ok(block) => {
1166-
return Ok(block.parent_ptr());
1174+
// recent_blocks_cache can contain full format {"block": {...}, "transaction_receipts": [...]}
1175+
// or light format (just block fields). Extract block data for deserialization.
1176+
let inner = cached_json.get("block").unwrap_or(cached_json);
1177+
match json::from_value::<LightEthereumBlock>(inner.clone()) {
1178+
Ok(light_block) => {
1179+
return Ok(light_block.parent_ptr());
11671180
}
11681181
Err(e) => {
11691182
warn!(
11701183
self.logger,
11711184
"Failed to deserialize cached block #{} {}: {}. \
1172-
This may indicate stale cache data from a previous version. \
11731185
Falling back to Firehose.",
11741186
block.number,
11751187
block.hash_hex(),

chain/ethereum/src/ethereum_adapter.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1614,14 +1614,16 @@ impl EthereumAdapterTrait for EthereumAdapter {
16141614
.unwrap_or_default()
16151615
.into_iter()
16161616
.filter_map(|value| {
1617-
json::from_value(value.clone())
1617+
// recent_blocks_cache can contain full format {"block": {...}, "transaction_receipts": [...]}
1618+
// or light format (just block fields). Extract block data for deserialization.
1619+
let inner = value.get("block").unwrap_or(&value);
1620+
json::from_value(inner.clone())
16181621
.map_err(|e| {
1619-
let block_num = value.get("number").and_then(|n| n.as_u64());
1620-
let block_hash = value.get("hash").and_then(|h| h.as_str());
1622+
let block_num = inner.get("number").and_then(|n| n.as_str());
1623+
let block_hash = inner.get("hash").and_then(|h| h.as_str());
16211624
warn!(
16221625
&logger,
16231626
"Failed to deserialize cached block #{:?} {:?}: {}. \
1624-
This may indicate stale cache data from a previous version. \
16251627
Block will be re-fetched from RPC.",
16261628
block_num,
16271629
block_hash,

0 commit comments

Comments
 (0)