Skip to content

Commit

Permalink
fix conflict
Browse files Browse the repository at this point in the history
Signed-off-by: Naohiro Yoshida <[email protected]>
  • Loading branch information
Naohiro Yoshida committed Nov 26, 2024
2 parents b0c92af + bd83fed commit f97baa3
Show file tree
Hide file tree
Showing 10 changed files with 473 additions and 130 deletions.
8 changes: 8 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,11 @@ jobs:
with:
command: test
args: --release --features=std --manifest-path light-client/Cargo.toml
- uses: actions-rs/cargo@v1
name: unit-test-dev-test
with:
command: test
args: --release --features=dev --manifest-path light-client/Cargo.toml --lib test::dev_test
env:
MINIMUM_TIMESTAMP_SUPPORTED: 1731495592
MINIMUM_HEIGHT_SUPPORTED: 100
18 changes: 17 additions & 1 deletion light-client/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,23 @@ fn main() {
writeln!(
file,
"pub const BLOCKS_PER_EPOCH: u64 = {};",
blocks_per_epoch
blocks_per_epoch,
)
.unwrap();
}

{
use std::io::Write;
let mut file = std::fs::File::create("src/header/hardfork.rs").unwrap();
let minimum_time_stamp_supported =
std::env::var("MINIMUM_TIMESTAMP_SUPPORTED").unwrap_or_else(|_| "0".to_string());
let minimum_height_supported =
std::env::var("MINIMUM_HEIGHT_SUPPORTED").unwrap_or_else(|_| "0".to_string());
writeln!(
file,
"pub const MINIMUM_TIMESTAMP_SUPPORTED: u64 = {};\npub const MINIMUM_HEIGHT_SUPPORTED: u64 = {};",
minimum_time_stamp_supported,
minimum_height_supported
)
.unwrap();
}
Expand Down
116 changes: 107 additions & 9 deletions light-client/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use crate::commitment::{
};
use crate::consensus_state::ConsensusState;
use crate::errors::{ClientError, Error};

use crate::header::hardfork::{MINIMUM_HEIGHT_SUPPORTED, MINIMUM_TIMESTAMP_SUPPORTED};
use crate::header::Header;
use crate::message::ClientMessage;
use crate::misbehaviour::Misbehaviour;
Expand Down Expand Up @@ -165,6 +165,18 @@ impl InnerLightClient {
let height = client_state.latest_height;
let timestamp = consensus_state.timestamp;

#[allow(clippy::absurd_extreme_comparisons)]
if timestamp.as_unix_timestamp_secs() < MINIMUM_TIMESTAMP_SUPPORTED {
return Err(Error::UnsupportedMinimumTimestamp(timestamp));
}
#[allow(clippy::absurd_extreme_comparisons)]
if height.revision_height() < MINIMUM_HEIGHT_SUPPORTED {
return Err(Error::UnsupportedMinimumHeight(height));
}
if height.revision_height() == 0 {
return Err(Error::UnexpectedRevisionHeight(height.revision_height()));
}

Ok(CreateClientResult {
height,
message: UpdateStateProxyMessage {
Expand Down Expand Up @@ -559,7 +571,7 @@ mod test {
fn test_success_create_client() {
let client_state = hex!("0a272f6962632e6c69676874636c69656e74732e7061726c69612e76312e436c69656e745374617465124d08381214151f3951fa218cac426edfe078fa9e5c6dcea5001a2000000000000000000000000000000000000000000000000000000000000000002205109b9ea90f2a040880a305320410c0843d").to_vec();
let consensus_state = hex!("0a2a2f6962632e6c69676874636c69656e74732e7061726c69612e76312e436f6e73656e7375735374617465126c0a2056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42110de82d5a8061a209c59cf0b5717cb6e2bd8620b7f3481605c8abcd45636bdf45c86db06338f0c5e22207a1dede35f5c835fecdc768324928cd0d9d9161e8529e1ba1e60451f3a9d088a").to_vec();
let client = ParliaLightClient::default();
let client = ParliaLightClient;
let mock_consensus_state = BTreeMap::new();
let ctx = MockClientReader {
client_state: None,
Expand Down Expand Up @@ -590,6 +602,26 @@ mod test {
_ => unreachable!("invalid commitment"),
}
}
#[test]
fn test_error_create_client() {
let client_state = hex!("0a272f6962632e6c69676874636c69656e74732e7061726c69612e76312e436c69656e745374617465124d08381214151f3951fa218cac426edfe078fa9e5c6dcea5001a2000000000000000000000000000000000000000000000000000000000000000002205109b9ea90f2a040880a305320410c0843d").to_vec();
let consensus_state = hex!("0a2a2f6962632e6c69676874636c69656e74732e7061726c69612e76312e436f6e73656e7375735374617465126c0a2056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42110de82d5a8061a209c59cf0b5717cb6e2bd8620b7f3481605c8abcd45636bdf45c86db06338f0c5e22207a1dede35f5c835fecdc768324928cd0d9d9161e8529e1ba1e60451f3a9d088a").to_vec();
let client = ParliaLightClient::default();
let mock_consensus_state = BTreeMap::new();
let ctx = MockClientReader {
client_state: None,
consensus_state: mock_consensus_state,
};
let mut any_client_state: Any = client_state.try_into().unwrap();
let mut client_state = ClientState::try_from(any_client_state.clone()).unwrap();
client_state.latest_height = Height::new(0, 0);
any_client_state = client_state.try_into().unwrap();
let any_consensus_state: Any = consensus_state.try_into().unwrap();
let result = client
.create_client(&ctx, any_client_state.clone(), any_consensus_state.clone())
.unwrap_err();
assert_err(result, "UnexpectedRevisionHeight");
}

#[rstest]
#[case::localnet(localnet())]
Expand Down Expand Up @@ -641,7 +673,7 @@ mod test {
) {
let any: Any = header.try_into().unwrap();
let header = Header::try_from(any.clone()).unwrap();
let client = ParliaLightClient::default();
let client = ParliaLightClient;
let client_id = ClientId::new(&client.client_type(), 1).unwrap();
let mut mock_consensus_state = BTreeMap::new();
let trusted_cs = ConsensusState {
Expand Down Expand Up @@ -711,7 +743,7 @@ mod test {
#[rstest]
#[case::localnet(localnet())]
fn test_success_update_state_continuous(#[case] hp: Box<dyn Network>) {
let client = ParliaLightClient::default();
let client = ParliaLightClient;
let client_id = ClientId::new(&client.client_type(), 1).unwrap();
let header_groups = hp.success_update_client_continuous_input();

Expand Down Expand Up @@ -768,7 +800,7 @@ mod test {
let header = input.header;
let any: Any = header.try_into().unwrap();

let client = ParliaLightClient::default();
let client = ParliaLightClient;
let client_id = ClientId::new(&client.client_type(), 1).unwrap();
let mut mock_consensus_state = BTreeMap::new();

Expand Down Expand Up @@ -845,7 +877,7 @@ mod test {
let header = Header::try_from(input.clone()).unwrap();
let trusted_height = header.trusted_height();

let client = ParliaLightClient::default();
let client = ParliaLightClient;
let client_id = ClientId::new(&client.client_type(), 1).unwrap();
let mut mock_consensus_state = BTreeMap::new();
mock_consensus_state.insert(trusted_height, ConsensusState::default());
Expand Down Expand Up @@ -945,7 +977,7 @@ mod test {
latest_height: Height,
frozen: bool,
) -> Result<VerifyMembershipResult, light_client::Error> {
let client = ParliaLightClient::default();
let client = ParliaLightClient;
let client_id = ClientId::new(client.client_type().as_str(), 0).unwrap();
let mut mock_consensus_state = BTreeMap::new();
mock_consensus_state.insert(
Expand Down Expand Up @@ -976,7 +1008,7 @@ mod test {

#[test]
fn test_success_submit_misbehaviour() {
let client = ParliaLightClient::default();
let client = ParliaLightClient;
let client_id = ClientId::new(client.client_type().as_str(), 1).unwrap();

// Detect misbehaviour
Expand Down Expand Up @@ -1042,7 +1074,7 @@ mod test {
consensus_state: BTreeMap::new(),
};

let client = ParliaLightClient::default();
let client = ParliaLightClient;
let client_id = ClientId::new(client.client_type().as_str(), 1).unwrap();

// fail: exactly same block
Expand Down Expand Up @@ -1122,4 +1154,70 @@ mod test {
fn assert_err(err: light_client::Error, contains: &str) {
assert!(format!("{:?}", err).contains(contains), "{}", err);
}

#[cfg(feature = "dev")]
mod dev_test {
use crate::client::test::MockClientReader;
use crate::client::ParliaLightClient;
use crate::client_state::ClientState;
use crate::consensus_state::ConsensusState;
use crate::header::hardfork::{MINIMUM_HEIGHT_SUPPORTED, MINIMUM_TIMESTAMP_SUPPORTED};
use crate::misc::{new_height, new_timestamp};
use hex_literal::hex;
use light_client::{types::Any, LightClient};
use std::collections::BTreeMap;

#[test]
fn test_supported_timestamp() {
let client_state = hex!("0a272f6962632e6c69676874636c69656e74732e7061726c69612e76312e436c69656e745374617465124d08381214151f3951fa218cac426edfe078fa9e5c6dcea5001a2000000000000000000000000000000000000000000000000000000000000000002205109b9ea90f2a040880a305320410c0843d").to_vec();
let consensus_state = hex!("0a2a2f6962632e6c69676874636c69656e74732e7061726c69612e76312e436f6e73656e7375735374617465126c0a2056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42110de82d5a8061a209c59cf0b5717cb6e2bd8620b7f3481605c8abcd45636bdf45c86db06338f0c5e22207a1dede35f5c835fecdc768324928cd0d9d9161e8529e1ba1e60451f3a9d088a").to_vec();
let client = ParliaLightClient::default();
let mock_consensus_state = BTreeMap::new();
let ctx = MockClientReader {
client_state: None,
consensus_state: mock_consensus_state,
};
let any_client_state: Any = client_state.try_into().unwrap();
let any_consensus_state: Any = consensus_state.try_into().unwrap();
let err = client
.create_client(&ctx, any_client_state.clone(), any_consensus_state.clone())
.unwrap_err();
assert!(
format!("{:?}", err).contains("UnsupportedMinimumTimestamp"),
"{}",
err
);
}

#[test]
fn test_supported_height() {
let client_state = hex!("0a272f6962632e6c69676874636c69656e74732e7061726c69612e76312e436c69656e745374617465124d08381214151f3951fa218cac426edfe078fa9e5c6dcea5001a2000000000000000000000000000000000000000000000000000000000000000002205109b9ea90f2a040880a305320410c0843d").to_vec();
let consensus_state = hex!("0a2a2f6962632e6c69676874636c69656e74732e7061726c69612e76312e436f6e73656e7375735374617465126c0a2056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42110de82d5a8061a209c59cf0b5717cb6e2bd8620b7f3481605c8abcd45636bdf45c86db06338f0c5e22207a1dede35f5c835fecdc768324928cd0d9d9161e8529e1ba1e60451f3a9d088a").to_vec();
let client = ParliaLightClient::default();
let mock_consensus_state = BTreeMap::new();
let ctx = MockClientReader {
client_state: None,
consensus_state: mock_consensus_state,
};
let any_client_state: Any = client_state.try_into().unwrap();
let any_consensus_state: Any = consensus_state.try_into().unwrap();

let mut client_state: ClientState = any_client_state.try_into().unwrap();
client_state.latest_height = new_height(0, MINIMUM_HEIGHT_SUPPORTED - 1);
let mut consensus_state: ConsensusState = any_consensus_state.try_into().unwrap();
consensus_state.timestamp = new_timestamp(MINIMUM_TIMESTAMP_SUPPORTED).unwrap();

let any_client_state: Any = client_state.try_into().unwrap();
let any_consensus_state: Any = consensus_state.try_into().unwrap();

let err = client
.create_client(&ctx, any_client_state.clone(), any_consensus_state.clone())
.unwrap_err();
assert!(
format!("{:?}", err).contains("UnsupportedMinimumHeight"),
"{}",
err
);
}
}
}
99 changes: 98 additions & 1 deletion light-client/src/client_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use parlia_ibc_proto::ibc::lightclients::parlia::v1::ClientState as RawClientSta
use crate::commitment::resolve_account;
use crate::consensus_state::ConsensusState;
use crate::errors::Error;
use crate::header::hardfork::{MINIMUM_HEIGHT_SUPPORTED, MINIMUM_TIMESTAMP_SUPPORTED};
use crate::header::Header;
use crate::misbehaviour::Misbehaviour;
use crate::misc::{new_height, Address, ChainId, Hash};
Expand Down Expand Up @@ -97,12 +98,23 @@ impl ClientState {
}

fn check_header(&self, now: Time, cs: &ConsensusState, header: &Header) -> Result<(), Error> {
// Ensure header has supported timestamp
let ts = header.timestamp()?;

#[allow(clippy::absurd_extreme_comparisons)]
if ts.as_unix_timestamp_secs() < MINIMUM_TIMESTAMP_SUPPORTED {
return Err(Error::UnsupportedMinimumTimestamp(ts));
}
#[allow(clippy::absurd_extreme_comparisons)]
if header.height().revision_height() < MINIMUM_HEIGHT_SUPPORTED {
return Err(Error::UnsupportedMinimumHeight(header.height()));
}
// Ensure last consensus state is within the trusting period
validate_within_trusting_period(
now,
self.trusting_period,
self.max_clock_drift,
header.timestamp()?,
ts,
cs.timestamp,
)?;

Expand Down Expand Up @@ -159,6 +171,13 @@ impl TryFrom<RawClientState> for ClientState {

let chain_id = ChainId::new(value.chain_id);

if chain_id.version() != raw_latest_height.revision_number {
return Err(Error::UnexpectedLatestHeightRevision(
chain_id.version(),
raw_latest_height.revision_number,
));
}

let latest_height = new_height(
raw_latest_height.revision_number,
raw_latest_height.revision_height,
Expand Down Expand Up @@ -489,6 +508,19 @@ mod test {
err => unreachable!("{:?}", err),
}

cs.latest_height = Some(Height {
revision_number: 1,
revision_height: 0,
});
let err = ClientState::try_from(cs.clone()).unwrap_err();
match err {
Error::UnexpectedLatestHeightRevision(e1, e2) => {
assert_eq!(e1, 0);
assert_eq!(e2, 1);
}
err => unreachable!("{:?}", err),
}

cs.latest_height = Some(Height::default());
let err = ClientState::try_from(cs.clone()).unwrap_err();
match err {
Expand Down Expand Up @@ -673,4 +705,69 @@ mod test {
panic!("expected error");
}
}
#[cfg(feature = "dev")]
mod dev_test {
use crate::client_state::ClientState;
use crate::consensus_state::ConsensusState;
use crate::errors::Error;
use crate::fixture::localnet;
use crate::header::eth_headers::ETHHeaders;
use crate::header::hardfork::{MINIMUM_HEIGHT_SUPPORTED, MINIMUM_TIMESTAMP_SUPPORTED};
use crate::header::Header;
use crate::misc::new_timestamp;
use parlia_ibc_proto::ibc::core::client::v1::Height;

#[test]
fn test_supported_timestamp() {
let header = Header::new(
vec![1],
ETHHeaders {
target: localnet().previous_epoch_header(),
all: vec![],
},
Height::default(),
localnet().previous_epoch_header().epoch.unwrap(),
localnet().epoch_header().epoch.unwrap(),
);
let cs = ClientState::default();
let cons_state = ConsensusState::default();
let err = cs
.check_header(new_timestamp(0).unwrap(), &cons_state, &header)
.unwrap_err();
match err {
Error::UnsupportedMinimumTimestamp(e1) => {
assert_eq!(e1, header.timestamp().unwrap());
}
err => unreachable!("{:?}", err),
}
}

#[test]
fn test_supported_height() {
let mut header = Header::new(
vec![1],
ETHHeaders {
target: localnet().previous_epoch_header(),
all: vec![],
},
Height::default(),
localnet().previous_epoch_header().epoch.unwrap(),
localnet().epoch_header().epoch.unwrap(),
);
header.eth_header_mut().target.timestamp = MINIMUM_TIMESTAMP_SUPPORTED;
header.eth_header_mut().target.number = MINIMUM_HEIGHT_SUPPORTED - 1;

let cs = ClientState::default();
let cons_state = ConsensusState::default();
let err = cs
.check_header(new_timestamp(0).unwrap(), &cons_state, &header)
.unwrap_err();
match err {
Error::UnsupportedMinimumHeight(e1) => {
assert_eq!(e1, header.height());
}
err => unreachable!("{:?}", err),
}
}
}
}
Loading

0 comments on commit f97baa3

Please sign in to comment.