Skip to content

Commit b05dea1

Browse files
authored
fix: use nanoseconds instead of seconds in sp1 light client (#408)
1 parent a284ab0 commit b05dea1

File tree

51 files changed

+203
-189
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+203
-189
lines changed

contracts/light-clients/SP1ICS07Tendermint.sol

+32-11
Original file line numberDiff line numberDiff line change
@@ -151,19 +151,19 @@ contract SP1ICS07Tendermint is ISP1ICS07TendermintErrors, ISP1ICS07Tendermint, I
151151
/// @param proofHeight The height of the proof.
152152
/// @param path The path of the key-value pair.
153153
/// @param value The value of the key-value pair.
154-
/// @return timestamp The timestamp of the trusted consensus state.
154+
/// @return The timestamp of the trusted consensus state in unix seconds.
155155
function _membership(
156156
bytes calldata proof,
157157
IICS02ClientMsgs.Height calldata proofHeight,
158158
bytes[] calldata path,
159159
bytes memory value
160160
)
161161
private
162-
returns (uint256 timestamp)
162+
returns (uint256)
163163
{
164164
if (proof.length == 0) {
165165
// cached proof
166-
return _getCachedKvPair(proofHeight.revisionHeight, IMembershipMsgs.KVPair(path, value));
166+
return _nanosToSeconds(_getCachedKvPair(proofHeight.revisionHeight, IMembershipMsgs.KVPair(path, value)));
167167
}
168168

169169
IMembershipMsgs.MembershipProof memory membershipProof = abi.decode(proof, (IMembershipMsgs.MembershipProof));
@@ -261,7 +261,7 @@ contract SP1ICS07Tendermint is ISP1ICS07TendermintErrors, ISP1ICS07Tendermint, I
261261
if (output.kvPairs.length > 1) {
262262
_cacheKvPairs(proofHeight.revisionHeight, output.kvPairs, proof.trustedConsensusState.timestamp);
263263
}
264-
return proof.trustedConsensusState.timestamp;
264+
return _getTimestampInSeconds(proof.trustedConsensusState);
265265
}
266266

267267
/// @notice The entrypoint for handling the `SP1MembershipAndUpdateClientProof` proof type.
@@ -360,7 +360,7 @@ contract SP1ICS07Tendermint is ISP1ICS07TendermintErrors, ISP1ICS07Tendermint, I
360360
proofHeight.revisionHeight, output.kvPairs, output.updateClientOutput.newConsensusState.timestamp
361361
);
362362
}
363-
return output.updateClientOutput.newConsensusState.timestamp;
363+
return _getTimestampInSeconds(output.updateClientOutput.newConsensusState);
364364
}
365365

366366
/// @notice Validates the MembershipOutput public values.
@@ -428,16 +428,19 @@ contract SP1ICS07Tendermint is ISP1ICS07TendermintErrors, ISP1ICS07Tendermint, I
428428
/// @notice Validates the client state and time.
429429
/// @dev This function does not check the equality of the latest height and isFrozen.
430430
/// @param publicClientState The public client state.
431-
/// @param time The time.
431+
/// @param time The time in unix nanoseconds.
432432
function _validateClientStateAndTime(
433433
IICS07TendermintMsgs.ClientState memory publicClientState,
434-
uint64 time
434+
uint128 time
435435
)
436436
private
437437
view
438438
{
439-
require(time <= block.timestamp, ProofIsInTheFuture(block.timestamp, time));
440-
require(block.timestamp - time <= ALLOWED_SP1_CLOCK_DRIFT, ProofIsTooOld(block.timestamp, time));
439+
require(_nanosToSeconds(time) <= block.timestamp, ProofIsInTheFuture(block.timestamp, _nanosToSeconds(time)));
440+
require(
441+
block.timestamp - _nanosToSeconds(time) <= ALLOWED_SP1_CLOCK_DRIFT,
442+
ProofIsTooOld(block.timestamp, _nanosToSeconds(time))
443+
);
441444

442445
// Check client state equality
443446
// NOTE: We do not check the equality of latest height and isFrozen, this is because:
@@ -508,7 +511,7 @@ contract SP1ICS07Tendermint is ISP1ICS07TendermintErrors, ISP1ICS07Tendermint, I
508511
/// @notice Caches the key-value pairs to the transient storage with the timestamp.
509512
/// @param proofHeight The height of the proof.
510513
/// @param kvPairs The key-value pairs.
511-
/// @param timestamp The timestamp of the trusted consensus state.
514+
/// @param timestamp The timestamp of the trusted consensus state in unix nanoseconds.
512515
/// @dev WARNING: Transient store is not reverted even if a message within a transaction reverts.
513516
/// @dev WARNING: This function must be called after all proof and validation checks.
514517
function _cacheKvPairs(uint64 proofHeight, IMembershipMsgs.KVPair[] memory kvPairs, uint256 timestamp) private {
@@ -521,7 +524,7 @@ contract SP1ICS07Tendermint is ISP1ICS07TendermintErrors, ISP1ICS07Tendermint, I
521524
/// @notice Gets the timestamp of the cached key-value pair from the transient storage.
522525
/// @param proofHeight The height of the proof.
523526
/// @param kvPair The key-value pair.
524-
/// @return The timestamp of the cached key-value pair.
527+
/// @return The timestamp of the cached key-value pair in unix nanoseconds.
525528
function _getCachedKvPair(
526529
uint64 proofHeight,
527530
IMembershipMsgs.KVPair memory kvPair
@@ -536,6 +539,24 @@ contract SP1ICS07Tendermint is ISP1ICS07TendermintErrors, ISP1ICS07Tendermint, I
536539
return timestamp;
537540
}
538541

542+
/// @notice Returns the timestamp of the trusted consensus state in unix seconds.
543+
/// @param consensusState The consensus state.
544+
/// @return The timestamp of the trusted consensus state in unix seconds.
545+
function _getTimestampInSeconds(IICS07TendermintMsgs.ConsensusState memory consensusState)
546+
private
547+
pure
548+
returns (uint256)
549+
{
550+
return _nanosToSeconds(consensusState.timestamp);
551+
}
552+
553+
/// @notice Converts nanoseconds to seconds.
554+
/// @param nanos The nanoseconds.
555+
/// @return The seconds.
556+
function _nanosToSeconds(uint256 nanos) private pure returns (uint256) {
557+
return nanos / 1e9;
558+
}
559+
539560
/// @notice Modifier to check if the client is not frozen.
540561
modifier notFrozen() {
541562
require(!clientState.isFrozen, FrozenClientState());

contracts/light-clients/msgs/IICS07TendermintMsgs.sol

+2-2
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,11 @@ interface IICS07TendermintMsgs {
3636

3737
/// @notice Defines the Tendermint light client's consensus state at some height.
3838
/// @param timestamp timestamp that corresponds to the counterparty block height
39-
/// in which the ConsensusState was generated.
39+
/// in which the ConsensusState was generated. (in unix nanoseconds)
4040
/// @param root commitment root (i.e app hash)
4141
/// @param nextValidatorsHash next validators hash
4242
struct ConsensusState {
43-
uint64 timestamp;
43+
uint128 timestamp;
4444
bytes32 root;
4545
bytes32 nextValidatorsHash;
4646
}

contracts/light-clients/msgs/IMisbehaviourMsgs.sol

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@ interface IMisbehaviourMsgs {
1717

1818
/// @notice The public value output for the sp1 misbehaviour program.
1919
/// @param clientState The client state that was used to verify the misbehaviour.
20-
/// @param time The time which the misbehaviour was verified in seconds.
20+
/// @param time The time which the misbehaviour was verified in unix nanoseconds.
2121
/// @param trustedHeight1 The trusted height of header 1
2222
/// @param trustedHeight2 The trusted height of header 2
2323
/// @param trustedConsensusState1 The trusted consensus state of header 1
2424
/// @param trustedConsensusState2 The trusted consensus state of header 2
2525
struct MisbehaviourOutput {
2626
IICS07TendermintMsgs.ClientState clientState;
27-
uint64 time;
27+
uint128 time;
2828
IICS02ClientMsgs.Height trustedHeight1;
2929
IICS02ClientMsgs.Height trustedHeight2;
3030
IICS07TendermintMsgs.ConsensusState trustedConsensusState1;

contracts/light-clients/msgs/IUpdateClientMsgs.sol

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,14 @@ interface IUpdateClientMsgs {
1919
/// @param clientState The client state that was used to verify the header.
2020
/// @param trustedConsensusState The trusted consensus state.
2121
/// @param newConsensusState The new consensus state with the verified header.
22-
/// @param time The time which the header was verified in seconds.
22+
/// @param time The time which the header was verified in unix nanoseconds.
2323
/// @param trustedHeight The trusted height.
2424
/// @param newHeight The new height.
2525
struct UpdateClientOutput {
2626
IICS07TendermintMsgs.ClientState clientState;
2727
IICS07TendermintMsgs.ConsensusState trustedConsensusState;
2828
IICS07TendermintMsgs.ConsensusState newConsensusState;
29-
uint64 time;
29+
uint128 time;
3030
IICS02ClientMsgs.Height trustedHeight;
3131
IICS02ClientMsgs.Height newHeight;
3232
}

packages/relayer-lib/src/tx_builder/cosmos_to_cosmos.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -78,24 +78,22 @@ impl TxBuilderService<CosmosSdk, CosmosSdk> for TxBuilder {
7878
revision_height,
7979
};
8080

81-
let now = std::time::SystemTime::now()
82-
.duration_since(std::time::UNIX_EPOCH)?
83-
.as_secs();
81+
let now_since_unix = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH)?;
8482

8583
let mut timeout_msgs = cosmos::target_events_to_timeout_msgs(
8684
target_events,
8785
&target_client_id,
8886
&target_height,
8987
&self.signer_address,
90-
now,
88+
now_since_unix.as_secs(),
9189
);
9290

9391
let (mut recv_msgs, mut ack_msgs) = cosmos::src_events_to_recv_and_ack_msgs(
9492
src_events,
9593
&target_client_id,
9694
&target_height,
9795
&self.signer_address,
98-
now,
96+
now_since_unix.as_secs(),
9997
);
10098

10199
cosmos::inject_tendermint_proofs(

packages/relayer-lib/src/tx_builder/cosmos_to_eth.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,7 @@ where
9191
dest_events: Vec<EurekaEventWithHeight>,
9292
target_client_id: String,
9393
) -> Result<Vec<u8>> {
94-
let now = std::time::SystemTime::now()
95-
.duration_since(std::time::UNIX_EPOCH)?
96-
.as_secs();
94+
let now_since_unix = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH)?;
9795

9896
let latest_light_block = self.tm_client.get_light_block(None).await?;
9997
let revision_height = latest_light_block.height().value();
@@ -108,14 +106,14 @@ where
108106
dest_events,
109107
&target_client_id,
110108
&latest_height,
111-
now,
109+
now_since_unix.as_secs(),
112110
);
113111

114112
let recv_and_ack_msgs = eth_eureka::src_events_to_recv_and_ack_msgs(
115113
src_events,
116114
&target_client_id,
117115
&latest_height,
118-
now,
116+
now_since_unix.as_secs(),
119117
);
120118

121119
let mut all_msgs = timeout_msgs
@@ -136,7 +134,7 @@ where
136134
&self.tm_client,
137135
latest_light_block,
138136
client_state,
139-
now,
137+
now_since_unix.as_nanos(),
140138
)
141139
.await?;
142140

packages/relayer-lib/src/tx_builder/eth_to_cosmos.rs

+6-10
Original file line numberDiff line numberDiff line change
@@ -254,24 +254,22 @@ where
254254
revision_height: minimum_block_number,
255255
};
256256

257-
let now = std::time::SystemTime::now()
258-
.duration_since(std::time::UNIX_EPOCH)?
259-
.as_secs();
257+
let now_since_unix = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH)?;
260258

261259
let mut timeout_msgs = cosmos::target_events_to_timeout_msgs(
262260
dest_events,
263261
&target_client_id,
264262
&target_height,
265263
&self.signer_address,
266-
now,
264+
now_since_unix.as_secs(),
267265
);
268266

269267
let (mut recv_msgs, mut ack_msgs) = cosmos::src_events_to_recv_and_ack_msgs(
270268
src_events,
271269
&target_client_id,
272270
&target_height,
273271
&self.signer_address,
274-
now,
272+
now_since_unix.as_secs(),
275273
);
276274

277275
let ethereum_client_state = self.ethereum_client_state(target_client_id.clone()).await?;
@@ -547,24 +545,22 @@ where
547545
revision_height: target_block_number,
548546
};
549547

550-
let now = std::time::SystemTime::now()
551-
.duration_since(std::time::UNIX_EPOCH)?
552-
.as_secs();
548+
let now_since_unix = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH)?;
553549

554550
let mut timeout_msgs = cosmos::target_events_to_timeout_msgs(
555551
dest_events,
556552
&target_client_id,
557553
&target_height,
558554
&self.signer_address,
559-
now,
555+
now_since_unix.as_secs(),
560556
);
561557

562558
let (mut recv_msgs, mut ack_msgs) = cosmos::src_events_to_recv_and_ack_msgs(
563559
src_events,
564560
&target_client_id,
565561
&target_height,
566562
&self.signer_address,
567-
now,
563+
now_since_unix.as_secs(),
568564
);
569565

570566
tracing::debug!("Timeout messages: #{}", timeout_msgs.len());

packages/relayer-lib/src/utils/eth_eureka.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ pub async fn inject_sp1_proof<C: SP1ProverComponents>(
109109
tm_client: &HttpClient,
110110
target_light_block: LightBlock,
111111
client_state: ClientState,
112-
now: u64,
112+
now: u128,
113113
) -> Result<()> {
114114
let target_height = target_light_block.height().value();
115115

packages/solidity/src/msgs.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,9 @@ impl From<ICS07TendermintConsensusState> for IICS07TendermintMsgs::ConsensusStat
5959
.unwrap();
6060
Self {
6161
#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
62-
timestamp: ics07_tendermint_consensus_state.timestamp.unix_timestamp() as u64,
62+
timestamp: ics07_tendermint_consensus_state
63+
.timestamp
64+
.unix_timestamp_nanos() as u128,
6365
root: root.into(),
6466
nextValidatorsHash: next_validators_hash.into(),
6567
}
@@ -69,9 +71,10 @@ impl From<ICS07TendermintConsensusState> for IICS07TendermintMsgs::ConsensusStat
6971
#[allow(clippy::fallible_impl_from)]
7072
impl From<IICS07TendermintMsgs::ConsensusState> for ICS07TendermintConsensusState {
7173
fn from(consensus_state: IICS07TendermintMsgs::ConsensusState) -> Self {
72-
let time =
73-
OffsetDateTime::from_unix_timestamp(consensus_state.timestamp.try_into().unwrap())
74-
.unwrap();
74+
let time = OffsetDateTime::from_unix_timestamp_nanos(
75+
consensus_state.timestamp.try_into().unwrap(),
76+
)
77+
.unwrap();
7578
let seconds = time.unix_timestamp();
7679
let nanos = time.nanosecond();
7780
Self {

packages/sp1-ics07-tendermint-prover/src/prover.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ where
164164
client_state: &SolClientState,
165165
trusted_consensus_state: &SolConsensusState,
166166
proposed_header: &Header,
167-
time: u64,
167+
time: u128,
168168
) -> SP1ProofWithPublicValues {
169169
// Encode the inputs into our program.
170170
let encoded_1 = client_state.abi_encode();
@@ -229,7 +229,7 @@ where
229229
client_state: &SolClientState,
230230
trusted_consensus_state: &SolConsensusState,
231231
proposed_header: &Header,
232-
time: u64,
232+
time: u128,
233233
kv_proofs: Vec<(KVPair, MerkleProof)>,
234234
) -> SP1ProofWithPublicValues {
235235
assert!(!kv_proofs.is_empty(), "No key-value pairs to prove");
@@ -271,7 +271,7 @@ where
271271
misbehaviour: &Misbehaviour,
272272
trusted_consensus_state_1: &SolConsensusState,
273273
trusted_consensus_state_2: &SolConsensusState,
274-
time: u64,
274+
time: u128,
275275
) -> SP1ProofWithPublicValues {
276276
let encoded_1 = client_state.abi_encode();
277277
let encoded_2 = misbehaviour.encode_to_vec();

programs/operator/src/runners/fixtures/misbehaviour.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -102,16 +102,13 @@ pub async fn run(args: MisbehaviourCmd) -> anyhow::Result<()> {
102102
let verify_misbehaviour_prover =
103103
SP1ICS07TendermintProver::<MisbehaviourProgram, _>::new(args.proof_type, &sp1_prover);
104104

105-
let now = std::time::SystemTime::now()
106-
.duration_since(std::time::UNIX_EPOCH)?
107-
.as_secs();
108-
105+
let now_since_unix = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH)?;
109106
let proof_data = verify_misbehaviour_prover.generate_proof(
110107
&trusted_client_state_2,
111108
&misbehaviour,
112109
&trusted_consensus_state_1,
113110
&trusted_consensus_state_2,
114-
now,
111+
now_since_unix.as_nanos(),
115112
);
116113

117114
let submit_msg = MsgSubmitMisbehaviour {

programs/operator/src/runners/fixtures/uc_and_mem.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,6 @@ pub async fn run(args: UpdateClientAndMembershipCmd) -> anyhow::Result<()> {
5757
SolConsensusState::abi_decode(&genesis.trusted_consensus_state, false)?.into();
5858

5959
let proposed_header = target_light_block.into_header(&trusted_light_block);
60-
let now = std::time::SystemTime::now()
61-
.duration_since(std::time::UNIX_EPOCH)?
62-
.as_secs();
6360

6461
let kv_proofs: Vec<(_, _)> =
6562
futures::future::try_join_all(args.membership.key_paths.into_iter().map(|path| async {
@@ -83,12 +80,13 @@ pub async fn run(args: UpdateClientAndMembershipCmd) -> anyhow::Result<()> {
8380
.await?;
8481

8582
let kv_len = kv_proofs.len();
83+
let now_since_unix = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH)?;
8684
// Generate a header update proof for the specified blocks.
8785
let proof_data = uc_mem_prover.generate_proof(
8886
&trusted_client_state,
8987
&trusted_consensus_state.into(),
9088
&proposed_header,
91-
now,
89+
now_since_unix.as_nanos(),
9290
kv_proofs,
9391
);
9492

0 commit comments

Comments
 (0)