fvm_shared/address/
mod.rs

1// Copyright 2021-2023 Protocol Labs
2// Copyright 2019-2022 ChainSafe Systems
3// SPDX-License-Identifier: Apache-2.0, MIT
4
5mod errors;
6mod network;
7mod payload;
8mod protocol;
9
10use std::borrow::Cow;
11use std::fmt;
12use std::hash::Hash;
13use std::str::FromStr;
14
15use data_encoding::Encoding;
16use data_encoding_macro::new_encoding;
17use fvm_ipld_encoding::strict_bytes;
18use serde::{Deserialize, Deserializer, Serialize, Serializer, de};
19
20pub use self::errors::Error;
21pub use self::network::{Network, current_network, set_current_network};
22pub use self::payload::{DelegatedAddress, Payload};
23pub use self::protocol::Protocol;
24use crate::ActorID;
25
26/// defines the encoder for base32 encoding with the provided string with no padding
27const ADDRESS_ENCODER: Encoding = new_encoding! {
28    symbols: "abcdefghijklmnopqrstuvwxyz234567",
29    padding: None,
30};
31
32/// Hash length of payload for Secp and Actor addresses.
33pub const PAYLOAD_HASH_LEN: usize = 20;
34
35/// Uncompressed secp public key used for validation of Secp addresses.
36pub const SECP_PUB_LEN: usize = 65;
37
38/// BLS public key length used for validation of BLS addresses.
39pub const BLS_PUB_LEN: usize = 48;
40
41/// Max length of f4 sub addresses.
42pub const MAX_SUBADDRESS_LEN: usize = 54;
43
44/// Defines first available ID address after builtin actors
45pub const FIRST_NON_SINGLETON_ADDR: ActorID = 100;
46
47/// The payload bytes of a "zero" BLS key.
48const BLS_ZERO_ADDRESS_BYTES: [u8; BLS_PUB_LEN] = {
49    let mut buf = [0u8; BLS_PUB_LEN];
50    buf[0] = 192;
51    buf
52};
53
54/// Length of the checksum hash for string encodings.
55pub const CHECKSUM_HASH_LEN: usize = 4;
56
57/// The max encoded length of an address.
58pub const MAX_ADDRESS_LEN: usize = 65;
59
60const MAX_ADDRRESS_TEXT_LEN: usize = 138;
61const MAINNET_PREFIX: &str = "f";
62const TESTNET_PREFIX: &str = "t";
63
64/// Address is the struct that defines the protocol and data payload conversion from either
65/// a public key or value
66#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
67#[cfg_attr(feature = "testing", derive(Default))]
68#[cfg_attr(feature = "arb", derive(arbitrary::Arbitrary))]
69pub struct Address {
70    payload: Payload,
71}
72
73impl Address {
74    /// Construct a new address with the specified network.
75    fn new(protocol: Protocol, bz: &[u8]) -> Result<Self, Error> {
76        Ok(Self {
77            payload: Payload::new(protocol, bz)?,
78        })
79    }
80
81    /// Creates address from encoded bytes.
82    pub fn from_bytes(bz: &[u8]) -> Result<Self, Error> {
83        if bz.len() < 2 {
84            Err(Error::InvalidLength)
85        } else {
86            let protocol = Protocol::from_byte(bz[0]).ok_or(Error::UnknownProtocol)?;
87            Self::new(protocol, &bz[1..])
88        }
89    }
90
91    /// Generates new address using ID protocol.
92    pub const fn new_id(id: u64) -> Self {
93        Self {
94            payload: Payload::ID(id),
95        }
96    }
97
98    /// Generates new address using Secp256k1 pubkey.
99    pub fn new_secp256k1(pubkey: &[u8]) -> Result<Self, Error> {
100        if pubkey.len() != SECP_PUB_LEN {
101            return Err(Error::InvalidSECPLength(pubkey.len()));
102        }
103        Ok(Self {
104            payload: Payload::Secp256k1(address_hash(pubkey)),
105        })
106    }
107
108    /// Generates new address using the Actor protocol.
109    pub fn new_actor(data: &[u8]) -> Self {
110        Self {
111            payload: Payload::Actor(address_hash(data)),
112        }
113    }
114
115    /// Generates a new delegated address from a namespace and a subaddress.
116    pub fn new_delegated(ns: ActorID, subaddress: &[u8]) -> Result<Self, Error> {
117        Ok(Self {
118            payload: Payload::Delegated(DelegatedAddress::new(ns, subaddress)?),
119        })
120    }
121
122    /// Generates new address using BLS pubkey.
123    pub fn new_bls(pubkey: &[u8]) -> Result<Self, Error> {
124        if pubkey.len() != BLS_PUB_LEN {
125            return Err(Error::InvalidBLSLength(pubkey.len()));
126        }
127        let mut key = [0u8; BLS_PUB_LEN];
128        key.copy_from_slice(pubkey);
129        Ok(Self {
130            payload: Payload::BLS(key),
131        })
132    }
133
134    pub fn is_bls_zero_address(&self) -> bool {
135        match self.payload {
136            Payload::BLS(payload_bytes) => payload_bytes == BLS_ZERO_ADDRESS_BYTES,
137            _ => false,
138        }
139    }
140
141    /// Returns protocol for Address
142    pub fn protocol(&self) -> Protocol {
143        Protocol::from(self.payload)
144    }
145
146    /// Returns the `Payload` object from the address, where the respective protocol data is kept
147    /// in an enum separated by protocol
148    pub fn payload(&self) -> &Payload {
149        &self.payload
150    }
151
152    /// Converts Address into `Payload` object, where the respective protocol data is kept
153    /// in an enum separated by protocol
154    pub fn into_payload(self) -> Payload {
155        self.payload
156    }
157
158    /// Returns the raw bytes data payload of the Address
159    pub fn payload_bytes(&self) -> Vec<u8> {
160        self.payload.to_raw_bytes()
161    }
162
163    /// Returns encoded bytes of Address
164    pub fn to_bytes(self) -> Vec<u8> {
165        self.payload.to_bytes()
166    }
167
168    /// Get ID of the address. ID protocol only.
169    pub fn id(&self) -> Result<u64, Error> {
170        match self.payload {
171            Payload::ID(id) => Ok(id),
172            _ => Err(Error::NonIDAddress),
173        }
174    }
175}
176
177impl fmt::Display for Address {
178    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
179        let protocol = self.protocol();
180
181        // write `fP` where P is the protocol number.
182        write!(f, "{}{}", current_network().to_prefix(), protocol)?;
183
184        fn write_payload(
185            f: &mut fmt::Formatter<'_>,
186            protocol: Protocol,
187            prefix: Option<&[u8]>,
188            data: &[u8],
189        ) -> fmt::Result {
190            let mut hasher = blake2b_simd::Params::new()
191                .hash_length(CHECKSUM_HASH_LEN)
192                .to_state();
193            hasher.update(&[protocol as u8]);
194            if let Some(prefix) = prefix {
195                hasher.update(prefix);
196            }
197            hasher.update(data);
198
199            let mut buf = Vec::with_capacity(data.len() + CHECKSUM_HASH_LEN);
200            buf.extend(data);
201            buf.extend(hasher.finalize().as_bytes());
202
203            f.write_str(&ADDRESS_ENCODER.encode(&buf))
204        }
205
206        match self.payload() {
207            Payload::ID(id) => write!(f, "{}", id),
208            Payload::Secp256k1(data) | Payload::Actor(data) => {
209                write_payload(f, protocol, None, data)
210            }
211            Payload::BLS(data) => write_payload(f, protocol, None, data),
212            Payload::Delegated(addr) => {
213                write!(f, "{}f", addr.namespace())?;
214                write_payload(
215                    f,
216                    protocol,
217                    Some(unsigned_varint::encode::u64(
218                        addr.namespace(),
219                        &mut unsigned_varint::encode::u64_buffer(),
220                    )),
221                    addr.subaddress(),
222                )
223            }
224        }
225    }
226}
227
228// Manually implement Debug so we print a "real" address.
229impl fmt::Debug for Address {
230    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
231        f.debug_tuple("Address")
232            .field(&format_args!("\"{}\"", self))
233            .finish()
234    }
235}
236
237#[cfg(feature = "arb")]
238impl quickcheck::Arbitrary for Address {
239    fn arbitrary(g: &mut quickcheck::Gen) -> Self {
240        Self {
241            payload: Payload::arbitrary(g),
242        }
243    }
244}
245
246fn parse_address(addr: &str) -> Result<(Address, Network), Error> {
247    if addr.len() > MAX_ADDRRESS_TEXT_LEN || addr.len() < 3 {
248        return Err(Error::InvalidLength);
249    }
250    let network = Network::from_prefix(addr.get(0..1).ok_or(Error::UnknownNetwork)?)?;
251
252    // get protocol from second character
253    let protocol: Protocol = match addr.get(1..2).ok_or(Error::UnknownProtocol)? {
254        "0" => Protocol::ID,
255        "1" => Protocol::Secp256k1,
256        "2" => Protocol::Actor,
257        "3" => Protocol::BLS,
258        "4" => Protocol::Delegated,
259        _ => {
260            return Err(Error::UnknownProtocol);
261        }
262    };
263
264    fn validate_and_split_checksum<'a>(
265        protocol: Protocol,
266        prefix: Option<&[u8]>,
267        payload: &'a [u8],
268    ) -> Result<&'a [u8], Error> {
269        if payload.len() < CHECKSUM_HASH_LEN {
270            return Err(Error::InvalidLength);
271        }
272        let (payload, csum) = payload.split_at(payload.len() - CHECKSUM_HASH_LEN);
273        let mut hasher = blake2b_simd::Params::new()
274            .hash_length(CHECKSUM_HASH_LEN)
275            .to_state();
276        hasher.update(&[protocol as u8]);
277        if let Some(prefix) = prefix {
278            hasher.update(prefix);
279        }
280        hasher.update(payload);
281        if hasher.finalize().as_bytes() != csum {
282            return Err(Error::InvalidChecksum);
283        }
284        Ok(payload)
285    }
286
287    // bytes after the protocol character is the data payload of the address
288    let raw = addr.get(2..).ok_or(Error::InvalidPayload)?;
289    let addr = match protocol {
290        Protocol::ID => {
291            if raw.len() > 20 {
292                // 20 is max u64 as string
293                return Err(Error::InvalidLength);
294            }
295            let id = raw.parse::<u64>()?;
296            Address {
297                payload: Payload::ID(id),
298            }
299        }
300        Protocol::Delegated => {
301            let (id, subaddr) = raw.split_once('f').ok_or(Error::InvalidPayload)?;
302            if id.len() > 20 {
303                // 20 is max u64 as string
304                return Err(Error::InvalidLength);
305            }
306            let id = id.parse::<u64>()?;
307            // decode subaddr
308            let subaddr_csum = ADDRESS_ENCODER.decode(subaddr.as_bytes())?;
309            // validate and split subaddr.
310            let subaddr = validate_and_split_checksum(
311                protocol,
312                Some(unsigned_varint::encode::u64(
313                    id,
314                    &mut unsigned_varint::encode::u64_buffer(),
315                )),
316                &subaddr_csum,
317            )?;
318
319            Address {
320                payload: Payload::Delegated(DelegatedAddress::new(id, subaddr)?),
321            }
322        }
323        Protocol::Secp256k1 | Protocol::Actor | Protocol::BLS => {
324            // decode using byte32 encoding
325            let payload_csum = ADDRESS_ENCODER.decode(raw.as_bytes())?;
326            // validate and split payload.
327            let payload = validate_and_split_checksum(protocol, None, &payload_csum)?;
328
329            // sanity check to make sure address hash values are correct length
330            if match protocol {
331                Protocol::Secp256k1 | Protocol::Actor => PAYLOAD_HASH_LEN,
332                Protocol::BLS => BLS_PUB_LEN,
333                _ => unreachable!(),
334            } != payload.len()
335            {
336                return Err(Error::InvalidPayload);
337            }
338
339            Address::new(protocol, payload)?
340        }
341    };
342    Ok((addr, network))
343}
344
345impl FromStr for Address {
346    type Err = Error;
347    fn from_str(addr: &str) -> Result<Self, Error> {
348        current_network().parse_address(addr)
349    }
350}
351
352impl Serialize for Address {
353    fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
354    where
355        S: Serializer,
356    {
357        let address_bytes = self.to_bytes();
358        strict_bytes::Serialize::serialize(&address_bytes, s)
359    }
360}
361
362impl<'de> Deserialize<'de> for Address {
363    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
364    where
365        D: Deserializer<'de>,
366    {
367        let bz: Cow<'de, [u8]> = strict_bytes::Deserialize::deserialize(deserializer)?;
368
369        // Create and return created address of unmarshalled bytes
370        Address::from_bytes(&bz).map_err(de::Error::custom)
371    }
372}
373
374pub(crate) fn to_leb_bytes(id: u64) -> Vec<u8> {
375    // write id to buffer in leb128 format
376    unsigned_varint::encode::u64(id, &mut unsigned_varint::encode::u64_buffer()).into()
377}
378
379pub(crate) fn from_leb_bytes(bz: &[u8]) -> Result<u64, Error> {
380    // write id to buffer in leb128 format
381    let (id, remaining) = unsigned_varint::decode::u64(bz)?;
382    if !remaining.is_empty() {
383        return Err(Error::InvalidPayload);
384    }
385    Ok(id)
386}
387
388/// Returns an address hash for given data
389fn address_hash(ingest: &[u8]) -> [u8; 20] {
390    let digest = blake2b_simd::Params::new()
391        .hash_length(PAYLOAD_HASH_LEN)
392        .to_state()
393        .update(ingest)
394        .finalize();
395
396    let mut hash = [0u8; 20];
397    hash.copy_from_slice(digest.as_bytes());
398    hash
399}
400
401#[cfg(test)]
402mod tests {
403    // Test cases for FOR-02: https://github.com/ChainSafe/forest/issues/1134
404    use crate::address::errors::Error;
405    use crate::address::{from_leb_bytes, to_leb_bytes};
406
407    #[test]
408    fn test_debug() {
409        // the address string is dependent on current network state which is set
410        // globally so we need to check against possible valid options
411        let addr_debug_str = format!("{:?}", super::Address::new_id(1));
412        assert!(
413            ["Address(\"f01\")", "Address(\"t01\")"]
414                .iter()
415                .any(|&s| s == addr_debug_str)
416        );
417    }
418
419    #[test]
420    fn test_from_leb_bytes_passing() {
421        let passing = vec![67];
422        assert_eq!(to_leb_bytes(from_leb_bytes(&passing).unwrap()), vec![67]);
423    }
424
425    #[test]
426    fn test_from_leb_bytes_extra_bytes() {
427        let extra_bytes = vec![67, 0, 1, 2];
428
429        match from_leb_bytes(&extra_bytes) {
430            Ok(id) => {
431                println!(
432                    "Successfully decoded bytes when it was not supposed to. Result was: {:?}",
433                    &to_leb_bytes(id)
434                );
435                panic!();
436            }
437            Err(e) => {
438                assert_eq!(e, Error::InvalidPayload);
439            }
440        }
441    }
442
443    #[test]
444    fn test_from_leb_bytes_minimal_encoding() {
445        let minimal_encoding = vec![67, 0, 130, 0];
446
447        match from_leb_bytes(&minimal_encoding) {
448            Ok(id) => {
449                println!(
450                    "Successfully decoded bytes when it was not supposed to. Result was: {:?}",
451                    &to_leb_bytes(id)
452                );
453                panic!();
454            }
455            Err(e) => {
456                assert_eq!(e, Error::InvalidPayload);
457            }
458        }
459    }
460}