Skip to content
Snippets Groups Projects
Commit 003926dd authored by Éloïs's avatar Éloïs
Browse files

[fix] base58: handle leading zero

parent 7dd9af14
No related branches found
No related tags found
1 merge request!7[fix] base58: handle leading zero
Pipeline #8251 passed
......@@ -26,25 +26,23 @@ pub trait ToBase58 {
/// Create an array of 32 bytes from a Base58 string.
pub fn str_base58_to_32bytes(base58_data: &str) -> Result<([u8; 32], usize), BaseConvertionError> {
let mut source = base58_data;
let mut count_leading_1 = 0;
while !source.is_empty() && &source[0..1] == "1" {
source = &source[1..];
count_leading_1 += 1;
}
match bs58::decode(source).into_vec() {
Ok(result) => {
let len = result.len();
if len <= 32 {
let mut len = result.len();
if len > 32 {
len = 32;
}
let mut u8_array = [0; 32];
u8_array[..len].clone_from_slice(&result[..len]);
u8_array[(32 - len)..].clone_from_slice(&result[..len]);
Ok((u8_array, len))
} else {
Err(BaseConvertionError::InvalidLength {
expected: 32,
found: len,
})
}
Ok((u8_array, count_leading_1))
}
Err(bs58::decode::Error::InvalidCharacter { character, index }) => {
Err(BaseConvertionError::InvalidCharacter {
......@@ -60,8 +58,56 @@ pub fn str_base58_to_32bytes(base58_data: &str) -> Result<([u8; 32], usize), Bas
}
/// Create a Base58 string from a slice of bytes.
pub fn bytes_to_str_base58(bytes: &[u8]) -> String {
bs58::encode(bytes).into_string()
pub fn bytes_to_str_base58(bytes: &[u8], mut count_leading_1: usize) -> String {
let mut str_base58 = String::new();
let bytes = &bytes[count_leading_1..];
let bytes = if count_leading_1 == 0 && !bytes.is_empty() && bytes[0] == 0 {
&bytes[1..]
} else {
while count_leading_1 > 0 {
count_leading_1 -= 1;
str_base58.push('1');
}
&bytes[count_leading_1..]
};
str_base58.push_str(&bs58::encode(bytes).into_string());
str_base58
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_base_58_str_with_leading_1() -> Result<(), BaseConvertionError> {
let base58str = "1V27SH9TiVEDs8TWFPydpRKxhvZari7wjGwQnPxMnkr";
let (bytes, count_leading_1) = str_base58_to_32bytes(base58str)?;
println!("{:?}", bytes);
assert_eq!(base58str, &bytes_to_str_base58(&bytes[..], count_leading_1),);
Ok(())
}
#[test]
fn test_base_58_str_with_43_char() -> Result<(), BaseConvertionError> {
let base58str = "2nV7Dv4nhTJ9dZUvRJpL34vFP9b2BkDjKWv9iBW2JaR";
let (bytes, count_leading_1) = str_base58_to_32bytes(base58str)?;
println!("{}", count_leading_1);
println!("{:?}", bytes);
assert_eq!(base58str, &bytes_to_str_base58(&bytes[..], count_leading_1),);
Ok(())
}
}
/*/// Create an array of 64bytes from a Base58 string.
......
......@@ -159,21 +159,21 @@ impl Eq for Signature {}
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct PublicKey {
datas: [u8; 32],
len: usize,
count_leading_zero: usize,
}
impl Default for PublicKey {
fn default() -> Self {
PublicKey {
datas: [0u8; 32],
len: 0,
count_leading_zero: 32,
}
}
}
impl AsRef<[u8]> for PublicKey {
fn as_ref(&self) -> &[u8] {
&self.datas[..self.len]
&self.datas[..]
}
}
......@@ -187,11 +187,11 @@ impl TryFrom<&[u8]> for PublicKey {
found: bytes.len(),
})
} else {
let mut u8_array = [0; 32];
u8_array[..bytes.len()].copy_from_slice(&bytes);
let mut u8_array = [0; PUBKEY_SIZE_IN_BYTES];
u8_array[(PUBKEY_SIZE_IN_BYTES - bytes.len())..].copy_from_slice(&bytes);
Ok(PublicKey {
datas: u8_array,
len: bytes.len(),
count_leading_zero: 0,
})
}
}
......@@ -199,13 +199,17 @@ impl TryFrom<&[u8]> for PublicKey {
impl ToBase58 for PublicKey {
fn to_base58(&self) -> String {
bytes_to_str_base58(self.as_ref())
bytes_to_str_base58(self.as_ref(), self.count_leading_zero)
}
}
impl Display for PublicKey {
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
write!(f, "{}", bytes_to_str_base58(self.as_ref()))
write!(
f,
"{}",
bytes_to_str_base58(self.as_ref(), self.count_leading_zero)
)
}
}
......@@ -221,8 +225,11 @@ impl super::PublicKey for PublicKey {
#[inline]
fn from_base58(base58_data: &str) -> Result<Self, BaseConvertionError> {
let (datas, len) = b58::str_base58_to_32bytes(base58_data)?;
Ok(PublicKey { datas, len })
let (datas, count_leading_zero) = b58::str_base58_to_32bytes(base58_data)?;
Ok(PublicKey {
datas,
count_leading_zero,
})
}
fn to_bytes_vector(&self) -> Vec<u8> {
......@@ -447,13 +454,6 @@ mod tests {
assert!(!seed.eq(&other_seed));
// Test seed parsing
assert_eq!(
Seed32::from_base58("DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLVgth",).unwrap_err(),
BaseConvertionError::InvalidLength {
found: 35,
expected: 32
}
);
/*assert_eq!(
Seed32::from_base58("DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQd",).unwrap_err(),
BaseConvertionError::InvalidLength {
......@@ -468,22 +468,6 @@ mod tests {
offset: 42
}
);
assert_eq!(
Seed32::from_base58(
"\
DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV\
DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV\
DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV\
DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV\
DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV\
"
)
.unwrap_err(),
BaseConvertionError::InvalidLength {
expected: 32,
found: 161
}
);
}
#[test]
......@@ -527,22 +511,6 @@ mod tests {
offset: 42
}
);
assert_eq!(
super::PublicKey::from_base58(
"\
DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV\
DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV\
DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV\
DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV\
DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV\
"
)
.unwrap_err(),
BaseConvertionError::InvalidLength {
expected: 32,
found: 161
}
);
}
#[test]
......
......@@ -507,10 +507,11 @@ mod tests {
#[test]
fn pubkey() {
let pubkey_default = PubKey::default();
let pubkey_bytes = [];
let pubkey = PubKey::Ed25519(unwrap!(ed25519::PublicKey::try_from(&pubkey_bytes[..])));
assert_eq!(pubkey_default, pubkey);
let ed25519_pubkey_default = ed25519::PublicKey::default();
let pubkey_default = PubKey::Ed25519(ed25519_pubkey_default);
let pubkey = PubKey::Ed25519(unwrap!(ed25519::PublicKey::try_from(
ed25519_pubkey_default.as_ref()
)));
let pubkey_str_b58 = "11111111111111111111111111111111".to_owned();
assert_eq!(
......@@ -519,14 +520,14 @@ mod tests {
);
assert_eq!(pubkey.size_in_bytes(), ed25519::PUBKEY_SIZE_IN_BYTES + 3);
assert_eq!("", &format!("{}", pubkey));
assert_eq!("1111111111111111111111111111111", &format!("{}", pubkey));
assert_eq!(KeysAlgo::Ed25519, pubkey.algo());
assert_eq!(KeysAlgo::Schnorr, PubKey::Schnorr().algo());
assert_eq!(pubkey_bytes.to_vec(), pubkey.to_bytes_vector());
assert_eq!([0u8; 32].to_vec(), pubkey.to_bytes_vector());
assert_eq!("", &pubkey.to_base58());
assert_eq!("1111111111111111111111111111111", &pubkey.to_base58());
assert_eq!(
Err(SigError::InvalidSig),
......@@ -548,7 +549,7 @@ mod tests {
0u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0,
];
let seed_str_b58 = "11111111111111111111111111111111".to_owned();
let seed_str_b58 = "1111111111111111111111111111111".to_owned();
let seed = Seed32::new(seed_bytes);
assert_eq!(seed_default, seed);
......@@ -557,7 +558,7 @@ mod tests {
Seed32::from_base58(&seed_str_b58).expect("Fail to parse seed !")
);
assert_eq!(seed_str_b58, format!("{}", seed));
assert_eq!("1111111111111111111111111111111", format!("{}", seed));
assert_eq!(seed_str_b58, seed.to_base58());
}
......@@ -725,9 +726,5 @@ mod tests {
23, 24, 25, 26, 27, 28, 29, 30, 31, 31
]),
);
assert_eq!(
Ok(PubKey::Ed25519(ed25519::PublicKey::default())),
PubKey::from_bytes(&[]),
);
}
}
......@@ -38,7 +38,7 @@ impl AsRef<[u8]> for Seed32 {
impl ToBase58 for Seed32 {
fn to_base58(&self) -> String {
bytes_to_str_base58(&self.0[..])
bytes_to_str_base58(&self.0[..], 0)
}
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment