address.rs 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. use std::str::FromStr;
  2. use darkfi_serial::{SerialDecodable, SerialEncodable};
  3. use sha2::Digest;
  4. use crate::{crypto::keypair::PublicKey, Error, Result};
  5. enum AddressType {
  6. Payment = 0,
  7. }
  8. #[derive(
  9. Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Hash, SerialEncodable, SerialDecodable,
  10. )]
  11. pub struct Address(pub [u8; 37]);
  12. impl Address {
  13. fn is_valid_address(address: Vec<u8>) -> bool {
  14. if address.starts_with(&[AddressType::Payment as u8]) && address.len() == 37 {
  15. // hash the version + publickey to check the checksum
  16. let mut hasher = sha2::Sha256::new();
  17. hasher.update(&address[..33]);
  18. let payload_hash = hasher.finalize().to_vec();
  19. payload_hash[..4] == address[33..]
  20. } else {
  21. false
  22. }
  23. }
  24. }
  25. impl std::fmt::Display for Address {
  26. fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
  27. // base58 encoding
  28. let address: String = bs58::encode(self.0).into_string();
  29. write!(f, "{}", address)
  30. }
  31. }
  32. impl FromStr for Address {
  33. type Err = Error;
  34. fn from_str(address: &str) -> Result<Self> {
  35. let bytes = bs58::decode(&address).into_vec();
  36. if let Ok(v) = bytes {
  37. if Self::is_valid_address(v.clone()) {
  38. let mut bytes_arr = [0u8; 37];
  39. bytes_arr.copy_from_slice(v.as_slice());
  40. return Ok(Self(bytes_arr))
  41. }
  42. }
  43. Err(Error::InvalidAddress)
  44. }
  45. }
  46. impl From<PublicKey> for Address {
  47. fn from(publickey: PublicKey) -> Self {
  48. let mut publickey = publickey.to_bytes().to_vec();
  49. // add version
  50. let mut address = vec![AddressType::Payment as u8];
  51. // add public key
  52. address.append(&mut publickey);
  53. // hash the version + publickey
  54. let mut hasher = sha2::Sha256::new();
  55. hasher.update(address.clone());
  56. let payload_hash = hasher.finalize().to_vec();
  57. // add the 4 first bytes from the hash as checksum
  58. address.append(&mut payload_hash[..4].to_vec());
  59. let mut payment_address = [0u8; 37];
  60. payment_address.copy_from_slice(address.as_slice());
  61. Self(payment_address)
  62. }
  63. }
  64. #[cfg(test)]
  65. mod tests {
  66. use rand::rngs::OsRng;
  67. use super::*;
  68. use crate::crypto::keypair::{Keypair, PublicKey};
  69. #[test]
  70. fn test_address() -> Result<()> {
  71. // from/to PublicKey
  72. let keypair = Keypair::random(&mut OsRng);
  73. let address = Address::from(keypair.public);
  74. assert_eq!(keypair.public, PublicKey::try_from(address)?);
  75. // from/to string
  76. let address_str = address.to_string();
  77. let from_str = Address::from_str(&address_str)?;
  78. assert_eq!(from_str, address);
  79. Ok(())
  80. }
  81. }