Skip to content

Commit a159525

Browse files
committed
fix(node): use array for handshake commit hashes
1 parent 0f7d2f9 commit a159525

File tree

4 files changed

+51
-35
lines changed

4 files changed

+51
-35
lines changed

node/bft/events/src/challenge_request.rs

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,25 +16,31 @@
1616
use super::*;
1717

1818
use snarkos_node_network::built_info;
19+
use snarkvm::prelude::{FromBytes, ToBytes, io_error};
20+
21+
use std::borrow::Cow;
1922

2023
#[derive(Clone, Debug, PartialEq, Eq)]
2124
pub struct ChallengeRequest<N: Network> {
2225
pub version: u32,
2326
pub listener_port: u16,
2427
pub address: Address<N>,
2528
pub nonce: u64,
26-
pub snarkos_sha: String,
29+
pub snarkos_sha: [u8; 40],
2730
}
2831

2932
impl<N: Network> ChallengeRequest<N> {
30-
/// Creates a new `ChallengeRequest` event.
33+
pub const UNKNOWN_SHA: [u8; 40] = snarkos_node_network::UNKNOWN_SHA;
34+
3135
pub fn new(listener_port: u16, address: Address<N>, nonce: u64) -> Self {
3236
Self {
3337
version: Event::<N>::VERSION,
3438
listener_port,
3539
address,
3640
nonce,
37-
snarkos_sha: built_info::GIT_COMMIT_HASH.unwrap_or_default().into(),
41+
snarkos_sha: built_info::GIT_COMMIT_HASH
42+
.and_then(|s| s.as_bytes().try_into().ok())
43+
.unwrap_or(Self::UNKNOWN_SHA),
3844
}
3945
}
4046
}
@@ -48,27 +54,25 @@ impl<N: Network> EventTrait for ChallengeRequest<N> {
4854
}
4955

5056
impl<N: Network> ToBytes for ChallengeRequest<N> {
51-
fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
57+
fn write_le<W: Write>(&self, mut writer: W) -> io::Result<()> {
5258
self.version.write_le(&mut writer)?;
5359
self.listener_port.write_le(&mut writer)?;
5460
self.address.write_le(&mut writer)?;
5561
self.nonce.write_le(&mut writer)?;
56-
self.snarkos_sha.as_bytes().write_le(&mut writer)?;
62+
self.snarkos_sha.write_le(&mut writer)?;
5763

5864
Ok(())
5965
}
6066
}
6167

6268
impl<N: Network> FromBytes for ChallengeRequest<N> {
63-
fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
69+
fn read_le<R: Read>(mut reader: R) -> io::Result<Self> {
6470
let version = u32::read_le(&mut reader)?;
6571
let listener_port = u16::read_le(&mut reader)?;
6672
let address = Address::<N>::read_le(&mut reader)?;
6773
let nonce = u64::read_le(&mut reader)?;
68-
let snarkos_sha = str::from_utf8(&<[u8; 40]>::read_le(&mut reader).unwrap_or([b'?'; 40])[..])
69-
.map(|str| if str.starts_with('?') { "unknown" } else { str })
70-
.map_err(|_| error("Invalid snarkOS SHA"))?
71-
.to_owned();
74+
let snarkos_sha =
75+
<[u8; 40]>::read_le(&mut reader).map_err(|err| io_error(format!("Invalid snarkOS SHA - {err}")))?;
7276

7377
Ok(Self { version, listener_port, address, nonce, snarkos_sha })
7478
}
@@ -102,21 +106,21 @@ pub mod prop_tests {
102106
nonce,
103107
version,
104108
listener_port,
105-
snarkos_sha: sha.into_iter().map(|b| b as char).collect(),
109+
snarkos_sha: sha.try_into().unwrap(),
106110
})
107111
.boxed()
108112
}
109113

110114
#[proptest]
111-
fn serialize_deserialize(#[strategy(any_challenge_request())] original: ChallengeRequest<CurrentNetwork>) {
115+
fn challenge_request_roundtrip(#[strategy(any_challenge_request())] original: ChallengeRequest<CurrentNetwork>) {
112116
let mut buf = BytesMut::default().writer();
113117
ChallengeRequest::write_le(&original, &mut buf).unwrap();
114118

115119
let mut deserialized: ChallengeRequest<CurrentNetwork> =
116120
ChallengeRequest::read_le(buf.into_inner().reader()).unwrap();
117121
// Upon deserialization, unsupplied SHA is registered as "unknown".
118-
if deserialized.snarkos_sha == "unknown" {
119-
deserialized.snarkos_sha = original.snarkos_sha.clone();
122+
if deserialized.snarkos_sha == snarkos_node_network::UNKNOWN_SHA {
123+
deserialized.snarkos_sha = original.snarkos_sha;
120124
}
121125
assert_eq!(original, deserialized);
122126
}

node/bft/tests/gateway_e2e.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ async fn handshake_responder_side_invalid_challenge_request() {
110110
let listener_port = test_peer.listening_addr().port();
111111
let address = accounts.get(1).unwrap().address();
112112
let nonce = rng.r#gen();
113-
let snarkos_sha = String::new();
113+
let snarkos_sha = ChallengeRequest::<CurrentNetwork>::UNKNOWN_SHA;
114114
// Set the wrong version so the challenge request is invalid.
115115
let challenge_request = ChallengeRequest { version: 0, listener_port, address, nonce, snarkos_sha };
116116

@@ -150,7 +150,7 @@ async fn handshake_responder_side_invalid_challenge_response() {
150150
let listener_port = test_peer.listening_addr().port();
151151
let address = accounts.get(1).unwrap().address();
152152
let our_nonce = rng.r#gen();
153-
let snarkos_sha = String::new();
153+
let snarkos_sha = ChallengeRequest::<CurrentNetwork>::UNKNOWN_SHA;
154154
let version = Event::<CurrentNetwork>::VERSION;
155155
let challenge_request = ChallengeRequest { version, listener_port, address, nonce: our_nonce, snarkos_sha };
156156

node/network/src/lib.rs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ pub mod built_info {
3737
include!(concat!(env!("OUT_DIR"), "/built.rs"));
3838
}
3939

40+
/// Constant for an unknown commit hash.
41+
pub const UNKNOWN_SHA: [u8; 40] = [b'?'; 40];
42+
4043
/// Returns the list of bootstrap peers.
4144
#[allow(clippy::if_same_then_else)]
4245
pub fn bootstrap_peers<N: Network>(is_dev: bool) -> Vec<SocketAddr> {
@@ -80,16 +83,23 @@ pub fn bootstrap_peers<N: Network>(is_dev: bool) -> Vec<SocketAddr> {
8083
}
8184

8285
/// Logs the peer's snarkOS repo SHA and how it compares to ours.
83-
pub fn log_repo_sha_comparison(peer_addr: SocketAddr, peer_sha: &str, ctx: &str) {
84-
let our_sha = built_info::GIT_COMMIT_HASH.unwrap_or_default();
85-
let sha_cmp = if peer_sha == "unknown" {
86+
pub fn log_repo_sha_comparison(peer_addr: SocketAddr, peer_sha: &[u8; 40], ctx: &str) {
87+
// Get our SHA from the build information (or None if it is not set or does not 40 bytes long).
88+
let our_sha: Option<[u8; 40]> = built_info::GIT_COMMIT_HASH.and_then(|sha| sha.as_bytes().try_into().ok());
89+
let peer_sha_str = str::from_utf8(peer_sha).unwrap_or("");
90+
91+
let sha_cmp = if peer_sha == &UNKNOWN_SHA || peer_sha_str.is_empty() {
92+
// Handle the case where the peer send no or an invalid SHA.
8693
" with an unknown repo SHA".to_owned()
87-
} else if peer_sha == our_sha {
88-
format!("@{peer_sha} (same as us)")
89-
} else if our_sha.is_empty() {
90-
format!("@{peer_sha} (potentially different than us)")
94+
} else if let Some(our_sha) = &our_sha {
95+
if peer_sha == our_sha {
96+
format!("@{peer_sha_str} (same as us)")
97+
} else {
98+
format!("@{peer_sha_str} (different than us)")
99+
}
91100
} else {
92-
format!("@{peer_sha} (different than us)")
101+
// Handle the case where our SHA is unknown.
102+
format!("@{peer_sha_str} (potentially different than us)")
93103
};
94104

95105
debug!("{ctx} Peer '{peer_addr}' uses snarkOS{sha_cmp}");

node/router/messages/src/challenge_request.rs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
use super::*;
1717

1818
use snarkos_node_network::{NodeType, built_info};
19-
use snarkvm::prelude::{FromBytes, ToBytes};
19+
use snarkvm::prelude::{FromBytes, ToBytes, io_error};
2020

2121
use std::borrow::Cow;
2222

@@ -27,7 +27,7 @@ pub struct ChallengeRequest<N: Network> {
2727
pub node_type: NodeType,
2828
pub address: Address<N>,
2929
pub nonce: u64,
30-
pub snarkos_sha: String,
30+
pub snarkos_sha: [u8; 40],
3131
}
3232

3333
impl<N: Network> MessageTrait for ChallengeRequest<N> {
@@ -45,7 +45,7 @@ impl<N: Network> ToBytes for ChallengeRequest<N> {
4545
self.node_type.write_le(&mut writer)?;
4646
self.address.write_le(&mut writer)?;
4747
self.nonce.write_le(&mut writer)?;
48-
self.snarkos_sha.as_bytes().write_le(&mut writer)?;
48+
self.snarkos_sha.write_le(&mut writer)?;
4949

5050
Ok(())
5151
}
@@ -58,24 +58,26 @@ impl<N: Network> FromBytes for ChallengeRequest<N> {
5858
let node_type = NodeType::read_le(&mut reader)?;
5959
let address = Address::<N>::read_le(&mut reader)?;
6060
let nonce = u64::read_le(&mut reader)?;
61-
let snarkos_sha = str::from_utf8(&<[u8; 40]>::read_le(&mut reader).unwrap_or([b'?'; 40])[..])
62-
.map(|str| if str.starts_with('?') { "unknown" } else { str })
63-
.map_err(|_| error("Invalid snarkOS SHA"))?
64-
.to_owned();
61+
let snarkos_sha =
62+
<[u8; 40]>::read_le(&mut reader).map_err(|err| io_error(format!("Invalid snarkOS SHA - {err}")))?;
6563

6664
Ok(Self { version, listener_port, node_type, address, nonce, snarkos_sha })
6765
}
6866
}
6967

7068
impl<N: Network> ChallengeRequest<N> {
69+
pub const UNKNOWN_SHA: [u8; 40] = snarkos_node_network::UNKNOWN_SHA;
70+
7171
pub fn new(listener_port: u16, node_type: NodeType, address: Address<N>, nonce: u64) -> Self {
7272
Self {
7373
version: Message::<N>::latest_message_version(),
7474
listener_port,
7575
node_type,
7676
address,
7777
nonce,
78-
snarkos_sha: built_info::GIT_COMMIT_HASH.unwrap_or_default().into(),
78+
snarkos_sha: built_info::GIT_COMMIT_HASH
79+
.and_then(|s| s.as_bytes().try_into().ok())
80+
.unwrap_or(Self::UNKNOWN_SHA),
7981
}
8082
}
8183
}
@@ -121,7 +123,7 @@ pub mod prop_tests {
121123
version,
122124
listener_port,
123125
node_type,
124-
snarkos_sha: sha.into_iter().map(|b| b as char).collect(),
126+
snarkos_sha: sha.try_into().unwrap(),
125127
})
126128
.boxed()
127129
}
@@ -134,8 +136,8 @@ pub mod prop_tests {
134136
let mut deserialized: ChallengeRequest<CurrentNetwork> =
135137
ChallengeRequest::read_le(buf.into_inner().reader()).unwrap();
136138
// Upon deserialization, unsupplied SHA is registered as "unknown".
137-
if deserialized.snarkos_sha == "unknown" {
138-
deserialized.snarkos_sha = original.snarkos_sha.clone();
139+
if deserialized.snarkos_sha == snarkos_node_network::UNKNOWN_SHA {
140+
deserialized.snarkos_sha = original.snarkos_sha;
139141
}
140142
assert_eq!(original, deserialized);
141143
}

0 commit comments

Comments
 (0)