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
Branches
Tags
No related merge requests found
...@@ -26,25 +26,23 @@ pub trait ToBase58 { ...@@ -26,25 +26,23 @@ pub trait ToBase58 {
/// Create an array of 32 bytes from a Base58 string. /// Create an array of 32 bytes from a Base58 string.
pub fn str_base58_to_32bytes(base58_data: &str) -> Result<([u8; 32], usize), BaseConvertionError> { pub fn str_base58_to_32bytes(base58_data: &str) -> Result<([u8; 32], usize), BaseConvertionError> {
let mut source = base58_data; let mut source = base58_data;
let mut count_leading_1 = 0;
while !source.is_empty() && &source[0..1] == "1" { while !source.is_empty() && &source[0..1] == "1" {
source = &source[1..]; source = &source[1..];
count_leading_1 += 1;
} }
match bs58::decode(source).into_vec() { match bs58::decode(source).into_vec() {
Ok(result) => { Ok(result) => {
let len = result.len(); let mut len = result.len();
if len <= 32 { if len > 32 {
len = 32;
}
let mut u8_array = [0; 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)) Ok((u8_array, count_leading_1))
} else {
Err(BaseConvertionError::InvalidLength {
expected: 32,
found: len,
})
}
} }
Err(bs58::decode::Error::InvalidCharacter { character, index }) => { Err(bs58::decode::Error::InvalidCharacter { character, index }) => {
Err(BaseConvertionError::InvalidCharacter { Err(BaseConvertionError::InvalidCharacter {
...@@ -60,8 +58,56 @@ pub fn str_base58_to_32bytes(base58_data: &str) -> Result<([u8; 32], usize), Bas ...@@ -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. /// Create a Base58 string from a slice of bytes.
pub fn bytes_to_str_base58(bytes: &[u8]) -> String { pub fn bytes_to_str_base58(bytes: &[u8], mut count_leading_1: usize) -> String {
bs58::encode(bytes).into_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. /*/// Create an array of 64bytes from a Base58 string.
......
...@@ -159,21 +159,21 @@ impl Eq for Signature {} ...@@ -159,21 +159,21 @@ impl Eq for Signature {}
#[derive(Copy, Clone, PartialEq, Eq, Hash)] #[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct PublicKey { pub struct PublicKey {
datas: [u8; 32], datas: [u8; 32],
len: usize, count_leading_zero: usize,
} }
impl Default for PublicKey { impl Default for PublicKey {
fn default() -> Self { fn default() -> Self {
PublicKey { PublicKey {
datas: [0u8; 32], datas: [0u8; 32],
len: 0, count_leading_zero: 32,
} }
} }
} }
impl AsRef<[u8]> for PublicKey { impl AsRef<[u8]> for PublicKey {
fn as_ref(&self) -> &[u8] { fn as_ref(&self) -> &[u8] {
&self.datas[..self.len] &self.datas[..]
} }
} }
...@@ -187,11 +187,11 @@ impl TryFrom<&[u8]> for PublicKey { ...@@ -187,11 +187,11 @@ impl TryFrom<&[u8]> for PublicKey {
found: bytes.len(), found: bytes.len(),
}) })
} else { } else {
let mut u8_array = [0; 32]; let mut u8_array = [0; PUBKEY_SIZE_IN_BYTES];
u8_array[..bytes.len()].copy_from_slice(&bytes); u8_array[(PUBKEY_SIZE_IN_BYTES - bytes.len())..].copy_from_slice(&bytes);
Ok(PublicKey { Ok(PublicKey {
datas: u8_array, datas: u8_array,
len: bytes.len(), count_leading_zero: 0,
}) })
} }
} }
...@@ -199,13 +199,17 @@ impl TryFrom<&[u8]> for PublicKey { ...@@ -199,13 +199,17 @@ impl TryFrom<&[u8]> for PublicKey {
impl ToBase58 for PublicKey { impl ToBase58 for PublicKey {
fn to_base58(&self) -> String { 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 { impl Display for PublicKey {
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> { 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 { ...@@ -221,8 +225,11 @@ impl super::PublicKey for PublicKey {
#[inline] #[inline]
fn from_base58(base58_data: &str) -> Result<Self, BaseConvertionError> { fn from_base58(base58_data: &str) -> Result<Self, BaseConvertionError> {
let (datas, len) = b58::str_base58_to_32bytes(base58_data)?; let (datas, count_leading_zero) = b58::str_base58_to_32bytes(base58_data)?;
Ok(PublicKey { datas, len }) Ok(PublicKey {
datas,
count_leading_zero,
})
} }
fn to_bytes_vector(&self) -> Vec<u8> { fn to_bytes_vector(&self) -> Vec<u8> {
...@@ -447,13 +454,6 @@ mod tests { ...@@ -447,13 +454,6 @@ mod tests {
assert!(!seed.eq(&other_seed)); assert!(!seed.eq(&other_seed));
// Test seed parsing // Test seed parsing
assert_eq!(
Seed32::from_base58("DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLVgth",).unwrap_err(),
BaseConvertionError::InvalidLength {
found: 35,
expected: 32
}
);
/*assert_eq!( /*assert_eq!(
Seed32::from_base58("DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQd",).unwrap_err(), Seed32::from_base58("DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQd",).unwrap_err(),
BaseConvertionError::InvalidLength { BaseConvertionError::InvalidLength {
...@@ -468,22 +468,6 @@ mod tests { ...@@ -468,22 +468,6 @@ mod tests {
offset: 42 offset: 42
} }
); );
assert_eq!(
Seed32::from_base58(
"\
DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV\
DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV\
DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV\
DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV\
DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV\
"
)
.unwrap_err(),
BaseConvertionError::InvalidLength {
expected: 32,
found: 161
}
);
} }
#[test] #[test]
...@@ -527,22 +511,6 @@ mod tests { ...@@ -527,22 +511,6 @@ mod tests {
offset: 42 offset: 42
} }
); );
assert_eq!(
super::PublicKey::from_base58(
"\
DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV\
DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV\
DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV\
DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV\
DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV\
"
)
.unwrap_err(),
BaseConvertionError::InvalidLength {
expected: 32,
found: 161
}
);
} }
#[test] #[test]
......
...@@ -507,10 +507,11 @@ mod tests { ...@@ -507,10 +507,11 @@ mod tests {
#[test] #[test]
fn pubkey() { fn pubkey() {
let pubkey_default = PubKey::default(); let ed25519_pubkey_default = ed25519::PublicKey::default();
let pubkey_bytes = []; let pubkey_default = PubKey::Ed25519(ed25519_pubkey_default);
let pubkey = PubKey::Ed25519(unwrap!(ed25519::PublicKey::try_from(&pubkey_bytes[..]))); let pubkey = PubKey::Ed25519(unwrap!(ed25519::PublicKey::try_from(
assert_eq!(pubkey_default, pubkey); ed25519_pubkey_default.as_ref()
)));
let pubkey_str_b58 = "11111111111111111111111111111111".to_owned(); let pubkey_str_b58 = "11111111111111111111111111111111".to_owned();
assert_eq!( assert_eq!(
...@@ -519,14 +520,14 @@ mod tests { ...@@ -519,14 +520,14 @@ mod tests {
); );
assert_eq!(pubkey.size_in_bytes(), ed25519::PUBKEY_SIZE_IN_BYTES + 3); 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::Ed25519, pubkey.algo());
assert_eq!(KeysAlgo::Schnorr, PubKey::Schnorr().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!( assert_eq!(
Err(SigError::InvalidSig), Err(SigError::InvalidSig),
...@@ -548,7 +549,7 @@ mod tests { ...@@ -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, 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, 0, 0, 0, 0,
]; ];
let seed_str_b58 = "11111111111111111111111111111111".to_owned(); let seed_str_b58 = "1111111111111111111111111111111".to_owned();
let seed = Seed32::new(seed_bytes); let seed = Seed32::new(seed_bytes);
assert_eq!(seed_default, seed); assert_eq!(seed_default, seed);
...@@ -557,7 +558,7 @@ mod tests { ...@@ -557,7 +558,7 @@ mod tests {
Seed32::from_base58(&seed_str_b58).expect("Fail to parse seed !") 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()); assert_eq!(seed_str_b58, seed.to_base58());
} }
...@@ -725,9 +726,5 @@ mod tests { ...@@ -725,9 +726,5 @@ mod tests {
23, 24, 25, 26, 27, 28, 29, 30, 31, 31 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 { ...@@ -38,7 +38,7 @@ impl AsRef<[u8]> for Seed32 {
impl ToBase58 for Seed32 { impl ToBase58 for Seed32 {
fn to_base58(&self) -> String { 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