Add util functions for bytes32 string encoding/decoding (#337)
This commit is contained in:
parent
330b62c986
commit
4afa1c9517
|
@ -808,6 +808,7 @@ dependencies = [
|
||||||
"generic-array 0.14.4",
|
"generic-array 0.14.4",
|
||||||
"glob",
|
"glob",
|
||||||
"hex",
|
"hex",
|
||||||
|
"hex-literal",
|
||||||
"k256",
|
"k256",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"rand 0.8.4",
|
"rand 0.8.4",
|
||||||
|
@ -1174,6 +1175,12 @@ version = "0.4.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hex-literal"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "76505e26b6ca3bbdbbb360b68472abbb80998c5fa5dc43672eca34f28258e138"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hidapi"
|
name = "hidapi"
|
||||||
version = "1.2.6"
|
version = "1.2.6"
|
||||||
|
|
|
@ -44,7 +44,7 @@ ethers = { version = "0.4.0", path = "../ethers" }
|
||||||
serde_json = { version = "1.0.64", default-features = false }
|
serde_json = { version = "1.0.64", default-features = false }
|
||||||
bincode = { version = "1.3.3", default-features = false }
|
bincode = { version = "1.3.3", default-features = false }
|
||||||
once_cell = { version = "1.8.0" }
|
once_cell = { version = "1.8.0" }
|
||||||
|
hex-literal = "0.3.2"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
celo = [] # celo support extends the transaction format with extra fields
|
celo = [] # celo support extends the transaction format with extra fields
|
||||||
|
|
|
@ -36,6 +36,13 @@ pub use rlp;
|
||||||
use crate::types::{Address, Bytes, U256};
|
use crate::types::{Address, Bytes, U256};
|
||||||
use k256::{ecdsa::SigningKey, EncodedPoint as K256PublicKey};
|
use k256::{ecdsa::SigningKey, EncodedPoint as K256PublicKey};
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
pub enum FormatBytes32StringError {
|
||||||
|
#[error("bytes32 strings must not exceed 32 bytes in length")]
|
||||||
|
TextTooLong,
|
||||||
|
}
|
||||||
|
|
||||||
/// 1 Ether = 1e18 Wei == 0x0de0b6b3a7640000 Wei
|
/// 1 Ether = 1e18 Wei == 0x0de0b6b3a7640000 Wei
|
||||||
pub const WEI_IN_ETHER: U256 = U256([0x0de0b6b3a7640000, 0x0, 0x0, 0x0]);
|
pub const WEI_IN_ETHER: U256 = U256([0x0de0b6b3a7640000, 0x0, 0x0, 0x0]);
|
||||||
|
@ -156,6 +163,30 @@ pub fn to_checksum(addr: &Address, chain_id: Option<u8>) -> String {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a bytes32 string representation of text. If the length of text exceeds 32 bytes,
|
||||||
|
/// an error is returned.
|
||||||
|
pub fn format_bytes32_string(text: &str) -> Result<[u8; 32], FormatBytes32StringError> {
|
||||||
|
let str_bytes: &[u8] = text.as_bytes();
|
||||||
|
if str_bytes.len() > 32 {
|
||||||
|
return Err(FormatBytes32StringError::TextTooLong);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut bytes32: [u8; 32] = [0u8; 32];
|
||||||
|
bytes32[..str_bytes.len()].copy_from_slice(str_bytes);
|
||||||
|
|
||||||
|
Ok(bytes32)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the decoded string represented by the bytes32 encoded data.
|
||||||
|
pub fn parse_bytes32_string(bytes: &[u8; 32]) -> Result<&str, std::str::Utf8Error> {
|
||||||
|
let mut length = 0;
|
||||||
|
while length < 32 && bytes[length] != 0 {
|
||||||
|
length += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::str::from_utf8(&bytes[..length])
|
||||||
|
}
|
||||||
|
|
||||||
/// A bit of hack to find an unused TCP port.
|
/// A bit of hack to find an unused TCP port.
|
||||||
///
|
///
|
||||||
/// Does not guarantee that the given port is unused after the function exists, just that it was
|
/// Does not guarantee that the given port is unused after the function exists, just that it was
|
||||||
|
@ -173,6 +204,7 @@ pub(crate) fn unused_port() -> u16 {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use hex_literal::hex;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn wei_in_ether() {
|
fn wei_in_ether() {
|
||||||
|
@ -359,4 +391,64 @@ mod tests {
|
||||||
assert_eq!(expected, get_create2_address(from, salt, init_code))
|
assert_eq!(expected, get_create2_address(from, salt, init_code))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn bytes32_string_parsing() {
|
||||||
|
let text_bytes_list = vec![
|
||||||
|
(
|
||||||
|
"",
|
||||||
|
hex!("0000000000000000000000000000000000000000000000000000000000000000"),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"A",
|
||||||
|
hex!("4100000000000000000000000000000000000000000000000000000000000000"),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZ012345",
|
||||||
|
hex!("4142434445464748494a4b4c4d4e4f505152535455565758595a303132333435"),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"!@#$%^&*(),./;'[]",
|
||||||
|
hex!("21402324255e262a28292c2e2f3b275b5d000000000000000000000000000000"),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
for (text, bytes) in text_bytes_list {
|
||||||
|
assert_eq!(text, parse_bytes32_string(&bytes).unwrap());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn bytes32_string_formatting() {
|
||||||
|
let text_bytes_list = vec![
|
||||||
|
(
|
||||||
|
"",
|
||||||
|
hex!("0000000000000000000000000000000000000000000000000000000000000000"),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"A",
|
||||||
|
hex!("4100000000000000000000000000000000000000000000000000000000000000"),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZ012345",
|
||||||
|
hex!("4142434445464748494a4b4c4d4e4f505152535455565758595a303132333435"),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"!@#$%^&*(),./;'[]",
|
||||||
|
hex!("21402324255e262a28292c2e2f3b275b5d000000000000000000000000000000"),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
for (text, bytes) in text_bytes_list {
|
||||||
|
assert_eq!(bytes, format_bytes32_string(text).unwrap());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn bytes32_string_formatting_too_long() {
|
||||||
|
assert!(matches!(
|
||||||
|
format_bytes32_string("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456").unwrap_err(),
|
||||||
|
FormatBytes32StringError::TextTooLong
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue