address.rs 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. use std::{io, str::FromStr};
  2. use sha2::Digest;
  3. use crate::{
  4. crypto::keypair::PublicKey,
  5. serial::{Decodable, Encodable, ReadExt, WriteExt},
  6. Error, Result,
  7. };
  8. enum AddressType {
  9. Payment = 0,
  10. }
  11. #[derive(Copy, Clone, PartialEq, Debug)]
  12. pub struct Address(pub [u8; 37]);
  13. impl Address {
  14. fn is_valid_address(address: Vec<u8>) -> bool {
  15. if address.starts_with(&[AddressType::Payment as u8]) && address.len() == 37 {
  16. // hash the version + publickey to check the checksum
  17. let mut hasher = sha2::Sha256::new();
  18. hasher.update(&address[..33]);
  19. let payload_hash = hasher.finalize().to_vec();
  20. payload_hash[..4] == address[33..]
  21. } else {
  22. false
  23. }
  24. }
  25. }
  26. impl std::fmt::Display for Address {
  27. fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
  28. // base58 encoding
  29. let address: String = bs58::encode(self.0).into_string();
  30. write!(f, "{}", address)
  31. }
  32. }
  33. impl FromStr for Address {
  34. type Err = Error;
  35. fn from_str(address: &str) -> Result<Self> {
  36. let bytes = bs58::decode(&address).into_vec();
  37. if bytes.is_ok() && Self::is_valid_address(bytes.as_ref().unwrap().clone()) {
  38. let mut bytes_arr = [0u8; 37];
  39. bytes_arr.copy_from_slice(bytes.unwrap().as_slice());
  40. Ok(Self(bytes_arr))
  41. } else {
  42. Err(Error::InvalidAddress)
  43. }
  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. impl Encodable for Address {
  65. fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
  66. s.write_slice(&self.0)?;
  67. Ok(37)
  68. }
  69. }
  70. impl Decodable for Address {
  71. fn decode<D: io::Read>(mut d: D) -> Result<Self> {
  72. let mut bytes = [0u8; 37];
  73. d.read_slice(&mut bytes)?;
  74. Ok(Self(bytes))
  75. }
  76. }
  77. #[cfg(test)]
  78. mod tests {
  79. use rand::rngs::OsRng;
  80. use super::*;
  81. use crate::crypto::keypair::{Keypair, PublicKey};
  82. #[test]
  83. fn test_address() -> Result<()> {
  84. // from/to PublicKey
  85. let keypair = Keypair::random(&mut OsRng);
  86. let address = Address::from(keypair.public);
  87. assert_eq!(keypair.public, PublicKey::try_from(address)?);
  88. // from/to string
  89. let address_str = address.to_string();
  90. let from_str = Address::from_str(&address_str)?;
  91. assert_eq!(from_str, address);
  92. Ok(())
  93. }
  94. }