Skip to content
This repository has been archived by the owner on Nov 5, 2023. It is now read-only.

Commit

Permalink
Upstream merge
Browse files Browse the repository at this point in the history
  • Loading branch information
refcell committed Oct 31, 2023
2 parents 4983ef6 + c0b7d34 commit 4a9de7f
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 106 deletions.
144 changes: 74 additions & 70 deletions crates/consensus/common/src/validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,37 +22,37 @@ pub fn validate_header_standalone(
return Err(ConsensusError::HeaderGasUsedExceedsGasLimit {
gas_used: header.gas_used,
gas_limit: header.gas_limit,
})
});
}

// Check if base fee is set.
if chain_spec.fork(Hardfork::London).active_at_block(header.number) &&
header.base_fee_per_gas.is_none()
if chain_spec.fork(Hardfork::London).active_at_block(header.number)
&& header.base_fee_per_gas.is_none()
{
return Err(ConsensusError::BaseFeeMissing)
return Err(ConsensusError::BaseFeeMissing);
}

let wd_root_missing = header.withdrawals_root.is_none() && !chain_spec.is_optimism();

// EIP-4895: Beacon chain push withdrawals as operations
if chain_spec.fork(Hardfork::Shanghai).active_at_timestamp(header.timestamp) && wd_root_missing
{
return Err(ConsensusError::WithdrawalsRootMissing)
} else if !chain_spec.fork(Hardfork::Shanghai).active_at_timestamp(header.timestamp) &&
header.withdrawals_root.is_some()
return Err(ConsensusError::WithdrawalsRootMissing);
} else if !chain_spec.fork(Hardfork::Shanghai).active_at_timestamp(header.timestamp)
&& header.withdrawals_root.is_some()
{
return Err(ConsensusError::WithdrawalsRootUnexpected)
return Err(ConsensusError::WithdrawalsRootUnexpected);
}

// Ensures that EIP-4844 fields are valid once cancun is active.
if chain_spec.fork(Hardfork::Cancun).active_at_timestamp(header.timestamp) {
validate_4844_header_standalone(header)?;
} else if header.blob_gas_used.is_some() {
return Err(ConsensusError::BlobGasUsedUnexpected)
return Err(ConsensusError::BlobGasUsedUnexpected);
} else if header.excess_blob_gas.is_some() {
return Err(ConsensusError::ExcessBlobGasUnexpected)
return Err(ConsensusError::ExcessBlobGasUnexpected);
} else if header.parent_beacon_block_root.is_some() {
return Err(ConsensusError::ParentBeaconBlockRootUnexpected)
return Err(ConsensusError::ParentBeaconBlockRootUnexpected);
}

Ok(())
Expand All @@ -70,17 +70,17 @@ pub fn validate_transaction_regarding_header(
let chain_id = match transaction {
Transaction::Legacy(TxLegacy { chain_id, .. }) => {
// EIP-155: Simple replay attack protection: https://eips.ethereum.org/EIPS/eip-155
if chain_spec.fork(Hardfork::SpuriousDragon).active_at_block(at_block_number) &&
chain_id.is_some()
if chain_spec.fork(Hardfork::SpuriousDragon).active_at_block(at_block_number)
&& chain_id.is_some()
{
return Err(InvalidTransactionError::OldLegacyChainId.into())
return Err(InvalidTransactionError::OldLegacyChainId.into());
}
*chain_id
}
Transaction::Eip2930(TxEip2930 { chain_id, .. }) => {
// EIP-2930: Optional access lists: https://eips.ethereum.org/EIPS/eip-2930 (New transaction type)
if !chain_spec.fork(Hardfork::Berlin).active_at_block(at_block_number) {
return Err(InvalidTransactionError::Eip2930Disabled.into())
return Err(InvalidTransactionError::Eip2930Disabled.into());
}
Some(*chain_id)
}
Expand All @@ -92,13 +92,13 @@ pub fn validate_transaction_regarding_header(
}) => {
// EIP-1559: Fee market change for ETH 1.0 chain https://eips.ethereum.org/EIPS/eip-1559
if !chain_spec.fork(Hardfork::Berlin).active_at_block(at_block_number) {
return Err(InvalidTransactionError::Eip1559Disabled.into())
return Err(InvalidTransactionError::Eip1559Disabled.into());
}

// EIP-1559: add more constraints to the tx validation
// https://github.com/ethereum/EIPs/pull/3594
if max_priority_fee_per_gas > max_fee_per_gas {
return Err(InvalidTransactionError::TipAboveFeeCap.into())
return Err(InvalidTransactionError::TipAboveFeeCap.into());
}

Some(*chain_id)
Expand All @@ -112,7 +112,7 @@ pub fn validate_transaction_regarding_header(
// EIP-1559: add more constraints to the tx validation
// https://github.com/ethereum/EIPs/pull/3594
if max_priority_fee_per_gas > max_fee_per_gas {
return Err(InvalidTransactionError::TipAboveFeeCap.into())
return Err(InvalidTransactionError::TipAboveFeeCap.into());
}

Some(*chain_id)
Expand All @@ -122,14 +122,14 @@ pub fn validate_transaction_regarding_header(
};
if let Some(chain_id) = chain_id {
if chain_id != chain_spec.chain().id() {
return Err(InvalidTransactionError::ChainIdMismatch.into())
return Err(InvalidTransactionError::ChainIdMismatch.into());
}
}
// Check basefee and few checks that are related to that.
// https://github.com/ethereum/EIPs/pull/3594
if let Some(base_fee_per_gas) = base_fee {
if transaction.max_fee_per_gas() < base_fee_per_gas as u128 {
return Err(InvalidTransactionError::FeeCapTooLow.into())
return Err(InvalidTransactionError::FeeCapTooLow.into());
}
}

Expand Down Expand Up @@ -173,7 +173,7 @@ pub fn validate_all_transaction_regarding_block_and_nonces<
return Err(ConsensusError::from(
InvalidTransactionError::SignerAccountHasBytecode,
)
.into())
.into());
}
let nonce = account.nonce;
entry.insert(account.nonce + 1);
Expand All @@ -183,7 +183,7 @@ pub fn validate_all_transaction_regarding_block_and_nonces<

// check nonce
if transaction.nonce() != nonce {
return Err(ConsensusError::from(InvalidTransactionError::NonceNotConsistent).into())
return Err(ConsensusError::from(InvalidTransactionError::NonceNotConsistent).into());
}
}

Expand All @@ -206,7 +206,7 @@ pub fn validate_block_standalone(
return Err(ConsensusError::BodyOmmersHashDiff {
got: ommers_hash,
expected: block.header.ommers_hash,
})
});
}

// Check transaction root
Expand All @@ -216,7 +216,7 @@ pub fn validate_block_standalone(
return Err(ConsensusError::BodyTransactionRootDiff {
got: transaction_root,
expected: block.header.transactions_root,
})
});
}

// EIP-4895: Beacon chain push withdrawals as operations
Expand All @@ -230,7 +230,7 @@ pub fn validate_block_standalone(
return Err(ConsensusError::BodyWithdrawalsRootDiff {
got: withdrawals_root,
expected: *header_withdrawals_root,
})
});
}
}

Expand All @@ -244,8 +244,42 @@ pub fn validate_block_standalone(
return Err(ConsensusError::BlobGasUsedDiff {
header_blob_gas_used,
expected_blob_gas_used: total_blob_gas,
})
});
}
}

Ok(())
}

// Check gas limit, max diff between child/parent gas_limit should be max_diff=parent_gas/1024
// On Optimism, the gas limit can adjust instantly, so we skip this check if the optimism
// flag is enabled in the chainspec.
#[inline(always)]
fn check_gas_limit(
parent: &SealedHeader,
child: &SealedHeader,
chain_spec: &ChainSpec,
) -> Result<(), ConsensusError> {
let mut parent_gas_limit = parent.gas_limit;

// By consensus, gas_limit is multiplied by elasticity (*2) on
// on exact block that hardfork happens.
if chain_spec.fork(Hardfork::London).transitions_at_block(child.number) {
parent_gas_limit = parent.gas_limit * chain_spec.base_fee_params.elasticity_multiplier;
}

if child.gas_limit > parent_gas_limit {
if child.gas_limit - parent_gas_limit >= parent_gas_limit / 1024 {
return Err(ConsensusError::GasLimitInvalidIncrease {
parent_gas_limit,
child_gas_limit: child.gas_limit,
});
}
} else if parent_gas_limit - child.gas_limit >= parent_gas_limit / 1024 {
return Err(ConsensusError::GasLimitInvalidDecrease {
parent_gas_limit,
child_gas_limit: child.gas_limit,
});
}

Ok(())
Expand All @@ -262,61 +296,31 @@ pub fn validate_header_regarding_parent(
return Err(ConsensusError::ParentBlockNumberMismatch {
parent_block_number: parent.number,
block_number: child.number,
})
});
}

if parent.hash != child.parent_hash {
return Err(ConsensusError::ParentHashMismatch {
expected_parent_hash: parent.hash,
got_parent_hash: child.parent_hash,
})
});
}

// timestamp in past check
if child.timestamp <= parent.timestamp {
return Err(ConsensusError::TimestampIsInPast {
parent_timestamp: parent.timestamp,
timestamp: child.timestamp,
})
});
}

// TODO Check difficulty increment between parent and child
// Ace age did increment it by some formula that we need to follow.

// Check gas limit, max diff between child/parent gas_limit should be max_diff=parent_gas/1024
// On Optimism, the gas limit can adjust instantly, so we skip this check if the optimism
// flag is enabled in the chainspec.
#[inline(always)]
fn check_gas_limit(
parent: &SealedHeader,
child: &SealedHeader,
chain_spec: &ChainSpec,
) -> Result<(), ConsensusError> {
let mut parent_gas_limit = parent.gas_limit;

// By consensus, gas_limit is multiplied by elasticity (*2) on
// on exact block that hardfork happens.
if chain_spec.fork(Hardfork::London).transitions_at_block(child.number) {
parent_gas_limit = parent.gas_limit * chain_spec.base_fee_params.elasticity_multiplier;
}

if child.gas_limit > parent_gas_limit {
if child.gas_limit - parent_gas_limit >= parent_gas_limit / 1024 {
return Err(ConsensusError::GasLimitInvalidIncrease {
parent_gas_limit,
child_gas_limit: child.gas_limit,
})
}
} else if parent_gas_limit - child.gas_limit >= parent_gas_limit / 1024 {
return Err(ConsensusError::GasLimitInvalidDecrease {
parent_gas_limit,
child_gas_limit: child.gas_limit,
})
}

Ok(())
}
#[cfg(not(feature = "optimism"))]
check_gas_limit(parent, child, chain_spec)?;

#[cfg(feature = "optimism")]
if !chain_spec.is_optimism() {
check_gas_limit(parent, child, chain_spec)?;
}
Expand All @@ -335,7 +339,7 @@ pub fn validate_header_regarding_parent(
.ok_or(ConsensusError::BaseFeeMissing)?
};
if expected_base_fee != base_fee {
return Err(ConsensusError::BaseFeeDiff { expected: expected_base_fee, got: base_fee })
return Err(ConsensusError::BaseFeeDiff { expected: expected_base_fee, got: base_fee });
}
}

Expand All @@ -362,7 +366,7 @@ pub fn validate_block_regarding_chain<PROV: HeaderProvider + WithdrawalsProvider

// Check if block is known.
if provider.is_known(&hash)? {
return Err(ConsensusError::BlockKnown { hash, number: block.header.number }.into())
return Err(ConsensusError::BlockKnown { hash, number: block.header.number }.into());
}

// Check if parent is known.
Expand Down Expand Up @@ -419,7 +423,7 @@ pub fn validate_4844_header_with_parent(
let parent_excess_blob_gas = parent.excess_blob_gas.unwrap_or(0);

if child.blob_gas_used.is_none() {
return Err(ConsensusError::BlobGasUsedMissing)
return Err(ConsensusError::BlobGasUsedMissing);
}
let excess_blob_gas = child.excess_blob_gas.ok_or(ConsensusError::ExcessBlobGasMissing)?;

Expand All @@ -431,7 +435,7 @@ pub fn validate_4844_header_with_parent(
got: excess_blob_gas,
parent_excess_blob_gas,
parent_blob_gas_used,
})
});
}

Ok(())
Expand All @@ -448,25 +452,25 @@ pub fn validate_4844_header_standalone(header: &SealedHeader) -> Result<(), Cons
let blob_gas_used = header.blob_gas_used.ok_or(ConsensusError::BlobGasUsedMissing)?;

if header.excess_blob_gas.is_none() {
return Err(ConsensusError::ExcessBlobGasMissing)
return Err(ConsensusError::ExcessBlobGasMissing);
}

if header.parent_beacon_block_root.is_none() {
return Err(ConsensusError::ParentBeaconBlockRootMissing)
return Err(ConsensusError::ParentBeaconBlockRootMissing);
}

if blob_gas_used > MAX_DATA_GAS_PER_BLOCK {
return Err(ConsensusError::BlobGasUsedExceedsMaxBlobGasPerBlock {
blob_gas_used,
max_blob_gas_per_block: MAX_DATA_GAS_PER_BLOCK,
})
});
}

if blob_gas_used % DATA_GAS_PER_BLOB != 0 {
return Err(ConsensusError::BlobGasUsedNotMultipleOfBlobGasPerBlob {
blob_gas_used,
blob_gas_per_blob: DATA_GAS_PER_BLOB,
})
});
}

Ok(())
Expand Down
3 changes: 1 addition & 2 deletions crates/interfaces/src/blockchain_tree/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,8 +244,7 @@ impl InsertBlockErrorKind {
BlockExecutionError::AppendChainDoesntConnect { .. } |
BlockExecutionError::UnavailableForTest => false,
#[cfg(feature = "optimism")]
BlockExecutionError::L1BlockInfoError { .. } |
BlockExecutionError::InsufficientFundsForL1Cost { .. } => false,
BlockExecutionError::OptimismBlockExecution(_) => false,
}
}
InsertBlockErrorKind::Tree(err) => {
Expand Down
20 changes: 10 additions & 10 deletions crates/interfaces/src/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,22 +129,22 @@ pub enum BlockExecutionError {
#[error("execution unavailable for tests")]
UnavailableForTest,

/// Error when trying to parse L1 block info
/// Optimism Block Executor Errors
#[cfg(feature = "optimism")]
#[error(transparent)]
OptimismBlockExecution(#[from] OptimismBlockExecutionError),
}

/// Optimism Block Executor Errors
#[cfg(feature = "optimism")]
#[derive(Error, Debug, Clone, PartialEq, Eq)]
pub enum OptimismBlockExecutionError {
/// Error when trying to parse L1 block info
#[error("Could not get L1 block info from L2 block: {message:?}")]
L1BlockInfoError {
/// The inner error message
message: String,
},
/// Error for when there is insufficient funds for the L1 cost of an L2 transaction
#[cfg(feature = "optimism")]
#[error("Insufficient funds to cover transaction L1 cost: want {want}, have {have}")]
InsufficientFundsForL1Cost {
/// How much ETH the L1 fee requires
want: u64,
/// How much ETH the account has
have: u64,
},
}

impl BlockExecutionError {
Expand Down
Loading

0 comments on commit 4a9de7f

Please sign in to comment.