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