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

feat: add l1_gas_consumed for block hash #268

Merged
merged 2 commits into from
Jun 4, 2024
Merged
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
15 changes: 3 additions & 12 deletions src/block_hash/block_hash_calculator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,12 @@ use super::event_commitment::{calculate_events_commitment, EventLeafElement};
use super::receipt_commitment::{calculate_receipt_commitment, ReceiptElement};
use super::state_diff_hash::calculate_state_diff_hash;
use super::transaction_commitment::{calculate_transactions_commitment, TransactionLeafElement};
use crate::block::{BlockHash, BlockHeaderWithoutHash, GasPricePerToken};
use crate::block::{BlockHash, BlockHeaderWithoutHash};
use crate::core::{EventCommitment, ReceiptCommitment, StateDiffCommitment, TransactionCommitment};
use crate::crypto::utils::HashChain;
use crate::data_availability::L1DataAvailabilityMode;
use crate::state::ThinStateDiff;
use crate::transaction::{
TransactionHash, TransactionOutputCommon, TransactionSignature, TransactionVersion,
};
use crate::transaction::{TransactionHash, TransactionOutputCommon, TransactionSignature};
use crate::transaction_hash::ascii_as_felt;

#[cfg(test)]
Expand All @@ -28,7 +26,6 @@ pub struct TransactionHashingData {
pub transaction_signature: Option<TransactionSignature>,
pub transaction_output: TransactionOutputCommon,
pub transaction_hash: TransactionHash,
pub transaction_version: TransactionVersion,
}

/// Commitments of a block.
Expand Down Expand Up @@ -77,8 +74,6 @@ pub fn calculate_block_hash(
pub fn calculate_block_commitments(
transactions_data: &[TransactionHashingData],
state_diff: &ThinStateDiff,
l1_data_gas_price_per_token: GasPricePerToken,
l1_gas_price_per_token: GasPricePerToken,
l1_da_mode: L1DataAvailabilityMode,
) -> BlockHeaderCommitments {
let transaction_leaf_elements: Vec<TransactionLeafElement> =
Expand All @@ -99,11 +94,7 @@ pub fn calculate_block_commitments(

let receipt_elements: Vec<ReceiptElement> =
transactions_data.iter().map(ReceiptElement::from).collect();
let receipts_commitment = calculate_receipt_commitment::<Poseidon>(
&receipt_elements,
l1_data_gas_price_per_token,
l1_gas_price_per_token,
);
let receipts_commitment = calculate_receipt_commitment::<Poseidon>(&receipt_elements);
let state_diff_commitment = calculate_state_diff_hash(state_diff);
let concatenated_counts = concat_counts(
transactions_data.len(),
Expand Down
12 changes: 3 additions & 9 deletions src/block_hash/block_hash_calculator_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::core::{ContractAddress, GlobalRoot, PatriciaKey, SequencerContractAdd
use crate::data_availability::L1DataAvailabilityMode;
use crate::felt;
use crate::hash::{FeltConverter, TryIntoFelt};
use crate::transaction::{TransactionHash, TransactionSignature, TransactionVersion};
use crate::transaction::{TransactionHash, TransactionSignature};

#[test]
fn test_block_hash_regression() {
Expand All @@ -35,17 +35,11 @@ fn test_block_hash_regression() {
transaction_signature: Some(TransactionSignature(vec![Felt::TWO, Felt::THREE])),
transaction_output: get_transaction_output(),
transaction_hash: TransactionHash(Felt::ONE),
transaction_version: TransactionVersion::THREE,
}];

let state_diff = get_state_diff();
let block_commitments = calculate_block_commitments(
&transactions_data,
&state_diff,
block_header.l1_data_gas_price,
block_header.l1_gas_price,
block_header.l1_da_mode,
);
let block_commitments =
calculate_block_commitments(&transactions_data, &state_diff, block_header.l1_da_mode);

let expected_hash = felt!("0x061e4998d51a248f1d0288d7e17f6287757b0e5e6c5e1e58ddf740616e312134");

Expand Down
59 changes: 8 additions & 51 deletions src/block_hash/receipt_commitment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@ use starknet_types_core::felt::Felt;
use starknet_types_core::hash::StarkHash;

use super::block_hash_calculator::TransactionHashingData;
use crate::block::{GasPrice, GasPricePerToken};
use crate::core::ReceiptCommitment;
use crate::crypto::patricia_hash::calculate_root;
use crate::crypto::utils::HashChain;
use crate::hash::starknet_keccak_hash;
use crate::transaction::{
ExecutionResources, Fee, MessageToL1, TransactionExecutionStatus, TransactionHash,
TransactionOutputCommon, TransactionVersion,
ExecutionResources, MessageToL1, TransactionExecutionStatus, TransactionHash,
TransactionOutputCommon,
};

#[cfg(test)]
Expand All @@ -21,61 +20,38 @@ mod receipt_commitment_test;
pub struct ReceiptElement {
pub transaction_hash: TransactionHash,
pub transaction_output: TransactionOutputCommon,
pub transaction_version: TransactionVersion,
}

impl From<&TransactionHashingData> for ReceiptElement {
fn from(transaction_data: &TransactionHashingData) -> Self {
Self {
transaction_hash: transaction_data.transaction_hash,
transaction_output: transaction_data.transaction_output.clone(),
transaction_version: transaction_data.transaction_version,
}
}
}

/// Returns the root of a Patricia tree where each leaf is a receipt hash.
pub fn calculate_receipt_commitment<H: StarkHash>(
receipt_elements: &[ReceiptElement],
l1_data_gas_price_per_token: GasPricePerToken,
l1_gas_price_per_token: GasPricePerToken,
) -> ReceiptCommitment {
ReceiptCommitment(calculate_root::<H>(
receipt_elements
.iter()
.map(|receipt| {
calculate_receipt_hash(receipt, l1_data_gas_price_per_token, l1_gas_price_per_token)
})
.collect(),
receipt_elements.iter().map(calculate_receipt_hash).collect(),
))
}

// Poseidon(
// transaction hash, amount of fee paid, hash of messages sent, revert reason,
// execution resources
// ).
fn calculate_receipt_hash(
receipt_element: &ReceiptElement,
l1_data_gas_price_per_token: GasPricePerToken,
l1_gas_price_per_token: GasPricePerToken,
) -> Felt {
let l1_gas_price =
get_price_by_version(l1_gas_price_per_token, &receipt_element.transaction_version);
let l1_data_gas_price =
get_price_by_version(l1_data_gas_price_per_token, &receipt_element.transaction_version);
fn calculate_receipt_hash(receipt_element: &ReceiptElement) -> Felt {
let hash_chain = HashChain::new()
.chain(&receipt_element.transaction_hash)
.chain(&receipt_element.transaction_output.actual_fee.0.into())
.chain(&calculate_messages_sent_hash(&receipt_element.transaction_output.messages_sent))
.chain(&get_revert_reason_hash(&receipt_element.transaction_output.execution_status));
chain_execution_resources(
hash_chain,
&receipt_element.transaction_output.execution_resources,
receipt_element.transaction_output.actual_fee,
l1_data_gas_price,
l1_gas_price,
)
.get_poseidon_hash()
chain_execution_resources(hash_chain, &receipt_element.transaction_output.execution_resources)
.get_poseidon_hash()
}

// Poseidon(
Expand Down Expand Up @@ -108,32 +84,13 @@ fn get_revert_reason_hash(execution_status: &TransactionExecutionStatus) -> Felt
// L2 gas consumed (In the current RPC: always 0),
// L1 gas consumed (In the current RPC:
// L1 gas consumed for calldata + L1 gas consumed for steps and builtins.
// Calculated as: (actual_fee - actual_l1_data_gas_fee) / l1_gas_price
// L1 data gas consumed (In the current RPC: L1 data gas consumed for blob).
fn chain_execution_resources(
hash_chain: HashChain,
execution_resources: &ExecutionResources,
actual_fee: Fee,
l1_data_gas_price: GasPrice,
l1_gas_price: GasPrice,
) -> HashChain {
let l1_gas_consumed: u128 = (actual_fee.0
- (l1_data_gas_price.0) * u128::from(execution_resources.da_l1_data_gas_consumed))
/ l1_gas_price.0;
hash_chain
.chain(&Felt::ZERO) // L2 gas consumed
.chain(&l1_gas_consumed.into())
.chain(&execution_resources.da_l1_data_gas_consumed.into())
}

// TODO(yoav): move this function to transaction.rs and make it public.
fn get_price_by_version(
price_per_token: GasPricePerToken,
transaction_version: &TransactionVersion,
) -> GasPrice {
if transaction_version >= &TransactionVersion::THREE {
price_per_token.price_in_fri
} else {
price_per_token.price_in_wei
}
.chain(&execution_resources.gas_consumed.l1_gas.into())
.chain(&execution_resources.gas_consumed.l1_data_gas.into())
}
30 changes: 5 additions & 25 deletions src/block_hash/receipt_commitment_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use starknet_types_core::felt::Felt;
use starknet_types_core::hash::Poseidon;

use super::calculate_messages_sent_hash;
use crate::block::{GasPrice, GasPricePerToken};
use crate::block_hash::receipt_commitment::{
calculate_receipt_commitment, calculate_receipt_hash, get_revert_reason_hash, ReceiptElement,
};
Expand All @@ -12,41 +11,22 @@ use crate::felt;
use crate::hash::{FeltConverter, TryIntoFelt};
use crate::transaction::{
RevertedTransactionExecutionStatus, TransactionExecutionStatus, TransactionHash,
TransactionVersion,
};

#[test]
fn test_receipt_hash_regression() {
let mut transaction_receipt = ReceiptElement {
let transaction_receipt = ReceiptElement {
transaction_hash: TransactionHash(Felt::from(1234_u16)),
transaction_output: get_transaction_output(),
transaction_version: TransactionVersion::TWO,
};
let l1_data_gas_price =
GasPricePerToken { price_in_fri: GasPrice(123), price_in_wei: GasPrice(456) };
let l1_gas_price =
GasPricePerToken { price_in_fri: GasPrice(456), price_in_wei: GasPrice(789) };

let expected_hash = felt!("0x06cb27bfc55dee54e6d0fc7a6790e39f0f3c003576d50f7b8e8a1be24c351bcf");
assert_eq!(
calculate_receipt_hash(&transaction_receipt, l1_data_gas_price, l1_gas_price),
expected_hash
);
let expected_hash = felt!("0x6276abf21e7c68b2eecfdc8a845b11b44401901f5f040efe10c60d625049646");
assert_eq!(calculate_receipt_hash(&transaction_receipt), expected_hash);

let expected_root = ReceiptCommitment(felt!(
"0x03a0af1272fc3b0b83894fd7b6b70d89acb07772bc28efc9091e3cc1c2c72493"
"0x31963cb891ebb825e83514deb748c89b6967b5368cbc48a9b56193a1464ca87"
));

// Test for a V3 transactions.
transaction_receipt.transaction_version = TransactionVersion::THREE;
assert_eq!(
calculate_receipt_commitment::<Poseidon>(
&[transaction_receipt],
l1_data_gas_price,
l1_gas_price
),
expected_root
);
assert_eq!(calculate_receipt_commitment::<Poseidon>(&[transaction_receipt]), expected_root);
}

#[test]
Expand Down
6 changes: 3 additions & 3 deletions src/block_hash/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use starknet_types_core::felt::Felt;
use crate::core::{ClassHash, CompiledClassHash, ContractAddress, EthAddress, Nonce};
use crate::state::ThinStateDiff;
use crate::transaction::{
Builtin, ExecutionResources, Fee, L2ToL1Payload, MessageToL1,
Builtin, ExecutionResources, Fee, GasVector, L2ToL1Payload, MessageToL1,
RevertedTransactionExecutionStatus, TransactionExecutionStatus, TransactionOutputCommon,
};

Expand All @@ -20,8 +20,8 @@ pub(crate) fn get_transaction_output() -> TransactionOutputCommon {
steps: 98,
builtin_instance_counter: HashMap::from([(Builtin::Bitwise, 11), (Builtin::EcOp, 22)]),
memory_holes: 76,
da_l1_gas_consumed: 54,
da_l1_data_gas_consumed: 32,
da_gas_consumed: GasVector { l1_gas: 54, l1_data_gas: 10 },
gas_consumed: GasVector { l1_gas: 16580, l1_data_gas: 32 },
};
TransactionOutputCommon {
actual_fee: Fee(99804),
Expand Down
10 changes: 8 additions & 2 deletions src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -958,14 +958,20 @@ pub struct PaymasterData(pub Vec<Felt>);
#[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)]
pub struct AccountDeploymentData(pub Vec<Felt>);

#[derive(Debug, Default, Deserialize, Serialize, Clone, Eq, PartialEq)]
pub struct GasVector {
pub l1_gas: u64,
pub l1_data_gas: u64,
}

/// The execution resources used by a transaction.
#[derive(Debug, Default, Deserialize, Serialize, Clone, Eq, PartialEq)]
pub struct ExecutionResources {
pub steps: u64,
pub builtin_instance_counter: HashMap<Builtin, u64>,
pub memory_holes: u64,
pub da_l1_gas_consumed: u64,
pub da_l1_data_gas_consumed: u64,
pub da_gas_consumed: GasVector,
pub gas_consumed: GasVector,
}

#[derive(Hash, Debug, Deserialize, Serialize, Clone, Eq, PartialEq)]
Expand Down
Loading