Skip to content
Closed
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
2 changes: 2 additions & 0 deletions crates/apollo_p2p_sync/src/client/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,7 @@ fn create_random_sync_block(
sequencer,
l1_da_mode,
starknet_version,
fee_proposal,
} = BlockHeaderWithoutHash::get_test_instance(&mut rng);
let block_header_without_hash = BlockHeaderWithoutHash {
block_number,
Expand All @@ -359,6 +360,7 @@ fn create_random_sync_block(
sequencer,
l1_da_mode,
starknet_version,
fee_proposal,
};
let block_header_commitments = BlockHeaderCommitments::get_test_instance(&mut rng);
SyncBlock {
Expand Down
2 changes: 2 additions & 0 deletions crates/apollo_protobuf/src/converters/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use starknet_api::block::{
BlockHeaderWithoutHash,
BlockNumber,
BlockSignature,
GasPrice,
GasPricePerToken,
StarknetVersion,
};
Expand Down Expand Up @@ -205,6 +206,7 @@ impl TryFrom<protobuf::SignedBlockHeader> for SignedBlockHeader {
timestamp,
l1_da_mode,
starknet_version,
fee_proposal: GasPrice::default(),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fee_proposal not serialized in protobuf conversion

Medium Severity

The fee_proposal field is not included in the From<(BlockHeader, Vec<BlockSignature>)> for protobuf::SignedBlockHeader serialization (around line 246–292), and on deserialization it is hardcoded to GasPrice::default(). This means any non-default fee_proposal will be silently lost during P2P block header exchange, causing peers to always see a zero value.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 645e3f3. Configure here.

},
state_diff_commitment,
state_diff_length,
Expand Down
1 change: 1 addition & 0 deletions crates/apollo_starknet_client/src/reader/objects/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,7 @@ impl Block {
l1_data_gas_price: self.l1_data_gas_price(),
l1_da_mode: self.l1_da_mode(),
starknet_version: self.starknet_version(),
fee_proposal: GasPrice::default(),
},
state_diff_commitment: self.state_diff_commitment(),
transaction_commitment,
Expand Down
2 changes: 2 additions & 0 deletions crates/apollo_storage/src/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ impl<Mode: TransactionKind> HeaderStorageReader for StorageTxn<'_, Mode> {
timestamp: block_header.timestamp,
l1_da_mode: block_header.l1_da_mode,
starknet_version,
fee_proposal: GasPrice::default(),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fee_proposal silently lost during storage round-trip

High Severity

The new fee_proposal field is added to BlockHeaderWithoutHash but StorageBlockHeader has no corresponding field. In append_header, block_header.block_header_without_hash.fee_proposal is silently dropped. When reading back via get_block_header or reverting via revert_header, fee_proposal is hardcoded to GasPrice::default(). This causes permanent data loss — any non-default fee_proposal value written to storage cannot be recovered. Contrast with starknet_version, which also isn't in StorageBlockHeader but is stored in a dedicated table.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 1419739. Configure here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

solved #13813

},
state_diff_commitment: block_header.state_diff_commitment,
transaction_commitment: block_header.transaction_commitment,
Expand Down Expand Up @@ -429,6 +430,7 @@ impl HeaderStorageWriter for StorageTxn<'_, RW> {
timestamp: reverted_header.timestamp,
l1_da_mode: reverted_header.l1_da_mode,
starknet_version,
fee_proposal: GasPrice::default(),
},
state_diff_commitment: reverted_header.state_diff_commitment,
transaction_commitment: reverted_header.transaction_commitment,
Expand Down
1 change: 1 addition & 0 deletions crates/apollo_test_utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,7 @@ auto_impl_get_test_instance! {
pub timestamp: BlockTimestamp,
pub l1_da_mode: L1DataAvailabilityMode,
pub starknet_version: StarknetVersion,
pub fee_proposal: GasPrice,
}
pub struct BlockHeaderCommitments {
pub transaction_commitment: TransactionCommitment,
Expand Down
2 changes: 2 additions & 0 deletions crates/starknet_api/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,8 @@ pub struct BlockHeaderWithoutHash {
pub timestamp: BlockTimestamp,
pub l1_da_mode: L1DataAvailabilityMode,
pub starknet_version: StarknetVersion,
/// SNIP-35: proposer's oracle-derived recommended fee.
pub fee_proposal: GasPrice,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing serde default breaks deserialization of older data

Medium Severity

The new fee_proposal field on BlockHeaderWithoutHash lacks a #[serde(default)] attribute. This struct is embedded in SyncBlock, which is serialized/deserialized in StateSyncRequest and StateSyncResponse for inter-process communication. During rolling deployments, an older component producing a serialized SyncBlock without fee_proposal will cause deserialization failures on newer components, since serde requires the field to be present unless a default is specified.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 2b22515. Configure here.

}

/// The [transactions](`crate::transaction::Transaction`) and their
Expand Down
Loading