From 10d84b0abd6cdda1801c924481510a11ae393234 Mon Sep 17 00:00:00 2001 From: Naohiro Yoshida Date: Mon, 28 Apr 2025 17:20:50 +0900 Subject: [PATCH 1/2] fix BELC1 Signed-off-by: Naohiro Yoshida --- light-client/src/client.rs | 3 ++ light-client/src/client_state.rs | 1 + light-client/src/errors.rs | 4 ++ light-client/src/fixture/mod.rs | 3 ++ light-client/src/fork_spec.rs | 33 ++++++++++++ light-client/src/header/eth_header.rs | 50 ++++++++++++++++--- light-client/src/header/eth_headers.rs | 2 + light-client/src/header/mod.rs | 2 +- .../ibc/lightclients/parlia/v1/parlia.proto | 1 + proto/src/prost/ibc.lightclients.parlia.v1.rs | 2 + 10 files changed, 94 insertions(+), 7 deletions(-) diff --git a/light-client/src/client.rs b/light-client/src/client.rs index 8958a59..4fe4ddf 100644 --- a/light-client/src/client.rs +++ b/light-client/src/client.rs @@ -1369,6 +1369,7 @@ mod test { additional_header_item_count: 0, epoch_length: 200, max_turn_length: 9, + gas_limit_bound_divider: 256, }]; (client_state, cons_state) })); @@ -1382,6 +1383,7 @@ mod test { additional_header_item_count: 0, epoch_length: 200, max_turn_length: 9, + gas_limit_bound_divider: 256, }]; (client_state, cons_state) })); @@ -1396,6 +1398,7 @@ mod test { additional_header_item_count: 0, epoch_length: 200, max_turn_length: 9, + gas_limit_bound_divider: 256, }]; (client_state, cons_state) })) diff --git a/light-client/src/client_state.rs b/light-client/src/client_state.rs index f776eda..96b1b1c 100644 --- a/light-client/src/client_state.rs +++ b/light-client/src/client_state.rs @@ -325,6 +325,7 @@ mod test { additional_header_item_count: 1, // requestsHash epoch_length: 200, max_turn_length: 9, + gas_limit_bound_divider: 256, } } diff --git a/light-client/src/errors.rs b/light-client/src/errors.rs index eecf279..680ec13 100644 --- a/light-client/src/errors.rs +++ b/light-client/src/errors.rs @@ -82,6 +82,7 @@ pub enum Error { MissingSignerInValidator(BlockNumber, Address), UnexpectedGasDiff(BlockNumber, u64, u64), UnexpectedGasUsed(BlockNumber, u64, u64), + UnexpectedGasLimitDivider(BlockNumber), UnexpectedHeaderRelation(BlockNumber, BlockNumber, Hash, Vec, u64, u64), ProofRLPError(rlp::DecoderError), InvalidProofFormatError(Vec), @@ -506,6 +507,9 @@ impl core::fmt::Display for Error { Error::UnexpectedEpochInfo(e1, e2) => { write!(f, "UnexpectedEpochInfo : {} {}", e1, e2) } + Error::UnexpectedGasLimitDivider(e1) => { + write!(f, "UnexpectedGasLimitDivider : {}", e1) + } } } } diff --git a/light-client/src/fixture/mod.rs b/light-client/src/fixture/mod.rs index cf814bf..f9eb948 100644 --- a/light-client/src/fixture/mod.rs +++ b/light-client/src/fixture/mod.rs @@ -75,6 +75,7 @@ pub fn fork_spec_after_pascal() -> ForkSpec { additional_header_item_count: 1, epoch_length: 200, max_turn_length: 64, + gas_limit_bound_divider: 256, } } @@ -84,6 +85,7 @@ pub fn fork_spec_after_lorentz() -> ForkSpec { additional_header_item_count: 1, epoch_length: 500, max_turn_length: 64, + gas_limit_bound_divider: 1024, } } @@ -93,5 +95,6 @@ pub fn fork_spec_after_maxwell() -> ForkSpec { additional_header_item_count: 1, epoch_length: 1000, max_turn_length: 64, + gas_limit_bound_divider: 1024, } } diff --git a/light-client/src/fork_spec.rs b/light-client/src/fork_spec.rs index c59db31..a084307 100644 --- a/light-client/src/fork_spec.rs +++ b/light-client/src/fork_spec.rs @@ -18,6 +18,8 @@ pub struct ForkSpec { pub epoch_length: u64, /// Max turn length pub max_turn_length: u64, + /// Gas Limit bound diriver + pub gas_limit_bound_divider: u64, } impl ForkSpec { @@ -182,6 +184,7 @@ impl TryFrom for ForkSpec { additional_header_item_count: value.additional_header_item_count, epoch_length: value.epoch_length, max_turn_length: value.max_turn_length, + gas_limit_bound_divider: value.gas_limit_bound_divider, }) } } @@ -198,6 +201,7 @@ impl From for RawForkSpec { additional_header_item_count: value.additional_header_item_count, epoch_length: value.epoch_length, max_turn_length: value.max_turn_length, + gas_limit_bound_divider: value.gas_limit_bound_divider, } } } @@ -290,12 +294,14 @@ mod test { additional_header_item_count: 1, epoch_length: 200, max_turn_length: 9, + gas_limit_bound_divider: 256, }, ForkSpec { height_or_timestamp: HeightOrTimestamp::Height(20), additional_header_item_count: 2, epoch_length: 200, max_turn_length: 9, + gas_limit_bound_divider: 256, }, ]; let v = find_target_fork_spec(specs, 10, 0).unwrap(); @@ -316,12 +322,14 @@ mod test { additional_header_item_count: 1, epoch_length: 200, max_turn_length: 9, + gas_limit_bound_divider: 256, }, ForkSpec { height_or_timestamp: HeightOrTimestamp::Time(20), additional_header_item_count: 2, epoch_length: 200, max_turn_length: 9, + gas_limit_bound_divider: 256, }, ]; let v = find_target_fork_spec(specs, 0, 10).unwrap(); @@ -342,12 +350,14 @@ mod test { additional_header_item_count: 1, epoch_length: 200, max_turn_length: 9, + gas_limit_bound_divider: 256, }, ForkSpec { height_or_timestamp: HeightOrTimestamp::Time(10), additional_header_item_count: 20, epoch_length: 200, max_turn_length: 9, + gas_limit_bound_divider: 256, }, ]; // After value is primary @@ -369,12 +379,14 @@ mod test { additional_header_item_count: 1, epoch_length: 200, max_turn_length: 9, + gas_limit_bound_divider: 256, }, ForkSpec { height_or_timestamp: HeightOrTimestamp::Height(20), additional_header_item_count: 2, epoch_length: 200, max_turn_length: 9, + gas_limit_bound_divider: 256, }, ]; let v = find_target_fork_spec(specs, 9, 0).unwrap_err(); @@ -395,12 +407,14 @@ mod test { additional_header_item_count: 1, epoch_length: 200, max_turn_length: 9, + gas_limit_bound_divider: 256, }, ForkSpec { height_or_timestamp: HeightOrTimestamp::Time(20), additional_header_item_count: 2, epoch_length: 200, max_turn_length: 9, + gas_limit_bound_divider: 256, }, ]; let v = find_target_fork_spec(specs, 0, 9).unwrap_err(); @@ -421,12 +435,14 @@ mod test { additional_header_item_count: 1, epoch_length: 200, max_turn_length: 9, + gas_limit_bound_divider: 256, }, ForkSpec { height_or_timestamp: HeightOrTimestamp::Time(10), additional_header_item_count: 2, epoch_length: 200, max_turn_length: 9, + gas_limit_bound_divider: 256, }, ]; let v = find_target_fork_spec(specs, 9, 9).unwrap_err(); @@ -447,12 +463,14 @@ mod test { additional_header_item_count: 1, epoch_length: 200, max_turn_length: 9, + gas_limit_bound_divider: 256, }, ForkSpec { height_or_timestamp: HeightOrTimestamp::Height(11), additional_header_item_count: 2, epoch_length: 200, max_turn_length: 9, + gas_limit_bound_divider: 256, }, ]; verify_sorted_asc(specs).unwrap(); @@ -466,12 +484,14 @@ mod test { additional_header_item_count: 1, epoch_length: 200, max_turn_length: 9, + gas_limit_bound_divider: 256, }, ForkSpec { height_or_timestamp: HeightOrTimestamp::Time(11), additional_header_item_count: 2, epoch_length: 200, max_turn_length: 9, + gas_limit_bound_divider: 256, }, ]; verify_sorted_asc(specs).unwrap(); @@ -485,12 +505,14 @@ mod test { additional_header_item_count: 1, epoch_length: 200, max_turn_length: 9, + gas_limit_bound_divider: 256, }, ForkSpec { height_or_timestamp: HeightOrTimestamp::Height(10), additional_header_item_count: 2, epoch_length: 200, max_turn_length: 9, + gas_limit_bound_divider: 256, }, ]; let v = verify_sorted_asc(specs).unwrap_err(); @@ -508,12 +530,14 @@ mod test { additional_header_item_count: 1, epoch_length: 200, max_turn_length: 9, + gas_limit_bound_divider: 256, }, ForkSpec { height_or_timestamp: HeightOrTimestamp::Height(10), additional_header_item_count: 2, epoch_length: 200, max_turn_length: 9, + gas_limit_bound_divider: 256, }, ]; let v = verify_sorted_asc(specs).unwrap_err(); @@ -534,12 +558,14 @@ mod test { additional_header_item_count: 1, epoch_length: 200, max_turn_length: 9, + gas_limit_bound_divider: 256, }, ForkSpec { height_or_timestamp: HeightOrTimestamp::Time(10), additional_header_item_count: 2, epoch_length: 200, max_turn_length: 9, + gas_limit_bound_divider: 256, }, ]; let v = verify_sorted_asc(specs).unwrap_err(); @@ -557,12 +583,14 @@ mod test { additional_header_item_count: 1, epoch_length: 200, max_turn_length: 9, + gas_limit_bound_divider: 256, }, ForkSpec { height_or_timestamp: HeightOrTimestamp::Time(10), additional_header_item_count: 2, epoch_length: 200, max_turn_length: 9, + gas_limit_bound_divider: 256, }, ]; let v = verify_sorted_asc(specs).unwrap_err(); @@ -582,6 +610,7 @@ mod test { additional_header_item_count: 1, epoch_length: 500, max_turn_length: 64, + gas_limit_bound_divider: 256, }; match current .boundary_epochs(&fork_spec_after_pascal()) @@ -705,12 +734,14 @@ mod test { additional_header_item_count: 1, epoch_length: 200, max_turn_length: 9, + gas_limit_bound_divider: 256, }, ForkSpec { height_or_timestamp: HeightOrTimestamp::Height(20), additional_header_item_count: 2, epoch_length: 200, max_turn_length: 9, + gas_limit_bound_divider: 256, }, ]; let v = get_boundary_epochs(&fork_spec_after_pascal(), specs).unwrap_err(); @@ -730,12 +761,14 @@ mod test { additional_header_item_count: 1, epoch_length: 200, max_turn_length: 9, + gas_limit_bound_divider: 256, }, ForkSpec { height_or_timestamp: HeightOrTimestamp::Height(20), additional_header_item_count: 2, epoch_length: 500, max_turn_length: 9, + gas_limit_bound_divider: 256, }, ]; let v = get_boundary_epochs(&specs[1], specs).unwrap(); diff --git a/light-client/src/header/eth_header.rs b/light-client/src/header/eth_header.rs index f58cf43..7411554 100644 --- a/light-client/src/header/eth_header.rs +++ b/light-client/src/header/eth_header.rs @@ -28,8 +28,6 @@ const VALIDATOR_NUM_SIZE: usize = 1; const TURN_LENGTH_SIZE: usize = 1; -const PARAMS_GAS_LIMIT_BOUND_DIVISOR: u64 = 256; - const EMPTY_UNCLE_HASH: Hash = hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"); const EMPTY_NONCE: [u8; 8] = hex!("0000000000000000"); @@ -177,7 +175,16 @@ impl ETHHeader { } else { self.gas_limit - parent.gas_limit }; - let limit = parent.gas_limit / PARAMS_GAS_LIMIT_BOUND_DIVISOR; + let gas_limit_divider = self + .boundary_epochs + .as_ref() + .ok_or(Error::MissingBoundaryEpochs(self.number))? + .current_fork_spec() + .gas_limit_bound_divider; + if gas_limit_divider == 0 { + return Err(Error::UnexpectedGasLimitDivider(self.number)); + } + let limit = parent.gas_limit / gas_limit_divider; if diff >= limit { return Err(Error::UnexpectedGasDiff(self.number, diff, limit)); } @@ -512,13 +519,13 @@ pub(crate) mod test { use crate::errors::Error; use crate::header::eth_header::{ ETHHeader, DIFFICULTY_INTURN, DIFFICULTY_NOTURN, EXTRA_SEAL, EXTRA_VANITY, - PARAMS_GAS_LIMIT_BOUND_DIVISOR, VALIDATOR_BYTES_LENGTH_BEFORE_LUBAN, + VALIDATOR_BYTES_LENGTH_BEFORE_LUBAN, }; use rlp::RlpStream; use rstest::*; - use crate::fixture::{localnet, Network}; + use crate::fixture::{fork_spec_after_lorentz, fork_spec_after_pascal, localnet, Network}; use crate::header::epoch::Epoch; use crate::fork_spec::{ForkSpec, HeightOrTimestamp}; @@ -754,11 +761,30 @@ pub(crate) mod test { match result.unwrap_err() { Error::UnexpectedGasDiff(number, diff, limit) => { assert_eq!(block.number, number); - assert_eq!(parent.gas_limit / PARAMS_GAS_LIMIT_BOUND_DIVISOR, limit); + assert_eq!( + parent.gas_limit + / block + .boundary_epochs + .unwrap() + .current_fork_spec() + .gas_limit_bound_divider, + limit + ); assert_eq!(parent.gas_limit - block.gas_limit, diff); } err => unreachable!("{:?}", err), } + + let mut current = fork_spec_after_lorentz(); + current.gas_limit_bound_divider = 0; + block.boundary_epochs = Some(current.boundary_epochs(&fork_spec_after_pascal()).unwrap()); + let result = block.verify_cascading_fields(&parent); + match result.unwrap_err() { + Error::UnexpectedGasLimitDivider(number) => { + assert_eq!(block.number, number); + } + err => unreachable!("{:?}", err), + } } #[rstest] @@ -878,6 +904,7 @@ pub(crate) mod test { additional_header_item_count: header.additional_items.len() as u64, epoch_length: 500, max_turn_length: 64, + gas_limit_bound_divider: 1024, }]) .unwrap(); @@ -888,18 +915,21 @@ pub(crate) mod test { additional_header_item_count: header.additional_items.len() as u64, epoch_length: 500, max_turn_length: 64, + gas_limit_bound_divider: 1024, }, ForkSpec { height_or_timestamp: HeightOrTimestamp::Height(header.number), additional_header_item_count: header.additional_items.len() as u64, epoch_length: 500, max_turn_length: 64, + gas_limit_bound_divider: 1024, }, ForkSpec { height_or_timestamp: HeightOrTimestamp::Height(header.number + 1), additional_header_item_count: header.additional_items.len() as u64 + 1, epoch_length: 500, max_turn_length: 64, + gas_limit_bound_divider: 1024, }, ]) .unwrap(); @@ -916,6 +946,7 @@ pub(crate) mod test { additional_header_item_count: header.additional_items.len() as u64 - 1, epoch_length: 500, max_turn_length: 64, + gas_limit_bound_divider: 1024, }]) .unwrap_err(); match err { @@ -930,18 +961,21 @@ pub(crate) mod test { additional_header_item_count: header.additional_items.len() as u64, epoch_length: 500, max_turn_length: 64, + gas_limit_bound_divider: 1024, }, ForkSpec { height_or_timestamp: HeightOrTimestamp::Height(header.number), additional_header_item_count: header.additional_items.len() as u64 - 1, epoch_length: 500, max_turn_length: 64, + gas_limit_bound_divider: 1024, }, ForkSpec { height_or_timestamp: HeightOrTimestamp::Height(header.number + 1), additional_header_item_count: header.additional_items.len() as u64, epoch_length: 500, max_turn_length: 64, + gas_limit_bound_divider: 1024, }, ]) .unwrap_err(); @@ -964,6 +998,7 @@ pub(crate) mod test { additional_header_item_count: header.additional_items.len() as u64, epoch_length: 500, max_turn_length: turn_length - 1, + gas_limit_bound_divider: 1024, }]) .unwrap_err(); match err { @@ -978,18 +1013,21 @@ pub(crate) mod test { additional_header_item_count: header.additional_items.len() as u64, epoch_length: 500, max_turn_length: turn_length, + gas_limit_bound_divider: 1024, }, ForkSpec { height_or_timestamp: HeightOrTimestamp::Height(header.number), additional_header_item_count: header.additional_items.len() as u64, epoch_length: 500, max_turn_length: turn_length - 1, + gas_limit_bound_divider: 1024, }, ForkSpec { height_or_timestamp: HeightOrTimestamp::Height(header.number + 1), additional_header_item_count: header.additional_items.len() as u64, epoch_length: 500, max_turn_length: turn_length, + gas_limit_bound_divider: 1024, }, ]) .unwrap_err(); diff --git a/light-client/src/header/eth_headers.rs b/light-client/src/header/eth_headers.rs index 7eb9468..3666dd4 100644 --- a/light-client/src/header/eth_headers.rs +++ b/light-client/src/header/eth_headers.rs @@ -922,6 +922,7 @@ mod test { epoch_length: 10, additional_header_item_count: 1, max_turn_length: 64, + gas_limit_bound_divider: 256, }; let invalid_current_fork_spec = ForkSpec { @@ -929,6 +930,7 @@ mod test { epoch_length: 500, additional_header_item_count: 1, max_turn_length: 64, + gas_limit_bound_divider: 1024, }; for _i in 0..1000 { let mut header = headers.all.last().unwrap().clone(); diff --git a/light-client/src/header/mod.rs b/light-client/src/header/mod.rs index 60e984e..f704d44 100644 --- a/light-client/src/header/mod.rs +++ b/light-client/src/header/mod.rs @@ -97,7 +97,7 @@ impl Header { } } - // Set boundary epoch to verify header size. + // Set boundary epoch. for header in &mut self.headers.all { header.set_boundary_epochs(&fork_specs)? } diff --git a/proto/definitions/ibc/lightclients/parlia/v1/parlia.proto b/proto/definitions/ibc/lightclients/parlia/v1/parlia.proto index 261f5c0..e7af7c0 100644 --- a/proto/definitions/ibc/lightclients/parlia/v1/parlia.proto +++ b/proto/definitions/ibc/lightclients/parlia/v1/parlia.proto @@ -17,6 +17,7 @@ message ForkSpec { uint64 additional_header_item_count = 3; uint64 epoch_length = 4; uint64 max_turn_length = 5; + uint64 gas_limit_bound_divider = 6; } message ClientState { diff --git a/proto/src/prost/ibc.lightclients.parlia.v1.rs b/proto/src/prost/ibc.lightclients.parlia.v1.rs index 33fe1f1..94c9415 100644 --- a/proto/src/prost/ibc.lightclients.parlia.v1.rs +++ b/proto/src/prost/ibc.lightclients.parlia.v1.rs @@ -9,6 +9,8 @@ pub struct ForkSpec { pub epoch_length: u64, #[prost(uint64, tag = "5")] pub max_turn_length: u64, + #[prost(uint64, tag = "6")] + pub gas_limit_bound_divider: u64, #[prost(oneof = "fork_spec::HeightOrTimestamp", tags = "1, 2")] pub height_or_timestamp: ::core::option::Option, } From 13b99a4c078e5699cb7bfc51e29ed20826620f62 Mon Sep 17 00:00:00 2001 From: Naohiro Yoshida Date: Mon, 12 May 2025 19:44:08 +0900 Subject: [PATCH 2/2] fix conflict Signed-off-by: Naohiro Yoshida --- light-client/src/fork_spec.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/light-client/src/fork_spec.rs b/light-client/src/fork_spec.rs index 9c06c85..0055c5a 100644 --- a/light-client/src/fork_spec.rs +++ b/light-client/src/fork_spec.rs @@ -648,6 +648,7 @@ mod test { additional_header_item_count: 1, epoch_length: 0, max_turn_length: 64, + gas_limit_bound_divider: 256, }; match current .boundary_epochs(&fork_spec_after_pascal()) @@ -668,6 +669,7 @@ mod test { additional_header_item_count: 1, epoch_length: 0, max_turn_length: 64, + gas_limit_bound_divider: 256, }; match fork_spec_after_pascal() .boundary_epochs(&previous)