1mod 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
26const ADDRESS_ENCODER: Encoding = new_encoding! {
28 symbols: "abcdefghijklmnopqrstuvwxyz234567",
29 padding: None,
30};
31
32pub const PAYLOAD_HASH_LEN: usize = 20;
34
35pub const SECP_PUB_LEN: usize = 65;
37
38pub const BLS_PUB_LEN: usize = 48;
40
41pub const MAX_SUBADDRESS_LEN: usize = 54;
43
44pub const FIRST_NON_SINGLETON_ADDR: ActorID = 100;
46
47const BLS_ZERO_ADDRESS_BYTES: [u8; BLS_PUB_LEN] = {
49 let mut buf = [0u8; BLS_PUB_LEN];
50 buf[0] = 192;
51 buf
52};
53
54pub const CHECKSUM_HASH_LEN: usize = 4;
56
57pub 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#[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 fn new(protocol: Protocol, bz: &[u8]) -> Result<Self, Error> {
76 Ok(Self {
77 payload: Payload::new(protocol, bz)?,
78 })
79 }
80
81 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 pub const fn new_id(id: u64) -> Self {
93 Self {
94 payload: Payload::ID(id),
95 }
96 }
97
98 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 pub fn new_actor(data: &[u8]) -> Self {
110 Self {
111 payload: Payload::Actor(address_hash(data)),
112 }
113 }
114
115 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 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 pub fn protocol(&self) -> Protocol {
143 Protocol::from(self.payload)
144 }
145
146 pub fn payload(&self) -> &Payload {
149 &self.payload
150 }
151
152 pub fn into_payload(self) -> Payload {
155 self.payload
156 }
157
158 pub fn payload_bytes(&self) -> Vec<u8> {
160 self.payload.to_raw_bytes()
161 }
162
163 pub fn to_bytes(self) -> Vec<u8> {
165 self.payload.to_bytes()
166 }
167
168 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!(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
228impl 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 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 let raw = addr.get(2..).ok_or(Error::InvalidPayload)?;
289 let addr = match protocol {
290 Protocol::ID => {
291 if raw.len() > 20 {
292 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 return Err(Error::InvalidLength);
305 }
306 let id = id.parse::<u64>()?;
307 let subaddr_csum = ADDRESS_ENCODER.decode(subaddr.as_bytes())?;
309 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 let payload_csum = ADDRESS_ENCODER.decode(raw.as_bytes())?;
326 let payload = validate_and_split_checksum(protocol, None, &payload_csum)?;
328
329 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 Address::from_bytes(&bz).map_err(de::Error::custom)
371 }
372}
373
374pub(crate) fn to_leb_bytes(id: u64) -> Vec<u8> {
375 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 let (id, remaining) = unsigned_varint::decode::u64(bz)?;
382 if !remaining.is_empty() {
383 return Err(Error::InvalidPayload);
384 }
385 Ok(id)
386}
387
388fn 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 use crate::address::errors::Error;
405 use crate::address::{from_leb_bytes, to_leb_bytes};
406
407 #[test]
408 fn test_debug() {
409 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}