Skip to content

Commit 64e7c90

Browse files
committed
Add more clippy rules
1 parent 281b2e7 commit 64e7c90

File tree

6 files changed

+89
-28
lines changed

6 files changed

+89
-28
lines changed

Cargo.toml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,45 @@ mockall = "0.13.1"
3737

3838
[profile.release]
3939
overflow-checks = true
40+
41+
[lints.rust]
42+
unsafe_code = "deny"
43+
44+
[lints.clippy]
45+
# See https://github.com/pyth-network/pyth-crosschain/blob/main/doc/rust-code-guidelines.md
46+
47+
wildcard_dependencies = "deny"
48+
49+
collapsible_if = "allow"
50+
collapsible_else_if = "allow"
51+
52+
allow_attributes_without_reason = "warn"
53+
54+
# Panics
55+
expect_used = "warn"
56+
fallible_impl_from = "warn"
57+
indexing_slicing = "warn"
58+
panic = "warn"
59+
panic_in_result_fn = "warn"
60+
string_slice = "warn"
61+
todo = "warn"
62+
unchecked_duration_subtraction = "warn"
63+
unreachable = "warn"
64+
unwrap_in_result = "warn"
65+
unwrap_used = "warn"
66+
67+
# Correctness
68+
cast_lossless = "warn"
69+
cast_possible_truncation = "warn"
70+
cast_possible_wrap = "warn"
71+
cast_sign_loss = "warn"
72+
collection_is_never_read = "warn"
73+
match_wild_err_arm = "warn"
74+
path_buf_push_overwrite = "warn"
75+
read_zero_byte_vec = "warn"
76+
same_name_method = "warn"
77+
suspicious_operation_groupings = "warn"
78+
suspicious_xor_used_as_pow = "warn"
79+
unused_self = "warn"
80+
used_underscore_binding = "warn"
81+
while_float = "warn"

clippy.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
allow-unwrap-in-tests = true
2+
allow-expect-in-tests = true
3+
allow-indexing-slicing-in-tests = true
4+
allow-panic-in-tests = true

src/api_client.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ mod tests {
148148
let digest = body.digest().expect("Failed to compute digest");
149149
let message = Message::from_digest(digest.secp256k_hash);
150150

151-
let recovery_id: RecoveryId = (observation.signature[64] as i32)
151+
let recovery_id: RecoveryId = i32::from(observation.signature[64])
152152
.try_into()
153153
.expect("Invalid recovery ID");
154154
let recoverable_sig =
@@ -194,7 +194,10 @@ mod tests {
194194
let message = parsed["body"].as_array().expect("Body should be an array");
195195
let bytes = message
196196
.iter()
197-
.map(|v| v.as_u64().expect("Body elements should be u64") as u8)
197+
.map(|v| {
198+
u8::try_from(v.as_u64().expect("Body elements should be u64"))
199+
.expect("Failed to convert to u8")
200+
})
198201
.collect::<Vec<u8>>();
199202
let deserialized: Body<&RawMessage> =
200203
serde_wormhole::from_slice(&bytes).expect("Failed to deserialize body");

src/main.rs

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use {
33
config::Command,
44
signer::{GuardianKey, Signer, GUARDIAN_KEY_ARMORED_BLOCK, STANDARD_ARMOR_LINE_HEADER},
55
},
6+
anyhow::Context,
67
api_client::{ApiClient, Observation},
78
borsh::BorshDeserialize,
89
clap::Parser,
@@ -215,27 +216,27 @@ async fn get_signer(run_options: config::RunOptions) -> anyhow::Result<Arc<dyn S
215216
}
216217
}
217218

218-
async fn run(run_options: config::RunOptions) {
219+
async fn run(run_options: config::RunOptions) -> anyhow::Result<()> {
219220
let signer = get_signer(run_options.clone())
220221
.await
221-
.expect("Failed to create signer");
222+
.context("Failed to create signer")?;
222223
let client = PubsubClient::new(&run_options.pythnet_url)
223224
.await
224-
.expect("Invalid WebSocket URL");
225+
.context("Invalid WebSocket URL")?;
225226
drop(client); // Drop the client to avoid holding the connection open
226227
let accumulator_address = Pubkey::from_str("G9LV2mp9ua1znRAfYwZz5cPiJMAbo1T6mbjdQsDZuMJg")
227-
.expect("Invalid accumulator address");
228+
.context("Invalid accumulator address")?;
228229
let wormhole_pid =
229-
Pubkey::from_str(&run_options.wormhole_pid).expect("Invalid Wormhole program ID");
230+
Pubkey::from_str(&run_options.wormhole_pid).context("Invalid Wormhole program ID")?;
230231
let api_clients: Vec<ApiClient> = run_options
231232
.server_urls
232233
.into_iter()
233-
.map(|server_url| {
234-
ApiClient::try_new(server_url, None).expect("Failed to create API client")
235-
})
236-
.collect();
234+
.map(|server_url| ApiClient::try_new(server_url, None))
235+
.collect::<anyhow::Result<Vec<_>>>()?;
237236

238-
let (pubkey, pubkey_evm) = signer.get_public_key().expect("Failed to get public key");
237+
let (pubkey, pubkey_evm) = signer
238+
.get_public_key()
239+
.context("Failed to get public key")?;
239240
let evm_encded_public_key = format!("0x{}", hex::encode(pubkey_evm));
240241
tracing::info!(
241242
public_key = ?pubkey,
@@ -260,7 +261,7 @@ async fn run(run_options: config::RunOptions) {
260261
}
261262

262263
#[tokio::main]
263-
async fn main() {
264+
async fn main() -> anyhow::Result<()> {
264265
// Initialize a Tracing Subscriber
265266
let fmt_builder = tracing_subscriber::fmt()
266267
.with_file(false)
@@ -272,24 +273,26 @@ async fn main() {
272273
// Use the compact formatter if we're in a terminal, otherwise use the JSON formatter.
273274
if std::io::stderr().is_terminal() {
274275
tracing::subscriber::set_global_default(fmt_builder.compact().finish())
275-
.expect("Failed to set global default subscriber");
276+
.context("Failed to set global default subscriber")?;
276277
} else {
277278
tracing::subscriber::set_global_default(fmt_builder.json().finish())
278-
.expect("Failed to set global default subscriber");
279+
.context("Failed to set global default subscriber")?;
279280
}
280281

281282
// Parse the command line arguments with StructOpt, will exit automatically on `--help` or
282283
// with invalid arguments.
283284
match Command::parse() {
284-
Command::Run(run_options) => run(run_options).await,
285+
Command::Run(run_options) => run(run_options).await?,
285286
Command::GenerateKey(opts) => {
286287
let secp = Secp256k1::new();
287288
let mut rng = OsRng;
288289

289290
// Generate keypair (secret + public key)
290291
let (secret_key, _) = secp.generate_keypair(&mut rng);
291292
let signer = signer::FileSigner { secret_key };
292-
let (pubkey, pubkey_evm) = signer.get_public_key().expect("Failed to get public key");
293+
let (pubkey, pubkey_evm) = signer
294+
.get_public_key()
295+
.context("Failed to get public key")?;
293296

294297
let guardian_key = GuardianKey {
295298
data: secret_key.secret_bytes().to_vec(),
@@ -300,24 +303,25 @@ async fn main() {
300303
Kind::SecretKey,
301304
vec![("PublicKey", format!("0x{}", hex::encode(pubkey_evm)))],
302305
)
303-
.expect("Failed to create writer");
306+
.context("Failed to create writer")?;
304307
writer
305308
.write_all(guardian_key.encode_to_vec().as_slice())
306-
.expect("Failed to write GuardianKey to writer");
307-
let buffer = writer.finalize().expect("Failed to finalize writer");
309+
.context("Failed to write GuardianKey to writer")?;
310+
let buffer = writer.finalize().context("Failed to finalize writer")?;
308311
let armored_string =
309-
String::from_utf8(buffer).expect("Failed to convert buffer to string");
312+
String::from_utf8(buffer).context("Failed to convert buffer to string")?;
310313
let armored_string =
311314
armored_string.replace(STANDARD_ARMOR_LINE_HEADER, GUARDIAN_KEY_ARMORED_BLOCK);
312315

313-
fs::write(&opts.output_path, armored_string)
314-
.expect("Failed to write GuardianKey to file");
316+
fs::write(&opts.output_path, armored_string).context("Failed to write key to file")?;
315317

316318
tracing::info!("Generated secret key at: {}", opts.output_path);
317319
tracing::info!("Public key: {}", pubkey);
318320
tracing::info!("EVM encoded public key: 0x{}", hex::encode(pubkey_evm));
319321
}
320322
}
323+
324+
Ok(())
321325
}
322326

323327
#[cfg(test)]

src/posted_message.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,9 @@ impl BorshDeserialize for PostedMessageUnreliableData {
7070
}
7171

7272
let expected = b"msu";
73-
let magic: &[u8] = &buf[0..3];
73+
let magic: &[u8] = buf
74+
.get(0..3)
75+
.ok_or(Error::new(InvalidData, "Failed to get magic bytes"))?;
7476
if magic != expected {
7577
return Err(Error::new(
7678
InvalidData,
@@ -80,7 +82,9 @@ impl BorshDeserialize for PostedMessageUnreliableData {
8082
),
8183
));
8284
};
83-
*buf = &buf[3..];
85+
*buf = buf
86+
.get(3..)
87+
.ok_or(Error::new(InvalidData, "Failed to get remaining bytes"))?;
8488
Ok(PostedMessageUnreliableData {
8589
message: <MessageData as BorshDeserialize>::deserialize(buf)?,
8690
})

src/signer.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,11 @@ fn get_evm_address(public_key: &PublicKey) -> anyhow::Result<[u8; 20]> {
8787
let pubkey_hash: [u8; 32] = Keccak256::new_with_prefix(&pubkey_uncompressed[1..])
8888
.finalize()
8989
.into();
90-
let pubkey_evm: [u8; 20] = pubkey_hash[pubkey_hash.len() - 20..]
90+
let pubkey_evm: [u8; 20] = pubkey_hash
91+
.get(pubkey_hash.len() - 20..)
92+
.ok_or(anyhow::anyhow!(
93+
"Failed to get EVM address from public key hash"
94+
))?
9195
.try_into()
9296
.map_err(|e| anyhow::anyhow!("Failed to convert public key hash to EVM format: {}", e))?;
9397
Ok(pubkey_evm)
@@ -102,7 +106,7 @@ impl Signer for FileSigner {
102106
let recovery_id: i32 = recovery_id.into();
103107
let mut signature = [0u8; 65];
104108
signature[..64].copy_from_slice(&signature_bytes);
105-
signature[64] = recovery_id as u8;
109+
signature[64] = u8::try_from(recovery_id)?;
106110
Ok(signature)
107111
}
108112

@@ -220,7 +224,7 @@ impl Signer for KMSSigner {
220224
if recovered_public_key == public_key.0 {
221225
let mut signature = [0u8; 65];
222226
signature[..64].copy_from_slice(&signature_bytes);
223-
signature[64] = raw_id as u8;
227+
signature[64] = u8::try_from(raw_id)?;
224228
return Ok(signature);
225229
}
226230
}

0 commit comments

Comments
 (0)