address.rs 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. use std::{io, str::FromStr};
  2. use sha2::Digest;
  3. use crate::{
  4. crypto::keypair::PublicKey,
  5. util::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 let Ok(v) = bytes {
  38. if Self::is_valid_address(v.clone()) {
  39. let mut bytes_arr = [0u8; 37];
  40. bytes_arr.copy_from_slice(v.as_slice());
  41. return Ok(Self(bytes_arr))
  42. }
  43. }
  44. Err(Error::InvalidAddress)
  45. }
  46. }
  47. impl From<PublicKey> for Address {
  48. fn from(publickey: PublicKey) -> Self {
  49. let mut publickey = publickey.to_bytes().to_vec();
  50. // add version
  51. let mut address = vec![AddressType::Payment as u8];
  52. // add public key
  53. address.append(&mut publickey);
  54. // hash the version + publickey
  55. let mut hasher = sha2::Sha256::new();
  56. hasher.update(address.clone());
  57. let payload_hash = hasher.finalize().to_vec();
  58. // add the 4 first bytes from the hash as checksum
  59. address.append(&mut payload_hash[..4].to_vec());
  60. let mut payment_address = [0u8; 37];
  61. payment_address.copy_from_slice(address.as_slice());
  62. Self(payment_address)
  63. }
  64. }
  65. impl Encodable for Address {
  66. fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
  67. s.write_slice(&self.0)?;
  68. Ok(37)
  69. }
  70. }
  71. impl Decodable for Address {
  72. fn decode<D: io::Read>(mut d: D) -> Result<Self> {
  73. let mut bytes = [0u8; 37];
  74. d.read_slice(&mut bytes)?;
  75. Ok(Self(bytes))
  76. }
  77. }
  78. #[cfg(test)]
  79. mod tests {
  80. use rand::rngs::OsRng;
  81. use super::*;
  82. use crate::crypto::keypair::{Keypair, PublicKey};
  83. #[test]
  84. fn test_address() -> Result<()> {
  85. // from/to PublicKey
  86. let keypair = Keypair::random(&mut OsRng);
  87. let address = Address::from(keypair.public);
  88. assert_eq!(keypair.public, PublicKey::try_from(address)?);
  89. // from/to string
  90. let address_str = address.to_string();
  91. let from_str = Address::from_str(&address_str)?;
  92. assert_eq!(from_str, address);
  93. Ok(())
  94. }
  95. }