forest_address/
lib.rs

1// Copyright 2019-2022 ChainSafe Systems
2// SPDX-License-Identifier: Apache-2.0, MIT
3
4mod errors;
5mod network;
6mod payload;
7mod protocol;
8pub use self::errors::Error;
9pub use self::network::Network;
10pub use self::payload::{BLSPublicKey, Payload};
11pub use self::protocol::Protocol;
12
13use data_encoding::Encoding;
14#[allow(unused_imports)]
15use data_encoding_macro::{internal_new_encoding, new_encoding};
16use encoding::{blake2b_variable, serde_bytes, Cbor};
17use once_cell::sync::OnceCell;
18use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
19use std::hash::Hash;
20use std::str::FromStr;
21use std::{borrow::Cow, fmt};
22
23/// defines the encoder for base32 encoding with the provided string with no padding
24const ADDRESS_ENCODER: Encoding = new_encoding! {
25    symbols: "abcdefghijklmnopqrstuvwxyz234567",
26    padding: None,
27};
28
29/// Hash length of payload for Secp and Actor addresses.
30pub const PAYLOAD_HASH_LEN: usize = 20;
31
32/// Uncompressed secp public key used for validation of Secp addresses.
33pub const SECP_PUB_LEN: usize = 65;
34
35/// BLS public key length used for validation of BLS addresses.
36pub const BLS_PUB_LEN: usize = 48;
37
38/// Length of the checksum hash for string encodings.
39pub const CHECKSUM_HASH_LEN: usize = 4;
40
41const MAX_ADDRESS_LEN: usize = 84 + 2;
42const MAINNET_PREFIX: &str = "f";
43const TESTNET_PREFIX: &str = "t";
44
45#[cfg(feature = "json")]
46const UNDEF_ADDR_STRING: &str = "<empty>";
47
48// TODO pull network from config (probably)
49pub static NETWORK_DEFAULT: OnceCell<Network> = OnceCell::new();
50
51/// Address is the struct that defines the protocol and data payload conversion from either
52/// a public key or value
53#[derive(PartialEq, Eq, Clone, Debug, Hash, Copy)]
54pub struct Address {
55    network: Network,
56    payload: Payload,
57}
58
59impl Address {
60    /// Address constructor
61    fn new(network: Network, protocol: Protocol, bz: &[u8]) -> Result<Self, Error> {
62        Ok(Self {
63            network,
64            payload: Payload::new(protocol, bz)?,
65        })
66    }
67
68    /// Creates address from encoded bytes
69    pub fn from_bytes(bz: &[u8]) -> Result<Self, Error> {
70        if bz.len() < 2 {
71            Err(Error::InvalidLength)
72        } else {
73            let protocol = Protocol::from_byte(bz[0]).ok_or(Error::UnknownProtocol)?;
74            Self::new(
75                *NETWORK_DEFAULT.get_or_init(|| Network::Mainnet),
76                protocol,
77                &bz[1..],
78            )
79        }
80    }
81
82    /// Generates new address using ID protocol
83    pub fn new_id(id: u64) -> Self {
84        Self {
85            network: *NETWORK_DEFAULT.get_or_init(|| Network::Mainnet),
86            payload: Payload::ID(id),
87        }
88    }
89
90    /// Generates new address using Secp256k1 pubkey
91    pub fn new_secp256k1(pubkey: &[u8]) -> Result<Self, Error> {
92        if pubkey.len() != 65 {
93            return Err(Error::InvalidSECPLength(pubkey.len()));
94        }
95        Ok(Self {
96            network: *NETWORK_DEFAULT.get_or_init(|| Network::Mainnet),
97            payload: Payload::Secp256k1(address_hash(pubkey)),
98        })
99    }
100
101    /// Generates new address using the Actor protocol
102    pub fn new_actor(data: &[u8]) -> Self {
103        Self {
104            network: *NETWORK_DEFAULT.get_or_init(|| Network::Mainnet),
105            payload: Payload::Actor(address_hash(data)),
106        }
107    }
108
109    /// Generates new address using BLS pubkey
110    pub fn new_bls(pubkey: &[u8]) -> Result<Self, Error> {
111        if pubkey.len() != BLS_PUB_LEN {
112            return Err(Error::InvalidBLSLength(pubkey.len()));
113        }
114        let mut key = [0u8; BLS_PUB_LEN];
115        key.copy_from_slice(pubkey);
116        Ok(Self {
117            network: *NETWORK_DEFAULT.get_or_init(|| Network::Mainnet),
118            payload: Payload::BLS(key.into()),
119        })
120    }
121
122    /// Returns protocol for Address
123    pub fn protocol(&self) -> Protocol {
124        Protocol::from(self.payload)
125    }
126
127    /// Returns the `Payload` object from the address, where the respective protocol data is kept
128    /// in an enum separated by protocol
129    pub fn payload(&self) -> &Payload {
130        &self.payload
131    }
132
133    /// Converts Address into `Payload` object, where the respective protocol data is kept
134    /// in an enum separated by protocol
135    pub fn into_payload(self) -> Payload {
136        self.payload
137    }
138
139    /// Returns the raw bytes data payload of the Address
140    pub fn payload_bytes(&self) -> Vec<u8> {
141        self.payload.to_raw_bytes()
142    }
143
144    /// Returns network configuration of Address
145    pub fn network(&self) -> Network {
146        self.network
147    }
148
149    /// Sets the network for the address and returns a mutable reference to it
150    pub fn set_network(&mut self, network: Network) -> &mut Self {
151        self.network = network;
152        self
153    }
154
155    /// Returns encoded bytes of Address
156    pub fn to_bytes(self) -> Vec<u8> {
157        self.payload.to_bytes()
158    }
159
160    /// Get ID of the address. ID protocol only.
161    pub fn id(&self) -> Result<u64, Error> {
162        match self.payload {
163            Payload::ID(id) => Ok(id),
164            _ => Err(Error::NonIDAddress),
165        }
166    }
167}
168
169impl fmt::Display for Address {
170    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
171        write!(f, "{}", encode(self))
172    }
173}
174
175impl FromStr for Address {
176    type Err = Error;
177    fn from_str(addr: &str) -> Result<Self, Error> {
178        if addr.len() > MAX_ADDRESS_LEN || addr.len() < 3 {
179            return Err(Error::InvalidLength);
180        }
181        // ensure the network character is valid before converting
182        let network: Network = match addr.get(0..1).ok_or(Error::UnknownNetwork)? {
183            TESTNET_PREFIX => Network::Testnet,
184            MAINNET_PREFIX => Network::Mainnet,
185            _ => {
186                return Err(Error::UnknownNetwork);
187            }
188        };
189
190        // get protocol from second character
191        let protocol: Protocol = match addr.get(1..2).ok_or(Error::UnknownProtocol)? {
192            "0" => Protocol::ID,
193            "1" => Protocol::Secp256k1,
194            "2" => Protocol::Actor,
195            "3" => Protocol::BLS,
196            _ => {
197                return Err(Error::UnknownProtocol);
198            }
199        };
200
201        // bytes after the protocol character is the data payload of the address
202        let raw = addr.get(2..).ok_or(Error::InvalidPayload)?;
203        if protocol == Protocol::ID {
204            if raw.len() > 20 {
205                // 20 is max u64 as string
206                return Err(Error::InvalidLength);
207            }
208            let id = raw.parse::<u64>()?;
209            return Ok(Address {
210                network,
211                payload: Payload::ID(id),
212            });
213        }
214
215        // decode using byte32 encoding
216        let mut payload = ADDRESS_ENCODER.decode(raw.as_bytes())?;
217        // payload includes checksum at end, so split after decoding
218        let cksm = payload.split_off(payload.len() - CHECKSUM_HASH_LEN);
219
220        // sanity check to make sure address hash values are correct length
221        if (protocol == Protocol::Secp256k1 || protocol == Protocol::Actor)
222            && payload.len() != PAYLOAD_HASH_LEN
223        {
224            return Err(Error::InvalidPayload);
225        }
226
227        // sanity check to make sure bls pub key is correct length
228        if protocol == Protocol::BLS && payload.len() != BLS_PUB_LEN {
229            return Err(Error::InvalidPayload);
230        }
231
232        // validate checksum
233        let mut ingest = payload.clone();
234        ingest.insert(0, protocol as u8);
235        if !validate_checksum(&ingest, cksm) {
236            return Err(Error::InvalidChecksum);
237        }
238
239        Address::new(network, protocol, &payload)
240    }
241}
242
243impl Serialize for Address {
244    fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
245    where
246        S: Serializer,
247    {
248        let address_bytes = self.to_bytes();
249        serde_bytes::Serialize::serialize(&address_bytes, s)
250    }
251}
252
253impl<'de> Deserialize<'de> for Address {
254    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
255    where
256        D: Deserializer<'de>,
257    {
258        let bz: Cow<'de, [u8]> = serde_bytes::Deserialize::deserialize(deserializer)?;
259
260        // Create and return created address of unmarshalled bytes
261        Address::from_bytes(&bz).map_err(de::Error::custom)
262    }
263}
264
265impl Cbor for Address {}
266
267/// encode converts the address into a string
268fn encode(addr: &Address) -> String {
269    match addr.protocol() {
270        Protocol::Secp256k1 | Protocol::Actor | Protocol::BLS => {
271            let ingest = addr.to_bytes();
272            let mut bz = addr.payload_bytes();
273
274            // payload bytes followed by calculated checksum
275            bz.extend(checksum(&ingest));
276            format!(
277                "{}{}{}",
278                addr.network.to_prefix(),
279                addr.protocol().to_string(),
280                ADDRESS_ENCODER.encode(bz.as_mut()),
281            )
282        }
283        Protocol::ID => format!(
284            "{}{}{}",
285            addr.network.to_prefix(),
286            addr.protocol().to_string(),
287            from_leb_bytes(&addr.payload_bytes()).expect("should read encoded bytes"),
288        ),
289    }
290}
291
292pub(crate) fn to_leb_bytes(id: u64) -> Result<Vec<u8>, Error> {
293    let mut buf = Vec::new();
294
295    // write id to buffer in leb128 format
296    leb128::write::unsigned(&mut buf, id)?;
297
298    // Create byte vector from buffer
299    Ok(buf)
300}
301
302pub(crate) fn from_leb_bytes(bz: &[u8]) -> Result<u64, Error> {
303    let mut readable = bz;
304
305    // write id to buffer in leb128 format
306    let id = leb128::read::unsigned(&mut readable)?;
307
308    if to_leb_bytes(id)? == bz {
309        Ok(id)
310    } else {
311        Err(Error::InvalidAddressIDPayload(bz.to_owned()))
312    }
313}
314
315#[cfg(test)]
316mod tests {
317    // Test cases for FOR-02: https://github.com/ChainSafe/forest/issues/1134
318    use crate::{errors::Error, from_leb_bytes, to_leb_bytes};
319
320    #[test]
321    fn test_from_leb_bytes_passing() {
322        let passing = vec![67];
323        assert_eq!(
324            to_leb_bytes(from_leb_bytes(&passing).unwrap()),
325            Ok(vec![67])
326        );
327    }
328
329    #[test]
330    fn test_from_leb_bytes_extra_bytes() {
331        let extra_bytes = vec![67, 0, 1, 2];
332
333        match from_leb_bytes(&extra_bytes) {
334            Ok(id) => {
335                println!(
336                    "Successfully decoded bytes when it was not supposed to. Result was: {:?}",
337                    &to_leb_bytes(id).unwrap()
338                );
339                panic!();
340            }
341            Err(e) => {
342                assert_eq!(e, Error::InvalidAddressIDPayload(extra_bytes));
343            }
344        }
345    }
346
347    #[test]
348    fn test_from_leb_bytes_minimal_encoding() {
349        let minimal_encoding = vec![67, 0, 130, 0];
350
351        match from_leb_bytes(&minimal_encoding) {
352            Ok(id) => {
353                println!(
354                    "Successfully decoded bytes when it was not supposed to. Result was: {:?}",
355                    &to_leb_bytes(id).unwrap()
356                );
357                panic!();
358            }
359            Err(e) => {
360                assert_eq!(e, Error::InvalidAddressIDPayload(minimal_encoding));
361            }
362        }
363    }
364}
365
366/// Checksum calculates the 4 byte checksum hash
367pub fn checksum(ingest: &[u8]) -> Vec<u8> {
368    blake2b_variable(ingest, CHECKSUM_HASH_LEN)
369}
370
371/// Validates the checksum against the ingest data
372pub fn validate_checksum(ingest: &[u8], expect: Vec<u8>) -> bool {
373    let digest = checksum(ingest);
374    digest == expect
375}
376
377/// Returns an address hash for given data
378fn address_hash(ingest: &[u8]) -> [u8; 20] {
379    let digest = blake2b_variable(ingest, PAYLOAD_HASH_LEN);
380    let mut hash = [0u8; 20];
381    hash.clone_from_slice(&digest);
382    hash
383}
384
385#[cfg(feature = "json")]
386pub mod json {
387    use super::*;
388    use serde::{Deserialize, Deserializer, Serializer};
389    use std::borrow::Cow;
390
391    /// Wrapper for serializing and deserializing a SignedMessage from JSON.
392    #[derive(Deserialize, Serialize)]
393    #[serde(transparent)]
394    pub struct AddressJson(#[serde(with = "self")] pub Address);
395
396    /// Wrapper for serializing a SignedMessage reference to JSON.
397    #[derive(Serialize)]
398    #[serde(transparent)]
399    pub struct AddressJsonRef<'a>(#[serde(with = "self")] pub &'a Address);
400
401    impl From<Address> for AddressJson {
402        fn from(address: Address) -> Self {
403            Self(address)
404        }
405    }
406
407    impl From<AddressJson> for Address {
408        fn from(address: AddressJson) -> Self {
409            address.0
410        }
411    }
412
413    pub fn serialize<S>(m: &Address, serializer: S) -> Result<S::Ok, S::Error>
414    where
415        S: Serializer,
416    {
417        serializer.serialize_str(&encode(m))
418    }
419
420    pub fn deserialize<'de, D>(deserializer: D) -> Result<Address, D::Error>
421    where
422        D: Deserializer<'de>,
423    {
424        let address_as_string: Cow<'de, str> = Deserialize::deserialize(deserializer)?;
425        Address::from_str(&address_as_string).map_err(de::Error::custom)
426    }
427
428    #[cfg(feature = "json")]
429    pub mod vec {
430        use super::*;
431        use crate::json::{AddressJson, AddressJsonRef};
432        use forest_json_utils::GoVecVisitor;
433        use serde::ser::SerializeSeq;
434
435        /// Wrapper for serializing and deserializing a Cid vector from JSON.
436        #[derive(Deserialize, Serialize)]
437        #[serde(transparent)]
438        pub struct AddressJsonVec(#[serde(with = "self")] pub Vec<Address>);
439
440        /// Wrapper for serializing a cid slice to JSON.
441        #[derive(Serialize)]
442        #[serde(transparent)]
443        pub struct AddressJsonSlice<'a>(#[serde(with = "self")] pub &'a [Address]);
444
445        pub fn serialize<S>(m: &[Address], serializer: S) -> Result<S::Ok, S::Error>
446        where
447            S: Serializer,
448        {
449            let mut seq = serializer.serialize_seq(Some(m.len()))?;
450            for e in m {
451                seq.serialize_element(&AddressJsonRef(e))?;
452            }
453            seq.end()
454        }
455
456        pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<Address>, D::Error>
457        where
458            D: Deserializer<'de>,
459        {
460            deserializer.deserialize_any(GoVecVisitor::<Address, AddressJson>::new())
461        }
462    }
463
464    pub mod opt {
465        use super::*;
466        use serde::{self, Deserialize, Deserializer, Serializer};
467        use std::borrow::Cow;
468
469        pub fn serialize<S>(v: &Option<Address>, serializer: S) -> Result<S::Ok, S::Error>
470        where
471            S: Serializer,
472        {
473            if let Some(unwrapped_address) = v.as_ref() {
474                serializer.serialize_str(&encode(unwrapped_address))
475            } else {
476                serializer.serialize_str(UNDEF_ADDR_STRING)
477            }
478        }
479
480        pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<Address>, D::Error>
481        where
482            D: Deserializer<'de>,
483        {
484            let address_as_string: Cow<'de, str> = Deserialize::deserialize(deserializer)?;
485            if address_as_string == UNDEF_ADDR_STRING {
486                return Ok(None);
487            }
488            Ok(Some(
489                Address::from_str(&address_as_string).map_err(de::Error::custom)?,
490            ))
491        }
492    }
493}